[gdal] 01/01: Imported Upstream version 1.11.0+dfsg

Bas Couwenberg sebastic at xs4all.nl
Sun May 4 12:27:41 UTC 2014


This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch upstream
in repository gdal.

commit 51fa5115231cb2c04d52fcfd6fae662d27b25b96
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Wed Apr 30 20:07:37 2014 +0200

    Imported Upstream version 1.11.0+dfsg
---
 .gitignore                                         |    65 -
 COMMITERS                                          |    20 +-
 GDALmake.opt.in                                    |    32 +-
 GNUmakefile                                        |    17 +-
 LICENSE.TXT                                        |    11 +
 MIGRATION_GUIDE.TXT                                |    29 +
 NEWS                                               |   774 +-
 VERSION                                            |     2 +-
 Vagrantfile                                        |    99 +
 alg/GNUmakefile                                    |     9 +-
 alg/contour.cpp                                    |     5 +-
 alg/gdal_alg.h                                     |     3 +-
 alg/gdal_alg_priv.h                                |    11 +-
 alg/gdal_crs.c                                     |   100 +-
 alg/gdal_rpc.cpp                                   |    59 +-
 alg/gdal_tps.cpp                                   |   132 +-
 alg/gdalchecksum.cpp                               |     5 +-
 alg/gdalcutline.cpp                                |    51 +-
 alg/gdaldither.cpp                                 |     5 +-
 alg/gdalgeoloc.cpp                                 |    68 +-
 alg/gdalgrid.cpp                                   |    81 +-
 alg/gdalgrid.h                                     |     3 +-
 alg/gdalgrid_priv.h                                |    75 +
 alg/gdalgridavx.cpp                                |   225 +
 alg/gdalmediancut.cpp                              |     5 +-
 alg/gdalproximity.cpp                              |     5 +-
 alg/gdalrasterize.cpp                              |   307 +-
 alg/gdalsievefilter.cpp                            |     5 +-
 alg/gdaltransformer.cpp                            |   298 +-
 alg/gdalwarper.cpp                                 |     6 +-
 alg/gdalwarper.h                                   |     3 +-
 alg/gdalwarpkernel.cpp                             |   103 +-
 alg/gdalwarpkernel_opencl.c                        |    39 +-
 alg/gdalwarpoperation.cpp                          |     5 +-
 alg/llrasterize.cpp                                |     3 +-
 alg/polygonize.cpp                                 |     5 +-
 alg/rasterfill.cpp                                 |     5 +-
 alg/thinplatespline.cpp                            |   405 +-
 alg/thinplatespline.h                              |    22 +-
 apps/GNUmakefile                                   |     8 +
 apps/commonutils.cpp                               |     6 +-
 apps/commonutils.h                                 |     4 +-
 apps/dumpoverviews.cpp                             |     5 +-
 apps/gdal2ogr.c                                    |     2 +-
 apps/gdal_contour.cpp                              |     5 +-
 apps/gdal_grid.cpp                                 |  2182 ++--
 apps/gdal_rasterize.cpp                            |     7 +-
 apps/gdal_translate.cpp                            |   267 +-
 apps/gdal_utilities.dox                            |   132 +-
 apps/gdaladdo.cpp                                  |     7 +-
 apps/gdalbuildvrt.cpp                              |    40 +-
 apps/gdaldem.cpp                                   |    37 +-
 apps/gdalenhance.cpp                               |     5 +-
 apps/gdalflattenmask.c                             |     2 +-
 apps/gdalinfo.c                                    |    73 +-
 apps/gdallocationinfo.cpp                          |    14 +-
 apps/gdalmanage.cpp                                |     5 +-
 apps/gdalserver.c                                  |    17 +-
 apps/gdalsrsinfo.cpp                               |    22 +-
 apps/gdaltindex.c                                  |   245 +-
 apps/gdaltorture.cpp                               |     2 +-
 apps/gdaltransform.cpp                             |     3 +-
 apps/gdalwarp.cpp                                  |   128 +-
 apps/makefile.vc                                   |     9 +-
 apps/nearblack.cpp                                 |     7 +-
 apps/ogr2ogr.cpp                                   |   787 +-
 apps/ogr_utilities.dox                             |   127 +-
 apps/ogrinfo.cpp                                   |   147 +-
 apps/ogrlineref.cpp                                |  1733 +++
 apps/ogrtindex.cpp                                 |     5 +-
 apps/test_ogrsf.cpp                                |   799 +-
 apps/testreprojmulti.cpp                           |     6 +-
 configure                                          |  1039 +-
 configure.in                                       |   425 +-
 data/compdcs.csv                                   |    67 +
 data/coordinate_axis.csv                           |    10 +
 data/datum_shift.csv                               |  1490 +--
 data/ellipsoid.csv                                 |     6 +-
 data/gcs.csv                                       |    12 +-
 data/gdal_datum.csv                                |    30 +-
 data/gdalicon.png                                  |   Bin 2037 -> 2021 bytes
 data/geoccs.csv                                    |     4 +-
 data/gml_registry.xml                              |    40 +
 data/inspire_cp_BasicPropertyUnit.gfs              |    57 +
 data/inspire_cp_CadastralBoundary.gfs              |    60 +
 data/inspire_cp_CadastralParcel.gfs                |    81 +
 data/inspire_cp_CadastralZoning.gfs                |   161 +
 data/ogrvrt.xsd                                    |   413 +
 data/osmconf.ini                                   |    12 +-
 data/pcs.csv                                       |   158 +-
 data/projop_wparm.csv                              |    99 +
 data/ruian_vf_ob_v1.gfs                            |  1041 ++
 data/ruian_vf_st_v1.gfs                            |  1391 +++
 data/unit_of_measure.csv                           |     2 +-
 data/vertcs.csv                                    |    18 +-
 doc/br/index_br.dox                                |     2 +-
 doc/gdal_tutorial.dox                              |    15 +-
 doc/images/foss4g09.png                            |   Bin 8025 -> 0 bytes
 doc/images/foss4g2013.png                          |   Bin 0 -> 21679 bytes
 doc/index.dox                                      |    28 +-
 frmts/aaigrid/aaigriddataset.cpp                   |    76 +-
 frmts/adrg/adrgdataset.cpp                         |    34 +-
 frmts/adrg/srpdataset.cpp                          |   995 +-
 frmts/aigrid/aigccitt.c                            |     5 +-
 frmts/aigrid/aigdataset.cpp                        |    54 +-
 frmts/aigrid/aigopen.c                             |     5 +-
 frmts/aigrid/aigrid_format.html                    |   790 ++
 frmts/aigrid/gridlib.c                             |     5 +-
 frmts/airsar/airsardataset.cpp                     |     5 +-
 frmts/arg/GNUmakefile                              |     2 +-
 frmts/arg/argdataset.cpp                           |    31 +-
 frmts/arg/makefile.vc                              |     2 +-
 frmts/blx/blx.c                                    |     1 +
 frmts/blx/blxdataset.cpp                           |     5 +-
 frmts/bmp/bmpdataset.cpp                           |     5 +-
 frmts/bsb/bsb_read.c                               |     7 +-
 frmts/bsb/bsbdataset.cpp                           |     5 +-
 frmts/ceos/ceosdataset.cpp                         |     5 +-
 frmts/ceos/ceosopen.c                              |     5 +-
 frmts/ceos2/sar_ceosdataset.cpp                    |    24 +-
 frmts/coasp/coasp_dataset.cpp                      |     5 +-
 frmts/ctg/ctgdataset.cpp                           |     6 +-
 frmts/dds/ddsdataset.cpp                           |     1 +
 frmts/dimap/dimapdataset.cpp                       |   463 +-
 frmts/dods/dodsdataset2.cpp                        |     5 +-
 frmts/dted/dted_api.c                              |     5 +-
 frmts/dted/dted_api.h                              |     3 +-
 frmts/dted/dted_test.c                             |     3 +-
 frmts/dted/dteddataset.cpp                         |    41 +-
 frmts/e00grid/e00griddataset.cpp                   |     6 +-
 frmts/ecw/ecwasyncreader.cpp                       |     1 +
 frmts/ecw/ecwcreatecopy.cpp                        |    55 +-
 frmts/ecw/ecwdataset.cpp                           |   215 +-
 frmts/ecw/gdal_ecw.h                               |    23 +-
 frmts/elas/elasdataset.cpp                         |     5 +-
 frmts/envisat/EnvisatFile.c                        |    77 +-
 frmts/envisat/EnvisatFile.h                        |     7 +-
 frmts/envisat/GNUmakefile                          |     2 +-
 frmts/envisat/adsrange.cpp                         |   153 +
 frmts/envisat/adsrange.hpp                         |   173 +
 frmts/envisat/envisatdataset.cpp                   |   163 +-
 frmts/envisat/makefile.vc                          |     2 +-
 frmts/envisat/timedelta.hpp                        |   221 +
 frmts/envisat/unwrapgcps.cpp                       |   182 +
 frmts/epsilon/epsilondataset.cpp                   |     6 +-
 frmts/ers/ersdataset.cpp                           |    17 +-
 frmts/fit/fitdataset.cpp                           |     5 +-
 frmts/fits/fitsdataset.cpp                         |     5 +-
 frmts/formats_list.html                            |    26 +-
 frmts/frmt_various.html                            |    47 +-
 frmts/gdalallregister.cpp                          |    20 +-
 frmts/georaster/frmt_georaster.html                |    30 +-
 frmts/georaster/georaster_dataset.cpp              |   230 +-
 frmts/georaster/georaster_priv.h                   |   921 +-
 frmts/georaster/georaster_rasterband.cpp           |    61 +-
 frmts/georaster/georaster_wrapper.cpp              |   177 +-
 frmts/georaster/oci_wrapper.cpp                    |    74 +-
 frmts/georaster/oci_wrapper.h                      |     6 +-
 frmts/gff/gff_dataset.cpp                          |     5 +-
 frmts/gif/biggifdataset.cpp                        |    10 +-
 frmts/gif/gifabstractdataset.cpp                   |    17 +-
 frmts/gif/gifabstractdataset.h                     |     5 +-
 frmts/gif/gifdataset.cpp                           |     5 +-
 frmts/grass/frmt_grass.html                        |   113 +-
 frmts/grass/grass57dataset.cpp                     |    17 +-
 frmts/grass/grassdataset.cpp                       |     5 +-
 frmts/grib/degrib18/degrib/myutil.c                |     3 +
 frmts/grib/gribdataset.cpp                         |    31 +-
 frmts/gsg/gs7bgdataset.cpp                         |     5 +-
 frmts/gsg/gsagdataset.cpp                          |     5 +-
 frmts/gsg/gsbgdataset.cpp                          |     7 +-
 frmts/gta/gtadataset.cpp                           |     9 +-
 frmts/gtiff/GNUmakefile                            |     2 +-
 frmts/gtiff/frmt_gtiff.html                        |    23 +-
 frmts/gtiff/geotiff.cpp                            |  1242 +-
 frmts/gtiff/gt_citation.cpp                        |    46 +-
 frmts/gtiff/gt_citation.h                          |     5 +-
 frmts/gtiff/gt_jpeg_copy.cpp                       |     6 +-
 frmts/gtiff/gt_jpeg_copy.h                         |     4 +-
 frmts/gtiff/gt_overview.cpp                        |     5 +-
 frmts/gtiff/gt_overview.h                          |     1 +
 frmts/gtiff/gt_wkt_srs.cpp                         |   162 +-
 frmts/gtiff/gt_wkt_srs.h                           |     4 +-
 frmts/gtiff/gt_wkt_srs_for_gdal.h                  |    16 +-
 frmts/gtiff/gtiff.h                                |     3 +-
 frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h   |     1 +
 frmts/gtiff/libtiff/tif_codec.c                    |     5 +-
 frmts/gtiff/libtiff/tif_dir.c                      |    13 +-
 frmts/gtiff/libtiff/tif_dirinfo.c                  |     4 +-
 frmts/gtiff/libtiff/tif_read.c                     |     6 +-
 frmts/gtiff/libtiff/tif_write.c                    |    10 +-
 frmts/gtiff/makefile.vc                            |     2 +-
 frmts/gtiff/tif_float.h                            |     3 +-
 frmts/gtiff/tifvsi.cpp                             |     3 +-
 frmts/gtiff/tifvsi.h                               |     3 +-
 frmts/gxf/gxf_ogcwkt.c                             |     5 +-
 frmts/gxf/gxfdataset.cpp                           |     5 +-
 frmts/gxf/gxfopen.c                                |     5 +-
 frmts/hdf4/GNUmakefile                             |     8 +
 frmts/hdf4/hdf4dataset.cpp                         |    28 +-
 frmts/hdf4/hdf4dataset.h                           |     3 +-
 frmts/hdf4/hdf4imagedataset.cpp                    |    10 +-
 frmts/hdf4/makefile.vc                             |    12 +
 frmts/hdf5/bagdataset.cpp                          |    17 +-
 frmts/hdf5/gh5_convenience.cpp                     |     4 +-
 frmts/hdf5/hdf5dataset.cpp                         |     9 +-
 frmts/hdf5/hdf5dataset.h                           |     3 +-
 frmts/hdf5/hdf5imagedataset.cpp                    |   204 +-
 frmts/hdf5/iso19115_srs.cpp                        |     5 +-
 frmts/hf2/hf2dataset.cpp                           |     6 +-
 frmts/hfa/frmt_hfa.html                            |    14 +
 frmts/hfa/hfaband.cpp                              |    24 +-
 frmts/hfa/hfadataset.cpp                           |  1801 ++-
 frmts/hfa/hfaentry.cpp                             |     5 +-
 frmts/hfa/hfafield.cpp                             |    49 +-
 frmts/hfa/hfaopen.cpp                              |    77 +-
 frmts/hfa/hfatest.cpp                              |     5 +-
 frmts/hfa/hfatype.cpp                              |     5 +-
 frmts/idrisi/IdrisiDataset.cpp                     |   540 +-
 frmts/idrisi/idrisi.h                              |     5 +-
 frmts/ilwis/ilwiscoordinatesystem.cpp              |     1 +
 frmts/ilwis/ilwisdataset.cpp                       |     1 +
 frmts/ingr/IngrTypes.cpp                           |     5 +-
 frmts/ingr/IngrTypes.h                             |     5 +-
 frmts/ingr/IntergraphBand.cpp                      |     5 +-
 frmts/ingr/IntergraphBand.h                        |     5 +-
 frmts/ingr/IntergraphDataset.cpp                   |     5 +-
 frmts/ingr/IntergraphDataset.h                     |     5 +-
 frmts/ingr/JpegHelper.cpp                          |     2 +-
 frmts/ingr/JpegHelper.h                            |     3 +-
 frmts/iris/irisdataset.cpp                         |    47 +-
 frmts/iso8211/8211dump.cpp                         |     5 +-
 frmts/iso8211/ddfmodule.cpp                        |     5 +-
 frmts/iso8211/ddfrecord.cpp                        |     5 +-
 frmts/iso8211/ddfsubfielddefn.cpp                  |     5 +-
 frmts/jaxapalsar/jaxapalsardataset.cpp             |     5 +-
 frmts/jdem/jdemdataset.cpp                         |     5 +-
 frmts/jp2kak/frmt_jp2kak.html                      |     2 +-
 frmts/jp2kak/jp2kak.lst                            |     5 +
 frmts/jp2kak/jp2kakdataset.cpp                     |   298 +-
 frmts/jp2kak/subfile_source.h                      |    20 +-
 frmts/jpeg/frmt_jpeg.html                          |    11 +
 frmts/jpeg/jpgdataset.cpp                          |   330 +-
 frmts/jpeg/jpgdataset_12.cpp                       |     4 +-
 frmts/jpeg/libjpeg/README                          |    10 +
 frmts/jpeg/libjpeg/jdmarker.c                      |     6 +
 frmts/jpeg/vsidataio.h                             |     3 +-
 frmts/jpeg2000/jpeg2000_vsil_io.cpp                |     5 +-
 frmts/jpeg2000/jpeg2000_vsil_io.h                  |     4 +-
 frmts/jpeg2000/jpeg2000dataset.cpp                 |   143 +-
 frmts/jpegls/jpeglsdataset.cpp                     |     6 +-
 frmts/jpipkak/GNUmakefile                          |     1 +
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp   |   980 +-
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h     |     1 +
 frmts/l1b/frmt_l1b.html                            |    53 +-
 frmts/l1b/l1bdataset.cpp                           |  1891 ++-
 frmts/leveller/levellerdataset.cpp                 |     3 +-
 frmts/map/mapdataset.cpp                           |     3 +-
 frmts/mbtiles/GNUmakefile                          |     2 +-
 frmts/mbtiles/makefile.vc                          |     2 +-
 frmts/mbtiles/mbtilesdataset.cpp                   |    67 +-
 frmts/mem/memdataset.cpp                           |    41 +-
 frmts/mrsid/mrsiddataset.cpp                       |    84 +-
 frmts/mrsid/mrsidstream.cpp                        |     5 +-
 frmts/mrsid/nmake.opt                              |     4 +
 frmts/msg/msgdataset.cpp                           |     3 +-
 frmts/msgn/msgndataset.cpp                         |     5 +-
 frmts/netcdf/gmtdataset.cpp                        |     5 +-
 frmts/netcdf/netcdfdataset.cpp                     |    40 +-
 frmts/netcdf/netcdfdataset.h                       |     5 +-
 frmts/ngsgeoid/ngsgeoiddataset.cpp                 |     6 +-
 frmts/nitf/ecrgtocdataset.cpp                      |     6 +-
 frmts/nitf/frmt_nitf.html                          |    18 +-
 frmts/nitf/nitfaridpcm.cpp                         |     5 +-
 frmts/nitf/nitfbilevel.cpp                         |     5 +-
 frmts/nitf/nitfdataset.cpp                         |    81 +-
 frmts/nitf/nitfdataset.h                           |     4 +-
 frmts/nitf/nitfdes.c                               |     6 +-
 frmts/nitf/nitfdump.c                              |     5 +-
 frmts/nitf/nitffile.c                              |   207 +-
 frmts/nitf/nitfimage.c                             |     5 +-
 frmts/nitf/nitflib.h                               |     3 +-
 frmts/nitf/nitfrasterband.cpp                      |     5 +-
 frmts/nitf/nitfwritejpeg.cpp                       |     3 +-
 frmts/nitf/rpftocdataset.cpp                       |     6 +-
 frmts/nitf/rpftocfile.cpp                          |     6 +-
 frmts/nitf/rpftoclib.h                             |     4 +-
 frmts/northwood/grcdataset.cpp                     |     3 +-
 frmts/northwood/grddataset.cpp                     |     3 +-
 frmts/northwood/northwood.cpp                      |     3 +-
 frmts/northwood/northwood.h                        |     3 +-
 frmts/ogdi/ogdidataset.cpp                         |    17 +-
 frmts/openjpeg/openjpegdataset.cpp                 |   209 +-
 frmts/ozi/ozidataset.cpp                           |     6 +-
 frmts/pcidsk/GNUmakefile                           |     6 +-
 frmts/pcidsk/pcidskdataset.cpp                     |     5 +-
 frmts/pcidsk/pcidskdataset2.cpp                    |    29 +-
 frmts/pcidsk/vsi_pcidsk_io.cpp                     |     5 +-
 frmts/pdf/frmt_pdf.html                            |     9 +-
 frmts/pdf/pdfcreatecopy.cpp                        |    83 +-
 frmts/pdf/pdfcreatecopy.h                          |     4 +-
 frmts/pdf/pdfdataset.cpp                           |    53 +-
 frmts/pdf/pdfdataset.h                             |     4 +-
 frmts/pdf/pdfio.cpp                                |     4 +-
 frmts/pdf/pdfio.h                                  |     4 +-
 frmts/pdf/pdfobject.cpp                            |     6 +-
 frmts/pdf/pdfobject.h                              |     7 +-
 frmts/pds/isis2dataset.cpp                         |     5 +-
 frmts/pds/isis3dataset.cpp                         |     1 +
 frmts/pds/nasakeywordhandler.cpp                   |     1 +
 frmts/pds/pdsdataset.cpp                           |     5 +-
 frmts/pgchip/pgchipdataset.cpp                     |     1 +
 frmts/png/pngdataset.cpp                           |   292 +-
 frmts/postgisraster/GNUmakefile                    |     2 +-
 frmts/postgisraster/makefile.vc                    |     2 +-
 frmts/postgisraster/postgisraster.h                |   396 +-
 frmts/postgisraster/postgisrasterdataset.cpp       |  3426 ++++--
 frmts/postgisraster/postgisrasterdriver.cpp        |    84 +-
 frmts/postgisraster/postgisrasterrasterband.cpp    |  1487 +--
 frmts/postgisraster/postgisrastertiledataset.cpp   |   114 +
 .../postgisraster/postgisrastertilerasterband.cpp  |   194 +
 frmts/postgisraster/postgisrastertools.cpp         |   226 +
 frmts/r/rdataset.cpp                               |     5 +-
 frmts/rasdaman/rasdamandataset.cpp                 |   536 +-
 frmts/rasterlite/rasterlitecreatecopy.cpp          |     6 +-
 frmts/rasterlite/rasterlitedataset.cpp             |    19 +-
 frmts/rasterlite/rasterlitedataset.h               |     5 +-
 frmts/rasterlite/rasterliteoverviews.cpp           |     6 +-
 frmts/raw/GNUmakefile                              |     3 +-
 frmts/raw/ace2dataset.cpp                          |     6 +-
 frmts/raw/btdataset.cpp                            |     7 +-
 frmts/raw/cpgdataset.cpp                           |     5 +-
 frmts/raw/dipxdataset.cpp                          |     5 +-
 frmts/raw/doq1dataset.cpp                          |     5 +-
 frmts/raw/doq2dataset.cpp                          |     5 +-
 frmts/raw/ehdrdataset.cpp                          |    11 +-
 frmts/raw/eirdataset.cpp                           |     1 +
 frmts/raw/envidataset.cpp                          |     5 +-
 frmts/raw/fastdataset.cpp                          |     5 +-
 frmts/raw/frmt_lcp.html                            |    43 +-
 frmts/raw/fujibasdataset.cpp                       |     5 +-
 frmts/raw/genbindataset.cpp                        |     1 +
 frmts/raw/gscdataset.cpp                           |     5 +-
 frmts/raw/gtxdataset.cpp                           |    17 +-
 frmts/raw/hkvdataset.cpp                           |     5 +-
 frmts/raw/idadataset.cpp                           |    10 +-
 frmts/raw/krodataset.cpp                           |   317 +
 frmts/raw/landataset.cpp                           |     5 +-
 frmts/raw/lcpdataset.cpp                           |  1012 +-
 frmts/raw/makefile.vc                              |     2 +-
 frmts/raw/mffdataset.cpp                           |     5 +-
 frmts/raw/ndfdataset.cpp                           |     5 +-
 frmts/raw/ntv2dataset.cpp                          |     5 +-
 frmts/raw/pauxdataset.cpp                          |     5 +-
 frmts/raw/pnmdataset.cpp                           |     5 +-
 frmts/raw/rawdataset.cpp                           |   252 +-
 frmts/raw/rawdataset.h                             |    13 +-
 frmts/raw/snodasdataset.cpp                        |     6 +-
 frmts/rik/rikdataset.cpp                           |     5 +-
 frmts/rmf/rmfdataset.cpp                           |     5 +-
 frmts/rmf/rmfdem.cpp                               |     2 +-
 frmts/rs2/rs2dataset.cpp                           |    17 +-
 frmts/saga/sagadataset.cpp                         |   114 +-
 frmts/sdts/sdts_al.h                               |     6 +-
 frmts/sdts/sdtsdataset.cpp                         |     5 +-
 frmts/sdts/sdtslib.cpp                             |     5 +-
 frmts/sdts/sdtsrasterreader.cpp                    |     5 +-
 frmts/sgi/sgidataset.cpp                           |     5 +-
 frmts/srtmhgt/srtmhgtdataset.cpp                   |     5 +-
 frmts/til/tildataset.cpp                           |     5 +-
 frmts/tsx/tsxdataset.cpp                           |     5 +-
 frmts/usgsdem/usgsdem_create.cpp                   |     5 +-
 frmts/usgsdem/usgsdemdataset.cpp                   |     5 +-
 frmts/vrt/vrt_tutorial.dox                         |    31 +-
 frmts/vrt/vrtdataset.cpp                           |   119 +-
 frmts/vrt/vrtdataset.h                             |    54 +-
 frmts/vrt/vrtderivedrasterband.cpp                 |     1 +
 frmts/vrt/vrtdriver.cpp                            |    16 +-
 frmts/vrt/vrtfilters.cpp                           |     9 +-
 frmts/vrt/vrtrasterband.cpp                        |     5 +-
 frmts/vrt/vrtrawrasterband.cpp                     |    25 +-
 frmts/vrt/vrtsourcedrasterband.cpp                 |   175 +-
 frmts/vrt/vrtsources.cpp                           |   247 +-
 frmts/vrt/vrtwarped.cpp                            |    28 +-
 frmts/wcs/httpdriver.cpp                           |     8 +-
 frmts/wcs/wcsdataset.cpp                           |    22 +-
 frmts/webp/frmt_webp.html                          |     4 +-
 frmts/webp/webpdataset.cpp                         |    18 +-
 frmts/wms/GNUmakefile                              |     5 +-
 frmts/wms/cache.cpp                                |    93 -
 frmts/wms/dataset.cpp                              |   676 --
 frmts/wms/frmt_wms.html                            |     4 +-
 frmts/wms/frmt_wms_metacarta_tms.xml               |     2 +-
 frmts/wms/frmt_wms_metacarta_wmsc.xml              |     2 +-
 frmts/wms/gdalhttp.cpp                             |    14 +-
 frmts/wms/gdalwmscache.cpp                         |   111 +
 frmts/wms/gdalwmsdataset.cpp                       |   635 +
 frmts/wms/gdalwmsrasterband.cpp                    |   867 ++
 frmts/wms/makefile.vc                              |     9 +-
 frmts/wms/minidriver.cpp                           |     7 +-
 frmts/wms/minidriver_tiled_wms.cpp                 |     4 +-
 frmts/wms/minidriver_tileservice.cpp               |     5 +-
 frmts/wms/minidriver_tms.cpp                       |     6 +-
 frmts/wms/minidriver_virtualearth.cpp              |     8 +-
 frmts/wms/minidriver_virtualearth.h                |     4 +-
 frmts/wms/minidriver_wms.cpp                       |     6 +-
 frmts/wms/minidriver_worldwind.cpp                 |     5 +-
 frmts/wms/rasterband.cpp                           |   857 --
 frmts/wms/stdinc.h                                 |    25 -
 frmts/wms/stuff.cpp                                |   152 -
 frmts/wms/wmsdriver.cpp                            |    66 +-
 frmts/wms/wmsdriver.h                              |   143 +-
 frmts/wms/wmsmetadataset.cpp                       |    54 +-
 frmts/wms/wmsmetadataset.h                         |     9 +-
 frmts/wms/wmsutils.cpp                             |   151 +
 frmts/xpm/xpmdataset.cpp                           |     5 +-
 frmts/xyz/xyzdataset.cpp                           |   429 +-
 frmts/zlib/inflate.c                               |     2 +
 frmts/zmap/zmapdataset.cpp                         |     6 +-
 gcore/GNUmakefile                                  |     8 +-
 gcore/gdal.h                                       |    93 +-
 gcore/gdal_frmts.h                                 |     4 +-
 gcore/gdal_misc.cpp                                |   326 +-
 gcore/gdal_pam.h                                   |     4 +-
 gcore/gdal_priv.h                                  |    37 +-
 gcore/gdal_proxy.h                                 |    12 +-
 gcore/gdal_rat.cpp                                 |  2221 ++--
 gcore/gdal_rat.h                                   |   296 +-
 gcore/gdal_version.h                               |     8 +-
 gcore/gdalclientserver.cpp                         |    55 +-
 gcore/gdalcolortable.cpp                           |     5 +-
 gcore/gdaldataset.cpp                              |   173 +-
 gcore/gdaldefaultoverviews.cpp                     |     8 +-
 gcore/gdaldllmain.cpp                              |     3 +-
 gcore/gdaldriver.cpp                               |    35 +-
 gcore/gdaldrivermanager.cpp                        |    32 +-
 gcore/gdalexif.cpp                                 |     5 +-
 gcore/gdalgeorefpamdataset.cpp                     |   158 +
 gcore/gdalgeorefpamdataset.h                       |    57 +
 gcore/gdaljp2abstractdataset.cpp                   |   142 +
 gcore/gdaljp2abstractdataset.h                     |    46 +
 gcore/gdaljp2box.cpp                               |     5 +-
 gcore/gdaljp2metadata.cpp                          |   215 +-
 gcore/gdaljp2metadata.h                            |    10 +-
 gcore/gdalmajorobject.cpp                          |    86 +-
 gcore/gdalmultidomainmetadata.cpp                  |     5 +-
 gcore/gdalnodatamaskband.cpp                       |     5 +-
 gcore/gdalnodatavaluesmaskband.cpp                 |     6 +-
 gcore/gdalopeninfo.cpp                             |     5 +-
 gcore/gdalpamdataset.cpp                           |   106 +-
 gcore/gdalpamrasterband.cpp                        |     9 +-
 gcore/gdalproxydataset.cpp                         |    14 +-
 gcore/gdalproxypool.cpp                            |     6 +-
 gcore/gdalrasterband.cpp                           |   186 +-
 gcore/gdalrasterblock.cpp                          |    17 +-
 gcore/gdalvirtualmem.cpp                           |  1541 +++
 gcore/jp2dump.cpp                                  |    57 +
 gcore/makefile.vc                                  |     4 +-
 gcore/overview.cpp                                 |     5 +-
 gcore/rasterio.cpp                                 |   331 +-
 gdal.pc.in                                         |    11 +
 m4/acinclude.m4                                    |    32 +-
 makegdal10.sln                                     |    20 -
 makegdal10.vcxproj                                 |  1595 ---
 makegdal10.vcxproj.filters                         |  6189 ----------
 makegdal71.sln                                     |    21 -
 makegdal71.vcproj                                  |  2365 ----
 makegdal80.sln                                     |    20 -
 makegdal80.vcproj                                  |  8258 -------------
 makegdal90.vcproj                                  |  7158 -----------
 makegdal_gen.bat                                   |    42 +-
 man/man1/gdal-config.1                             |     4 +-
 man/man1/gdal2tiles.1                              |     4 +-
 man/man1/gdal_calc.1                               |    74 +
 man/man1/gdal_contour.1                            |     4 +-
 man/man1/gdal_edit.1                               |    11 +-
 man/man1/gdal_fillnodata.1                         |     4 +-
 man/man1/gdal_grid.1                               |    12 +-
 man/man1/gdal_merge.1                              |     4 +-
 man/man1/gdal_polygonize.1                         |     4 +-
 man/man1/gdal_proximity.1                          |     4 +-
 man/man1/gdal_rasterize.1                          |     4 +-
 man/man1/gdal_retile.1                             |     4 +-
 man/man1/gdal_sieve.1                              |     4 +-
 man/man1/gdal_translate.1                          |    16 +-
 man/man1/gdal_utilities.1                          |     8 +-
 man/man1/gdaladdo.1                                |     4 +-
 man/man1/gdalbuildvrt.1                            |     4 +-
 man/man1/gdalcompare.1                             |    38 +
 man/man1/gdaldem.1                                 |    14 +-
 man/man1/gdalinfo.1                                |    13 +-
 man/man1/gdallocationinfo.1                        |     4 +-
 man/man1/gdalmanage.1                              |     4 +-
 man/man1/gdalmove.1                                |     4 +-
 man/man1/gdalsrsinfo.1                             |     4 +-
 man/man1/gdaltindex.1                              |    70 +-
 man/man1/gdaltransform.1                           |     4 +-
 man/man1/gdalwarp.1                                |     8 +-
 man/man1/nearblack.1                               |     4 +-
 man/man1/ogr2ogr.1                                 |    25 +-
 man/man1/ogr_utilities.1                           |     6 +-
 man/man1/ogrinfo.1                                 |     8 +-
 man/man1/ogrlineref.1                              |   110 +
 man/man1/ogrtindex.1                               |     4 +-
 man/man1/pct2rgb.1                                 |     4 +-
 man/man1/rgb2pct.1                                 |     4 +-
 mkgdaldist.sh                                      |    10 +-
 nmake.opt                                          |    35 +-
 ogr/GNUmakefile                                    |     2 +
 ogr/file.lst                                       |     6 +-
 ogr/generate_encoding_table.c                      |     4 +-
 ogr/gml2ogrgeometry.cpp                            |   355 +-
 ogr/makefile.vc                                    |     3 +-
 ogr/ogr2gmlgeometry.cpp                            |     3 +-
 ogr/ogr_api.cpp                                    |   102 +-
 ogr/ogr_api.h                                      |    66 +-
 ogr/ogr_apitut.dox                                 |   206 +-
 ogr/ogr_arch.dox                                   |    14 +-
 ogr/ogr_core.h                                     |    32 +-
 ogr/ogr_expat.cpp                                  |     6 +-
 ogr/ogr_expat.h                                    |     4 +-
 ogr/ogr_feature.h                                  |   117 +-
 ogr/ogr_fromepsg.cpp                               |     5 +-
 ogr/ogr_geocoding.cpp                              |    35 +-
 ogr/ogr_geocoding.h                                |     4 +-
 ogr/ogr_geometry.h                                 |    36 +-
 ogr/ogr_opt.cpp                                    |     5 +-
 ogr/ogr_p.h                                        |    20 +-
 ogr/ogr_spatialref.h                               |     3 +-
 ogr/ogr_sql.dox                                    |     5 +
 ogr/ogr_srs_api.h                                  |    46 +-
 ogr/ogr_srs_erm.cpp                                |     5 +-
 ogr/ogr_srs_esri.cpp                               |     6 +-
 ogr/ogr_srs_ozi.cpp                                |     5 +-
 ogr/ogr_srs_panorama.cpp                           |    26 +-
 ogr/ogr_srs_pci.cpp                                |     5 +-
 ogr/ogr_srs_proj4.cpp                              |   145 +-
 ogr/ogr_srs_usgs.cpp                               |     5 +-
 ogr/ogr_srs_validate.cpp                           |    47 +-
 ogr/ogr_srs_xml.cpp                                |     3 +-
 ogr/ogr_srsnode.cpp                                |     5 +-
 ogr/ograssemblepolygon.cpp                         |     5 +-
 ogr/ogrct.cpp                                      |   100 +-
 ogr/ogrfeature.cpp                                 |   600 +-
 ogr/ogrfeaturedefn.cpp                             |   442 +-
 ogr/ogrfeaturequery.cpp                            |    28 +-
 ogr/ogrfeaturestyle.cpp                            |    31 +-
 ogr/ogrfielddefn.cpp                               |     7 +-
 ogr/ogrgeomediageometry.cpp                        |     6 +-
 ogr/ogrgeomediageometry.h                          |     4 +-
 ogr/ogrgeometry.cpp                                |   658 +-
 ogr/ogrgeometrycollection.cpp                      |    35 +-
 ogr/ogrgeometryfactory.cpp                         |   190 +-
 ogr/ogrgeomfielddefn.cpp                           |   494 +
 ogr/ogrlinearring.cpp                              |    73 +-
 ogr/ogrlinestring.cpp                              |   346 +-
 ogr/ogrmultilinestring.cpp                         |     5 +-
 ogr/ogrmultipoint.cpp                              |     5 +-
 ogr/ogrmultipolygon.cpp                            |     5 +-
 ogr/ogrpgeogeometry.cpp                            |   549 +-
 ogr/ogrpgeogeometry.h                              |    13 +-
 ogr/ogrpoint.cpp                                   |    61 +-
 ogr/ogrpolygon.cpp                                 |    92 +-
 ogr/ogrsf_frmts/GNUmakefile                        |     8 +-
 ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h        |     7 +-
 .../aeronavfaa/ograeronavfaadatasource.cpp         |     6 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp |     6 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp  |     7 +-
 ogr/ogrsf_frmts/arcgen/ogr_arcgen.h                |     7 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp     |     6 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp         |     6 +-
 ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp          |     6 +-
 ogr/ogrsf_frmts/bna/ogr_bna.h                      |     4 +-
 ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp           |     4 +-
 ogr/ogrsf_frmts/bna/ogrbnadriver.cpp               |     2 +-
 ogr/ogrsf_frmts/bna/ogrbnalayer.cpp                |     4 +-
 ogr/ogrsf_frmts/bna/ogrbnaparser.cpp               |     4 +-
 ogr/ogrsf_frmts/cartodb/GNUmakefile                |    14 +
 ogr/ogrsf_frmts/cartodb/drv_cartodb.html           |   125 +
 ogr/ogrsf_frmts/cartodb/makefile.vc                |    16 +
 ogr/ogrsf_frmts/cartodb/ogr_cartodb.h              |   237 +
 ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp   |   641 +
 ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp       |    84 +
 ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp        |   426 +
 ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp  |   103 +
 ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp   |   953 ++
 ogr/ogrsf_frmts/couchdb/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/couchdb/makefile.vc                |     2 +-
 ogr/ogrsf_frmts/couchdb/ogr_couchdb.h              |    10 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp   |    13 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp       |     6 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp        |    18 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp    |     6 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp   |    20 +-
 ogr/ogrsf_frmts/csv/ogr_csv.h                      |    15 +-
 ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp           |    19 +-
 ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp               |     9 +-
 ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp                |   243 +-
 ogr/ogrsf_frmts/dgn/dgnwrite.cpp                   |     9 +-
 ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp                |    58 +-
 ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp         |     5 +-
 ogr/ogrsf_frmts/dwg/ogr_dwg.h                      |     1 +
 ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp               |    30 +-
 ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp               |     3 +-
 ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp                |    39 +
 ogr/ogrsf_frmts/dxf/drv_dxf.html                   |     6 +-
 ogr/ogrsf_frmts/dxf/ogr_dxf.h                      |     5 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp           |     5 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp               |    65 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp     |     2 +
 ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp           |    19 +-
 ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp                |   275 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp             |     5 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp          |     5 +-
 ogr/ogrsf_frmts/edigeo/ogr_edigeo.h                |     6 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp     |     6 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp         |     6 +-
 ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp          |     8 +-
 ogr/ogrsf_frmts/elastic/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/elastic/makefile.vc                |     2 +-
 ogr/ogrsf_frmts/elastic/ogr_elastic.h              |     4 +-
 ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp   |     5 +-
 ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp        |    17 +-
 ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp         |    61 +-
 ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp             |    23 +-
 ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp              |   236 +-
 ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp        |     2 +-
 ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp              |    34 +-
 ogr/ogrsf_frmts/filegdb/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/filegdb/drv_filegdb.html           |     8 +-
 ogr/ogrsf_frmts/filegdb/makefile.vc                |     2 +-
 ogr/ogrsf_frmts/filegdb/ogr_fgdb.h                 |    23 +-
 ogr/ogrsf_frmts/fme/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/generic/GNUmakefile                |    24 +-
 ogr/ogrsf_frmts/generic/makefile.vc                |    17 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.cpp             |   478 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.h               |    26 +-
 ogr/ogrsf_frmts/generic/ogr_miattrind.cpp          |     5 +-
 ogr/ogrsf_frmts/generic/ogrdatasource.cpp          |    76 +-
 ogr/ogrsf_frmts/generic/ogrlayer.cpp               |   365 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp      |    22 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.h        |    10 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.cpp           |    27 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.h             |     6 +-
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp   |   140 +
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h     |    89 +
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp        |   258 +
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.h          |   113 +
 ogr/ogrsf_frmts/generic/ogrregisterall.cpp         |    27 +-
 ogr/ogrsf_frmts/generic/ogrsfdriver.cpp            |     5 +-
 ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp   |    19 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.cpp          |   545 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.h            |    51 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp         |   291 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.h           |    17 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept.c            |     1 +
 ogr/ogrsf_frmts/geoconcept/geoconcept.h            |     1 +
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c   |     1 +
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h   |     1 +
 .../geoconcept/ogrgeoconceptdatasource.cpp         |     1 +
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp  |     1 +
 ogr/ogrsf_frmts/geojson/GNUmakefile                |    11 +-
 ogr/ogrsf_frmts/geojson/drv_geojson.html           |     2 +
 ogr/ogrsf_frmts/geojson/jsonc/AUTHORS              |     2 -
 ogr/ogrsf_frmts/geojson/jsonc/COPYING              |    19 -
 ogr/ogrsf_frmts/geojson/jsonc/ChangeLog            |   107 -
 ogr/ogrsf_frmts/geojson/jsonc/GNUmakefile          |    27 -
 ogr/ogrsf_frmts/geojson/jsonc/README.html          |    32 -
 ogr/ogrsf_frmts/geojson/jsonc/arraylist.c          |    94 -
 ogr/ogrsf_frmts/geojson/jsonc/arraylist.h          |    53 -
 ogr/ogrsf_frmts/geojson/jsonc/bits.h               |    27 -
 ogr/ogrsf_frmts/geojson/jsonc/config.h             |   128 -
 ogr/ogrsf_frmts/geojson/jsonc/debug.h              |    58 -
 ogr/ogrsf_frmts/geojson/jsonc/json.h               |    31 -
 ogr/ogrsf_frmts/geojson/jsonc/json_object.c        |   650 -
 ogr/ogrsf_frmts/geojson/jsonc/json_object.h        |   328 -
 .../geojson/jsonc/json_object_private.h            |    53 -
 ogr/ogrsf_frmts/geojson/jsonc/json_tokener.c       |   634 -
 ogr/ogrsf_frmts/geojson/jsonc/json_tokener.h       |    98 -
 ogr/ogrsf_frmts/geojson/jsonc/json_util.c          |   122 -
 ogr/ogrsf_frmts/geojson/jsonc/json_util.h          |    31 -
 ogr/ogrsf_frmts/geojson/jsonc/linkhash.c           |   216 -
 ogr/ogrsf_frmts/geojson/jsonc/linkhash.h           |   272 -
 ogr/ogrsf_frmts/geojson/jsonc/makefile.vc          |    25 -
 ogr/ogrsf_frmts/geojson/jsonc/printbuf.c           |   109 -
 ogr/ogrsf_frmts/geojson/jsonc/printbuf.h           |    64 -
 ogr/ogrsf_frmts/geojson/libjson/AUTHORS            |     5 +
 ogr/ogrsf_frmts/geojson/libjson/COPYING            |    42 +
 ogr/ogrsf_frmts/geojson/libjson/ChangeLog          |   175 +
 ogr/ogrsf_frmts/geojson/libjson/GNUmakefile        |    29 +
 ogr/ogrsf_frmts/geojson/{jsonc => libjson}/README  |     0
 ogr/ogrsf_frmts/geojson/libjson/README.html        |    34 +
 ogr/ogrsf_frmts/geojson/libjson/arraylist.c        |   101 +
 ogr/ogrsf_frmts/geojson/libjson/arraylist.h        |    56 +
 ogr/ogrsf_frmts/geojson/libjson/bits.h             |    28 +
 ogr/ogrsf_frmts/geojson/libjson/config.h           |   126 +
 ogr/ogrsf_frmts/geojson/{jsonc => libjson}/debug.c |     0
 ogr/ogrsf_frmts/geojson/libjson/debug.h            |    84 +
 ogr/ogrsf_frmts/geojson/libjson/dump_symbols.sh    |    19 +
 ogr/ogrsf_frmts/geojson/libjson/json.h             |    34 +
 ogr/ogrsf_frmts/geojson/libjson/json_c_version.c   |    20 +
 ogr/ogrsf_frmts/geojson/libjson/json_c_version.h   |    22 +
 ogr/ogrsf_frmts/geojson/libjson/json_config.h      |     4 +
 ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h    |    28 +
 ogr/ogrsf_frmts/geojson/libjson/json_object.c      |   778 ++
 ogr/ogrsf_frmts/geojson/libjson/json_object.h      |   563 +
 .../geojson/libjson/json_object_iterator.c         |   168 +
 .../geojson/libjson/json_object_iterator.h         |   239 +
 .../geojson/libjson/json_object_private.h          |    47 +
 ogr/ogrsf_frmts/geojson/libjson/json_tokener.c     |   771 ++
 ogr/ogrsf_frmts/geojson/libjson/json_tokener.h     |   209 +
 ogr/ogrsf_frmts/geojson/libjson/json_util.c        |   303 +
 ogr/ogrsf_frmts/geojson/libjson/json_util.h        |    41 +
 ogr/ogrsf_frmts/geojson/libjson/linkhash.c         |   233 +
 ogr/ogrsf_frmts/geojson/libjson/linkhash.h         |   292 +
 ogr/ogrsf_frmts/geojson/libjson/makefile.vc        |    27 +
 ogr/ogrsf_frmts/geojson/libjson/printbuf.c         |   148 +
 ogr/ogrsf_frmts/geojson/libjson/printbuf.h         |    77 +
 ogr/ogrsf_frmts/geojson/libjson/symbol_renames.h   |   127 +
 ogr/ogrsf_frmts/geojson/makefile.vc                |     9 +-
 ogr/ogrsf_frmts/geojson/ogr_geojson.h              |    12 +-
 ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp      |   461 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp   |   159 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp        |    56 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp       |   242 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h         |    51 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp        |    91 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h          |    21 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp   |     4 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp       |    88 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h         |     7 +-
 ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp      |   558 +
 ogr/ogrsf_frmts/geomedia/GNUmakefile               |     2 +-
 ogr/ogrsf_frmts/geomedia/makefile.vc               |     2 +-
 ogr/ogrsf_frmts/geomedia/ogr_geomedia.h            |    18 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp |    10 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp     |   150 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp      |    17 +-
 .../geomedia/ogrgeomediaselectlayer.cpp            |     5 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp |     6 +-
 ogr/ogrsf_frmts/georss/ogr_georss.h                |     4 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp     |     6 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp         |     6 +-
 ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp          |    26 +-
 ogr/ogrsf_frmts/gft/drv_gft.html                   |     4 +-
 ogr/ogrsf_frmts/gft/ogr_gft.h                      |    10 +-
 ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp           |    11 +-
 ogr/ogrsf_frmts/gft/ogrgftdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/gft/ogrgftlayer.cpp                |    59 +-
 ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp          |     9 +-
 ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp           |    13 +-
 ogr/ogrsf_frmts/gme/GNUmakefile                    |    16 +
 ogr/ogrsf_frmts/gme/makefile.vc                    |    15 +
 ogr/ogrsf_frmts/gme/ogr_gme.h                      |   209 +
 ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp           |   600 +
 ogr/ogrsf_frmts/gme/ogrgmedriver.cpp               |   115 +
 ogr/ogrsf_frmts/gme/ogrgmejson.cpp                 |   547 +
 ogr/ogrsf_frmts/gme/ogrgmejson.h                   |    59 +
 ogr/ogrsf_frmts/gme/ogrgmelayer.cpp                |   952 ++
 ogr/ogrsf_frmts/gml/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/gml/drv_gml.html                   |   377 +-
 ogr/ogrsf_frmts/gml/gfstemplate.cpp                |     8 +-
 ogr/ogrsf_frmts/gml/gmlfeature.cpp                 |    47 +-
 ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp            |   294 +-
 ogr/ogrsf_frmts/gml/gmlhandler.cpp                 |   584 +-
 ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp            |    58 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   225 +-
 ogr/ogrsf_frmts/gml/gmlreader.h                    |    69 +-
 ogr/ogrsf_frmts/gml/gmlreaderp.h                   |    54 +-
 ogr/ogrsf_frmts/gml/gmlreadstate.cpp               |     3 +-
 ogr/ogrsf_frmts/gml/gmlregistry.cpp                |   149 +
 ogr/ogrsf_frmts/gml/gmlregistry.h                  |    70 +
 ogr/ogrsf_frmts/gml/gmlutils.cpp                   |     4 +-
 ogr/ogrsf_frmts/gml/gmlutils.h                     |     4 +-
 ogr/ogrsf_frmts/gml/hugefileresolver.cpp           |    39 +-
 ogr/ogrsf_frmts/gml/makefile.vc                    |     2 +-
 ogr/ogrsf_frmts/gml/ogr_gml.h                      |    24 +-
 ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp           |   767 +-
 ogr/ogrsf_frmts/gml/ogrgmldriver.cpp               |    12 +-
 ogr/ogrsf_frmts/gml/ogrgmllayer.cpp                |   530 +-
 ogr/ogrsf_frmts/gml/parsexsd.cpp                   |   281 +-
 ogr/ogrsf_frmts/gml/parsexsd.h                     |     3 +-
 ogr/ogrsf_frmts/gml/resolvexlinks.cpp              |    12 +-
 ogr/ogrsf_frmts/gmt/ogr_gmt.h                      |     2 -
 ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp                |    12 +-
 ogr/ogrsf_frmts/gpkg/GNUmakefile                   |    21 +
 ogr/ogrsf_frmts/gpkg/drv_geopackage.html           |   105 +
 ogr/ogrsf_frmts/gpkg/makefile.vc                   |    21 +
 ogr/ogrsf_frmts/gpkg/ogr_geopackage.h              |   179 +
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |  1102 ++
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp       |   139 +
 ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp        |  1277 ++
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp      |   614 +
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h        |    80 +
 ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h            |     4 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp |     6 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp     |     2 +-
 .../gpsbabel/ogrgpsbabelwritedatasource.cpp        |     6 +-
 ogr/ogrsf_frmts/gpx/ogr_gpx.h                      |     6 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp                |    21 +-
 ogr/ogrsf_frmts/grass/GNUmakefile                  |     2 +-
 ogr/ogrsf_frmts/grass/drv_grass.html               |   150 +-
 ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp       |     7 +-
 ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp            |     5 +-
 ogr/ogrsf_frmts/gtm/gtm.cpp                        |     3 +-
 ogr/ogrsf_frmts/gtm/gtm.h                          |     3 +-
 ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp              |     3 +-
 ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp           |     4 +-
 ogr/ogrsf_frmts/gtm/ogr_gtm.h                      |     4 +-
 ogr/ogrsf_frmts/htf/ogr_htf.h                      |     8 +-
 ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/htf/ogrhtflayer.cpp                |     8 +-
 ogr/ogrsf_frmts/idb/ogridbdatasource.cpp           |     8 +-
 ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp           |     7 +-
 ogr/ogrsf_frmts/idrisi/generate_test_files.c       |     2 +-
 ogr/ogrsf_frmts/idrisi/ogr_idrisi.h                |     6 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp     |     6 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp         |     4 +-
 ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp          |     7 +-
 ogr/ogrsf_frmts/ili/GNUmakefile                    |    10 +-
 ogr/ogrsf_frmts/ili/ili1reader.cpp                 |   498 +-
 ogr/ogrsf_frmts/ili/ili1reader.h                   |     8 +-
 ogr/ogrsf_frmts/ili/ili1readerp.h                  |    16 +-
 ogr/ogrsf_frmts/ili/ili2handler.cpp                |     5 +-
 ogr/ogrsf_frmts/ili/ili2reader.cpp                 |   221 +-
 ogr/ogrsf_frmts/ili/ili2reader.h                   |     6 +-
 ogr/ogrsf_frmts/ili/ili2readerp.h                  |    11 +-
 ogr/ogrsf_frmts/ili/ilihelper.cpp                  |     4 +-
 ogr/ogrsf_frmts/ili/ilihelper.h                    |     2 +-
 ogr/ogrsf_frmts/ili/imdreader.cpp                  |   456 +
 ogr/ogrsf_frmts/ili/imdreader.h                    |    89 +
 ogr/ogrsf_frmts/ili/iom/GNUmakefile                |    20 -
 ogr/ogrsf_frmts/ili/iom/README.src.txt             |    55 -
 ogr/ogrsf_frmts/ili/iom/iom.h                      |   397 -
 ogr/ogrsf_frmts/ili/iom/iom_attr.cpp               |   300 -
 ogr/ogrsf_frmts/ili/iom/iom_basket.cpp             |   383 -
 ogr/ogrsf_frmts/ili/iom/iom_error.cpp              |   190 -
 ogr/ogrsf_frmts/ili/iom/iom_file.cpp               |   430 -
 ogr/ogrsf_frmts/ili/iom/iom_iterator.cpp           |   122 -
 ogr/ogrsf_frmts/ili/iom/iom_object.cpp             |   664 --
 ogr/ogrsf_frmts/ili/iom/iom_p.h                    |   835 --
 ogr/ogrsf_frmts/ili/iom/iom_utilities.cpp          |   282 -
 ogr/ogrsf_frmts/ili/iom/iom_value.cpp              |    63 -
 ogr/ogrsf_frmts/ili/iom/makefile.vc                |    18 -
 ogr/ogrsf_frmts/ili/iom/reader.cpp                 |   975 --
 ogr/ogrsf_frmts/ili/iom/tags.cpp                   |   373 -
 ogr/ogrsf_frmts/ili/iom/ustrings.cpp               |   239 -
 ogr/ogrsf_frmts/ili/iom/writer.cpp                 |   877 --
 ogr/ogrsf_frmts/ili/iomhelper.cpp                  |   105 -
 ogr/ogrsf_frmts/ili/iomhelper.h                    |    43 -
 ogr/ogrsf_frmts/ili/makefile.vc                    |    11 +-
 ogr/ogrsf_frmts/ili/ogr_ili1.h                     |    29 +-
 ogr/ogrsf_frmts/ili/ogr_ili2.h                     |    28 +-
 ogr/ogrsf_frmts/ili/ogrili1datasource.cpp          |    63 +-
 ogr/ogrsf_frmts/ili/ogrili1layer.cpp               |   150 +-
 ogr/ogrsf_frmts/ili/ogrili2datasource.cpp          |   153 +-
 ogr/ogrsf_frmts/ili/ogrili2layer.cpp               |   179 +-
 ogr/ogrsf_frmts/ingres/drv_ingres.html             |   122 +-
 ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp     |     8 +-
 ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp     |     7 +-
 ogr/ogrsf_frmts/kml/kml.cpp                        |     3 +-
 ogr/ogrsf_frmts/kml/kml.h                          |     3 +-
 ogr/ogrsf_frmts/kml/kmlnode.cpp                    |     3 +-
 ogr/ogrsf_frmts/kml/kmlnode.h                      |     3 +-
 ogr/ogrsf_frmts/kml/kmlutility.h                   |     3 +-
 ogr/ogrsf_frmts/kml/kmlvector.cpp                  |     3 +-
 ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp            |     3 +-
 ogr/ogrsf_frmts/kml/ogr_kml.h                      |     9 +-
 ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp           |    38 +-
 ogr/ogrsf_frmts/kml/ogrkmllayer.cpp                |    48 +-
 ogr/ogrsf_frmts/libkml/drv_libkml.html             |   575 +-
 ogr/ogrsf_frmts/libkml/ogr_libkml.h                |    86 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp     |   709 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp        |   669 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h          |     6 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp   |    75 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h     |     6 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp          |   770 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h            |    39 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp       |   127 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp          |   582 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp          |   206 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h            |    21 +-
 ogr/ogrsf_frmts/makefile.vc                        |    37 +-
 ogr/ogrsf_frmts/mdb/ogr_mdb.h                      |     7 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp               |    15 +-
 ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp             |     6 +-
 ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp                |    41 +-
 ogr/ogrsf_frmts/mem/ogr_mem.h                      |     8 +-
 ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/mem/ogrmemlayer.cpp                |    84 +-
 ogr/ogrsf_frmts/mitab/mitab_miffile.cpp            |    96 +-
 ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html |    11 +
 ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h    |     6 +-
 .../mssqlspatial/ogrmssqlspatialdatasource.cpp     |   137 +-
 .../mssqlspatial/ogrmssqlspatiallayer.cpp          |    11 +-
 .../mssqlspatial/ogrmssqlspatialselectlayer.cpp    |    29 +-
 .../mssqlspatial/ogrmssqlspatialtablelayer.cpp     |    11 +-
 ogr/ogrsf_frmts/mysql/GNUmakefile                  |     5 +
 ogr/ogrsf_frmts/mysql/ogr_mysql.h                  |     3 +-
 ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp       |    19 +-
 ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp            |     6 +-
 ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp      |     5 +-
 ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp       |    14 +-
 ogr/ogrsf_frmts/nas/nashandler.cpp                 |     3 +-
 ogr/ogrsf_frmts/nas/nasreader.cpp                  |    35 +-
 ogr/ogrsf_frmts/nas/nasreaderp.h                   |     7 +-
 ogr/ogrsf_frmts/nas/ogr_nas.h                      |     4 +-
 ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp           |    20 +-
 ogr/ogrsf_frmts/nas/ogrnasdriver.cpp               |    10 +-
 ogr/ogrsf_frmts/nas/ogrnaslayer.cpp                |    27 +-
 ogr/ogrsf_frmts/ntf/ntf.h                          |     6 +-
 ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp              |     5 +-
 ogr/ogrsf_frmts/ntf/ntf_raster.cpp                 |    15 +-
 ogr/ogrsf_frmts/ntf/ntffilereader.cpp              |     5 +-
 ogr/ogrsf_frmts/ntf/ntfrecord.cpp                  |     5 +-
 ogr/ogrsf_frmts/ntf/ogrntflayer.cpp                |    14 +-
 ogr/ogrsf_frmts/null/ogrnulldriver.cpp             |     6 +-
 ogr/ogrsf_frmts/oci/ogr_oci.h                      |     4 +-
 ogr/ogrsf_frmts/oci/ogrocidatasource.cpp           |     8 +-
 ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp           |     7 +-
 ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp        |    24 +-
 ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp         |    23 +-
 ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp         |     8 +-
 ogr/ogrsf_frmts/ods/ods_formula.cpp                |     4 +-
 ogr/ogrsf_frmts/ods/ods_formula.h                  |     5 +-
 ogr/ogrsf_frmts/ods/ods_formula_node.cpp           |     6 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.cpp         |     3 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.hpp         |     1 +
 ogr/ogrsf_frmts/ods/ogr_ods.h                      |     4 +-
 ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/ods/ogrodsdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/ods/testparser.cpp                 |     4 +-
 ogr/ogrsf_frmts/ogdi/ogrogdi.h                     |     6 +-
 ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp              |    75 +-
 ogr/ogrsf_frmts/ogr_formats.html                   |    63 +-
 ogr/ogrsf_frmts/ogrsf_frmts.dox                    |   360 +-
 ogr/ogrsf_frmts/ogrsf_frmts.h                      |    32 +-
 ogr/ogrsf_frmts/openair/ogr_openair.h              |    10 +-
 ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp   |     6 +-
 ogr/ogrsf_frmts/openair/ogropenairdriver.cpp       |     6 +-
 ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp   |     7 +-
 ogr/ogrsf_frmts/openair/ogropenairlayer.cpp        |     7 +-
 ogr/ogrsf_frmts/openfilegdb/GNUmakefile            |    14 +
 ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html   |   100 +
 ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp       |  1796 +++
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp       |  2556 ++++
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.h         |   376 +
 ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h    |   138 +
 ogr/ogrsf_frmts/openfilegdb/makefile.vc            |    13 +
 ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h      |   205 +
 .../openfilegdb/ogropenfilegdbdatasource.cpp       |  1147 ++
 .../openfilegdb/ogropenfilegdbdriver.cpp           |   185 +
 .../openfilegdb/ogropenfilegdblayer.cpp            |  1635 +++
 ogr/ogrsf_frmts/osm/drv_osm.html                   |    10 +-
 ogr/ogrsf_frmts/osm/gpb.h                          |    12 +-
 ogr/ogrsf_frmts/osm/ogr_osm.h                      |    51 +-
 ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp           |   244 +-
 ogr/ogrsf_frmts/osm/ogrosmdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/osm/ogrosmlayer.cpp                |    89 +-
 ogr/ogrsf_frmts/osm/osm2osm.c                      |     4 +-
 ogr/ogrsf_frmts/osm/osm_parser.cpp                 |    10 +-
 ogr/ogrsf_frmts/osm/osm_parser.h                   |     4 +-
 ogr/ogrsf_frmts/pcidsk/ogr_pcidsk.h                |     1 -
 ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp          |    15 +-
 ogr/ogrsf_frmts/pdf/ogr_pdf.h                      |     4 +-
 ogr/ogrsf_frmts/pdf/ogrpdfdatasource.cpp           |     8 +-
 ogr/ogrsf_frmts/pdf/ogrpdfdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/pds/ogr_pds.h                      |     6 +-
 ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/pds/ogrpdslayer.cpp                |    10 +-
 ogr/ogrsf_frmts/pg/drv_pg.html                     |     6 +-
 ogr/ogrsf_frmts/pg/drv_pg_advanced.html            |    15 +
 ogr/ogrsf_frmts/pg/ogr_pg.h                        |   183 +-
 ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp             |   312 +-
 ogr/ogrsf_frmts/pg/ogrpglayer.cpp                  |   564 +-
 ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp            |   246 +-
 ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp             |  1263 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.cpp                |     6 +-
 ogr/ogrsf_frmts/pgdump/drv_pgdump.html             |     6 +-
 ogr/ogrsf_frmts/pgdump/ogr_pgdump.h                |    49 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp     |    54 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp         |     6 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp          |   305 +-
 ogr/ogrsf_frmts/pgeo/ogr_pgeo.h                    |    25 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp         |     9 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp             |    21 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp              |    19 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp        |    20 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp         |     8 +-
 ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/s57/GNUmakefile                    |     6 +-
 ogr/ogrsf_frmts/s57/ogr_s57.h                      |     6 +-
 ogr/ogrsf_frmts/s57/ogrs57datasource.cpp           |    53 +-
 ogr/ogrsf_frmts/s57/ogrs57driver.cpp               |     5 +-
 ogr/ogrsf_frmts/s57/ogrs57layer.cpp                |    20 +-
 ogr/ogrsf_frmts/s57/s57.h                          |   107 +-
 ogr/ogrsf_frmts/s57/s57classregistrar.cpp          |   192 +-
 ogr/ogrsf_frmts/s57/s57dump.cpp                    |    33 +-
 ogr/ogrsf_frmts/s57/s57featuredefns.cpp            |    21 +-
 ogr/ogrsf_frmts/s57/s57reader.cpp                  |    61 +-
 ogr/ogrsf_frmts/s57/s57writer.cpp                  |    14 +-
 ogr/ogrsf_frmts/sde/ogrsdelayer.cpp                |     7 +-
 ogr/ogrsf_frmts/sdts/ogr_sdts.h                    |     4 +-
 ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp              |    16 +-
 ogr/ogrsf_frmts/segukooa/ogr_segukooa.h            |    11 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp |     6 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp     |     6 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp      |     9 +-
 ogr/ogrsf_frmts/segy/ogr_segy.h                    |     9 +-
 ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp         |     6 +-
 ogr/ogrsf_frmts/segy/ogrsegydriver.cpp             |     6 +-
 ogr/ogrsf_frmts/segy/ogrsegylayer.cpp              |    10 +-
 ogr/ogrsf_frmts/shape/dbfopen.c                    |    23 +-
 ogr/ogrsf_frmts/shape/drv_shapefile.html           |    28 +-
 ogr/ogrsf_frmts/shape/ogrshape.h                   |    15 +-
 ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp       |    83 +-
 ogr/ogrsf_frmts/shape/ogrshapelayer.cpp            |   144 +-
 ogr/ogrsf_frmts/shape/sbnsearch.c                  |    10 +-
 ogr/ogrsf_frmts/shape/shape2ogr.cpp                |     5 +-
 ogr/ogrsf_frmts/shape/shapefil.h                   |    30 +-
 ogr/ogrsf_frmts/shape/shp_vsi.c                    |   174 +-
 ogr/ogrsf_frmts/shape/shp_vsi.h                    |    46 +
 ogr/ogrsf_frmts/shape/shpopen.c                    |   246 +-
 ogr/ogrsf_frmts/shape/shptree.c                    |     1 +
 ogr/ogrsf_frmts/sosi/GNUmakefile                   |    16 +
 ogr/ogrsf_frmts/sosi/fyba_melding.cpp              |     3 +-
 ogr/ogrsf_frmts/sosi/makefile.vc                   |    23 +-
 ogr/ogrsf_frmts/sosi/ogr_sosi.h                    |     5 +-
 ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp         |    22 +-
 ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp             |     3 +-
 ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp              |    24 +-
 ogr/ogrsf_frmts/sqlite/GNUmakefile                 |     6 +-
 ogr/ogrsf_frmts/sqlite/drv_sqlite.html             |    25 +
 ogr/ogrsf_frmts/sqlite/makefile.vc                 |     6 +-
 ogr/ogrsf_frmts/sqlite/ogr_sqlite.h                |   106 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h             |    15 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c      |   275 +
 ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp     |   175 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp         |    12 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp     |   442 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h       |     3 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp          |   474 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp         |     4 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h           |     4 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp    |   294 +-
 .../sqlite/ogrsqlitesinglefeaturelayer.cpp         |     6 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp   |     4 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h     |     4 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp     |   275 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp            |     6 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp      |    56 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp     |    97 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h       |     4 +-
 ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c     |     4 +-
 ogr/ogrsf_frmts/sua/ogr_sua.h                      |     7 +-
 ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/sua/ogrsuadriver.cpp               |     6 +-
 ogr/ogrsf_frmts/sua/ogrsualayer.cpp                |     7 +-
 ogr/ogrsf_frmts/svg/ogr_svg.h                      |     8 +-
 ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/svg/ogrsvglayer.cpp                |    17 +-
 ogr/ogrsf_frmts/sxf/GNUmakefile                    |    14 +
 ogr/ogrsf_frmts/sxf/drv_sxf.html                   |    42 +
 ogr/ogrsf_frmts/sxf/makefile.vc                    |    15 +
 ogr/ogrsf_frmts/sxf/ogr_sxf.h                      |   154 +
 ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp           |  1295 ++
 ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp               |   140 +
 ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp                |  1429 +++
 ogr/ogrsf_frmts/sxf/org_sxf_defs.h                 |   372 +
 ogr/ogrsf_frmts/tiger/ogr_tiger.h                  |     5 +-
 ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp            |    22 +-
 ogr/ogrsf_frmts/tiger/tigerentitynames.cpp         |     5 +-
 ogr/ogrsf_frmts/tiger/tigerfilebase.cpp            |     7 +-
 ogr/ogrsf_frmts/tiger/tigerpolygon.cpp             |     5 +-
 ogr/ogrsf_frmts/vfk/drv_vfk.html                   |    23 +-
 ogr/ogrsf_frmts/vfk/ogr_vfk.h                      |     3 +-
 ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp           |    15 +-
 ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp                |    23 +-
 ogr/ogrsf_frmts/vfk/vfkdatablock.cpp               |    33 +-
 ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp         |    49 +-
 ogr/ogrsf_frmts/vfk/vfkfeature.cpp                 |     3 +-
 ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp           |     4 +-
 ogr/ogrsf_frmts/vfk/vfkreader.cpp                  |   128 +-
 ogr/ogrsf_frmts/vfk/vfkreader.h                    |    17 +-
 ogr/ogrsf_frmts/vfk/vfkreaderp.h                   |    20 +-
 ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp            |   314 +-
 ogr/ogrsf_frmts/vrt/drv_vrt.html                   |   160 +-
 ogr/ogrsf_frmts/vrt/ogr_vrt.h                      |    64 +-
 ogr/ogrsf_frmts/vrt/ogrvrt.xsd                     |   319 -
 ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp           |   222 +-
 ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp               |    47 +-
 ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp                |  1354 ++-
 ogr/ogrsf_frmts/walk/GNUmakefile                   |    14 +
 ogr/ogrsf_frmts/walk/drv_walk.html                 |    39 +
 ogr/ogrsf_frmts/walk/makefile.vc                   |    15 +
 ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h    |   234 +
 ogr/ogrsf_frmts/walk/ogrwalk.h                     |   211 +
 ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp         |   249 +
 ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp             |   147 +
 ogr/ogrsf_frmts/walk/ogrwalklayer.cpp              |   383 +
 ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp        |   139 +
 ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp         |   361 +
 ogr/ogrsf_frmts/walk/ogrwalktool.cpp               |   753 ++
 ogr/ogrsf_frmts/wasp/GNUmakefile                   |    15 +
 ogr/ogrsf_frmts/wasp/drv_wasp.html                 |    27 +
 ogr/ogrsf_frmts/wasp/makefile.vc                   |    15 +
 ogr/ogrsf_frmts/wasp/ogrwasp.h                     |   204 +
 ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp         |   300 +
 ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp             |   111 +
 ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp              |   827 ++
 ogr/ogrsf_frmts/wfs/ogr_wfs.h                      |     9 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp           |    54 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp               |     6 +-
 ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp                |    42 +-
 ogr/ogrsf_frmts/xls/ogr_xls.h                      |     4 +-
 ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/xls/ogrxlslayer.cpp                |     6 +-
 ogr/ogrsf_frmts/xlsx/ogr_xlsx.h                    |     4 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp         |    13 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp             |     6 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane.h                |     3 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp   |     7 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h     |     2 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp   |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h     |     2 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp   |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h     |     2 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp    |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h      |     2 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp   |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h     |     2 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp       |     6 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h         |     2 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp     |     4 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp         |     2 +-
 ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp          |     5 +-
 ogr/ogrspatialreference.cpp                        |     9 +-
 ogr/ogrutils.cpp                                   |    76 +-
 ogr/osr_cs_wkt.c                                   |   208 +
 ogr/osr_cs_wkt.h                                   |    55 +
 ogr/osr_cs_wkt_grammar.y                           |   304 +
 ogr/osr_cs_wkt_parser.c                            |  1642 +++
 ogr/osr_cs_wkt_parser.h                            |    90 +
 ogr/swq.cpp                                        |   128 +-
 ogr/swq.h                                          |    30 +-
 ogr/swq_expr_node.cpp                              |   109 +-
 ogr/swq_op_general.cpp                             |   124 +-
 ogr/swq_op_registrar.cpp                           |   158 +-
 ogr/swq_parser.cpp                                 |  3095 +++--
 ogr/swq_parser.hpp                                 |   106 +-
 ogr/swq_parser.y                                   |  1236 +-
 ogr/swq_select.cpp                                 |   178 +-
 port/GNUmakefile                                   |     2 +-
 port/cpl_atomic_ops.cpp                            |     4 +-
 port/cpl_atomic_ops.h                              |     4 +-
 port/cpl_base64.cpp                                |    11 +-
 port/cpl_conv.cpp                                  |    80 +-
 port/cpl_conv.h                                    |    11 +-
 port/cpl_csv.cpp                                   |     5 +-
 port/cpl_error.cpp                                 |    50 +-
 port/cpl_error.h                                   |     4 +-
 port/cpl_findfile.cpp                              |     5 +-
 port/cpl_hash_set.cpp                              |     4 +-
 port/cpl_hash_set.h                                |     4 +-
 port/cpl_http.cpp                                  |    29 +-
 port/cpl_http.h                                    |     3 +-
 port/cpl_list.cpp                                  |     5 +-
 port/cpl_list.h                                    |     7 +-
 port/cpl_minixml.cpp                               |    43 +-
 port/cpl_minizip_ioapi.cpp                         |     2 +-
 port/cpl_minizip_ioapi.h                           |     2 +-
 port/cpl_minizip_unzip.cpp                         |   115 +-
 port/cpl_minizip_unzip.h                           |     2 +-
 port/cpl_minizip_zip.cpp                           |     3 +-
 port/cpl_multiproc.cpp                             |    33 +-
 port/cpl_multiproc.h                               |    30 +-
 port/cpl_odbc.cpp                                  |     5 +-
 port/cpl_path.cpp                                  |     7 +-
 port/cpl_port.h                                    |    12 +-
 port/cpl_quad_tree.cpp                             |   130 +-
 port/cpl_quad_tree.h                               |     6 +-
 port/cpl_recode.cpp                                |    30 +-
 port/cpl_recode_iconv.cpp                          |     5 +-
 port/cpl_recode_stub.cpp                           |     7 +-
 port/cpl_spawn.cpp                                 |     8 +-
 port/cpl_spawn.h                                   |     4 +-
 port/cpl_string.cpp                                |     7 +-
 port/cpl_string.h                                  |     9 +-
 port/cpl_strtod.cpp                                |     5 +-
 port/cpl_time.h                                    |     4 +-
 port/cpl_virtualmem.cpp                            |  2059 ++++
 port/cpl_virtualmem.h                              |   389 +
 port/cpl_vsi.h                                     |    11 +-
 port/cpl_vsi_mem.cpp                               |    11 +-
 port/cpl_vsi_virtual.h                             |     6 +-
 port/cpl_vsil.cpp                                  |   199 +-
 port/cpl_vsil_abstract_archive.cpp                 |    10 +-
 port/cpl_vsil_buffered_reader.cpp                  |     6 +-
 port/cpl_vsil_cache.cpp                            |    99 +-
 port/cpl_vsil_curl.cpp                             |     9 +-
 port/cpl_vsil_curl_priv.h                          |     4 +-
 port/cpl_vsil_curl_streaming.cpp                   |     6 +-
 port/cpl_vsil_gzip.cpp                             |    52 +-
 port/cpl_vsil_sparsefile.cpp                       |     5 +-
 port/cpl_vsil_stdin.cpp                            |     6 +-
 port/cpl_vsil_stdout.cpp                           |     6 +-
 port/cpl_vsil_subfile.cpp                          |     9 +-
 port/cpl_vsil_tar.cpp                              |    14 +-
 port/cpl_vsil_unix_stdio_64.cpp                    |    39 +-
 port/cpl_vsil_win32.cpp                            |     6 +-
 port/cpl_vsisimple.cpp                             |     5 +-
 port/cpl_xml_validate.cpp                          |    58 +-
 port/cplgetsymbol.cpp                              |    20 +-
 port/cplkeywordparser.cpp                          |     3 +-
 port/cplstring.cpp                                 |    34 +-
 port/cplstringlist.cpp                             |     5 +-
 port/gdal_csv.h                                    |     3 +-
 port/makefile.vc                                   |     1 +
 port/vsipreload.cpp                                |  1618 +++
 scripts/vagrant/gdal.sh                            |    31 +
 scripts/vagrant/libkml.sh                          |    20 +
 scripts/vagrant/openjpeg.sh                        |    19 +
 scripts/vagrant/postgis.sh                         |     6 +
 scripts/vce2008_wine/build_vce2008.bat             |    14 +
 scripts/vce2008_wine/build_vce2008.patch           |    61 +
 scripts/vce2008_wine/build_vce2008.sh              |    65 +
 scripts/vce2008_wine/clean_vce2008.bat             |    13 +
 scripts/vce2008_wine/clean_vce2008.sh              |    10 +
 scripts/vce2008_wine/nmake_vce2008.local           |    73 +
 scripts/vce2008_wine/prepare-gdal-vce2008.sh       |    64 +
 swig/csharp/apps/OGRLayerAlg.cs                    |   208 +
 swig/csharp/apps/createdata.cs                     |     3 +-
 swig/csharp/const/GdalConst.cs                     |     3 +
 swig/csharp/const/GdalConstPINVOKE.cs              |     9 +
 swig/csharp/const/gdalconst_wrap.c                 |    30 +
 swig/csharp/gdal/Band.cs                           |    18 +-
 swig/csharp/gdal/Dataset.cs                        |    10 +-
 swig/csharp/gdal/Driver.cs                         |     6 +-
 swig/csharp/gdal/Gdal.cs                           |    82 +-
 swig/csharp/gdal/GdalPINVOKE.cs                    |    54 +-
 swig/csharp/gdal/MajorObject.cs                    |    23 +
 swig/csharp/gdal/RasterAttributeTable.cs           |     6 +
 swig/csharp/gdal/SWIGTYPE_p_double.cs              |    30 -
 swig/csharp/gdal/SWIGTYPE_p_int.cs                 |    30 -
 swig/csharp/gdal/SWIGTYPE_p_p_int.cs               |    30 -
 swig/csharp/gdal/SWIGTYPE_p_void.cs                |    30 -
 swig/csharp/gdal/gdal_wrap.cpp                     |   301 +-
 swig/csharp/makefile.vc                            |     5 +-
 swig/csharp/ogr/DataSource.cs                      |    12 +
 swig/csharp/ogr/Driver.cs                          |     8 +-
 swig/csharp/ogr/Feature.cs                         |    92 +-
 swig/csharp/ogr/FeatureDefn.cs                     |    36 +
 swig/csharp/ogr/GeomFieldDefn.cs                   |   128 +
 swig/csharp/ogr/Layer.cs                           |    68 +-
 swig/csharp/ogr/Ogr.cs                             |    30 +-
 swig/csharp/ogr/OgrPINVOKE.cs                      |   188 +-
 swig/csharp/ogr/Osr.cs                             |    62 +
 swig/csharp/ogr/OsrPINVOKE.cs                      |     3 +
 swig/csharp/ogr/SWIGTYPE_p_GDALProgressFunc.cs     |    30 -
 swig/csharp/ogr/SWIGTYPE_p_void.cs                 |    30 -
 swig/csharp/ogr/SpatialReference.cs                |     6 +
 swig/csharp/ogr/StyleTable.cs                      |   118 +
 swig/csharp/ogr/ogr_wrap.cpp                       |  4546 ++++---
 swig/csharp/ogr/osr_wrap.cpp                       |    36 +
 swig/csharp/osr/Osr.cs                             |    62 +
 swig/csharp/osr/OsrPINVOKE.cs                      |     3 +
 swig/csharp/osr/SpatialReference.cs                |     6 +
 swig/csharp/osr/osr_wrap.cpp                       |    36 +
 swig/include/Band.i                                |   103 +-
 swig/include/Dataset.i                             |   108 +-
 swig/include/MajorObject.i                         |     9 +-
 swig/include/RasterAttributeTable.i                |     4 +
 swig/include/cpl.i                                 |     4 +-
 swig/include/cplvirtualmem.i                       |    90 +
 swig/include/csharp/gdal_csharp.i                  |    17 +-
 swig/include/csharp/typemaps_csharp.i              |    57 +-
 swig/include/gdal.i                                |     8 +-
 swig/include/gdal_array.i                          |   412 +-
 swig/include/gdalconst.i                           |     8 +-
 swig/include/java/gdal_java.i                      |   386 +-
 swig/include/java/ogr_java.i                       |    11 +-
 swig/include/java/typemaps_java.i                  |    34 +-
 swig/include/ogr.i                                 |   357 +-
 swig/include/osr.i                                 |     6 +-
 swig/include/perl/gdal_perl.i                      |     6 +-
 swig/include/python/gdal_python.i                  |   156 +-
 swig/include/python/ogr_python.i                   |    64 +-
 swig/include/python/typemaps_python.i              |    70 +-
 swig/java/GNUmakefile                              |    40 +-
 swig/java/add_javadoc.c                            |     2 +-
 swig/java/apps/multireadtest.java                  |    71 +
 swig/java/java.opt                                 |     2 +-
 swig/perl/Doxyfile                                 |     2 +-
 swig/perl/GNUmakefile                              |     2 +-
 swig/perl/gdal_wrap.cpp                            |   143 +-
 swig/perl/gdalconst_wrap.c                         |    15 +
 swig/perl/index.dox                                |     1 +
 swig/perl/lib/Geo/GDAL.dox                         |     9 +-
 swig/perl/lib/Geo/GDAL.pm                          |     8 +-
 swig/perl/lib/Geo/GDAL/Const.pm                    |     3 +
 swig/perl/lib/Geo/OGR.pm                           |   111 +
 swig/perl/lib/Geo/OSR.pm                           |    39 +
 swig/perl/ogr_wrap.cpp                             | 11524 ++++++++++++------
 swig/perl/osr_wrap.cpp                             |   245 +
 swig/perl/pdl.dox                                  |    62 +
 swig/python/README.txt                             |    33 +-
 swig/python/extensions/gdal_array_wrap.cpp         |  1250 +-
 swig/python/extensions/gdal_wrap.cpp               |  2130 +++-
 swig/python/extensions/gdalconst_wrap.c            |     3 +
 swig/python/extensions/ogr_wrap.cpp                | 11771 ++++++++++++-------
 swig/python/extensions/osr_wrap.cpp                |    80 +-
 swig/python/fallback_build_mingw32_under_unix.sh   |    18 +-
 swig/python/osgeo/gdal.py                          |   220 +-
 swig/python/osgeo/gdal_array.py                    |    92 +-
 swig/python/osgeo/gdalconst.py                     |     3 +
 swig/python/osgeo/ogr.py                           |   275 +-
 swig/python/osgeo/osr.py                           |    42 +
 swig/python/samples/README                         |     8 +
 swig/python/samples/fft.py                         |     3 +-
 swig/python/samples/gdal2grd.py                    |     3 +-
 swig/python/samples/gdal_cp.py                     |     4 +-
 swig/python/samples/gdal_ls.py                     |    10 +-
 swig/python/samples/gdal_vrtmerge.py               |     1 +
 swig/python/samples/gdalcompare.py                 |   277 -
 swig/python/samples/gdalcopyproj.py                |     3 +-
 swig/python/samples/gdalinfo.py                    |     4 +-
 swig/python/samples/gdalpythonserver.py            |     2 +-
 swig/python/samples/histrep.py                     |     3 +-
 swig/python/samples/hsv_merge.py                   |     3 +-
 swig/python/samples/load2odbc.py                   |     3 +-
 swig/python/samples/ogr2ogr.py                     |    37 +-
 swig/python/samples/ogr2vrt.py                     |    74 +-
 swig/python/samples/ogr_build_junction_table.py    |   202 +
 swig/python/samples/ogr_dispatch.py                |   399 +
 swig/python/samples/ogr_layer_algebra.py           |     4 +-
 swig/python/samples/ogrinfo.py                     |   111 +-
 swig/python/samples/ogrupdate.py                   |     4 +-
 swig/python/samples/rel.py                         |     3 +-
 swig/python/samples/tigerpoly.py                   |     3 +-
 swig/python/samples/tolatlong.py                   |     3 +-
 swig/python/samples/val_at_coord.py                |     4 +-
 swig/python/samples/val_repl.py                    |     3 +-
 swig/python/samples/wcs_virtds_params.py           |   203 +
 swig/python/scripts/epsg_tr.py                     |     3 +-
 swig/python/scripts/gcps2wld.py                    |     3 +-
 swig/python/scripts/gdal2tiles.py                  |    52 +-
 swig/python/scripts/gdal_auth.py                   |    21 +-
 swig/python/scripts/gdal_calc.dox                  |    62 +
 swig/python/scripts/gdal_calc.py                   |   191 +-
 swig/python/scripts/gdal_edit.dox                  |    10 +-
 swig/python/scripts/gdal_edit.py                   |    16 +-
 swig/python/scripts/gdal_fillnodata.py             |     3 +-
 swig/python/scripts/gdal_merge.py                  |     3 +-
 swig/python/scripts/gdal_polygonize.py             |     3 +-
 swig/python/scripts/gdal_proximity.py              |     3 +-
 swig/python/scripts/gdal_retile.py                 |     3 +-
 swig/python/scripts/gdal_sieve.py                  |     3 +-
 swig/python/scripts/gdalcompare.dox                |    50 +
 swig/python/scripts/gdalcompare.py                 |   283 +
 swig/python/scripts/pct2rgb.py                     |     3 +-
 swig/python/scripts/rgb2pct.py                     |     2 +-
 swig/python/setup.py                               |     2 +-
 update_copyright.py                                |   178 +
 1372 files changed, 131171 insertions(+), 71051 deletions(-)

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 69df535..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,65 +0,0 @@
-GDALmake.opt
-config.log
-config.status
-libtool
-cpl_config.h
-*.o
-*.res
-*.obj
-*.lib
-*.exe
-*.exe.manifest
-*.dll
-*.dll.manifest
-*.exp
-*.lo
-*.la
-.libs
-*.pyc
-frmts/jpeg/libjpeg12/*.c
-frmts/jpeg/libjpeg12/*.h
-libgdal.a
-libgdal.so
-libgdal.so.*
-apps/gdal-config
-apps/gdal-config-inst
-apps/gdal_contour
-apps/gdal_grid
-apps/gdal_rasterize
-apps/gdal_translate
-apps/gdaladdo
-apps/gdalbuildvrt
-apps/gdaldem
-apps/gdalenhance
-apps/gdalinfo
-apps/gdallocationinfo
-apps/gdalmanage
-apps/gdalsrsinfo
-apps/gdaltindex
-apps/gdaltransform
-apps/gdalwarp
-apps/nearblack
-apps/ogr2ogr
-apps/ogrinfo
-apps/ogrtindex
-apps/testepsg
-swig/python/build
-swig/perl/Const.bs
-swig/perl/GDAL.bs
-swig/perl/Makefile_Geo__GDAL
-swig/perl/Makefile_Geo__GDAL__Const
-swig/perl/Makefile_Geo__OGR
-swig/perl/Makefile_Geo__OSR
-swig/perl/OGR.bs
-swig/perl/OSR.bs
-swig/perl/blib/
-swig/perl/lib/Geo/GDAL/*.pm
-swig/perl/lib/Geo/*.pm
-swig/perl/gdal_wrap.cpp
-swig/perl/gdalconst_wrap.c
-swig/perl/ogr_wrap.cpp
-swig/perl/osr_wrap.cpp
-swig/perl/pm_to_blib
-man/
-html/
-nmake.local
diff --git a/COMMITERS b/COMMITERS
index 7d2b609..5a92c22 100644
--- a/COMMITERS
+++ b/COMMITERS
@@ -43,8 +43,8 @@ shalasz       Steve Halasz                 DebianGIS Packaging
 mloskot	      Mateusz Loskot		   wince, geojson
               mateusz at loskot.net
 
-ilucena       Ivan Lucena                  idrisi, ingr, georaster
-              ivan.lucena at pmldnet.com
+ilucena       Ivan Lucena                  georaster, oci
+              ivan.lucena at oracle.com
 
 mbrudka	      Marek Brudka		   thread safety
               mbrudka at aster.pl
@@ -126,8 +126,8 @@ martinl       Martin Landa                 OGR: VFK and GRASS drivers
 gaige         Gaige B Paulsen
               osgeo at gbp.gaige.net
 
-kyle	      Kyle Shannon		   netcdf, lcp
-	      ksshannon at gmail.com
+kyle          Kyle Shannon                 netcdf, lcp
+              kyle at pobox.com
 
 winkey        Brian Case                   libkml
               rush at winkey.org
@@ -166,6 +166,18 @@ rcoup         Robert Coup                  OGR: FGDB
 dzwarg        David Zwarg                  PostGIS Raster
               dzwarg at azavea.com
 
+wolf          Wolf Bergenheim              GME, vector, python
+              wolf+grass at bergenheim.net
+
+goatbar       Kurt Schwehr                 ocean related drivers, python
+              schwehr at gmail.com
+
+jef           Juergen Fischer              OGR: NAS
+              jef at norbit.de
+
+vmo           Vincent Mora                 wasp
+              vincent.mora at oslandia.com
+
 ===============
 Past developers
 ===============
diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index d7273aa..7140214 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -34,9 +34,12 @@ INSTALL_DIR	= 	$(GDAL_ROOT)/install-sh -d
 
 LIBS	=	$(SDE_LIB) @LIBS@ $(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) \
 		$(MRSID_LIBS) $(MRSID_LIDAR_LIBS) $(ECW_LIBS) $(INGRES_LIB) \
-		$(PCIDSK_LIB) $(RASDAMAN_LIB) $(CHARLS_LIB) \
+		$(PCIDSK_LIB) $(RASDAMAN_LIB) $(CHARLS_LIB) $(SOSI_LIB) \
 		$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB)
 
+AVXFLAGS = @AVXFLAGS@
+HAVE_AVX_AT_COMPILE_TIME = @HAVE_AVX_AT_COMPILE_TIME@
+
 PYTHON = @PYTHON@
 PY_HAVE_SETUPTOOLS=@PY_HAVE_SETUPTOOLS@
 
@@ -83,9 +86,9 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
-LIBGDAL_CURRENT	:=	18
-LIBGDAL_REVISION	:=	1
-LIBGDAL_AGE	:=	17
+LIBGDAL_CURRENT	:=	19
+LIBGDAL_REVISION	:=	0
+LIBGDAL_AGE	:=	18
 
 # native build targets and variables
 GDAL_VER	=	@GDAL_VER@
@@ -123,6 +126,7 @@ INGRES_INC = @INGRES_INC@
 HAVE_MYSQL =	@HAVE_MYSQL@
 MYSQL_LIB  =	@MYSQL_LIB@
 MYSQL_INC  =	@MYSQL_INC@
+MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION  =    @MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION@
 LIBS	   +=	$(MYSQL_LIB)
 
 #
@@ -163,6 +167,7 @@ HAVE_SQLITE = @HAVE_SQLITE@
 HAVE_SPATIALITE = @HAVE_SPATIALITE@
 SPATIALITE_INC = @SPATIALITE_INC@
 SPATIALITE_AMALGAMATION = @SPATIALITE_AMALGAMATION@
+SPATIALITE_412_OR_LATER = @SPATIALITE_412_OR_LATER@
 HAVE_PCRE = @HAVE_PCRE@
 
 #
@@ -277,6 +282,12 @@ CURL_SETTING 	=	@CURL_SETTING@
 CURL_LIB	=	@CURL_LIB@
 CURL_INC	=	@CURL_INC@
 
+#
+# libjson-c
+#
+LIBJSONC_SETTING = @LIBJSONC_SETTING@
+JSON_INCLUDE = @JSON_INCLUDE@
+
 # 
 # OpenCL support
 #
@@ -284,6 +295,14 @@ OPENCL_LIB	=	@OPENCL_LIB@
 OPENCL_FLAGS	=	@OPENCL_FLAGS@
 
 #
+# SOSI support
+#
+SOSI_INC = @SOSI_INC@
+SOSI_LIB = @SOSI_LIB@
+HAVE_SOSI = @SOSI_ENABLED@
+
+
+#
 # PCIDSK SDK
 # 
 PCIDSK_SETTING  =       @PCIDSK_SETTING@
@@ -436,8 +455,9 @@ endif
 #
 # Java stuff
 #
-JAVA_INC  =   @JAVA_INC@
-JVM_LIB  =   @JVM_LIB@
+JAVA_HOME = @JAVA_HOME@
+JAVA_INC  = @JAVA_INC@
+JVM_LIB   = @JVM_LIB@
 
 MDB_ENABLED =   @MDB_ENABLED@
 
diff --git a/GNUmakefile b/GNUmakefile
index 305b2b8..7e8580f 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -18,7 +18,7 @@ LIBGDAL-$(HAVE_LD_SHARED)	+=	$(GDAL_SLIB)
 # override if we are using libtool
 LIBGDAL-$(HAVE_LIBTOOL)	:= $(LIBGDAL)
 
-default:	lib-target apps-target swig-target
+default:	lib-target apps-target swig-target gdal.pc
 
 lib-target:	check-lib;
 
@@ -74,7 +74,8 @@ else
 swig-target:    swig-modules;
 endif
 
-swig-modules:	lib-target
+# Python bindings needs gdal-config, hence apps-target
+swig-modules:	apps-target
 	(cd swig; $(MAKE) build)
 
 clean:	lclean
@@ -180,7 +181,8 @@ ifneq ($(BINDINGS),)
 endif
 	for f in LICENSE.TXT data/*.* ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_DATA) ; done
 	$(LIBTOOL_FINISH) $(DESTDIR)$(INST_LIB)
-
+	$(INSTALL_DIR) $(DESTDIR)$(INST_LIB)/pkgconfig
+	$(INSTALL_DATA) gdal.pc $(DESTDIR)$(INST_LIB)/pkgconfig/gdal.pc
 
 ifeq ($(HAVE_LIBTOOL),yes)
 
@@ -235,3 +237,12 @@ endif # HAVE_LD_SHARED=no
 
 endif # HAVE_LIBTOOL=no 
 
+
+gdal.pc:	gdal.pc.in GDALmake.opt ./GNUmakefile VERSION
+	rm -f gdal.pc
+	echo 'CONFIG_VERSION='`cat ./VERSION`'' >> gdal.pc
+	echo 'CONFIG_INST_PREFIX=$(INST_PREFIX)' >> gdal.pc
+	echo 'CONFIG_INST_LIBS=$(CONFIG_LIBS_INS)' >> gdal.pc
+	echo 'CONFIG_INST_CFLAGS=-I$(INST_INCLUDE)' >> gdal.pc
+	echo 'CONFIG_INST_DATA=$(INST_DATA)/data' >> gdal.pc
+	cat gdal.pc.in >> gdal.pc
diff --git a/LICENSE.TXT b/LICENSE.TXT
index 4752119..d65fdd2 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -249,4 +249,15 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 POSSIBILITY OF SUCH DAMAGE. 
 
+gdal/alg/thinplatespline.cpp
+----------------------------
+
+IEEE754 log() code derived from:
+@(#)e_log.c 1.3 95/01/18
+
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
diff --git a/MIGRATION_GUIDE.TXT b/MIGRATION_GUIDE.TXT
new file mode 100644
index 0000000..4e317b9
--- /dev/null
+++ b/MIGRATION_GUIDE.TXT
@@ -0,0 +1,29 @@
+MIGRATION GUIDE FROM GDAL 1.X to GDAL 2.0
+-----------------------------------------
+
+This file documents backwards incompatible changes.
+
+C++ API:
+
+  * GDALRasterAttributeTable is now an abstract class.
+    See http://trac.osgeo.org/gdal/wiki/rfc40_enhanced_rat_support
+    The functionnality of GDAL 1.X GDALRasterAttributeTable is now in
+    GDALDefaultRasterAttributeTable.
+
+OGR drivers :
+
+  * Due to RFC 41, if a OGR driver calls SetGeomType(wkbNone) on a layer,
+    it will be impossible to affect geometries to features of that layer.
+    This worked before, although it was inconsistant, but it does no longer now.
+    In the developmenet of RFC 41, the CSV and VRT drivers have been upgraded
+    to fix such errors.
+
+Changes that should likely not impact anybody :
+
+   * OGRGeometry::exportToGEOS() and OGRGeometryFactory::createFromGEOS() now
+     take a GEOSContextHandle_t argument ( GEOS >= 3.1.0 )
+
+   * OGRGeometryFactory::getGEOSGeometryFactory() has been removed.
+     This method returned NULL since 2006
+     ( http://trac.osgeo.org/gdal/changeset/9899/trunk/ogr/ogrgeometryfactory.cpp )
+
diff --git a/NEWS b/NEWS
index 7ba5299..6541e33 100644
--- a/NEWS
+++ b/NEWS
@@ -1,174 +1,733 @@
-= GDAL/OGR 1.10.1 Release Notes = 
+= GDAL/OGR 1.11.0 Release Notes (r25919 to r27200) =
 
-The 1.10.1 release is a bug fix release.
+== In a nutshell... ==
 
-== Build ==
+ * New GDAL drivers:
+    - KRO: read/write support for KRO KOKOR Raw format
+ * New OGR drivers:
+    - CartoDB : read/write support
+    - GME (Google Map Engine) : read/write support
+    - GPKG (GeoPackage): read-write support (vector part of the spec.)
+    - OpenFileGDB: read-only support (no external dependency)
+    - SXF driver: read-only support
+    - WALK : read-only support
+    - WasP : read-write support
+ * Significantly improved drivers: GML, LIBKML
+ * RFC 40: enhanced RAT support (#5129)
+ * RFC 41: multiple geometry fields support
+ * RFC 42: OGR Layer laundered field lookup 
+ * RFC 43: add GDALMajorObject::GetMetadataDomainList() (#5275)
+ * RFC 45: GDAL datasets and raster bands as virtual memory mapping
+ * Upgrade to EPSG 8.2 database
 
- * Compilation fixes for iOS (#5197, #5198)
+== New installed files ==
+ * bin/ogrlineref
+ * lib/pkgconfig/gdal.pc
+ * gdalcompare.py
+ * data/gml_registry.xml
+ * data/inspire_cp_CadastralParcel.gfs
+ * data/inspire_cp_BasicPropertyUnit.gfs
+ * data/inspire_cp_CadastralBoundary.gfs
+ * data/inspire_cp_CadastralZoning.gfs
+ * data/ruian_vf_ob_v1.gfs
+ * data/ruian_vf_st_v1.gfs
+ * data/ogrvrt.xsd
 
-== GDAL Core ==
+== Backward compatibility issues ==
 
- * Fix VSISubFileHandle::Eof() behaviour to be POSIX compliant, so that the
-   shapefile reader can read the last feature when using /vsitar (#5093)
- * vsicache: fix for 32bit binaries when file size is over 2GB (#5170)
- * warper: Fix warping when input pixel size is too close to 0 (#5190)
- * GDALFillNodata(): Fix use of uninitialized memory and integer overflows (#4010, #5203)
+== GDAL/OGR 1.11.0 - General Changes ==
 
-== Utilities ==
+Build(Unix):
+ * add Unix configure support for SOSI
+ * remove pointers to old ver of ingres library files
+ * add --with-libjson-c configure option to build against external libjson-c (>= 0.11) (#4676)
+ * compilation fixes for iOS (#5197, #5198)
+ * update to autoconf 2.69
+ * add pkg-config gdal.pc (#3470)
+ * configure for FileGDB: add explicit linking to libfgdbunixrtl (requires FileGDB SDK >= 1.2) (#5215); also try .dylib extension (#5221)
+ * fix so that Java installs are found on the MAC to enable the MDB driver (#5267)
+ * fix compilation with recent MySQL versions (5.6 for example) (#5284)
+ * support --with-jp2mrsid with standalone Kakadu with MRSID v8 or later
+ * Fix parallel build in Python bindings (#5346)
+ * PCIDSK: don't link against libjpeg if configured --without-jpeg
+ * Update configure script to pick up ECW JP2 SDK 5.1 (#5390)
+ * add a 'make install' target for the Java bindings  (#5424)
+ * add Vagrant configuration
 
-gdalwarp:
-  * Fix segfault where metadata values weren't being nullchecked properly
-    during conflict resolution. (#5069)
-  * make gdalwarp honor -s_srs when using cutline (#5081)
+Build(Windows):
+ * add option to generate VC project for x64 on makegdal_gen.bat
+ * nmake.opt: add WITH_PDB=1 option to optionaly generate .pdb file on Release builds (#5420)
+ * add support for building the OGR SOSI driver as a plugin (#3638)
+ * add support for building the HDF4 driver as plugin (#5294)
+ * add support for MrSID v9
+ * Remove makegdalXX.bat generated files
 
-gdaltindex:
-  * remove annoying warning 'Warning 1: Field location of width 255 truncated to 254' (#5121)
+== GDAL 1.11.0 - Overview of Changes ==
 
-rgb2pct.py:
-  * Use python tempfile logic to avoid permissions issues with cwd (#5079)
+Port:
+ * vsisubfile: fix Eof() behaviour to be POSIX compliant, so that the shapefile reader can read the last feature when using /vsitar (#5093)
+ * vsicache: fix for 32bit binaries when file size is over 2GB (#5170)
+ * vsicache: add optional nChunkSize and nCacheSize parameters to VSICreateCachedFile()
+ * vsicurl: add CPL_VSIL_CURL_USE_HEAD config option to disable use of CURL HEAD for other services like mapbox (likely lame python http implementations)
+ * vsitar: avoid infinite loop in case of invalid .tar structure
+ * vsizip: fix path separator in CPLFormFilename
+ * vsizip: allow additional extensions listed in CPL_VSIL_ZIP_ALLOWED_EXTENSIONS config option.
+ * vsizip: improve UTF-8 support of filenames inside ZIP file (#5361)
+ * vsizip: fix ZIP64 support
+ * vsigzip: reset EOF flag when doing a Seek() to be POSIX compliant
+ * curl: add .netrc support
+ * Windows CPLGetSymbol(): avoid dialog boxes to pop up when a DLL or one of its dependencies does not exist (#5211)
+ * Add CPLOPrintf() and CPLOvPrintf() functions for easy CPLString formatting
+ * CPLBase64DecodeInPlace() : fix to be robust to malformed base64 strings
+ * CPLQuadTree: add CPLQuadTreeInsertWithBounds() where the pfnGetBounds is not needed.
+ * CPLQuadTree: fix potential infinite recursion when inserting several points with identical coordinates in the mode with limited bucket size
+ * Protect concurrent calls to setlocale() by a mutex (#5366)
 
-ogr2ogr:
-  * make detection of duplicated field names case insensitive (#5208)
+Core:
+ * RFC 45: GDAL datasets and raster bands as virtual memory mapping
+ * GDALRasterBand::GetHistogram(): ignore nodata values (#4750, #5289)
+ * allow auto loading of drivers to be disabled via config option
+ * PAM .aux.xml and VRT: serialize Z component of a GCP as 'Z' attribute,
+   for consistency, instead of GCPZ that could not be read back previously.
+   In reading code, try reading 'Z' and if not found try 'GCPZ' (#5326)
+ * JPEG2000: Add GDALGeorefPamDataset and GDALJP2AbstractDataset classes and use
+             them in JP2KAK, JP2ECW, JP2OpenJPEG, JPEG2000 and MrSID drivers so that PAM
+             georeferencing consistently overrides internal georeferencing
+ * GDALDataset::IRasterIO(): don't use BlockBasedRasterIO() when INTERLEAVE=PIXEL if the request band count is just 1
+ * CopyWholeRaster(): make default GDAL_SWATH_SIZE to 1/4 of GDAL_CACHEMAX instead of hard-coded value of 10 MB
+ * don't report empty RAT on GDALGetDefaultRAT() (#5232)
+ * modify GDALGCPsToGeotransform() to do the regression in normalized coordinates to make the math more stable.
+ * expose new GDALComposeGeoTransforms() function.
+ * GDALDefaultOverviews::HaveMaskFile(): avoid fetching .ovr file
+ * JPEG2000: Fix reading georeferencing from some JPEG2000 files with duplicated GeoTIFF JP2Box (#5249)
+ * Cleanup raster block mutex (#5296)
+ * Driver registration: move JPEG2000 (Jasper based) after MrSID JPEG2000 support
 
-== Bindings ==
+Algorithms:
+ * warper: fix regression with lanczos resampling when yradius > xradius (#5058)
+ * warper: Make GDALCreateGenImgProjTransformer2() and GDALCreateGenImgProjTransformer3() fail when the creation of the reprojection transformer fails
+ * warper: Fix warping when input pixel size is too close to 0 (#5190)
+ * warper: revise formula of cubic resampling kernel, and a few optimizations (#5209)
+ * warper: added DST_METHOD and support for GCP and TPS dest
+ * warper: add support for DST_METHOD=RPC
+ * warper: fix mode and near resampling corner computation (#5311)
+ * warper: GDALGenImgProjTransform(): don't set panSuccess[i] to 1 in the middle of the function, if an intermediate transform before has set the flag to 0
+ * warper: fix cutline blending (#5343)
+ * warper: Average/mode kernels: make them less sensitive to numerical precision issues (#5350)
+ * warper: Average/mode kernels: avoid 'holes' when the source coordinates are in a reversed order from the target coordinates (#5433)
+ * warper: provide prototypes and work around strict compiler requirements on some opencl platforms (#5400) 
+ * RPC: fix for computation of adfGTFromLL (#5395)
+ * TPS: optimization for GCC x86_64 that make computation about twice faster with huge number of GCPs
+ * TPS: when using Armadillo to solve the coefficients, use solve(A,B) instead of inv(A)xB to faster resolution
+ * TPS: compute direct and inverse transformations in parallel when warping option NUM_THREADS or GDAL_NUM_THREADS config. options are set to > 1
+ * Geoloc: fix wrong bilinear interpolation in GDALGeoLocTransform() (#5305)
+ * Geoloc: fail transformation of coordinates that is located on a nodata place of the geoloc array
+ * rasterize: preliminary support for MERGE_ALG=ADD for heatmaps
+ * gdal_grid: Add AVX optimized version of GDALGridInverseDistanceToAPower2NoSmoothingNoSearch
+ * fill_nodata: GDALFillNodata(): Fix use of uninitialized memory and integer overflows (#4010, #5203)
+ * rpc: Fix out-of-bounds read in RPC dem cubic interpolation
 
-Python bindings:
-  * Fix ref-counting of callable passed to gdal.PushErrorHandler() (#5186)
+Utilities:
+ * gdalinfo: add -listmdd and -mdd all options (#5275)
+ * gdal_translate: add a -exponent option to be used with -scale
+ * gdal_translate: fix output file naming scheme in gdal_translate -sds (#5119)
+ * gdal_translate: fix logic in detection non-gray color table level (#5245)
+ * gdal_translate: add a -norat option
+ * gdal_translate: don't add 0.1 when -scale is used with a dstmin equal to dstmax (usefull to generate a raster with uniform color, i.e. scaleRatio = 0)
+ * gdal_translate: use floor() to compute image coordinates from world coordinates when specifying -projwin (usefull when extracting from left or top of upper-left corner, which generate negative image coordinates) (#5367)
+ * gdaltindex: remove annoying warning 'Warning 1: Field location of width 255 truncated to 254' (#5121)
+ * gdaltindex: add -src_srs_name and -src_srs_format to go with MapServer RFC100; add also a -f and -lyr_name options to be able to create a non-shapefile tileindex
+ * gdalwarp: Fix segfault where metadata values weren't being nullchecked properly during conflict resolution (#5069)
+ * gdalwarp: honor -s_srs when using cutline (#5081)
+ * gdalwarp: copy nodata values from source to dest if -dstnodata is not given ; add option to not set dest nodata with -dstnodata None (#5087)
+ * gdalwarp: do not return a non-zero exit status for warnings
+ * gdalwarp: prevent from copying statistics metadata (#5319)
+ * gdal_rasterize: set the progress bar to 100% even when there's nothing to do
+ * gdal_grid: add support for diffferent types of geometries (#5341)
+ * gdal_grid: add  -z_increase and -z_multiply options
+ * gdaldem: check that value of -z, -s, -az and -alt is numeric
+ * gdalbuildvrt: validate values of -srcnodata and -vrtnodata arguments
+ * gdal2tiles.py: Corrected OpenLayers code to reflect fix to geodetic resolution factor
+ * gdal2tiles.py: add --tmscompatible flag so as to produce 2 tiles at zoom level 0 in geodetic profile
+ * rgb2pct.py: Use python tempfile logic to avoid permissions issues with cwd (#5079)
+ * gdal_edit.py: add a -ro option for drivers refusing to use the dataset in update-mode.
+ * gdal_calc.py: add --allBands options (#5388)
+ * Add vsipreload.cpp that can be compiled as a shared library that can be LD_PRELOAD'ed as an overload of libc to enable VSI Virtual FILE API to be used with binaries using regular libc for I/O
+ * Add the wcs_virtds_params.py sample utility to be able to set the MapServer WCS virtual dataset parameters from a tileindex with rasters of mixed SRS (linked to MapServer RFC100)
+ * gdalcompare.py: move to scripts
+ * gdalcompare.py: ensure image dimensions match
+ * gdal_ls.py: Fix issue with UTF-8 characters
 
-== GDAL drivers ==
+Multi driver changes:
+ * JPEG2000 drivers: take into account PixelIsPoint in GeoJP2 boxes, and expose AREA_OR_POINT=Point (#5437)
+ * JP2KAK, JP2ECW, JP2OpenJPEG, JPEG2000 CreateCopy(): take into account AREA_OR_POINT=Point if present to write GeoJP2 box (#5437)
+
+AAIGRID:
+ * revert DECIMAL_PRECISION and add SIGNIFICANT_DIGITS to CreateCopy() (#3732)
+
+AIGRID:
+ * Turn off errors that can be triggered if the info has no VAT table related with this coverage (#3031)
 
 BAG driver:
-  * Recognise falseNorthing=10000000 as UTM South (#5152)
+ * Recognise falseNorthing=10000000 as UTM South (#5152)
+
+DIMAP driver:
+ * fix memleak in error-code path
+
+DTED driver:
+ * Speed optimization to be more friendly with CPU cache in GDAL_DTED_SINGLE_BLOCK=YES mode
 
 ECW driver:
-  * fix crash in GDALDeregister_ECW() with ECW SDK 5 called from GDALDestroy() (#5214)
+ * fix crash in GDALDeregister_ECW() with ECW SDK 5 called from GDALDestroy() (#5214)
+ * fix issue with ECW_CLEVER optimization when nPixelSpace != sizeof eBufDataType (#5262)
+
+Envisat driver:
+ * implement more reliable way of extracting GCPs from Meris tie-points (#5423)
+ * add DEM corrections of TP-ADS products when present (#5423)
+ * workaround dateline discontinuity in GCPs so they can be used with GDAL warping transformers (#5423)
 
 ERS driver:
-  * Fix wrong interpretation of RegistrationCellX/RegistrationCellY (#2612, #3056, #5075)
+ * fix wrong interpretation of RegistrationCellX/RegistrationCellY (#2612, #3056, #5075)
 
-HDF5 driver:
-  * Set SRS GEOGCS for all CSK products (reverts r25801, #4160)
-  * Support HDF5 NATIVE_SCHAR type, subdatsets without PAM (#5088)
-  * Release all opened handles so the file is closed at dataset closing (#5103)
+GeoRaster driver:
+ * fix RPC support (#4038)
+ * fix read error when reading from pyramids (#5076)
+ * make regular table and secure file a default for RDT (#5127)
+ * fix error when reading NBIT pyramid levels (#5199)
+ * show the VAT as RAT (#5200)
+ * fix reading and writing of statistics metadata (#5237)
+ * add generate pyramid create options (#5288)
+ * fix incorrect geotransform interpretation when there is no SRS (#5323)
+
+GRASS driver:
+ * fix compilation issues for GRASS 7
+
+GRIB driver:
+ * display temperature unit as deg Celcius in metadata (#3606)
 
 GTiff driver:
-  * Convert invalid TIFFTAG_RESOLUTIONUNIT=0 to 1(Unknown). This commonly comes
-    about when gdalwarp attempts to resolve metadata conflicts. (#5069)
+ * when compiling against internal libtiff, in read-only mode, optimization to
+   avoid fetching the whole Strip/TileCounts and Strip/TileOffsets arrays
+ * add validation of source overview characteristics with COPY_SRC_OVERVIEWS (#5059)
+ * convert invalid TIFFTAG_RESOLUTIONUNIT=0 to 1(Unknown) (#5069)
+ * fix potential issues in gt_citation.cpp / CheckUTM()
+ * upgrade internal libtiff to latest CVS
+ * implement reading and writing of ICC profiles (#5246)
+ * make SetColorInterpretation() round-trip with GetColorInterpreation();
+   read color interpretation from PAM if it exists (overrides internal tiff color interpretation);
+   set TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_RGB if calling SetColorInterpretation() with R,G,B and no explicit PHOTOMETRIC creation option defined
+ * gt_wkt_srs.cpp: fix compilation with external libgeotiff. The file is dependant of quite a few CPL stuff, don't try to pretend otherwise
+ * implement GetVirtualMemAuto() for some formulations of TIFF files (RFC 45)
+ * fix reading a single-strip TIFF file where the single strip is bigger than 2GB (32bit builds only) (#5403)
+ * look for .tab file before .wld/.tfw
+
+GTX driver:
+ * Add nodata support (#4660)
+
+HDF4 driver:
+ * Skip "SceneLineNumber" table if present in the list of geolocation fields of
+   ASTER L1A dataset.
+
+HDF5 driver:
+ * add support for ODIM H5 georeferencing method (#5032)
+ * set SRS GEOGCS in all cases (reverts r25801 and closes #4160)
+ * support HDF5 NATIVE_SCHAR type, subdatsets without PAM (#5088)
+ * release all opened handles so the file is closed at dataset closing (#5103)
+ * better deal with dimensions of CSK-L1A HDF5 subdatasets (#4227)
+ * avoid segmentation fault when H5Sget_simple_extent_ndims() returns negative value (#5291)
 
 HFA driver:
-  * fix rewriting of statics in existing HFA file where base data value is 8-bit
-    (#5175)
+ * add minimally tested support for u2 and u4 data in basedata
+ * use direct binning for thematic layers and real instead of integer for values (#5066)
+ * add a HFA_COMPRESS_OVR config option to select whether to create compressed overviews (#4866)
+ * fix rewriting of statics in existing HFA file where base data value is 8-bit (#5175)
+ * implement re-writing existing histogram in HFA file, after raster editing (#5176)
+ * avoid segfaults when creating a Imagine dataset with an invalid WKT (#5258)
+ * expose color columns in RAT as Integer with values in range [0-255] instead of Real with values [0-1] (#5362)
+ * report histogram column as GFU_PixelCount instead of GFU_Generic (#5359)
+ * ensure histogram column written as float for HFA when using RAT API (#5382)
+
+Idrisi driver:
+ * Improve coordinate system handling and min/max statistics (#4980)
+
+IRIS driver:
+ * add height information on bands; rename dataset metadata item CAPPI_HEIGHT --> CAPPI_BOTTOM_HEIGHT (#5104)
+ * IRIS: add support for two bytes data (#5431)
+
+JP2ECW driver:
+ * fix problem with JP2 write with SDK v5
+ * fix issue with ECW_CLEVER optimization when nPixelSpace != sizeof eBufDataType (#5262)
+ * avoid writing dummy GeoJP2 box when source dataset has no georeferencing (#5306)
+
+JP2KAK driver:
+ * preliminary support for Kakadu V7.x
+ * fix creation of unsigned int16 with reversible compression (#4050)
+ * on Windows, use VSI cache for I/O by default, instead Kakadu own I/O layer
+ * remove extension from 12bit to 16bit (#5328)
+
+JP2OpenJPEG driver:
+ * avoid 'Empty SOT marker detected: Psot=12.' warning to be repeated several times
+ * add support for encoding GCPs in a GeoJP2 box (#5279)
+ * avoid writing dummy GeoJP2 box when source dataset has no georeferencing (#5306)
 
 JPEG driver:
-  * Add autodetection of bitmasks that are msb ordered. The JPEG_MASK_BIT_ORDER
-    config option can also be set to MSB if the heuristics fails. (#5102)
+ * add autodetection of bitmasks that are msb ordered (#5102)
+ * avoid memory leak when GDALOpen'ing() a JPEG through a http:// URL, and make it possible to access its overviews
+ * return YCbCrK raw data for YCbCrK JPEG in GDAL_JPEG_TO_RGB = NO mode (instead of CMYK as before) (#5097)
+ * implement reading and writing of ICC profiles (#5246)
+ * internal libjpeg: apply patch for CVE-2013-6629
+ * allow fallback to PAM to read GCPs
+ * give priority to PAM GeoTransform if it exists and other source of geotransform (.wld, .tab) also exists (#5352)
 
 KMLSuperOverlay driver:
-  * fix horrible speed performance in Open() (#5094)
-  * fix crash at dataset closing and inability to read some big PNG tiles (#5154)
+ * recognize an alternate structure for raster KMZ file made of a single doc.kml
+    and tiles whose name pattern is kml_image_L{level}_{j}_{i}.{png|jpg}
+ * fix horrible speed performance in Open() (#5094)
+ * fix crash at dataset closing and inability to read some big PNG tiles (#5154)
+ * fix to generate files validating against OGC KML 2.2 schema
+ * put Style into conformity with ATC 7
+ * remove Region in root KML (ATC 41)
+ * add NAME and DESCRIPTION creation options; read them back as metadata
+ * add ALTITUDE and ALTITUDEMODE creation options
+ * directly write into .kmz file (instead of in temporary location)
+ * correctly write directories entry in .kmz file
+ * add progress callback
+
+L1B driver:
+ * report correct values for GCP (#2403)
+ * report more GCPS than before
+ * implement geolocation array
+ * add fetching of record metadata in .csv file
+ * add subdatasets with solar zenith angles, cloud coverage
+ * recognize NOAA-9/14 datasets whose dataset name in TBM header is encoded in EBCDIC and not in ASCII (#2848)
+ * support opening a few NOAA <= 9 datasets that have no dataset name in the TBM header
 
 LCP driver:
-  * Update to handle projections better (#3255)
+ * better handling of projections (#3255)
+ * add CreateCopy() (#5172)
+
+MBTiles driver:
+ * avoid failure when there's no tile at the center of the maximum zoom level (#5278)
+
+MEM driver:
+ * Create(): use calloc() instead of malloc()+memset() for faster creation of huge in-memory datasets
 
 NetCDF driver:
-  * fix for netcdf driver cannot read netcdf-4 files with UBYTE data (#5053)
-  * fix reading large netcdf-4 files with chunking and DEFLATE compression (#4484)
-  * fix netcdf chunking when creating file with > 2 dims ;
-    add CHUNKING creation option (#5082)
-  * fix duplicate nodata metadata when using CreateCopy() (#5084)
-  * fix copying large metadata in netcdf driver (#5113)
-  * fix netcdf geotransform detection (#5114, #5118)
-  * fix netcdf driver irregular grids management (#5118 and #4513)
+ * fix to read netcdf-4 files with UBYTE data (#5053)
+ * fix reading large netcdf-4 files with chunking and DEFLATE compression
+ * fix netcdf chunking when creating file with > 2 dims ; add CHUNKING creation option (#5082 )
+ * fix duplicate nodata metadata when using CreateCopy() (#5084)
+ * fix copying large metadata in netcdf driver (#5113)
+ * fix netcdf geotransform detection (#5114)
+ * fix netcdf driver irregular grids management (#5118 and #4513)
+ * only call nc_close on a valid netcdf id when closing dataset
+ * try and identify .grd (and .nc3) files in netcdf-4 format (#5291), so they are identified before the hdf5 driver
 
 NITF driver:
-  * Support reading horizontal and/or vertical mono-block uncompressed images,
-    even when the number of columns is <= 8192 (#3263)
+ * fix to support reading horizontal and/or vertical mono-block uncompressed images, even when the number of columns is <= 8192 (#3263)
+ * update NITF Series list with new entries from MIL-STD-2411_1_CHG-3.pdf (#5353)
+ * allow JP2KAK to be used as the JPEG2000 compression engine in the CreateCopy() case (#5386)
 
 PDF driver:
-  * Avoid reporting a Poppler error as a GDAL error on some newer USGS GeoPDF files (#5201)
+ * Avoid reporting a Poppler error as a GDAL error on some newer USGS GeoPDF files (#5201)
+ * PDF writing: automatically adjust DPI in case the page dimension exceeds the 14400 maximum value (in user units) allowed by Acrobat (#5412)
 
 PDS driver:
-  * Parse correctly MISSING_CONSTANT = 16#FF7FFFFB# ; add support for
-    ENCODING_TYPE = ZIP (data file compressed in a ZIP);
-    recognize IMAGE_MAP_PROJECTION as an object included in UNCOMPRESSED_FILE
-    object (#3939)
+ * Parse correctly MISSING_CONSTANT = 16#FF7FFFFB# as a IEEE754 single precision float expressed in hexadecimal; add support for ENCODING_TYPE = ZIP (data file compressed in a ZIP); recognize IMAGE_MAP_PROJECTION as an object included in UNCOMPRESSED_FILE object (#3939)
+
+PNG driver:
+ * Implement reading and writing of ICC profiles (#5246)
 
 PostgisRaster driver:
-  * Dataset open is now much faster because properties are fetched from
-    raster_columns view, if available. In case of not, the drive warns the user
-    and scans the whole table. (#5046)
+ * Speed-up dataset opening (#5046).
+ * Multi-tile multi-band caching added.
+ * Smarter use of the information advertized in raster_columns view.
+ * Avoid full table scan in situations without PKID/GIST indices.
+ * Use of quadtree.
+
+Rasdaman driver:
+ * caching of tiles for datasets with more than one band (#5298)
+ * connections are now kept for a whole session (#5298)
+ * fixing connection-string regex (#5298)
+ * fixing possible memory leaks (#5298)
+
+Rasterlite driver:
+ * fix resolution check typo in rasterlite driver
+
+Raw drivers:
+ * implement GetVirtualMemAuto() (RFC 45)
+ * IRasterIO(): add special behaviour to avoid going to block based IO when the dataset has INTERLEAVE=PIXEL and is elligible to direct I/O access pattern
+ * allow direct I/O access even if a small proportion of scanlines are loaded (improve QGIS use case where the overview display will load sparse scanlines, which would prevent direct I/O at full resolution afterwards)
+ * fix optimized RasterIO() when doing sub-sampling with non standard buffer pixel offset (#5438)
+
+RMF driver:
+ * fix decompression of 24-bit RMF DEM (#5268)
+
+RPFTOC driver:
+ * fix potential crash on some datasets when selecting the color palette (#5345)
+
+SAGA driver:
+ * add read/write support for .prj files (#5316)
+
+SRP driver:
+ * read TRANSH01.THF file to establish subdatasets (#5297)
 
 VRT driver:
-  * Make sure that VRTSourcedRasterBand::AddMaskBandSource() takes into account
-    specified window (#5120)
+ * Implement non-linear scaling with a power function (addition of Exponent, SrcMin, SrcMax, DstMin, DstMax sub-elements in <ComplexSource>)
+ * Preserve 64bit integer image offsets (#5086)
+ * Make sure that VRTSourcedRasterBand::AddMaskBandSource() takes into account specified window (#5120)
+ * Make GDALAutoCreateWarpedVRT() return NULL when GDALSuggestedWarpOutput() fails
+ * VRTDataset::IRasterIO(): use source DatasetRasterIO even if band count is 1
+ * VRTWarped: avoid setting up relative paths for things that aren't file-like
+ * make relativeToVRT=1 work with NITF_IM:, NETCDF:, HDF5:, RASTERLITE:
+
+WCS driver:
+ * ensure C locale is enforced before parsing floating point values
 
-== OGR core ==
+WMS driver:
+ * accept 'WMS:http://server/?SRS=EPSG:XXXX' syntax to select the preferred SRS in which to fetch layers
+ * CPLHTTPFetchMulti(): avoid doing a timeout-only select when there are no file descriptor to wait on (can happen when doing a file:// URL)
+ * allow cache location to be specified with GDAL_DEFAULT_WMS_CACHE_PATH configuration option if not provided in the XML (#4540)
+ * Update to be able to understand slight changes in formatting of JSon output of ArcGIS mapserver protocol
 
- * fix handling of method field mapping to output fields when output fields are
-   precreated (#5089)
- * Initialize bIgnore flag in OGRFieldDefn constructor (#5164)
- * OGR SQL: Fix thread-safety of swq_op_registrar::GetOperator() (#5196)
- * OSR: fix order of AXIS and UNIT nodes in a VERT_CS node (#5105)
- * OSR: Fix OGRSpatialReference::importFromProj4() to work with non-C locale (#5147)
- * OSR: Add sanity checks in OGR_SRSNode::importFromWkt() (#5193)
- * OSR_ESRI: Fix crash in CleanupESRIDatumMappingTable() if it is called twice (#5090)
- * OSR_ESRI: morph central_latitude to latitude_of_origin in morphFromESRI() (#3191)
+XYZ driver:
+ * accept datasets that have missing values at beginning and/or end of lines, such as MNT250_L93_FRANCE.XYZ
+ * fix detection when there are only integral values with comma field separator
+ * reopen with 'rb' flags for Windows happyness
 
-== OGR drivers ==
+== OGR 1.11.0 - Overview of Changes ==
+
+Core:
+ * GEOS support: require GEOS >= 3.1.0 and use the _r API of GEOS to avoid issues with the global GEOS error handlers
+ * exportToWkb(): ISO WKB generation with wkbVariant option (#5330)
+ * geocoding: when getting several answers from server for a query, report geometries on second, third, etc.. feature, and not only first one (#5057)
+ * allow auto loading of drivers to be disabled via config option
+ * remove obsolete OGRGeometryFactory::getGEOSGeometryFactory()
+ * OGRGeometryFactory::organizePolygons() in DEFAULT method: fix a case with 2 outer rings that are touching by the first point of the smallest one
+ * OGRGeometryFactory::organizePolygons(): optimization in ONLY_CCW case
+ * OGRGeometryFactory::organizePolygons(): Add an experimental mode : CCW_INNER_JUST_AFTER_CW_OUTER
+ * OGRLineString::segmentize() : don't set 0 as z for interpolated points, but the z from the previous point
+ * OGRLineString::setNumPoints() : add an optional argument to avoid zeroizing the arrays
+ * Add OGRLineString::setZ()
+ * Add OGRLineString::Project() and OGRLineString::getSubline()
+ * OGRPolygon: add stealExteriorRing() and stealInteriorRing(int iRing)
+ * OGRLinearRing::isClockwise(): optimizations and make it work in a degenerated case when a vertex is used several times in the vertex list (#5342)
+ * OGRLinearRing::isPointOnRingBoundary() : optimizations and take into account bTestEnvelope
+ * Add OGR_G_SetPointCount and OGR_G_SetPoints functions to API C (#5357)
+ * OGREnvelope3D::Contains(): fix incorrect test
+ * Layer algebra: fix handling of method field mapping to output fields when output fields are precreated (#5089)
+ * Layer algebra: when an error condition is skipped, call CPLErrorReset() (#5269)
+ * OGRLayer::GetFeature(): make sure that the behaviour is not influenced by
+   attribute or spatial filters in the generic implementation;
+   upgrade OGDI, PG, MySQL, MSSQLSpatial, OCI, SDE, PGeo, ODBC, WALK, IDB, SQLite and Ingres driver  (#5309)
+ * introduce OGRLayer::FindFieldIndex() / OGR_L_FindFieldIndex() to lookup potentially laundered field names (RFC 42)
+ * OGR SQL: upgrade to support RFC 41 (multiple geometry fields)
+ * OGR SQL: more stricter checks
+ * OGR SQL: make parsing error report a usefull hint where the syntax error occured
+ * OGR SQL: fix thread-safety of swq_op_registrar::GetOperator() (#5196)
+ * OGR SQL: support not explicitely specifying AS keyword for aliasing a column spec
+ * OGR SQL: don't call CONCAT(a_column ...) or SUBSTR(a_column ...) as a_column
+ * OGR SQL: validate that arguments of MAX, MIN, AVG, SUM, COUNT are columns and not any expression since this is not supported
+ * OGR SQL: make AVG field definition a OFTReal
+ * OGR SQL: implement MIN(), MAX() and AVG() on a date (#5333)
+ * OGR SQL: fix SELECT * on a layer with a field that has a dot character (#5379)
+ * SQL SQLITE dialect: Make it available to all OGR drivers that have a specialized ExecuteSQL() implementation
+
+OGRSpatialReference:
+ * Upgrade to EPSG 8.2 database
+ * identify LCC_2SP instead of LCC_1SP if lat_0==lat_1 and lat_2 is present (#5191)
+ * add a variety of linear units to proj4 parsing (#5370)
+ * Fix crash in CleanupESRIDatumMappingTable() if it is called twice (#5090)
+ * fix order of AXIS and UNIT nodes in a VERT_CS node (#5105)
+ * ecw_cs.wkt: add missing TOWGS84[-168,-60,320,0,0,0,0] to NTF datum (#5145)
+ * fix OGRSpatialReference::importFromProj4() to work with non-C locale (#5147)
+ * morph central_latitude to latitude_of_origin in morphFromESRI() (#3191)
+ * OGRProj4CT: avoid using proj when the 2 projections are actually identical (#5188)
+ * add sanity checks in OGR_SRSNode::importFromWkt() (#5193)
+ * VERT_CS: when importing from proj.4 put AXIS node after UNIT; COMPD_CS: when importing from EPSG:x+y, set a more meaningfull name for the COMPD_CS node
+ * OGRSpatialReference::Validate() : in addition to hand-validation, use WKT grammar from OGC 01-009 CT
+ * preserve authority when importing +init=auth_name:auth_code (e.g. +init=IGNF:LAMB93)
+
+Utilities:
+ * ogrlineref: new utility to deal with linear geometries.
+ * ogrinfo: upgrade to support RFC 41 (multiple geometry fields)
+ * ogr2ogr: upgrade to support RFC 41 (multiple geometry fields)
+ * ogr2ogr: bump default value for -gt from 200 to 20000 (#5391)
+ * ogr2ogr: add -addfields option to add new fields found in a source layer into an existing layer ; add -unsetFieldWidth option to unset field with and precision; add -dim layer_dim option to force the coordinate dimension of geometries to match the one of the layer geometry type
+ * ogr2ogr: Check that -t_srs is also specified when -s_srs is specified
+ * ogr2ogr: add an explicit error message to report FID of feature that couldn't be inserted when CreateFeature() fails
+ * ogr2ogr: make relaxed lookup optional and add a switch -relaxedFieldNameMatch to allow it (RFC 42)
+ * ogr2ogr: make sure that the progress bar reaches 100% when converting OSM
+ * ogr2ogr: make sure that target dataset is properly closed when a CreateFeature() fails (so that truncated shapefiles have their header file properly updated)
+ * ogr_dispatch.py: Sample Python script to dispatch features into layers according to the value of some fields or the geometry type
+ * ogrinfo.py: sync with ogrinfo (RFC 41)
+ * ogr2ogr.py: port -nlt PROMOTE_TO_MULTI option from ogr2ogr.cpp (#5139)
 
 CSV driver:
-  * Avoid erroneously reset of file content when opening in update mode a file
-    without header (#5161)
+ * avoid erroneously reset of file content when opening in update mode a file without header (#5161)
+ * upgrade to support RFC 41 in read/write (multiple geometry fields)
+ * allow backslash doublequote to load (#5318)
 
-DXF:
-  * fix writing of 25D linestring where z is not constant (#5210, #5217)
+DGN driver:
+ * DGN writing: added polygon inner ring (holes) writing and MSLink writing (#5381)
+
+DXF driver:
+ * fix writing of 25D linestring where z is not constant (#5210)
+ * fix writing of POLYLINE objects (#5217, #5210)
+ * accept reading files starting with a TABLES section (#5307)
+ * support reading 3DFACE and SOLID (#5380) entities
+ * fix an error when processing clockwise circle arc (#5182)
+ * avoid building an invalid polygon when edges cannot be reassembled: turn it into a multilinestring
+ * use CPLAtof() instead of atof() to avoid issues with locales
+ * fix linear approximation of circular and elliptic arc in HATCH boundaries (#5182)
+
+DWG driver:
+ * add support for reading AcDb3dPolyline (#5260)
+ * fix linear approximation of circular and elliptic arc in HATCH boundaries (#5182)
 
 FileGDB driver:
-  * implement ref counting of the FileGDB SDK API' Geodatabase* object to avoid
-    issues on Linux 64bit with interleaved opening and closing of databases (#4270)
+ * implement IgnoreFields API to speed-up a bit the conversion of a sub-set of fields when there's a huge amount of them (e.g. Tiger database).
+ * when writing <Length> of an attribute, use size in bytes (#5192)
+ * implement ref counting of the FileGDB SDK API' Geodatabase* object to avoid issues on Linux 64bit with interleaved opening and closing of databases (#4270)
+ * honour update flag to determine which operations are allowed or not
+ * add a driver global mutex to protect all calls as the FileGDB API SDK is not thread-safe at all
+ * add a COLUMN_TYPES layer creation option to override default column types; support reading/writing XML column types
+ * optimize GetFeatureCount() and GetExtent() when there are filters set
+ * set the default width for string fields to 65536.
+   The width can be configured with the FGDB_STRING_WIDTH configuration option
+ * fix creation and writing of Binary fields; enable reading
+ * add a CREATE_MULTIPATCH creation option
+
+FME driver:
+ * fix Linux compilation
 
-GeoRaster driver:
-  * Fix RPC support (#4038)
+GeoJSON driver:
+ * recognize alternate formats such as the ones of https://code.google.com/p/election-maps/
+ * add read support for TopoJSON
+ * upgrade internal libjson-c to json-c 0.11 (#4676)
+ * report integer values that are int64 as strings
+ * add 3d support to esri geojson reader (#5219)
+ * be less strict on looking for esri field type tag (#5219)
+ * fix sometimes incorrect result (significant digit losts...) when using -lco COORDINATE_PRECISION=0
+ * fix handling of huge coordinates when writing (#5377)
+
+GeoRSS driver:
+ * advertize OLCCreateField capability
+
+GFT driver:
+ * switch http to https for the oauth2 link to improve security
 
 GML driver:
-  * Fix writing of .xsd file to avoid fid/gml_id being written as regular fields (#5142)
-  * Fix writing of global srsName attribue on the global boundedBy.Envelope when
-    all layers have same SRS (#5143)
-  * Fix segfault when reading a GML file with huge coordinates (#5148)
-  * Avoid opening our own .xsd files as valid datasources (#5149)
+ * add support for multiple geometry columns (RFC 41)
+ * add support for reading Finnish National Land Survey Topographic data (MTK GML)
+ * add support for support Finnish NLS cadastral data and Inspire cadastral data.
+ * add support for Czech RUIAN VFR format
+ * add data/gml_registry.xml file to associate feature types with schemas.
+ * extend .gfs syntax to be able to fetch OGR fields from XML attributes.
+ * extend .gfs syntax to support multiple geometry columns, and define a geometry property name
+ * autodiscover all XML attributes as OGR fields when creating .gfs file if GML_ATTRIBUTES_TO_OGR_FIELDS is set to YES (#5418)
+ * allow the <ElementPath> in .gfs to have several components that give the full XML path
+ * fix writing of .xsd file to avoid fid/gml_id being written as regular fields (#5142)
+ * fix writing of global srsName attribue on the global boundedBy.Envelope when all layers have same SRS (#5143)
+ * support for writing .gml/.xsd with fields of type StringList, RealList, IntegerList and support for parsing such .xsd files
+ * when writing .xsd for a datasource that has fields of type StringList, RealList or IntegerList, advertize SF-1 profile in the .XSD schema
+ * recognize xsd:boolean in XSD parsing and map it to String (#5384)
+ * add STRIP_PREFIX and WRITE_FEATURE_BOUNDED_BY dataset creation option to help minimizing the size of GML files
+ * don't write top <gml:boundedBy> in GML files with multiple layers of different SRS
+ * fix segfault when reading a GML file with huge coordinates (#5148)
+ * avoid opening our own .xsd files as valid datasources (#5149)
+ * make driver thread-safe with Xerces
+ * open successfully GML datasources with 0 layers (#249, #5205)
+ * fix tweaking of DescribeFeatureType requests
+ * support reading WFS 2.0 GetFeature documents with wfs:FeatureCollection as a wfs:member of the top wfs:FeatureCollection
+ * fix for crash on certain xlink:href with GML_SKIP_RESOLVE_ELEMS=NONE (#5417)
+ * GML geometry: fix duplicated points in GML_FACE_HOLE_NEGATIVE=YES mode (TopoSurface) (#5230)
+ * GML geometry: accept CompositeSurface as a child of surfaceMembers (#5369)
+ * GML geometry: join multilinestrings to linestrings in rings
+ * GML geometry: correctly deal with MultiSurface of Surface of PolygonPatch where a PolygonPatch has only interior ring(s) and no exterior ring (#5421)
+ * GML geometry: accept formulations of 'MULTIPOINT EMPTY, MULTILINESTRING EMPTY, MULTIPOLYGON EMPTY and GEOMETRYCOLLECTION EMPTY that are valid GML 3 (and accepted by PostGIS)
+ * GML geometry: make use of cs, ts and decimal attributes of (deprecated) gml:coordinates element
+ * GML geometry: accept XML header and comments
+
+GPX driver:
+ * advertize OLCCreateField capability
+
+ILI driver:
+ * add support for multiple geometry columns (RFC 41)
+ * use IlisMeta model reader/writer instead of IOM 
+ * add layers for surface and area geometries
 
 KML driver:
-  * Output KML that validates the ogckml22.xsd schema by placing <Schema>
-    elements under the <Document> level (#5068)
-  * In writing mode, avoid defining an extending schema for the name and
-    description fields (related to #5208)
+ * output KML that validates the ogckml22.xsd schema by placing <Schema> elements under the <Document> level (#5068)
+ * in writing mode, avoid defining an extending schema for the name and description fields (related to #5208)
+
+LIBKML driver:
+ * various checks, fixes and improvements related to OGC KML 2.2 Abstract Test Suite
+ * add support for reading <gx:Track> as a LINESTRING (#5095)
+ * add support for writing and reading <snippet>
+ * add support for writing atom:author, atom:link, phonenumber, Region,
+   ScreenOverlay, 3D model, StlyeMap
+ * add support for reading and generating Camera object
+ * add layer creation options to generate a LookAt element at layer level
+ * if UPDATE_TARGETHREF dataset creation option is defined, a NetworkLinkControl/Update document will be created
+ * add dataset creation options to generate a NetworkLinkControl element
+ * add dataset and layer creation options LISTSTYLE_ICON_HREF and LISTSTYLE_TYPE
+ * add support for writing a NetworkLink
+ * add support for creating PhotoOverlay objects
+ * add support for creating BalloonStyle elements
+ * offer LIBKML_USE_SIMPLEFIELD configuration option can be set to NO to use Data element instead of SimpleField
+ * add layer creation option FOLDER to optionally write layers as Folder instead of Document
+ * add dataset and layer creation options NAME, VISIBILITY, OPEN, SNIPPET and DESCRIPTION
+ * workaround bugs in pretty serializers
+ * when writing a .kmz file, put layers .kml docs into a layers/ subdirectory
+ * fix mem leaks, and use after free in kml2FeatureDef() (#5240)
+ * create document with default namespace set to http://www.opengis.net/kml/2.2
+ * when writing, consider empty strings as unset (usefull when converting from CSV)
+ * don't write empty <Style /> element if OGR_STYLE is empty string
+ * transform multigeometry with one single component into single geometry
+ * create libkml/ subdirectory entry in .kmz
+
+MITAB driver:
+ * support reading MIF file with no associated MID file (when MIF file advertizes 'Columns 0') (#5141)
 
 MSSQLSpatial driver:
-  * Fix MSSQL to be aware of removed tables (#5071)
-  * Eliminate the per table server access when identifying the spatial
-    reference (#5072)
+ * Fix MSSQL to be aware of removed tables (#5071)
+ * Eliminate the per table server access when identifying the spatial reference (#5072)
+ * Improve detection of geometry column with MSSQL select layer (#4318)
+ * Fix for an issue with multicolumn primary keys (#5155)
+ * Add support for handling non spatial data tables (#5155)
+ * Fix creation of spatial_ref_sys and geometry_columns tables (#5339)
+
+MySQL:
+ * robustness for huge coordinates in spatial filter
+
+NAS driver:
+ * also accept XML files that have NAS-Operationen_optional.xsd in header
+ * make driver thread-safe with Xerces
+ * warn when geometry cannot be saved
+
+OCI driver:
+ * fix make plugin option
+
+ODBC driver:
 
 OSM driver:
-  * Always use quoting of key/values in other_tags field so as to produce
-    a valid value for PostgreSQL hstore column (#5096)
+ * support relations with more than 2000 members in a OSM XML file (#5055)
+ * make the driver work with PBF files produced by osmconvert.
+ * osmconf.ini: report the waterway attribute for the lines layer (#5056)
+ * add an option in osmconf.ini to enable creating a 'all_tags' field, combining both fields specificaly identified, and other tags
+ * always use quoting of key/values in other_tags field (#5096)
+ * use alternative implementation of FindNode() that is a bit more efficient when process is CPU-bound
+ * fix issue with attribute filtering
+ * avoid GetNextFeature() to be blocked in certain conditions in non-interleaved mode (#5404)
 
 PG driver:
-  * let PostgreSQL name the constraints to avoid long name truncation resulting
-    in conflicts (#5125)
+ * upgrade to support RFC 41 in read/write (multiple geometry fields)
+ * use ST_Estimated_Extent() on table layers if GetExtent() is called with force = 0 (#5427)
+ * add a OGR_TRUNCATE configuration option (#5091)
+ * let postgres name the constraints to avoid long name truncation resulting in conflicts (#5125)
+ * map PG 'numeric' to OFTReal instead of OFTInteger
+ * retrieve SRID from geometry value, if not found in geometry_columns (#5131)
+ * fix ResolveSRID() when the current user has no select rights on geometry_columns table (#5131)
+ * fix retrieval of SRID on a table without SRID constraint, and when the datasource is opened with ' tables=fake' (#5131)
+ * robustness for huge coordinates in spatial filter
+ * fix delete layer bug on PG 2.0 (#5349)
+ * fix to be able to detect version of EntrepriseDB (#5375)
+ * Fix UTF-8 encoded string length
 
-OCI driver:
-  * fix make plugin option (Unix build)
+PGDump driver:
+ * upgrade to support RFC 41 (multiple geometry fields)
+ * fix error when inserting a string that has backslash in it with PostgreSQL >= 9.1 (#5160)
 
-PGDUMP driver:
-  * fix error when inserting a string that has backslash in it with
-    PostgreSQL >= 9.1 (#5160)
+REC driver:
+ * fix runtime compatibility for Windows
 
 Shapefile driver:
- * Fix buffer overflow when creating a field of type Integer with a big width (#5135)
+ * fix buffer overflow when creating a field of type Integer with a big width (#5135)
+ * delete temporary .cpg file earlier in REPACK
+ * fix leak of file descriptor in error code paths
+ * speed optimizations when reading geometries from .shp (#5272)
+ * add a 2GB_LIMIT=YES layer creation option (and SHAPE_2GB_LIMIT configuration option)
+ * .sbn support: increase allowed max depth from 15 to 24 (#5383)
 
-SQLite driver:
-  * Spatialite: correctly set proj4text field of spatial_ref_sys when inserting
-    a new SRS in the spatial_ref_sys table (#5174)
+SOSI driver:
+ * fix memory leaks, and crashes
+ * advertize OLCCreateField capability
+
+S57 driver:
+ * make the driver thread-safe
+ * remove use of MAX_CLASSES in favor of dynamic sizing (#5227)
+ * fix GetFeature() on DSID layer
+
+SQLite/Spatialite driver:
+ * Make SQLite SQL dialect compatible with multiple geometry fields (note: however, multiple geom fields is not yet supported by OGR SQLite table layers)
+ * implement SetAttributeFilter() on SQL result layers, to directly inject it as a WHERE clause when possible
+ * add the OGR_SQLITE_PRAGMA configuration option
+ * Spatialite: correctly set proj4text field of spatial_ref_sys when inserting a new SRS in the spatial_ref_sys table (#5174)
+ * Spatialite: fix insertion in spatial_ref_sys to avoid issues with non-numeric authority codes (auth_srid)
+ * Spatialite: make creation of database much faster with spatialite 4.1 by using InitSpatialMetaData(1) (#5270)
+ * Spatialite: use thread-safe initialization for spatialite >= 4.1.2
+ * avoid spatiliate views to emit (hidden) errors that cause troubles to MapServer OGR input driver (#5060)
+ * attempt to make VirtualOGR (and thus sqlite dialect) work even with a libsqlite3 compiled with SQLITE_OMIT_LOAD_EXTENSION (on Unix only)
+ * add warning when calling CreateField() with a field name that is 'ROWID' since it can cause corrupted spatial index
+ * serialize StringList as non-truncated strings
+ * detection of DateTime/Date/Time column type on the result of a max() / min() function
+ * ensure fields of type DateTime/Date/Time are properly recognized if the table is empty (#5426)
+
+VFK driver:
+ * fix memory leak
+ * change VFK header check (first line starts with '&H')
+ * implement OGR_VFK_DB_DELETE configuration option
+ * read all data blocks by default
+ * fix GetFeatureCount()
+ * don't use existing internal db when it's older then original vfk file
+
+VRT driver:
+ * add support for multiple geometry columns in OGRVRTLayer, OGRVRTUnionLayer and OGRVRTWarpedLayer (RFC 41)
+ * add validation of OGR VRT document against the schema (if libXML2 available);
+   can be disabled by setting GDAL_XML_VALIDATION configuration option to NO
+ * make relativeToVRT=1 work with CSV:filename or GPSBABEL:driver:filename (#5419)
+
+WFS driver:
+ * WFS 2.0: be a good citizen and send TYPENAMES (with a S) for GetFeature request (but still TYPENAME for DescribeFeatureType)
+ * accept TYPENAME(S) in URL with characters escaped by '%' (#5354)
+
+XLS driver:
+ * don't use sheetId attribute from workbook.xml to link a sheet name to its filename. The first sheet is sheet1.xml, etc...
+
+XPlane driver:
+ * accept V1000 APT files
+
+== SWIG Language Bindings ==
+
+All bindings:
+ * include constraints.i in gdal.i so that NONNULL constraints are really applied
+ * add Feature.SetFieldBinaryFromHexString()
+ * add SpatialReference.EPSGTreatsAsNorthingEasting (#5385)
+ * map OGR_L_GetStyleTable(), OGR_L_SetStyleTable(), OGR_DS_GetStyleTable(), OGR_DS_SetStyleTable()
+ * Add OGR_STBL_AddStyle() and map all OGR_STBL_ C methods to SWIG
+
+CSharp bindings:
+ * Fix handling UTF8 strings in GDAL C# (#4971)
+ * Add C# typemaps for RFC-39 functions (#5264)
+ * Fix typo in OGRLayerAlg.cs (#5264)
+ * Add missing typemaps for C# (#5265)
+
+Java bindings:
+ * run 'make ANDROID=yes' in swig/java to generate SWIG bindings that compile for Android (#5107)
+ * fix linking issue that is encountered in non libtool builds with g++ 4.6
+ * add multireadtest utility
+ * respect JAVA_HOME set via configure
+
+Perl bindings:
+ * ColorTable method of ColorTable class was documented but ColorEntries was 
+   implemented. Implemented but deprecated ColorEntries.
+
+Python bindings:
+ * fix ref-counting of callable passed to gdal.PushErrorHandler() that could cause segfaults (#5186)
+ * make gdal_array.NumericTypeCodeToGDALTypeCode accept numpy dtype arguments (#5223)
+ * add default xoff,yoff,xsize,ysize values to ReadRaster calls
+ * make ogr.CreateGeometryFromWkt() and SpatialReference.ImportFromWkt() propery validate their argument (#5302)
 
 = GDAL/OGR 1.10.0 Release Notes (r23656 to r25905) =
 
@@ -4612,9 +5171,8 @@ Interlis Drivers:
    swig/python/samples.
  * Added Raster Attribute Tables to swig bindings.
  * Added Geometry.ExportToKML
- * Added CreateGeometryFromKML
- * Added !CreateGeometryFromJson
- * Added Geometry.!ExportToJson
+ * Added CreateGeometryFromJson
+ * Added Geometry.ExportToJson
 
 SWIG C# related changes:
  * Support for the enumerated types of the C# interface
diff --git a/VERSION b/VERSION
index 4dae298..1cac385 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.10.1
+1.11.0
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..6f2201b
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,99 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+require 'socket'
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+  config.vm.box = "precise64"
+
+  config.vm.hostname = "gdal-vagrant"
+  config.vm.box_url = "http://files.vagrantup.com/precise64.box"
+  config.vm.host_name = "gdal-vagrant"
+  
+  config.vm.network :forwarded_port, guest: 80, host: 8080
+
+  config.vm.provider :virtualbox do |vb|
+     vb.customize ["modifyvm", :id, "--memory", "1024"]
+     vb.customize ["modifyvm", :id, "--cpus", "2"]
+     vb.customize ["modifyvm", :id, "--ioapic", "on"]
+     vb.name = "gdal-vagrant"
+   end  
+
+  ppaRepos = [
+    "ppa:ubuntugis/ppa", "ppa:marlam/gta"
+  ]
+
+  packageList = [
+    "subversion",
+    "python-numpy",
+    "python-dev",
+    "postgis",
+    "postgresql-server-dev-9.1",
+    "postgresql-9.1-postgis",
+    "libmysqlclient-dev",
+    #"mysql-server",
+    "libpq-dev",
+    "libpng12-dev",
+    "libjpeg-dev",
+    "libgif-dev",
+    "liblzma-dev",
+    "libgeos-dev",
+    "libcurl4-gnutls-dev",
+    "libproj-dev",
+    "libxml2-dev",
+    "libexpat-dev",
+    "libxerces-c-dev",
+    "libnetcdf-dev",
+    "netcdf-bin",
+    "libpoppler-dev",
+    "libspatialite-dev",
+    "gpsbabel",
+    "swig",
+    "libhdf4-alt-dev",
+    "libhdf5-serial-dev",
+    "libpodofo-dev",
+    "poppler-utils",
+    "libfreexl-dev",
+    "unixodbc-dev",
+    "libwebp-dev",
+    "openjdk-7-jdk",
+    "libepsilon-dev",
+    "libgta-dev",
+    "liblcms2-2",
+    "libpcre3-dev",
+    "libjasper-dev",
+    "libarmadillo-dev",
+    "make",
+    "g++",
+    "autoconf", # for libkml
+    "cmake", # for openjpeg
+    "bison",
+    "flex",
+    "vim"
+  ];
+
+  if Dir.glob("#{File.dirname(__FILE__)}/.vagrant/machines/default/*/id").empty?
+	  pkg_cmd = "sed -i 's#deb http://us.archive.ubuntu.com/ubuntu/#deb mirror://mirrors.ubuntu.com/mirrors.txt#' /etc/apt/sources.list; "
+
+	  pkg_cmd << "apt-get update -qq; apt-get install -q -y python-software-properties; "
+
+	  if ppaRepos.length > 0
+		  ppaRepos.each { |repo| pkg_cmd << "add-apt-repository -y " << repo << " ; " }
+		  pkg_cmd << "apt-get update -qq; "
+	  end
+
+	  # install packages we need we need
+	  pkg_cmd << "apt-get install -q -y " + packageList.join(" ") << " ; "
+	  config.vm.provision :shell, :inline => pkg_cmd
+    scripts = [
+      "libkml.sh",
+      "openjpeg.sh",
+      "gdal.sh",
+      "postgis.sh"
+    ];
+    scripts.each { |script| config.vm.provision :shell, :privileged => false, :path => "scripts/vagrant/" << script }
+  end
+end
diff --git a/alg/GNUmakefile b/alg/GNUmakefile
index ced43ba..02f7f16 100644
--- a/alg/GNUmakefile
+++ b/alg/GNUmakefile
@@ -12,6 +12,10 @@ OBJ	=	gdalmediancut.o gdaldither.o gdal_crs.o gdaltransformer.o \
 		contour.o gdaltransformgeolocs.o \
 		gdal_octave.o gdal_simplesurf.o gdalmatching.o
 
+ifeq ($(HAVE_AVX_AT_COMPILE_TIME),yes)
+CPPFLAGS 	:=	-DHAVE_AVX_AT_COMPILE_TIME $(CPPFLAGS)
+endif
+
 ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
@@ -22,7 +26,10 @@ endif
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(OPENCL_FLAGS)
 
-default:	$(OBJ:.o=.$(OBJ_EXT))
+default:	$(OBJ:.o=.$(OBJ_EXT)) gdalgridavx.$(OBJ_EXT)
+
+gdalgridavx.$(OBJ_EXT):   gdalgridavx.cpp
+	$(CXX) $(CXXFLAGS) $(AVXFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 clean:
 	$(RM) *.o $(O_OBJ)
diff --git a/alg/contour.cpp b/alg/contour.cpp
index ae32f7f..40a0587 100644
--- a/alg/contour.cpp
+++ b/alg/contour.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: contour.cpp 25608 2013-02-06 20:44:38Z rouault $
+ * $Id: contour.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Contour Generation
  * Purpose:  Core algorithm implementation for contour line generation. 
@@ -8,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2003, Applied Coherent Technology Corporation, www.actgate.com
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "gdal_alg.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: contour.cpp 25608 2013-02-06 20:44:38Z rouault $");
+CPL_CVSID("$Id: contour.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifdef OGR_ENABLED
 
diff --git a/alg/gdal_alg.h b/alg/gdal_alg.h
index f8f6ba2..a22684b 100644
--- a/alg/gdal_alg.h
+++ b/alg/gdal_alg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg.h 25741 2013-03-13 19:19:16Z ilucena $
+ * $Id: gdal_alg.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes, and definitions for various GDAL based algorithms.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/alg/gdal_alg_priv.h b/alg/gdal_alg_priv.h
index 060a516..53f6586 100644
--- a/alg/gdal_alg_priv.h
+++ b/alg/gdal_alg_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg_priv.h 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: gdal_alg_priv.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes and definitions for various GDAL based algorithms:
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,6 +43,11 @@ typedef enum {
     /*! Use value form the M value */    GBV_M = 2
 } GDALBurnValueSrc;
 
+typedef enum {
+    GRMA_Replace = 0,
+    GRMA_Add = 1,
+} GDALRasterMergeAlg;
+
 typedef struct {
     unsigned char * pabyChunkBuf;
     int nXSize;
@@ -50,6 +56,7 @@ typedef struct {
     GDALDataType eType;
     double *padfBurnValue;
     GDALBurnValueSrc eBurnValueSource;
+    GDALRasterMergeAlg eMergeAlg;
 } GDALRasterizeInfo;
 
 /************************************************************************/
@@ -170,6 +177,8 @@ void* GDALCloneGenImgProjTransformer( void *pTransformArg );
 void* GDALCloneApproxTransformer( void *pTransformArg );
 /* TODO : GDALCloneGeoLocTransformer? , GDALCloneRPCTransformer? */ 
 
+void* GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                   int bReversed, char** papszOptions );
 
 void CPL_DLL * GDALCloneTransformer( void *pTranformerArg );
 
diff --git a/alg/gdal_crs.c b/alg/gdal_crs.c
index 7c7faf6..58e5d0e 100644
--- a/alg/gdal_crs.c
+++ b/alg/gdal_crs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_crs.c 22670 2011-07-08 17:15:19Z rouault $
+ * $Id: gdal_crs.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
@@ -31,6 +31,7 @@
       
 
     Copyright (c) 1992, Michigan State University
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
    
     Permission is hereby granted, free of charge, to any person obtaining a
     copy of this software and associated documentation files (the "Software"),
@@ -57,7 +58,21 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdal_crs.c 22670 2011-07-08 17:15:19Z rouault $");
+CPL_CVSID("$Id: gdal_crs.c 27044 2014-03-16 23:41:27Z rouault $");
+
+/* Hum, we cannot include gdal_priv.h from a .c file... */
+CPL_C_START
+
+void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
+                                GDAL_GCP* pasGCPList,
+                                int nGCPCount,
+                                const char* pszGCPProjection );
+void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
+                                    GDAL_GCP** ppasGCPList,
+                                    int* pnGCPCount,
+                                    char** ppszGCPProjection );
+
+CPL_C_END
 
 #define MAXORDER 3
 
@@ -392,43 +407,15 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     if( psInfo->nGCPCount > 0 )
     {
-        int iGCP;
-        CPLXMLNode *psGCPList = CPLCreateXMLNode( psTree, CXT_Element, 
-                                                  "GCPList" );
-
-	if(psInfo->bRefine)
-	{
-	  remove_outliers(psInfo);
-	}
-	
-        for( iGCP = 0; iGCP < psInfo->nGCPCount; iGCP++ )
+        if(psInfo->bRefine)
         {
-            CPLXMLNode *psXMLGCP;
-            GDAL_GCP *psGCP = psInfo->pasGCPList + iGCP;
-
-            psXMLGCP = CPLCreateXMLNode( psGCPList, CXT_Element, "GCP" );
-
-            CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
-
-            if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
-                CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
-
-            CPLSetXMLValue( psXMLGCP, "#Pixel", 
-                            CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Line", 
-                            CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
-
-            CPLSetXMLValue( psXMLGCP, "#X", 
-                            CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Y", 
-                            CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
-
-            if( psGCP->dfGCPZ != 0.0 )
-                CPLSetXMLValue( psXMLGCP, "#GCPZ", 
-                                CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
+            remove_outliers(psInfo);
         }
+
+        GDALSerializeGCPListToXML( psTree,
+                                   psInfo->pasGCPList,
+                                   psInfo->nGCPCount,
+                                   NULL );
     }
 
     return psTree;
@@ -457,41 +444,10 @@ void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
 
     if( psGCPList != NULL )
     {
-        int  nGCPMax = 0;
-        CPLXMLNode *psXMLGCP;
-         
-        // Count GCPs.
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-            nGCPMax++;
-         
-        pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
-
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-        {
-            GDAL_GCP *psGCP = pasGCPList + nGCPCount;
-
-            if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
-                psXMLGCP->eType != CXT_Element )
-                continue;
-             
-            GDALInitGCPs( 1, psGCP );
-             
-            CPLFree( psGCP->pszId );
-            psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
-             
-            CPLFree( psGCP->pszInfo );
-            psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
-             
-            psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
-            psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
-             
-            psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
-            psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
-            psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
-            nGCPCount++;
-        }
+        GDALDeserializeGCPListFromXML( psGCPList,
+                                       &pasGCPList,
+                                       &nGCPCount,
+                                       NULL );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index 9d27ddd..81e159b 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rpc.cpp 25741 2013-03-13 19:19:16Z ilucena $
+ * $Id: gdal_rpc.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Image Warper
  * Purpose:  Implements a rational polynomail (RPC) based transformer. 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: gdal_rpc.cpp 25741 2013-03-13 19:19:16Z ilucena $");
+CPL_CVSID("$Id: gdal_rpc.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
@@ -452,24 +453,28 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /*      vectors.                                                        */
 /* -------------------------------------------------------------------- */
     double dfRefPixelDelta, dfRefLineDelta, dfLLDelta = 0.0001;
-    
+
     RPCTransformPoint( psRPCInfo, dfRefLong+dfLLDelta, dfRefLat, 0.0, 
                        &dfRefPixelDelta, &dfRefLineDelta );
     adfGTFromLL[1] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
-    adfGTFromLL[2] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
+    adfGTFromLL[4] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
     
     RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat+dfLLDelta, 0.0, 
                        &dfRefPixelDelta, &dfRefLineDelta );
-    adfGTFromLL[4] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
+    adfGTFromLL[2] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
     adfGTFromLL[5] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
 
-    adfGTFromLL[0] = dfRefPixel 
+    adfGTFromLL[0] = dfRefPixel
         - adfGTFromLL[1] * dfRefLong - adfGTFromLL[2] * dfRefLat;
-    adfGTFromLL[3] = dfRefLine 
+    adfGTFromLL[3] = dfRefLine
         - adfGTFromLL[4] * dfRefLong - adfGTFromLL[5] * dfRefLat;
-
-    GDALInvGeoTransform( adfGTFromLL, psTransform->adfPLToLatLongGeoTransform);
     
+    if( !GDALInvGeoTransform( adfGTFromLL, psTransform->adfPLToLatLongGeoTransform) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
+        GDALDestroyRPCTransformer(psTransform);
+        return NULL;
+    }
     return psTransform;
 }
 
@@ -548,20 +553,24 @@ RPCInverseTransformPoint( GDALRPCTransformInfo *psTransform,
             //CPLDebug( "RPC", "Converged!" );
             break;
         }
-
     }
 
     if( iIter != -1 )
-        CPLDebug( "RPC", "Iterations %d: Got: %g,%g  Offset=%g,%g", 
+    {
+#ifdef notdef
+        CPLDebug( "RPC", "Failed Iterations %d: Got: %g,%g  Offset=%g,%g", 
                   iIter, 
                   dfResultX, dfResultY,
                   dfPixelDeltaX, dfPixelDeltaY );
+#endif
+    }
     
     *pdfLong = dfResultX;
     *pdfLat = dfResultY;
 }
 
 
+static
 double BiCubicKernel(double dfVal)
 {
 	if ( dfVal > 2.0 )
@@ -702,9 +711,9 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                         continue;
                     }
                     //cubic interpolation
-                    int adElevData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+                    int anElevData[16] = {0};
                     CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
-                                                              &adElevData, 4, 4,
+                                                              &anElevData, 4, 4,
                                                               GDT_Int32, 1, bands, 0, 0, 0);
                     if(eErr != CE_None)
                     {
@@ -713,10 +722,10 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                     }
 
                     double dfSumH(0);
-                    for ( int i = 0; i < 5; i++ )
+                    for ( int i = 0; i < 4; i++ )
                     {
                         // Loop across the X axis
-                        for ( int j = 0; j < 5; j++ )
+                        for ( int j = 0; j < 4; j++ )
                         {
                             // Calculate the weight for the specified pixel according
                             // to the bicubic b-spline kernel we're using for
@@ -727,7 +736,7 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 
                             // Create a sum of all values
                             // adjusted for the pixel's calculated weight
-                            dfSumH += adElevData[j + i * 4] * dfPixelWeight;
+                            dfSumH += anElevData[j + i * 4] * dfPixelWeight;
                         }
                     }
                     dfDEMH = dfSumH;
@@ -837,9 +846,9 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                     continue;
                 }
                 //cubic interpolation
-                int adElevData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+                int anElevData[16] = {0};
                 CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
-                                                          &adElevData, 4, 4,
+                                                          &anElevData, 4, 4,
                                                           GDT_Int32, 1, bands, 0, 0, 0);
                 if(eErr != CE_None)
                 {
@@ -848,10 +857,10 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 }
 
                 double dfSumH(0);
-                for ( int i = 0; i < 5; i++ )
+                for ( int i = 0; i < 4; i++ )
                 {
                     // Loop across the X axis
-                    for ( int j = 0; j < 5; j++ )
+                    for ( int j = 0; j < 4; j++ )
                     {
                         // Calculate the weight for the specified pixel according
                         // to the bicubic b-spline kernel we're using for
@@ -862,7 +871,7 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 
                         // Create a sum of all values
                         // adjusted for the pixel's calculated weight
-                        dfSumH += adElevData[j + i * 4] * dfPixelWeight;
+                        dfSumH += anElevData[j + i * 4] * dfPixelWeight;
                     }
                 }
                 dfDEMH = dfSumH;
@@ -875,9 +884,9 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                     continue;
                 }
                 //bilinear interpolation
-                int adElevData[4] = {0,0,0,0};
+                int anElevData[4] = {0,0,0,0};
                 CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 2, 2,
-                                                          &adElevData, 2, 2,
+                                                          &anElevData, 2, 2,
                                                           GDT_Int32, 1, bands, 0, 0, 0);
                 if(eErr != CE_None)
                 {
@@ -887,8 +896,8 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 double dfDeltaX1 = 1.0 - dfDeltaX;                
                 double dfDeltaY1 = 1.0 - dfDeltaY;
 
-                double dfXZ1 = adElevData[0] * dfDeltaX1 + adElevData[1] * dfDeltaX;
-                double dfXZ2 = adElevData[2] * dfDeltaX1 + adElevData[3] * dfDeltaX;
+                double dfXZ1 = anElevData[0] * dfDeltaX1 + anElevData[1] * dfDeltaX;
+                double dfXZ2 = anElevData[2] * dfDeltaX1 + anElevData[3] * dfDeltaX;
                 double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
                 dfDEMH = dfYZ;
             }
diff --git a/alg/gdal_tps.cpp b/alg/gdal_tps.cpp
index d2cae61..536d67a 100644
--- a/alg/gdal_tps.cpp
+++ b/alg/gdal_tps.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_tps.cpp 25304 2012-12-13 21:03:58Z rouault $
+ * $Id: gdal_tps.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Thin Plate Spline transformer (GDAL wrapper portion)
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,11 +30,14 @@
 
 #include "thinplatespline.h"
 #include "gdal_alg.h"
+#include "gdal_alg_priv.h"
+#include "gdal_priv.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_atomic_ops.h"
+#include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdal_tps.cpp 25304 2012-12-13 21:03:58Z rouault $");
+CPL_CVSID("$Id: gdal_tps.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
@@ -46,6 +50,8 @@ typedef struct
 
     VizGeorefSpline2D   *poForward;
     VizGeorefSpline2D   *poReverse;
+    int                  bForwardSolved;
+    int                  bReverseSolved;
 
     int       bReversed;
 
@@ -109,6 +115,18 @@ void* GDALCloneTPSTransformer( void *hTransformArg )
 
 void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
                                 int bReversed )
+{
+    return GDALCreateTPSTransformerInt(nGCPCount, pasGCPList, bReversed, NULL);
+}
+
+static void GDALTPSComputeForwardInThread(void* pData)
+{
+    TPSTransformInfo *psInfo = (TPSTransformInfo *)pData;
+    psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
+}
+
+void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                   int bReversed, char** papszOptions )
 
 {
     TPSTransformInfo *psInfo;
@@ -158,8 +176,39 @@ void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
 
     psInfo->nRefCount = 1;
 
-    psInfo->poForward->solve();
-    psInfo->poReverse->solve();
+    int nThreads = 1;
+    if( nGCPCount > 100 )
+    {
+        const char* pszWarpThreads = CSLFetchNameValue(papszOptions, "NUM_THREADS");
+        if (pszWarpThreads == NULL)
+            pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1");
+        if (EQUAL(pszWarpThreads, "ALL_CPUS"))
+            nThreads = CPLGetNumCPUs();
+        else
+            nThreads = atoi(pszWarpThreads);
+    }
+
+    if( nThreads > 1 )
+    {
+        /* Compute direct and reverse transforms in parallel */
+        void* hThread = CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo);
+        psInfo->bReverseSolved = psInfo->poReverse->solve() != 0;
+        if( hThread != NULL )
+            CPLJoinThread(hThread);
+        else
+            psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
+    }
+    else
+    {
+        psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
+        psInfo->bReverseSolved = psInfo->poReverse->solve() != 0;
+    }
+
+    if( !psInfo->bForwardSolved || !psInfo->bReverseSolved )
+    {
+        delete psInfo;
+        return NULL;
+    }
 
     return psInfo;
 }
@@ -281,38 +330,10 @@ CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     if( psInfo->nGCPCount > 0 )
     {
-        int iGCP;
-        CPLXMLNode *psGCPList = CPLCreateXMLNode( psTree, CXT_Element, 
-                                                  "GCPList" );
-
-        for( iGCP = 0; iGCP < psInfo->nGCPCount; iGCP++ )
-        {
-            CPLXMLNode *psXMLGCP;
-            GDAL_GCP *psGCP = psInfo->pasGCPList + iGCP;
-
-            psXMLGCP = CPLCreateXMLNode( psGCPList, CXT_Element, "GCP" );
-
-            CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
-
-            if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
-                CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
-
-            CPLSetXMLValue( psXMLGCP, "#Pixel", 
-                            CPLString().Printf( "%.4f", psGCP->dfGCPPixel ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Line", 
-                            CPLString().Printf( "%.4f", psGCP->dfGCPLine ) );
-
-            CPLSetXMLValue( psXMLGCP, "#X", 
-                            CPLString().Printf( "%.12E", psGCP->dfGCPX ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Y", 
-                            CPLString().Printf( "%.12E", psGCP->dfGCPY ) );
-
-            if( psGCP->dfGCPZ != 0.0 )
-                CPLSetXMLValue( psXMLGCP, "#GCPZ", 
-                                CPLString().Printf( "%.12E", psGCP->dfGCPZ ) );
-        }
+        GDALSerializeGCPListToXML( psTree,
+                                   psInfo->pasGCPList,
+                                   psInfo->nGCPCount,
+                                   NULL );
     }
 
     return psTree;
@@ -337,41 +358,10 @@ void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
 
     if( psGCPList != NULL )
     {
-        int  nGCPMax = 0;
-        CPLXMLNode *psXMLGCP;
-         
-        // Count GCPs.
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-            nGCPMax++;
-         
-        pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
-
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-        {
-            GDAL_GCP *psGCP = pasGCPList + nGCPCount;
-
-            if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
-                psXMLGCP->eType != CXT_Element )
-                continue;
-             
-            GDALInitGCPs( 1, psGCP );
-             
-            CPLFree( psGCP->pszId );
-            psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
-             
-            CPLFree( psGCP->pszInfo );
-            psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
-             
-            psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
-            psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
-             
-            psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
-            psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
-            psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
-            nGCPCount++;
-        }
+        GDALDeserializeGCPListFromXML( psGCPList,
+                                       &pasGCPList,
+                                       &nGCPCount,
+                                       NULL );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdalchecksum.cpp b/alg/gdalchecksum.cpp
index 61adc2b..b3fec60 100644
--- a/alg/gdalchecksum.cpp
+++ b/alg/gdalchecksum.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalchecksum.cpp 13893 2008-02-28 21:08:37Z rouault $
+ * $Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Compute simple checksum for a region of image data. 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2007-2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdal_alg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdalchecksum.cpp 13893 2008-02-28 21:08:37Z rouault $");
+CPL_CVSID("$Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         GDALChecksumImage()                          */
diff --git a/alg/gdalcutline.cpp b/alg/gdalcutline.cpp
index 4c12762..0545f7b 100644
--- a/alg/gdalcutline.cpp
+++ b/alg/gdalcutline.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalcutline.cpp 23033 2011-09-03 18:46:11Z rouault $
+ * $Id: gdalcutline.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implement cutline/blend mask generator.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "ogr_geometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalcutline.cpp 23033 2011-09-03 18:46:11Z rouault $");
+CPL_CVSID("$Id: gdalcutline.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         BlendMaskGenerator()                         */
@@ -88,6 +89,30 @@ BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
 
     if( poClipRect )
     {
+
+        /***** if it doesnt intersect the polym zero the mask and return *****/
+
+        if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) )
+        {
+            
+            memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize );
+
+            delete poLines;
+            delete poClipRect;
+
+            return CE_None;
+        }
+
+        /***** if it doesnt intersect the line at all just return *****/
+         
+        else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) )
+        {
+            delete poLines;
+            delete poClipRect;
+
+            return CE_None;
+        }
+
         OGRGeometry *poClippedLines = 
             poLines->Intersection( poClipRect );
         delete poLines;
@@ -101,19 +126,25 @@ BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     OGREnvelope sEnvelope;
     int iXMin, iYMin, iXMax, iYMax;
+    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
     GEOSGeom poGEOSPoly;
 
-    poGEOSPoly = poLines->exportToGEOS();
+    poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt);
     OGR_G_GetEnvelope( hPolygon, &sEnvelope );
 
     delete poLines;
 
-    if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize 
+    /***** this check was already done in the calling *****/
+    /***** function and should never be true          *****/
+
+    /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize 
         || sEnvelope.MaxY + dfBlendDist < nYOff 
         || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
         || sEnvelope.MaxX + dfBlendDist < nXOff )
         return CE_None;
-    
+    */
+
+
     iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff));
     iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff));
     iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff));
@@ -148,10 +179,10 @@ BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
             GEOSGeom poGEOSPoint;
 
             osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff );
-            poGEOSPoint = GEOSGeomFromWKT( osPointWKT );
+            poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT );
 
-            GEOSDistance( poGEOSPoly, poGEOSPoint, &dfDist );
-            GEOSGeom_destroy( poGEOSPoint );
+            GEOSDistance_r( hGEOSCtxt, poGEOSPoly, poGEOSPoint, &dfDist );
+            GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoint );
 
             dfLastDist = dfDist;
 
@@ -181,7 +212,8 @@ BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    GEOSGeom_destroy( poGEOSPoly );
+    GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoly );
+    OGRGeometry::freeGEOSContext( hGEOSCtxt );
 
     return CE_None;
 
@@ -279,6 +311,7 @@ GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
     }
 
     OGR_G_GetEnvelope( hPolygon, &sEnvelope );
+
     if( sEnvelope.MaxX + psWO->dfCutlineBlendDist < nXOff
         || sEnvelope.MinX - psWO->dfCutlineBlendDist > nXOff + nXSize
         || sEnvelope.MaxY + psWO->dfCutlineBlendDist < nYOff
diff --git a/alg/gdaldither.cpp b/alg/gdaldither.cpp
index 97d2406..80b4c04 100644
--- a/alg/gdaldither.cpp
+++ b/alg/gdaldither.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldither.cpp 13342 2007-12-14 20:58:31Z rouault $
+ * $Id: gdaldither.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CIETMap Phase 2
  * Purpose:  Convert RGB (24bit) to a pseudo-colored approximation using
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -50,7 +51,7 @@
 #include "gdal_priv.h"
 #include "gdal_alg.h"
 
-CPL_CVSID("$Id: gdaldither.cpp 13342 2007-12-14 20:58:31Z rouault $");
+CPL_CVSID("$Id: gdaldither.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define C_LEVELS	32
 
diff --git a/alg/gdalgeoloc.cpp b/alg/gdalgeoloc.cpp
index 08efe04..7f88e05 100644
--- a/alg/gdalgeoloc.cpp
+++ b/alg/gdalgeoloc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgeoloc.cpp 25403 2012-12-30 18:14:28Z rouault $
+ * $Id: gdalgeoloc.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements Geolocation array based transformer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@ SHPHandle hSHP = NULL;
 DBFHandle hDBF = NULL;
 #endif
 
-CPL_CVSID("$Id: gdalgeoloc.cpp 25403 2012-12-30 18:14:28Z rouault $");
+CPL_CVSID("$Id: gdalgeoloc.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
@@ -78,9 +79,9 @@ typedef struct {
     double           *padfGeoLocX;
     double           *padfGeoLocY;
 
+    int              bHasNoData;
     double           dfNoDataX;
-    double           dfNoDataY;
-    
+
     // geolocation <-> base image mapping.
     double           dfPIXEL_OFFSET;
     double           dfPIXEL_STEP;
@@ -199,9 +200,7 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
     }
 
     psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X, 
-                                                       NULL );
-    psTransform->dfNoDataY = GDALGetRasterNoDataValue( psTransform->hBand_Y, 
-                                                       NULL );
+                                                       &(psTransform->bHasNoData) );
 
     return TRUE;
 }
@@ -225,7 +224,8 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 
     for( i = nXSize * nYSize - 1; i >= 0; i-- )
     {
-        if( psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
+        if( !psTransform->bHasNoData ||
+            psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
         {
             if( bInit )
             {
@@ -319,7 +319,8 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
     {
         for( iX = 0; iX < nXSize; iX++ )
         {
-            if( psTransform->padfGeoLocX[iX + iY * nXSize] 
+            if( psTransform->bHasNoData &&
+                psTransform->padfGeoLocX[iX + iY * nXSize] 
                 == psTransform->dfNoDataX )
                 continue;
 
@@ -935,27 +936,42 @@ int GDALGeoLocTransform( void *pTransformArg, int bDstToSrc,
             double *padfGLX = psTransform->padfGeoLocX + iX + iY * nXSize;
             double *padfGLY = psTransform->padfGeoLocY + iX + iY * nXSize;
 
+            if( psTransform->bHasNoData &&
+                padfGLX[0] == psTransform->dfNoDataX )
+            {
+                panSuccess[i] = FALSE;
+                padfX[i] = HUGE_VAL;
+                padfY[i] = HUGE_VAL;
+                continue;
+            }
+
             // This assumes infinite extension beyond borders of available
             // data based on closest grid square.
 
             if( iX + 1 < psTransform->nGeoLocXSize &&
-                iY + 1 < psTransform->nGeoLocYSize )
+                iY + 1 < psTransform->nGeoLocYSize &&
+                (!psTransform->bHasNoData ||
+                    (padfGLX[1] != psTransform->dfNoDataX &&
+                     padfGLX[nXSize] != psTransform->dfNoDataX &&
+                     padfGLX[nXSize + 1] != psTransform->dfNoDataX) ))
             {
-                padfX[i] = padfGLX[0] 
-                    + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0])
-                    + (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
-                padfY[i] = padfGLY[0] 
-                    + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0])
-                    + (dfGeoLocLine -iY) * (padfGLY[nXSize] - padfGLY[0]);
+                padfX[i] = (1 - (dfGeoLocLine -iY)) * (padfGLX[0] + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]))
+                           + (dfGeoLocLine -iY) * (padfGLX[nXSize] + (dfGeoLocPixel-iX) * (padfGLX[nXSize+1] - padfGLX[nXSize]));
+                padfY[i] = (1 - (dfGeoLocLine -iY)) * (padfGLY[0] + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]))
+                           + (dfGeoLocLine -iY) * (padfGLY[nXSize] + (dfGeoLocPixel-iX) * (padfGLY[nXSize+1] - padfGLY[nXSize]));
             }
-            else if( iX + 1 < psTransform->nGeoLocXSize )
+            else if( iX + 1 < psTransform->nGeoLocXSize &&
+                     (!psTransform->bHasNoData ||
+                        padfGLX[1] != psTransform->dfNoDataX) )
             {
                 padfX[i] = padfGLX[0] 
                     + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]);
                 padfY[i] = padfGLY[0] 
                     + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]);
             }
-            else if( iY + 1 < psTransform->nGeoLocYSize )
+            else if( iY + 1 < psTransform->nGeoLocYSize &&
+                     (!psTransform->bHasNoData ||
+                        padfGLX[nXSize] != psTransform->dfNoDataX) )
             {
                 padfX[i] = padfGLX[0] 
                     + (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
@@ -1013,16 +1029,18 @@ int GDALGeoLocTransform( void *pTransformArg, int bDstToSrc,
 
             float* pafBMX = psTransform->pafBackMapX + iBM;
             float* pafBMY = psTransform->pafBackMapY + iBM;
+
             if( iBMX + 1 < psTransform->nBackMapWidth &&
                 iBMY + 1 < psTransform->nBackMapHeight &&
-                pafBMX[1] >=0 && pafBMX[psTransform->nBackMapWidth] >= 0 )
+                pafBMX[1] >=0 && pafBMX[psTransform->nBackMapWidth] >= 0 &&
+                pafBMX[psTransform->nBackMapWidth+1] >= 0)
             {
-                padfX[i] = pafBMX[0] +
-                            (dfBMX - iBMX) * (pafBMX[1] - pafBMX[0]) +
-                            (dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] - pafBMX[0]);
-                padfY[i] = pafBMY[0] +
-                            (dfBMX - iBMX) * (pafBMY[1] - pafBMY[0]) +
-                            (dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] - pafBMY[0]);
+                padfX[i] = (1-(dfBMY - iBMY)) * (pafBMX[0] + (dfBMX - iBMX) * (pafBMX[1] - pafBMX[0])) +
+                           (dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] +
+                                (dfBMX - iBMX) * (pafBMX[psTransform->nBackMapWidth+1] - pafBMX[psTransform->nBackMapWidth]));
+                padfY[i] = (1-(dfBMY - iBMY)) * (pafBMY[0] + (dfBMX - iBMX) * (pafBMY[1] - pafBMY[0])) +
+                           (dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] +
+                                (dfBMX - iBMX) * (pafBMY[psTransform->nBackMapWidth+1] - pafBMY[psTransform->nBackMapWidth]));
             }
             else if( iBMX + 1 < psTransform->nBackMapWidth &&
                      pafBMX[1] >=0)
diff --git a/alg/gdalgrid.cpp b/alg/gdalgrid.cpp
index 01989e6..af4e976 100644
--- a/alg/gdalgrid.cpp
+++ b/alg/gdalgrid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.cpp 25648 2013-02-12 18:40:49Z rouault $
+ * $Id: gdalgrid.cpp 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,14 +33,14 @@
 #include "gdalgrid.h"
 #include <float.h>
 #include <limits.h>
-#include "cpl_quad_tree.h"
 #include "cpl_multiproc.h"
+#include "gdalgrid_priv.h"
 
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 #include <xmmintrin.h>
 #endif
 
-CPL_CVSID("$Id: gdalgrid.cpp 25648 2013-02-12 18:40:49Z rouault $");
+CPL_CVSID("$Id: gdalgrid.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 #define TO_RADIANS (3.14159265358979323846 / 180.0)
 
@@ -51,34 +52,13 @@ CPL_CVSID("$Id: gdalgrid.cpp 25648 2013-02-12 18:40:49Z rouault $");
 # endif /* __DBL_MAX__ */
 #endif /* DBL_MAX */
 
-typedef struct
-{
-    const double* padfX;
-    const double* padfY;
-} GDALGridXYArrays;
-
-typedef struct
-{
-    GDALGridXYArrays* psXYArrays;
-    int               i;
-} GDALGridPoint;
-
-typedef struct
-{
-    CPLQuadTree* hQuadTree;
-    double       dfInitialSearchRadius;
-    const float *pafX;
-    const float *pafY;
-    const float *pafZ;
-} GDALGridExtraParameters;
-
 /************************************************************************/
 /*                          CPLHaveRuntimeSSE()                         */
 /************************************************************************/
 
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 
-#define CPUID_SSE_BIT     25
+#define CPUID_SSE_EDX_BIT     25
 
 #if (defined(_M_X64) || defined(__x86_64))
 
@@ -89,18 +69,11 @@ static int CPLHaveRuntimeSSE()
 
 #elif defined(__GNUC__) && defined(__i386__)
 
-#define GCC_CPUID(level, a, b, c, d)            \
-  __asm__ ("xchgl %%ebx, %1\n"                  \
-           "cpuid\n"                            \
-           "xchgl %%ebx, %1"                    \
-       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-       : "0" (level))
-
 static int CPLHaveRuntimeSSE()
 {
     int cpuinfo[4] = {0,0,0,0};
     GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
-    return (cpuinfo[3] & (1 << CPUID_SSE_BIT)) != 0;
+    return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
 }
 
 #elif defined(_MSC_VER) && defined(_M_IX86)
@@ -133,7 +106,7 @@ static int CPLHaveRuntimeSSE()
 {
     int cpuinfo[4] = {0,0,0,0};
     __cpuid(cpuinfo, 1);
-    return (cpuinfo[3] & (1 << CPUID_SSE_BIT)) != 0;
+    return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
 }
 
 #else
@@ -1681,6 +1654,10 @@ static void GDALGridJobProcess(void* user_data)
  * This can provide substantial speed-up, but sometimes at the expense of
  * reduced floating point precision. This can be disabled by setting the
  * GDAL_USE_SSE configuration option to NO.
+ * Starting with GDAL 1.11, a further optimized version can use the AVX
+ * instruction set. This can be disabled by setting the GDAL_USE_AVX
+ * configuration option to NO.
+ * 
  *
  * @param eAlgorithm Gridding method. 
  * @param poOptions Options to control choosen gridding method.
@@ -1756,6 +1733,42 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
                 pfnGDALGridMethod = GDALGridInverseDistanceToAPowerNoSearch;
                 if( dfPower == 2.0 && dfSmoothing == 0.0 )
                 {
+#ifdef HAVE_AVX_AT_COMPILE_TIME
+
+#define ALIGN32(x)  (((char*)(x)) + ((32 - (((size_t)(x)) % 32)) % 32))
+
+                    if( CSLTestBoolean(CPLGetConfigOption("GDAL_USE_AVX", "YES")) &&
+                        CPLHaveRuntimeAVX() )
+                    {
+                        pabyX = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
+                        pabyY = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
+                        pabyZ = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
+                        if( pabyX != NULL && pabyY != NULL && pabyZ != NULL)
+                        {
+                            CPLDebug("GDAL_GRID", "Using AVX optimized version");
+                            pafXAligned = (float*) ALIGN32(pabyX);
+                            pafYAligned = (float*) ALIGN32(pabyY);
+                            pafZAligned = (float*) ALIGN32(pabyZ);
+                            pfnGDALGridMethod = GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX;
+                            GUInt32 i;
+                            for(i=0;i<nPoints;i++)
+                            {
+                                pafXAligned[i] = (float) padfX[i];
+                                pafYAligned[i] = (float) padfY[i];
+                                pafZAligned[i] = (float) padfZ[i];
+                            }
+                        }
+                        else
+                        {
+                            VSIFree(pabyX);
+                            VSIFree(pabyY);
+                            VSIFree(pabyZ);
+                            pabyX = pabyY = pabyZ = NULL;
+                        }
+                    }
+                    else
+#endif
+
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 
 #define ALIGN16(x)  (((char*)(x)) + ((16 - (((size_t)(x)) % 16)) % 16))
diff --git a/alg/gdalgrid.h b/alg/gdalgrid.h
index 67d2882..dbd814f 100644
--- a/alg/gdalgrid.h
+++ b/alg/gdalgrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.h 25079 2012-10-07 21:31:36Z rouault $
+ * $Id: gdalgrid.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/alg/gdalgrid_priv.h b/alg/gdalgrid_priv.h
new file mode 100644
index 0000000..61aaa9d
--- /dev/null
+++ b/alg/gdalgrid_priv.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * $Id: gdalgrid_priv.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  GDAL Gridding API.
+ * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_error.h"
+#include "cpl_quad_tree.h"
+
+typedef struct
+{
+    const double* padfX;
+    const double* padfY;
+} GDALGridXYArrays;
+
+typedef struct
+{
+    GDALGridXYArrays* psXYArrays;
+    int               i;
+} GDALGridPoint;
+
+typedef struct
+{
+    CPLQuadTree* hQuadTree;
+    double       dfInitialSearchRadius;
+    const float *pafX;
+    const float *pafY;
+    const float *pafZ;
+} GDALGridExtraParameters;
+
+#ifdef HAVE_AVX_AT_COMPILE_TIME
+int CPLHaveRuntimeAVX();
+
+CPLErr GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
+                                        const void *poOptions,
+                                        GUInt32 nPoints,
+                                        const double *unused_padfX,
+                                        const double *unused_padfY,
+                                        const double *unused_padfZ,
+                                        double dfXPoint, double dfYPoint,
+                                        double *pdfValue,
+                                        void* hExtraParamsIn );
+#endif
+
+#if defined(__GNUC__) 
+#define GCC_CPUID(level, a, b, c, d)            \
+  __asm__ ("xchgl %%ebx, %1\n"                  \
+           "cpuid\n"                            \
+           "xchgl %%ebx, %1"                    \
+       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+       : "0" (level))
+#endif
diff --git a/alg/gdalgridavx.cpp b/alg/gdalgridavx.cpp
new file mode 100644
index 0000000..c7a3b08
--- /dev/null
+++ b/alg/gdalgridavx.cpp
@@ -0,0 +1,225 @@
+/******************************************************************************
+ * $Id: gdalgridavx.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  GDAL Gridding API.
+ * Purpose:  Implementation of GDAL scattered data gridder.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdalgrid.h"
+#include "gdalgrid_priv.h"
+
+#ifdef HAVE_AVX_AT_COMPILE_TIME
+#include <immintrin.h>
+
+CPL_CVSID("$Id: gdalgridavx.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/************************************************************************/
+/*                          CPLHaveRuntimeAVX()                         */
+/************************************************************************/
+
+#define CPUID_OSXSAVE_ECX_BIT   27
+#define CPUID_AVX_ECX_BIT       28
+
+#define BIT_XMM_STATE           (1 << 1)
+#define BIT_YMM_STATE           (2 << 1)
+
+int CPLHaveRuntimeAVX()
+{
+    int cpuinfo[4] = {0,0,0,0};
+    GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
+
+    /* Check OSXSAVE feature */
+    if( (cpuinfo[2] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
+    {
+        return FALSE;
+    }
+
+    /* Check AVX feature */
+    if( (cpuinfo[2] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
+    {
+        return FALSE;
+    }
+
+    /* Issue XGETBV and check the XMM and YMM state bit */
+    unsigned int nXCRLow;
+    unsigned int nXCRHigh;
+    __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));
+    if( (nXCRLow & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
+                   ( BIT_XMM_STATE | BIT_YMM_STATE ) )
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*         GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX()     */
+/************************************************************************/
+
+#define GDAL_mm256_load1_ps(x) _mm256_set_ps(x, x, x, x, x, x, x, x)
+
+CPLErr
+GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
+                                        const void *poOptions,
+                                        GUInt32 nPoints,
+                                        const double *unused_padfX,
+                                        const double *unused_padfY,
+                                        const double *unused_padfZ,
+                                        double dfXPoint, double dfYPoint,
+                                        double *pdfValue,
+                                        void* hExtraParamsIn )
+{
+    size_t i = 0;
+    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
+    const float* pafX = psExtraParams->pafX;
+    const float* pafY = psExtraParams->pafY;
+    const float* pafZ = psExtraParams->pafZ;
+
+    const float fEpsilon = 0.0000000000001f;
+    const float fXPoint = (float)dfXPoint;
+    const float fYPoint = (float)dfYPoint;
+    const __m256 ymm_small = GDAL_mm256_load1_ps(fEpsilon);
+    const __m256 ymm_x = GDAL_mm256_load1_ps(fXPoint);
+    const __m256 ymm_y = GDAL_mm256_load1_ps(fYPoint);
+    __m256 ymm_nominator = _mm256_setzero_ps();
+    __m256 ymm_denominator = _mm256_setzero_ps();
+    int mask = 0;
+
+#undef LOOP_SIZE
+#if defined(__x86_64) || defined(_M_X64)
+    /* This would also work in 32bit mode, but there are only 8 XMM registers */
+    /* whereas we have 16 for 64bit */
+#define LOOP_SIZE   16
+    size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
+    for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
+    {
+        __m256 ymm_rx = _mm256_sub_ps(_mm256_load_ps(pafX + i), ymm_x);            /* rx = pafX[i] - fXPoint */
+        __m256 ymm_rx_8 = _mm256_sub_ps(_mm256_load_ps(pafX + i + 8), ymm_x);
+        __m256 ymm_ry = _mm256_sub_ps(_mm256_load_ps(pafY + i), ymm_y);            /* ry = pafY[i] - fYPoint */
+        __m256 ymm_ry_8 = _mm256_sub_ps(_mm256_load_ps(pafY + i + 8), ymm_y);
+        __m256 ymm_r2 = _mm256_add_ps(_mm256_mul_ps(ymm_rx, ymm_rx),               /* r2 = rx * rx + ry * ry */
+                                   _mm256_mul_ps(ymm_ry, ymm_ry));
+        __m256 ymm_r2_8 = _mm256_add_ps(_mm256_mul_ps(ymm_rx_8, ymm_rx_8),
+                                     _mm256_mul_ps(ymm_ry_8, ymm_ry_8));
+        __m256 ymm_invr2 = _mm256_rcp_ps(ymm_r2);                               /* invr2 = 1.0f / r2 */
+        __m256 ymm_invr2_8 = _mm256_rcp_ps(ymm_r2_8);
+        ymm_nominator = _mm256_add_ps(ymm_nominator,                            /* nominator += invr2 * pafZ[i] */
+                            _mm256_mul_ps(ymm_invr2, _mm256_load_ps(pafZ + i)));
+        ymm_nominator = _mm256_add_ps(ymm_nominator,
+                            _mm256_mul_ps(ymm_invr2_8, _mm256_load_ps(pafZ + i + 8)));
+        ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2);           /* denominator += invr2 */
+        ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2_8);
+        mask = _mm256_movemask_ps(_mm256_cmp_ps(ymm_r2, ymm_small, _CMP_LT_OS)) |           /* if( r2 < fEpsilon) */
+              (_mm256_movemask_ps(_mm256_cmp_ps(ymm_r2_8, ymm_small, _CMP_LT_OS)) << 8);
+        if( mask )
+            break;
+    }
+#else
+#define LOOP_SIZE   8
+    size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
+    for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
+    {
+        __m256 ymm_rx = _mm256_sub_ps(_mm256_load_ps((float*)pafX + i), ymm_x);           /* rx = pafX[i] - fXPoint */
+        __m256 ymm_ry = _mm256_sub_ps(_mm256_load_ps((float*)pafY + i), ymm_y);           /* ry = pafY[i] - fYPoint */
+        __m256 ymm_r2 = _mm256_add_ps(_mm256_mul_ps(ymm_rx, ymm_rx),              /* r2 = rx * rx + ry * ry */
+                                   _mm256_mul_ps(ymm_ry, ymm_ry));
+        __m256 ymm_invr2 = _mm256_rcp_ps(ymm_r2);                              /* invr2 = 1.0f / r2 */
+        ymm_nominator = _mm256_add_ps(ymm_nominator,                           /* nominator += invr2 * pafZ[i] */
+                            _mm256_mul_ps(ymm_invr2, _mm256_load_ps((float*)pafZ + i)));
+        ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2);           /* denominator += invr2 */
+        mask = _mm256_movemask_ps(_mm256_cmp_ps(ymm_r2, ymm_small, _CMP_LT_OS));            /* if( r2 < fEpsilon) */
+        if( mask )
+            break;
+    }
+#endif
+
+    /* Find which i triggered r2 < fEpsilon */
+    if( mask )
+    {
+        for(int j = 0; j < LOOP_SIZE; j++ )
+        {
+            if( mask & (1 << j) )
+            {
+                (*pdfValue) = (pafZ)[i + j];
+                return CE_None;
+            }
+        }
+    }
+#undef LOOP_SIZE
+
+    /* Get back nominator and denominator values for YMM registers */
+    float afNominator[8], afDenominator[8];
+    _mm256_storeu_ps(afNominator, ymm_nominator);
+    _mm256_storeu_ps(afDenominator, ymm_denominator);
+
+    float fNominator = afNominator[0] + afNominator[1] +
+                       afNominator[2] + afNominator[3] +
+                       afNominator[4] + afNominator[5] +
+                       afNominator[6] + afNominator[7];
+    float fDenominator = afDenominator[0] + afDenominator[1] +
+                         afDenominator[2] + afDenominator[3] +
+                         afDenominator[4] + afDenominator[5] +
+                         afDenominator[6] + afDenominator[7];
+
+    /* Do the few remaining loop iterations */
+    for ( ; i < nPoints; i++ )
+    {
+        const float fRX = pafX[i] - fXPoint;
+        const float fRY = pafY[i] - fYPoint;
+        const float fR2 =
+            fRX * fRX + fRY * fRY;
+
+        // If the test point is close to the grid node, use the point
+        // value directly as a node value to avoid singularity.
+        if ( fR2 < 0.0000000000001 )
+        {
+            break;
+        }
+        else
+        {
+            const float fInvR2 = 1.0f / fR2;
+            fNominator += fInvR2 * pafZ[i];
+            fDenominator += fInvR2;
+        }
+    }
+
+    if( i != nPoints )
+    {
+        (*pdfValue) = pafZ[i];
+    }
+    else
+    if ( fDenominator == 0.0 )
+    {
+        (*pdfValue) =
+            ((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
+    }
+    else
+        (*pdfValue) = fNominator / fDenominator;
+
+    return CE_None;
+}
+
+#endif
diff --git a/alg/gdalmediancut.cpp b/alg/gdalmediancut.cpp
index 045aceb..735bfda 100644
--- a/alg/gdalmediancut.cpp
+++ b/alg/gdalmediancut.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmediancut.cpp 20629 2010-09-16 19:08:40Z rouault $
+ * $Id: gdalmediancut.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CIETMap Phase 2
  * Purpose:  Use median cut algorithm to generate an near-optimal PCT for a 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,7 +40,7 @@
 #include "gdal_priv.h"
 #include "gdal_alg.h"
 
-CPL_CVSID("$Id: gdalmediancut.cpp 20629 2010-09-16 19:08:40Z rouault $");
+CPL_CVSID("$Id: gdalmediancut.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define	MAX_CMAP_SIZE	256
 
diff --git a/alg/gdalproximity.cpp b/alg/gdalproximity.cpp
index b087891..8d0ce5f 100644
--- a/alg/gdalproximity.cpp
+++ b/alg/gdalproximity.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproximity.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdalproximity.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Compute each pixel's proximity to a set of target pixels.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalproximity.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdalproximity.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static CPLErr
 ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY, 
diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp
index 65e2b6f..bb4f7df 100644
--- a/alg/gdalrasterize.cpp
+++ b/alg/gdalrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterize.cpp 23250 2011-10-18 19:05:02Z rouault $
+ * $Id: gdalrasterize.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector rasterization.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -45,7 +46,7 @@
 /************************************************************************/
 
 void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
-                        double dfVariant )
+                     double dfVariant )
 
 {
     GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
@@ -78,7 +79,13 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
                 
-            memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
+            if( psInfo->eMergeAlg == GRMA_Add ) {
+                int	nPixels = nXEnd - nXStart + 1;
+                while( nPixels-- > 0 )
+                    *(pabyInsert++) += nBurnValue;
+            } else {
+                memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
+            }
         }
     }
     else if( psInfo->eType == GDT_Float64 )
@@ -96,8 +103,13 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
 
-            while( nPixels-- > 0 )
-                *(padfInsert++) = dfBurnValue;
+            if( psInfo->eMergeAlg == GRMA_Add ) {
+                while( nPixels-- > 0 )
+                    *(padfInsert++) += dfBurnValue;
+            } else {
+                while( nPixels-- > 0 )
+                    *(padfInsert++) = dfBurnValue;
+            }
         }
     }
     else
@@ -125,9 +137,15 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
                                       + iBand * psInfo->nXSize * psInfo->nYSize
                                       + nY * psInfo->nXSize + nX;
 
-            *pbyInsert = (unsigned char)( psInfo->padfBurnValue[iBand] +
+            if( psInfo->eMergeAlg == GRMA_Add ) {
+                *pbyInsert += (unsigned char)( psInfo->padfBurnValue[iBand] +
                           ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
+            } else {
+                *pbyInsert = (unsigned char)( psInfo->padfBurnValue[iBand] +
+                          ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
+                             0 : dfVariant ) );
+            }
         }
     }
     else if( psInfo->eType == GDT_Float64 )
@@ -138,9 +156,15 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
                                 + iBand * psInfo->nXSize * psInfo->nYSize
                                 + nY * psInfo->nXSize + nX;
 
-            *pdfInsert = ( psInfo->padfBurnValue[iBand] +
+            if( psInfo->eMergeAlg == GRMA_Add ) {
+                *pdfInsert += ( psInfo->padfBurnValue[iBand] +
                          ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                             0 : dfVariant ) );
+            } else {
+                *pdfInsert = ( psInfo->padfBurnValue[iBand] +
+                         ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
+                            0 : dfVariant ) );
+            }
         }
     }
     else
@@ -285,6 +309,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
                         int nBands, GDALDataType eType, int bAllTouched,
                         OGRGeometry *poShape, double *padfBurnValue, 
                         GDALBurnValueSrc eBurnValueSrc,
+                        GDALRasterMergeAlg eMergeAlg,
                         GDALTransformerFunc pfnTransformer, 
                         void *pTransformArg )
 
@@ -301,6 +326,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
     sInfo.eType = eType;
     sInfo.padfBurnValue = padfBurnValue;
     sInfo.eBurnValueSource = eBurnValueSrc;
+    sInfo.eMergeAlg = eMergeAlg;
 
 /* -------------------------------------------------------------------- */
 /*      Transform polygon geometries into a set of rings and a part     */
@@ -312,7 +338,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
     std::vector<int> aPartSize;
 
     GDALCollectRingsFromGeometry( poShape, aPointX, aPointY, aPointVariant,
-                                    aPartSize, eBurnValueSrc );
+                                  aPartSize, eBurnValueSrc );
 
 /* -------------------------------------------------------------------- */
 /*      Transform points if needed.                                     */
@@ -349,77 +375,131 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
     //    /* How to report this problem? */
     switch ( wkbFlatten(poShape->getGeometryType()) )
     {
-        case wkbPoint:
-        case wkbMultiPoint:
-            GDALdllImagePoint( sInfo.nXSize, nYSize, 
-                               aPartSize.size(), &(aPartSize[0]), 
-                               &(aPointX[0]), &(aPointY[0]), 
-                               (eBurnValueSrc == GBV_UserBurnValue)?
-                                   NULL : &(aPointVariant[0]),
-                               gvBurnPoint, &sInfo );
-            break;
-        case wkbLineString:
-        case wkbMultiLineString:
+      case wkbPoint:
+      case wkbMultiPoint:
+        GDALdllImagePoint( sInfo.nXSize, nYSize, 
+                           aPartSize.size(), &(aPartSize[0]), 
+                           &(aPointX[0]), &(aPointY[0]), 
+                           (eBurnValueSrc == GBV_UserBurnValue)?
+                           NULL : &(aPointVariant[0]),
+                           gvBurnPoint, &sInfo );
+        break;
+      case wkbLineString:
+      case wkbMultiLineString:
+      {
+          if( bAllTouched )
+              GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
+                                          aPartSize.size(), &(aPartSize[0]), 
+                                          &(aPointX[0]), &(aPointY[0]), 
+                                          (eBurnValueSrc == GBV_UserBurnValue)?
+                                          NULL : &(aPointVariant[0]),
+                                          gvBurnPoint, &sInfo );
+          else
+              GDALdllImageLine( sInfo.nXSize, nYSize, 
+                                aPartSize.size(), &(aPartSize[0]), 
+                                &(aPointX[0]), &(aPointY[0]), 
+                                (eBurnValueSrc == GBV_UserBurnValue)?
+                                NULL : &(aPointVariant[0]),
+                                gvBurnPoint, &sInfo );
+      }
+      break;
+
+      default:
+      {
+          GDALdllImageFilledPolygon( sInfo.nXSize, nYSize, 
+                                     aPartSize.size(), &(aPartSize[0]), 
+                                     &(aPointX[0]), &(aPointY[0]), 
+                                     (eBurnValueSrc == GBV_UserBurnValue)?
+                                     NULL : &(aPointVariant[0]),
+                                     gvBurnScanline, &sInfo );
+          if( bAllTouched )
+          {
+              /* Reverting the variants to the first value because the
+                 polygon is filled using the variant from the first point of
+                 the first segment. Should be removed when the code to full
+                 polygons more appropriately is added. */
+              if(eBurnValueSrc == GBV_UserBurnValue)
+              {
+                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
+                                              aPartSize.size(), &(aPartSize[0]), 
+                                              &(aPointX[0]), &(aPointY[0]), 
+                                              NULL,
+                                              gvBurnPoint, &sInfo );
+              }
+              else
+              {
+                  unsigned int n;
+                  for ( i = 0, n = 0; i < aPartSize.size(); i++ )
+                  {
+                      int j;
+                      for ( j = 0; j < aPartSize[i]; j++ )
+                          aPointVariant[n++] = aPointVariant[0];
+                  }
+
+                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
+                                              aPartSize.size(), &(aPartSize[0]), 
+                                              &(aPointX[0]), &(aPointY[0]), 
+                                              &(aPointVariant[0]),
+                                              gvBurnPoint, &sInfo );
+              }
+          }
+      }
+      break;
+    }
+}
+
+/************************************************************************/
+/*                        GDALRasterizeOptions()                        */
+/*                                                                      */
+/*      Recognise a few rasterize options used by all three entry       */
+/*      points.                                                         */
+/************************************************************************/
+
+static CPLErr GDALRasterizeOptions(char **papszOptions, 
+                                   int *pbAllTouched,
+                                   GDALBurnValueSrc *peBurnValueSource, 
+                                   GDALRasterMergeAlg *peMergeAlg) 
+{
+    *pbAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
+
+    const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
+    *peBurnValueSource = GBV_UserBurnValue;
+    if( pszOpt )
+    {
+        if( EQUAL(pszOpt,"Z"))
+            *peBurnValueSource = GBV_Z;
+        /*else if( EQUAL(pszOpt,"M"))
+            eBurnValueSource = GBV_M;*/
+        else
         {
-            if( bAllTouched )
-                GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                            aPartSize.size(), &(aPartSize[0]), 
-                                            &(aPointX[0]), &(aPointY[0]), 
-                                            (eBurnValueSrc == GBV_UserBurnValue)?
-                                                NULL : &(aPointVariant[0]),
-                                            gvBurnPoint, &sInfo );
-            else
-                GDALdllImageLine( sInfo.nXSize, nYSize, 
-                                  aPartSize.size(), &(aPartSize[0]), 
-                                  &(aPointX[0]), &(aPointY[0]), 
-                                  (eBurnValueSrc == GBV_UserBurnValue)?
-                                      NULL : &(aPointVariant[0]),
-                                  gvBurnPoint, &sInfo );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unrecognised value '%s' for BURN_VALUE_FROM.", 
+                      pszOpt );
+            return CE_Failure;
         }
-        break;
+    }
 
-        default:
+/* -------------------------------------------------------------------- */
+/*      MERGE_ALG=[REPLACE]/ADD                                         */
+/* -------------------------------------------------------------------- */
+    *peMergeAlg = GRMA_Replace;
+    pszOpt = CSLFetchNameValue( papszOptions, "MERGE_ALG" );
+    if( pszOpt )
+    {
+        if( EQUAL(pszOpt,"ADD"))
+            *peMergeAlg = GRMA_Add;
+        else if( EQUAL(pszOpt,"REPLACE"))
+            *peMergeAlg = GRMA_Replace;
+        else
         {
-            GDALdllImageFilledPolygon( sInfo.nXSize, nYSize, 
-                                       aPartSize.size(), &(aPartSize[0]), 
-                                       &(aPointX[0]), &(aPointY[0]), 
-                                       (eBurnValueSrc == GBV_UserBurnValue)?
-                                           NULL : &(aPointVariant[0]),
-                                       gvBurnScanline, &sInfo );
-            if( bAllTouched )
-            {
-                /* Reverting the variants to the first value because the
-                   polygon is filled using the variant from the first point of
-                   the first segment. Should be removed when the code to full
-                   polygons more appropriately is added. */
-                if(eBurnValueSrc == GBV_UserBurnValue)
-                {
-                GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                            aPartSize.size(), &(aPartSize[0]), 
-                                            &(aPointX[0]), &(aPointY[0]), 
-                                            NULL,
-                                            gvBurnPoint, &sInfo );
-                }
-                else
-                {
-                    unsigned int n;
-                    for ( i = 0, n = 0; i < aPartSize.size(); i++ )
-                    {
-                        int j;
-                        for ( j = 0; j < aPartSize[i]; j++ )
-                            aPointVariant[n++] = aPointVariant[0];
-                    }
-
-                    GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                                aPartSize.size(), &(aPartSize[0]), 
-                                                &(aPointX[0]), &(aPointY[0]), 
-                                                &(aPointVariant[0]),
-                                                gvBurnPoint, &sInfo );
-                }
-            }
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unrecognised value '%s' for MERGE_ALG.", 
+                      pszOpt );
+            return CE_Failure;
         }
-        break;
     }
+    
+    return CE_None;
 }
 
 /************************************************************************/
@@ -467,6 +547,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
  * Defaults to GDALBurnValueSrc.GBV_UserBurnValue in which case just the
  * dfBurnValue is burned. This is implemented only for points and lines for
  * now. The M value may be supported in the future.</dd>
+ * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
  * </dl>
  * @param pfnProgress the progress function to report completion.
  * @param pProgressArg callback data for progress function.
@@ -498,22 +579,25 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 /*      Do some rudimentary arg checking.                               */
 /* -------------------------------------------------------------------- */
     if( nBandCount == 0 || nGeomCount == 0 )
+    {
+        pfnProgress(1.0, "", pProgressArg );
         return CE_None;
+    }
 
     // prototype band.
     GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
     if (poBand == NULL)
         return CE_Failure;
 
-    int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
-    const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
-    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
-    if( pszOpt )
-    {
-        if( EQUAL(pszOpt,"Z"))
-            eBurnValueSource = GBV_Z;
-        /*else if( EQUAL(pszOpt,"M"))
-            eBurnValueSource = GBV_M;*/
+/* -------------------------------------------------------------------- */
+/*      Options                                                         */
+/* -------------------------------------------------------------------- */
+    int bAllTouched;
+    GDALBurnValueSrc eBurnValueSource;
+    GDALRasterMergeAlg eMergeAlg;
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+        return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
@@ -548,10 +632,20 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 
     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
         * (GDALGetDataTypeSize(eType)/8);
-    nYChunkSize = 10000000 / nScanlineBytes;
+
+    const char  *pszYChunkSize = CSLFetchNameValue(papszOptions, "CHUNKYSIZE");
+    if( pszYChunkSize == NULL || ((nYChunkSize = atoi(pszYChunkSize))) == 0) 
+    {
+        nYChunkSize = 10000000 / nScanlineBytes;
+    }
+
     if( nYChunkSize > poDS->GetRasterYSize() )
         nYChunkSize = poDS->GetRasterYSize();
 
+    CPLDebug( "GDAL", "Rasterizer operating on %d swaths of %d scanlines.",
+              (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
+              nYChunkSize );
+
     pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
     if( pabyChunkBuf == NULL )
     {
@@ -594,7 +688,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                                     nBandCount, eType, bAllTouched,
                                     (OGRGeometry *) pahGeometries[iShape],
                                     padfGeomBurnValue + iShape*nBandCount,
-                                    eBurnValueSource,
+                                    eBurnValueSource, eMergeAlg,
                                     pfnTransformer, pTransformArg );
         }
 
@@ -677,6 +771,8 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * is. This is implemented properly only for points and lines for now. Polygons
  * will be burned using the Z value from the first point. The M value may be
  * supported in the future.</dd>
+ * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
+ * </dl>
  * @param pfnProgress the progress function to report completion.
  * @param pProgressArg callback data for progress function.
  *
@@ -716,15 +812,15 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     if (poBand == NULL)
         return CE_Failure;
 
-    int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
-    const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
-    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
-    if( pszOpt )
-    {
-        if( EQUAL(pszOpt,"Z"))
-            eBurnValueSource = GBV_Z;
-        /*else if( EQUAL(pszOpt,"M"))
-            eBurnValueSource = GBV_M;*/
+/* -------------------------------------------------------------------- */
+/*      Options                                                         */
+/* -------------------------------------------------------------------- */
+    int bAllTouched;
+    GDALBurnValueSrc eBurnValueSource;
+    GDALRasterMergeAlg eMergeAlg;
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+        return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
@@ -760,6 +856,9 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     if( nYChunkSize > poDS->GetRasterYSize() )
         nYChunkSize = poDS->GetRasterYSize();
 
+    CPLDebug( "GDAL", "Rasterizer operating on %d swaths of %d scanlines.",
+              (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
+              nYChunkSize );
     pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
     if( pabyChunkBuf == NULL )
     {
@@ -919,6 +1018,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                                         nThisYChunkSize,
                                         nBandCount, eType, bAllTouched, poGeom,
                                         padfBurnValues, eBurnValueSource,
+                                        eMergeAlg,
                                         pfnTransformer, pTransformArg );
 
                 delete poFeat;
@@ -1045,6 +1145,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * is. This is implemented properly only for points and lines for now. Polygons
  * will be burned using the Z value from the first point. The M value may
  * be supported in the future.</dd>
+ * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
  * </dl>
  *
  * @param pfnProgress the progress function to report completion.
@@ -1091,15 +1192,15 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
     if( nLayerCount == 0 )
         return CE_None;
 
-    int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
-    const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
-    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
-    if( pszOpt )
-    {
-        if( EQUAL(pszOpt,"Z"))
-            eBurnValueSource = GBV_Z;
-        /*else if( EQUAL(pszOpt,"M"))
-            eBurnValueSource = GBV_M;*/
+/* -------------------------------------------------------------------- */
+/*      Options                                                         */
+/* -------------------------------------------------------------------- */
+    int bAllTouched;
+    GDALBurnValueSrc eBurnValueSource;
+    GDALRasterMergeAlg eMergeAlg;
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+        return CE_Failure;
     }
 
 /* ==================================================================== */
@@ -1193,7 +1294,7 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
             gv_rasterize_one_shape( (unsigned char *) pData, 0,
                                     nBufXSize, nBufYSize,
                                     1, eBufType, bAllTouched, poGeom,
-                                    &dfBurnValue, eBurnValueSource,
+                                    &dfBurnValue, eBurnValueSource, eMergeAlg,
                                     pfnTransformer, pTransformArg );
 
             delete poFeat;
diff --git a/alg/gdalsievefilter.cpp b/alg/gdalsievefilter.cpp
index c8ea707..7abefe6 100644
--- a/alg/gdalsievefilter.cpp
+++ b/alg/gdalsievefilter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsievefilter.cpp 23156 2011-10-01 15:34:16Z rouault $
+ * $Id: gdalsievefilter.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdalsievefilter.cpp 23156 2011-10-01 15:34:16Z rouault $");
+CPL_CVSID("$Id: gdalsievefilter.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define GP_NODATA_MARKER -51502112
 #define MY_MAX_INT 2147483647
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index aea8149..78d0c71 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 26279 2013-08-08 20:16:32Z rouault $
+ * $Id: gdaltransformer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of one or more GDALTrasformerFunc types, including
@@ -9,6 +9,7 @@
  ******************************************************************************
  * Copyright (c) 2002, i3 - information integration and imaging 
  *                          Fort Collin, CO
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 #include "cpl_list.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdaltransformer.cpp 26279 2013-08-08 20:16:32Z rouault $");
+CPL_CVSID("$Id: gdaltransformer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -829,6 +830,8 @@ typedef struct {
     double   adfDstInvGeoTransform[6];
     
     void     *pDstGCPTransformArg;
+    void     *pDstRPCTransformArg;
+    void     *pDstTPSTransformArg;
 
 } GDALGenImgProjTransformInfo;
 
@@ -859,6 +862,10 @@ void* GDALCloneGenImgProjTransformer( void *hTransformArg )
         psClonedInfo->pReprojectArg = GDALCloneTransformer( psInfo->pReprojectArg );
     if( psClonedInfo->pDstGCPTransformArg )
         psClonedInfo->pDstGCPTransformArg = GDALCloneTransformer( psInfo->pDstGCPTransformArg );
+    if( psClonedInfo->pDstRPCTransformArg )
+        psClonedInfo->pDstRPCTransformArg = GDALCloneTransformer( psInfo->pDstRPCTransformArg );
+    if( psClonedInfo->pDstTPSTransformArg )
+        psClonedInfo->pDstTPSTransformArg = GDALCloneTransformer( psInfo->pDstTPSTransformArg );
 
     return psClonedInfo;
 }
@@ -1061,9 +1068,14 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
  * <li> MAX_GCP_ORDER: the maximum order to use for GCP derived polynomials if
  * possible.  The default is to autoselect based on the number of GCPs.  
  * A value of -1 triggers use of Thin Plate Spline instead of polynomials.
- * <li> METHOD: may have a value which is one of GEOTRANSFORM, GCP_POLYNOMIAL,
- * GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation method to be
- * considered on the source dataset. 
+ * <li> SRC_METHOD: may have a value which is one of GEOTRANSFORM, 
+ * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation 
+ * method to be considered on the source dataset. Will be used for pixel/line 
+ * to georef transformation on the source dataset.
+ * <li> DST_METHOD: may have a value which is one of GEOTRANSFORM, 
+ * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation 
+ * method to be considered on the source dataset.  Will be used for pixel/line 
+ * to georef transformation on the destination dataset.
  * <li> RPC_HEIGHT: A fixed height to be used with RPC calculations.
  * <li> RPC_DEM: The name of a DEM file to be used with RPC calculations.
  * <li> INSERT_CENTER_LONG: May be set to FALSE to disable setting up a 
@@ -1087,7 +1099,9 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     GDALGenImgProjTransformInfo *psInfo;
     char **papszMD;
     GDALRPCInfo sRPCInfo;
-    const char *pszMethod = CSLFetchNameValue( papszOptions, "METHOD" );
+    const char *pszMethod = CSLFetchNameValue( papszOptions, "SRC_METHOD" );
+    if( pszMethod == NULL )
+        pszMethod = CSLFetchNameValue( papszOptions, "METHOD" );
     const char *pszValue;
     int nOrder = 0, bGCPUseOK = TRUE, nMinimumGcps = -1, bRefine = FALSE;
     double dfTolerance = 0.0;
@@ -1199,8 +1213,9 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
              && (pszMethod == NULL || EQUAL(pszMethod,"GCP_TPS")) )
     {
         psInfo->pSrcTPSTransformArg = 
-            GDALCreateTPSTransformer( GDALGetGCPCount( hSrcDS ),
-                                      GDALGetGCPs( hSrcDS ), FALSE );
+            GDALCreateTPSTransformerInt( GDALGetGCPCount( hSrcDS ),
+                                         GDALGetGCPs( hSrcDS ), FALSE,
+                                         papszOptions);
         if( psInfo->pSrcTPSTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
@@ -1265,11 +1280,113 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Setup reprojection.                                             */
+/*      Get forward and inverse geotransform for destination image.     */
+/*      If we have no destination use a unit transform.                 */
 /* -------------------------------------------------------------------- */
-    if( pszDstWKT == NULL && hDstDS != NULL )
-        pszDstWKT = GDALGetProjectionRef( hDstDS );
+    const char *pszDstMethod = CSLFetchNameValue( papszOptions, "DST_METHOD" );
+
+    if( !hDstDS )
+    {
+        psInfo->adfDstGeoTransform[0] = 0.0;
+        psInfo->adfDstGeoTransform[1] = 1.0;
+        psInfo->adfDstGeoTransform[2] = 0.0;
+        psInfo->adfDstGeoTransform[3] = 0.0;
+        psInfo->adfDstGeoTransform[4] = 0.0;
+        psInfo->adfDstGeoTransform[5] = 1.0;
+        memcpy( psInfo->adfDstInvGeoTransform, psInfo->adfDstGeoTransform,
+                sizeof(double) * 6 );
+    }
+    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod,"GEOTRANSFORM"))
+        && GDALGetGeoTransform( hDstDS, psInfo->adfDstGeoTransform ) == CE_None)
+    {
+        if( pszDstWKT == NULL )
+            pszDstWKT = GDALGetProjectionRef( hDstDS );
+
+        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform, 
+                                  psInfo->adfDstInvGeoTransform ) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
+            GDALDestroyGenImgProjTransformer( psInfo );
+            return NULL;
+        }
+    }
+    else if( bGCPUseOK 
+             && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_POLYNOMIAL") )
+             && GDALGetGCPCount( hDstDS ) > 0 && nOrder >= 0 )
+    {
+        if(bRefine)
+        {
+            psInfo->pDstGCPTransformArg = 
+                GDALCreateGCPRefineTransformer( GDALGetGCPCount( hDstDS ),
+                                                GDALGetGCPs( hDstDS ), nOrder, 
+                                                FALSE, dfTolerance, 
+                                                nMinimumGcps );
+        }
+        else
+        {
+            psInfo->pDstGCPTransformArg = 
+                GDALCreateGCPTransformer( GDALGetGCPCount( hDstDS ),
+                                          GDALGetGCPs( hDstDS ), nOrder, 
+                                          FALSE );
+        }
+
+        if( psInfo->pDstGCPTransformArg == NULL )
+        {
+            GDALDestroyGenImgProjTransformer( psInfo );
+            return NULL;
+        }
 
+        if( pszDstWKT == NULL )
+            pszDstWKT = GDALGetGCPProjection( hDstDS );
+    }
+    else if( bGCPUseOK 
+             && GDALGetGCPCount( hDstDS ) > 0 
+             && nOrder <= 0
+             && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_TPS")) )
+    {
+        psInfo->pDstTPSTransformArg = 
+            GDALCreateTPSTransformerInt( GDALGetGCPCount( hDstDS ),
+                                         GDALGetGCPs( hDstDS ), FALSE,
+                                         papszOptions );
+        if( psInfo->pDstTPSTransformArg == NULL )
+        {
+            GDALDestroyGenImgProjTransformer( psInfo );
+            return NULL;
+        }
+
+        if( pszDstWKT == NULL )
+            pszDstWKT = GDALGetGCPProjection( hDstDS );
+    }
+    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod,"RPC"))
+             && (papszMD = GDALGetMetadata( hDstDS, "RPC" )) != NULL
+             && GDALExtractRPCInfo( papszMD, &sRPCInfo ) )
+    {
+        psInfo->pDstRPCTransformArg = 
+            GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0.1, papszOptions );
+        if( psInfo->pDstRPCTransformArg == NULL )
+        {
+            GDALDestroyGenImgProjTransformer( psInfo );
+            return NULL;
+        }
+        if( pszDstWKT == NULL )
+            pszDstWKT = SRS_WKT_WGS84;
+    }
+
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to compute a transformation between pixel/line\n"
+                  "and georeferenced coordinates for %s.\n"
+                  "There is no affine transformation and no GCPs.", 
+                  GDALGetDescription( hDstDS ) );
+
+        GDALDestroyGenImgProjTransformer( psInfo );
+        return NULL;
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Setup reprojection.                                             */
+/* -------------------------------------------------------------------- */
     if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0 
         && pszDstWKT != NULL && strlen(pszDstWKT) > 0 
         && !EQUAL(pszSrcWKT,pszDstWKT) )
@@ -1288,33 +1405,6 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         }
     }
         
-/* -------------------------------------------------------------------- */
-/*      Get forward and inverse geotransform for destination image.     */
-/*      If we have no destination use a unit transform.                 */
-/* -------------------------------------------------------------------- */
-    if( hDstDS )
-    {
-        GDALGetGeoTransform( hDstDS, psInfo->adfDstGeoTransform );
-        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform, 
-                                  psInfo->adfDstInvGeoTransform ) )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
-            GDALDestroyGenImgProjTransformer( psInfo );
-            return NULL;
-        }
-    }
-    else
-    {
-        psInfo->adfDstGeoTransform[0] = 0.0;
-        psInfo->adfDstGeoTransform[1] = 1.0;
-        psInfo->adfDstGeoTransform[2] = 0.0;
-        psInfo->adfDstGeoTransform[3] = 0.0;
-        psInfo->adfDstGeoTransform[4] = 0.0;
-        psInfo->adfDstGeoTransform[5] = 1.0;
-        memcpy( psInfo->adfDstInvGeoTransform, psInfo->adfDstGeoTransform,
-                sizeof(double) * 6 );
-    }
-    
     return psInfo;
 }
 
@@ -1545,6 +1635,12 @@ void GDALDestroyGenImgProjTransformer( void *hTransformArg )
     if( psInfo->pDstGCPTransformArg != NULL )
         GDALDestroyGCPTransformer( psInfo->pDstGCPTransformArg );
 
+    if( psInfo->pDstRPCTransformArg != NULL )
+        GDALDestroyRPCTransformer( psInfo->pDstRPCTransformArg );
+
+    if( psInfo->pDstTPSTransformArg != NULL )
+        GDALDestroyTPSTransformer( psInfo->pDstTPSTransformArg );
+
     if( psInfo->pReprojectArg != NULL )
         GDALDestroyReprojectionTransformer( psInfo->pReprojectArg );
 
@@ -1578,6 +1674,11 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
     void *pTPSTransformArg;
     void *pGeoLocTransformArg;
 
+    for( i = 0; i < nPointCount; i++ )
+    {
+        panSuccess[i] = ( padfX[i] != HUGE_VAL && padfY[i] != HUGE_VAL );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Convert from src (dst) pixel/line to src (dst)                  */
 /*      georeferenced coordinates.                                      */
@@ -1586,8 +1687,8 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
     {
         padfGeoTransform = psInfo->adfDstGeoTransform;
         pGCPTransformArg = psInfo->pDstGCPTransformArg;
-        pRPCTransformArg = NULL;
-        pTPSTransformArg = NULL;
+        pRPCTransformArg = psInfo->pDstRPCTransformArg;
+        pTPSTransformArg = psInfo->pDstTPSTransformArg;
         pGeoLocTransformArg = NULL;
     }
     else
@@ -1661,11 +1762,6 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
                                         panSuccess ) )
             return FALSE;
     }
-    else
-    {
-        for( i = 0; i < nPointCount; i++ )
-            panSuccess[i] = 1;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Convert dst (src) georef coordinates back to pixel/line.        */
@@ -1682,8 +1778,8 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
     {
         padfGeoTransform = psInfo->adfDstInvGeoTransform;
         pGCPTransformArg = psInfo->pDstGCPTransformArg;
-        pRPCTransformArg = NULL;
-        pTPSTransformArg = NULL;
+        pRPCTransformArg = psInfo->pDstRPCTransformArg;
+        pTPSTransformArg = psInfo->pDstTPSTransformArg;
         pGeoLocTransformArg = NULL;
     }
         
@@ -1847,25 +1943,79 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
     }
     
 /* -------------------------------------------------------------------- */
+/*      Handle Dest GCP transformation.                                 */
+/* -------------------------------------------------------------------- */
+    if( psInfo->pDstGCPTransformArg != NULL )
+    {
+        CPLXMLNode *psTransformerContainer;
+        CPLXMLNode *psTransformer;
+
+        psTransformerContainer = 
+            CPLCreateXMLNode( psTree, CXT_Element, "DstGCPTransformer" );
+
+        psTransformer = GDALSerializeTransformer( GDALGCPTransform,
+                                                  psInfo->pDstGCPTransformArg);
+        if( psTransformer != NULL )
+            CPLAddXMLChild( psTransformerContainer, psTransformer );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle Dest TPS transformation.                                 */
+/* -------------------------------------------------------------------- */
+    else if( psInfo->pDstTPSTransformArg != NULL )
+    {
+        CPLXMLNode *psTransformerContainer;
+        CPLXMLNode *psTransformer;
+
+        psTransformerContainer = 
+            CPLCreateXMLNode( psTree, CXT_Element, "DstTPSTransformer" );
+
+        psTransformer = 
+            GDALSerializeTransformer( NULL, psInfo->pDstTPSTransformArg);
+        if( psTransformer != NULL )
+            CPLAddXMLChild( psTransformerContainer, psTransformer );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle Dest RPC transformation.                                 */
+/* -------------------------------------------------------------------- */
+    else if( psInfo->pDstRPCTransformArg != NULL )
+    {
+        CPLXMLNode *psTransformerContainer;
+        CPLXMLNode *psTransformer;
+
+        psTransformerContainer = 
+            CPLCreateXMLNode( psTree, CXT_Element, "DstRPCTransformer" );
+
+        psTransformer = 
+            GDALSerializeTransformer( NULL, psInfo->pDstRPCTransformArg);
+        if( psTransformer != NULL )
+            CPLAddXMLChild( psTransformerContainer, psTransformer );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Handle destination geotransforms.                               */
 /* -------------------------------------------------------------------- */
-    sprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-             psInfo->adfDstGeoTransform[0],
-             psInfo->adfDstGeoTransform[1],
-             psInfo->adfDstGeoTransform[2],
-             psInfo->adfDstGeoTransform[3],
-             psInfo->adfDstGeoTransform[4],
-             psInfo->adfDstGeoTransform[5] );
-    CPLCreateXMLElementAndValue( psTree, "DstGeoTransform", szWork );
-    
-    sprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-             psInfo->adfDstInvGeoTransform[0],
-             psInfo->adfDstInvGeoTransform[1],
-             psInfo->adfDstInvGeoTransform[2],
-             psInfo->adfDstInvGeoTransform[3],
-             psInfo->adfDstInvGeoTransform[4],
-             psInfo->adfDstInvGeoTransform[5] );
-    CPLCreateXMLElementAndValue( psTree, "DstInvGeoTransform", szWork );
+    else
+    {
+        sprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                 psInfo->adfDstGeoTransform[0],
+                 psInfo->adfDstGeoTransform[1],
+                 psInfo->adfDstGeoTransform[2],
+                 psInfo->adfDstGeoTransform[3],
+                 psInfo->adfDstGeoTransform[4],
+                 psInfo->adfDstGeoTransform[5] );
+        CPLCreateXMLElementAndValue( psTree, "DstGeoTransform", szWork );
+        
+        sprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                 psInfo->adfDstInvGeoTransform[0],
+                 psInfo->adfDstInvGeoTransform[1],
+                 psInfo->adfDstInvGeoTransform[2],
+                 psInfo->adfDstInvGeoTransform[3],
+                 psInfo->adfDstInvGeoTransform[4],
+                 psInfo->adfDstInvGeoTransform[5] );
+        CPLCreateXMLElementAndValue( psTree, "DstInvGeoTransform", szWork );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a reprojection transformer?                          */
@@ -1986,6 +2136,26 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Dst TPS Transform                                               */
+/* -------------------------------------------------------------------- */
+    psSubtree = CPLGetXMLNode( psTree, "DstTPSTransformer" );
+    if( psSubtree != NULL && psSubtree->psChild != NULL )
+    {
+        psInfo->pDstTPSTransformArg = 
+            GDALDeserializeTPSTransformer( psSubtree->psChild );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Dst RPC Transform                                               */
+/* -------------------------------------------------------------------- */
+    psSubtree = CPLGetXMLNode( psTree, "DstRPCTransformer" );
+    if( psSubtree != NULL && psSubtree->psChild != NULL )
+    {
+        psInfo->pDstRPCTransformArg = 
+            GDALDeserializeRPCTransformer( psSubtree->psChild );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      DstGeotransform                                                 */
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "DstGeoTransform" ) != NULL )
diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp
index b78b46f..c789da5 100644
--- a/alg/gdalwarper.cpp
+++ b/alg/gdalwarper.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.cpp 25884 2013-04-09 17:04:16Z etourigny $
+ * $Id: gdalwarper.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of high level convenience APIs for warper.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_api.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalwarper.cpp 25884 2013-04-09 17:04:16Z etourigny $");
+CPL_CVSID("$Id: gdalwarper.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -854,6 +855,7 @@ GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
 
     psOptions = (GDALWarpOptions *) CPLCalloc(sizeof(GDALWarpOptions),1);
 
+    psOptions->nBandCount = 0;
     psOptions->eResampleAlg = GRA_NearestNeighbour;
     psOptions->pfnProgress = GDALDummyProgress;
     psOptions->eWorkingDataType = GDT_Unknown;
diff --git a/alg/gdalwarper.h b/alg/gdalwarper.h
index b80f013..1fb5f3e 100644
--- a/alg/gdalwarper.h
+++ b/alg/gdalwarper.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.h 25884 2013-04-09 17:04:16Z etourigny $
+ * $Id: gdalwarper.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL High Performance Warper
  * Purpose:  Prototypes, and definitions for warping related work.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp
index f0dbf40..8b0f7e9 100644
--- a/alg/gdalwarpkernel.cpp
+++ b/alg/gdalwarpkernel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel.cpp 25935 2013-04-19 21:28:31Z rouault $
+ * $Id: gdalwarpkernel.cpp 27159 2014-04-12 15:49:25Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "cpl_atomic_ops.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalwarpkernel.cpp 25935 2013-04-19 21:28:31Z rouault $");
+CPL_CVSID("$Id: gdalwarpkernel.cpp 27159 2014-04-12 15:49:25Z rouault $");
 
 static const int anGWKFilterRadius[] =
 {
@@ -2021,12 +2022,11 @@ static int GWKBilinearResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
 /*                        GWKCubicResample()                            */
 /*     Set of bicubic interpolators using cubic convolution.            */
 /************************************************************************/
-
 #define CubicConvolution(distance1,distance2,distance3,f0,f1,f2,f3) \
-   (  (   -f0 +     f1 - f2 + f3) * distance3                       \
-    + (2.0*(f0 - f1) + f2 - f3) * distance2                         \
-    + (   -f0          + f2     ) * distance1                       \
-    +               f1                         )
+     (             f1                                               \
+      + distance1*0.5*(f2 - f0)                                     \
+      + distance2*0.5*(2.0*f0 - 5.0*f1 + 4.0*f2 - f3)               \
+      + distance3*0.5*(3.0*(f1 - f2) + f3 - f0))
 
 static int GWKCubicResample( GDALWarpKernel *poWK, int iBand,
                              double dfSrcX, double dfSrcY,
@@ -2034,8 +2034,8 @@ static int GWKCubicResample( GDALWarpKernel *poWK, int iBand,
                              double *pdfReal, double *pdfImag )
 
 {
-    int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    int     iSrcY = (int) floor( dfSrcY - 0.5 );
+    int     iSrcX = (int) (dfSrcX - 0.5);
+    int     iSrcY = (int) (dfSrcY - 0.5);
     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
@@ -2099,8 +2099,8 @@ static int GWKCubicResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
                                         GByte *pbValue )
 
 {
-    int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    int     iSrcY = (int) floor( dfSrcY - 0.5 );
+    int     iSrcX = (int) (dfSrcX - 0.5);
+    int     iSrcY = (int) (dfSrcY - 0.5);
     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
@@ -2146,8 +2146,8 @@ static int GWKCubicResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
                                          GInt16 *piValue )
 
 {
-    int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    int     iSrcY = (int) floor( dfSrcY - 0.5 );
+    int     iSrcX = (int) (dfSrcX - 0.5);
+    int     iSrcY = (int) (dfSrcY - 0.5);
     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
@@ -2175,8 +2175,16 @@ static int GWKCubicResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
                 (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset + 2]);
     }
 
-    *piValue = (GInt16)CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
-                        adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
+    double dfValue = CubicConvolution(
+        dfDeltaY, dfDeltaY2, dfDeltaY3,
+        adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
+    
+    if ( dfValue < -32768.0 )
+        *piValue = -32768;
+    else if ( dfValue > 32767.0 )
+        *piValue = 32767;
+    else
+        *piValue = (GInt16)floor(0.5 + dfValue);
     
     return TRUE;
 }
@@ -4991,6 +4999,10 @@ static void GWKAverageOrModeThread( void* pData)
     int *panVals = NULL;
     int nBins = 0, nBinsOffset = 0;
 
+    // only used with nAlgo = 2
+    float*   pafVals = NULL;
+    int*     panSums = NULL;
+
     if ( poWK->eResample == GRA_Average ) 
     {
         nAlgo = 1;
@@ -5021,11 +5033,25 @@ static void GWKAverageOrModeThread( void* pData)
             {
                 nBins = 65536;
             }
-            panVals = (int*) CPLMalloc(nBins * sizeof(int));            
+            panVals = (int*) VSIMalloc(nBins * sizeof(int));
+            if( panVals == NULL )
+                return;
         }
         else
         {
             nAlgo = 2;
+
+            if ( nSrcXSize > 0 && nSrcYSize > 0 )
+            {
+                pafVals = (float*) VSIMalloc3(nSrcXSize, nSrcYSize, sizeof(float));
+                panSums = (int*) VSIMalloc3(nSrcXSize, nSrcYSize, sizeof(int));
+                if( pafVals == NULL || panSums == NULL )
+                {
+                    VSIFree(pafVals);
+                    VSIFree(panSums);
+                    return;
+                }
+            }
         }
     }
     else
@@ -5116,11 +5142,32 @@ static void GWKAverageOrModeThread( void* pData)
                 int iSrcXMin, iSrcXMax,iSrcYMin,iSrcYMax;
 
                 // compute corners in source crs
-                iSrcXMin = MAX( ((int) floor((padfX[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 );
-                iSrcXMax = MIN( ((int) ceil((padfX2[iDstX] + 1e-10))) - poWK->nSrcXOff, nSrcXSize );
-                iSrcYMin = MAX( ((int) floor((padfY[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 );
-                iSrcYMax = MIN( ((int) ceil((padfY2[iDstX] + 1e-10))) - poWK->nSrcYOff, nSrcYSize );
+                iSrcXMin = MAX( ((int) floor((padfX[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 ); 
+                iSrcXMax = MIN( ((int) ceil((padfX2[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize ); 
+                iSrcYMin = MAX( ((int) floor((padfY[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 ); 
+                iSrcYMax = MIN( ((int) ceil((padfY2[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
                 
+                // The transformation might not have preserved ordering of coordinates
+                // so do the necessary swapping (#5433)
+                // NOTE: this is really an approximative fix. To do something more precise
+                // we would for example need to compute the transformation of coordinates
+                // in the [iDstX,iDstY]x[iDstX+1,iDstY+1] square back to source coordinates,
+                // and take the bounding box of the got source coordinates.
+                if( iSrcXMax < iSrcXMin )
+                {
+                    iSrcXMin = MAX( ((int) floor((padfX2[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 ); 
+                    iSrcXMax = MIN( ((int) ceil((padfX[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize ); 
+                }
+                if( iSrcYMax < iSrcYMin )
+                {
+                    iSrcYMin = MAX( ((int) floor((padfY2[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 ); 
+                    iSrcYMax = MIN( ((int) ceil((padfY[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
+                }
+                if( iSrcXMin == iSrcXMax && iSrcXMax < nSrcXSize )
+                    iSrcXMax ++;
+                if( iSrcYMin == iSrcYMax && iSrcYMax < nSrcYSize )
+                    iSrcYMax ++;
+
                 // loop over source lines and pixels - 3 possible algorithms
                 
                 if ( nAlgo == 1 ) // poWK->eResample == GRA_Average
@@ -5169,16 +5216,7 @@ static void GWKAverageOrModeThread( void* pData)
                            of compatability. It won't look right on RGB images by the
                            nature of the filter. */
                         int     iMaxInd = 0, iMaxVal = -1, i = 0;
-                        int     nNumPx = nSrcXSize * nSrcYSize;
 
-                        if ( nNumPx == 0 )
-                            continue;
-
-                        /* putting alloc outside of loop (and CPLRealloc here) saves time 
-                           but takes much more memory (why?), so just doing malloc here */
-                        float*   pafVals = (float*) CPLMalloc(nNumPx * sizeof(float));
-                        int*     panSums = (int*) CPLMalloc(nNumPx * sizeof(int));
-                        
                         for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                         {
                             for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
@@ -5228,9 +5266,6 @@ static void GWKAverageOrModeThread( void* pData)
                             dfBandDensity = 1;                
                             bHasFoundDensity = TRUE;
                         }
-
-                        CPLFree( pafVals );
-                        CPLFree( panSums );
                     }
                     
                     else // byte or int16
@@ -5329,6 +5364,8 @@ static void GWKAverageOrModeThread( void* pData)
     CPLFree( padfZ2 );
     CPLFree( pabSuccess );
     CPLFree( pabSuccess2 );
-    if ( panVals ) CPLFree( panVals );
+    VSIFree( panVals );
+    VSIFree(pafVals);
+    VSIFree(panSums);
 }
 
diff --git a/alg/gdalwarpkernel_opencl.c b/alg/gdalwarpkernel_opencl.c
index 7e8daa6..ad5dc1a 100644
--- a/alg/gdalwarpkernel_opencl.c
+++ b/alg/gdalwarpkernel_opencl.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel_opencl.c 25069 2012-10-07 14:13:39Z rouault $
+ * $Id: gdalwarpkernel_opencl.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenCL Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Seth Price <seth at pricepages.org>
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,7 +41,7 @@
 #include "cpl_string.h"
 #include "gdalwarpkernel_opencl.h"
 
-CPL_CVSID("$Id: gdalwarpkernel_opencl.c 25069 2012-10-07 14:13:39Z rouault $");
+CPL_CVSID("$Id: gdalwarpkernel_opencl.c 27044 2014-03-16 23:41:27Z rouault $");
 
 #define handleErr(err) if((err) != CL_SUCCESS) { \
     CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
@@ -535,6 +536,32 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     const char *dVecf = "float";
     const char *kernGenFuncs =
 // ********************* General Funcs ********************
+"void clampToDst(float fReal,\n"
+                "__global outType *dstPtr,\n"
+                "unsigned int iDstOffset,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "int bandNum);\n"
+"void setPixel(__global outType *dstReal,\n"
+                "__global outType *dstImag,\n"
+                "__global float *dstDensity,\n"
+                "__global int *nDstValid,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "const int bandNum,\n"
+                "vecf fDensity, vecf fReal, vecf fImag);\n"
+"int getPixel(__read_only image2d_t srcReal,\n"
+                "__read_only image2d_t srcImag,\n"
+                "__global float *fUnifiedSrcDensity,\n"
+                "__global int *nUnifiedSrcValid,\n"
+                "__constant char *useBandSrcValid,\n"
+                "__global int *nBandSrcValid,\n"
+                "const int2 iSrc,\n"
+                "int bandNum,\n"
+                "vecf *fDensity, vecf *fReal, vecf *fImag);\n"
+"int isValid(__global float *fUnifiedSrcDensity,\n"
+                "__global int *nUnifiedSrcValid,\n"
+                "float2 fSrcCoords );\n"
+"float2 getSrcCoords(__read_only image2d_t srcCoords);\n"
+
 "#ifdef USE_CLAMP_TO_DST_FLOAT\n"
 "void clampToDst(float fReal,\n"
                 "__global outType *dstPtr,\n"
@@ -666,7 +693,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     "int bHasValid = FALSE;\n"
     
     // Clamp the src offset values if needed
-    "if(useUnifiedSrcDensity || useUnifiedSrcValid || useUseBandSrcValid){\n"
+    "if(useUnifiedSrcDensity | useUnifiedSrcValid | useUseBandSrcValid){\n"
         "int iSrcX = iSrc.x;\n"
         "int iSrcY = iSrc.y;\n"
         
@@ -903,6 +930,9 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     const char *kernCubic =
 // ************************ Cubic ************************
 "vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
+                        "vecf f0, vecf f1, vecf f2, vecf f3);\n"
+
+"vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
                        "vecf f0, vecf f1, vecf f2, vecf f3)\n"
 "{\n"
     "return   (  -f0 +    f1  - f2 + f3) * dist3\n"
@@ -1023,6 +1053,9 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     const char *kernResampler =
 // ************************ LanczosSinc ************************
 
+"float lanczosSinc( float fX, float fR );\n"
+"float bSpline( float x );\n"
+
 "float lanczosSinc( float fX, float fR )\n"
 "{\n"
     "if ( fX > fR || fX < -fR)\n"
diff --git a/alg/gdalwarpoperation.cpp b/alg/gdalwarpoperation.cpp
index 61c5299..13088c7 100644
--- a/alg/gdalwarpoperation.cpp
+++ b/alg/gdalwarpoperation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpoperation.cpp 25884 2013-04-09 17:04:16Z etourigny $
+ * $Id: gdalwarpoperation.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpOperation class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_multiproc.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: gdalwarpoperation.cpp 25884 2013-04-09 17:04:16Z etourigny $");
+CPL_CVSID("$Id: gdalwarpoperation.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* Defined in gdalwarpkernel.cpp */
 int GWKGetFilterRadius(GDALResampleAlg eResampleAlg);
diff --git a/alg/llrasterize.cpp b/alg/llrasterize.cpp
index be341d0..258fc40 100644
--- a/alg/llrasterize.cpp
+++ b/alg/llrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: llrasterize.cpp 22998 2011-08-28 12:23:29Z rouault $
+ * $Id: llrasterize.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector polygon rasterization code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/alg/polygonize.cpp b/alg/polygonize.cpp
index 336295f..1959f6b 100644
--- a/alg/polygonize.cpp
+++ b/alg/polygonize.cpp
@@ -1,11 +1,12 @@
 /******************************************************************************
- * $Id: polygonize.cpp 22501 2011-06-04 21:28:47Z rouault $
+ * $Id: polygonize.cpp 27044 2014-03-16 23:41:27Z rouault $
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: polygonize.cpp 22501 2011-06-04 21:28:47Z rouault $");
+CPL_CVSID("$Id: polygonize.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define GP_NODATA_MARKER -51502112
 
diff --git a/alg/rasterfill.cpp b/alg/rasterfill.cpp
index aee49cb..609b9fd 100644
--- a/alg/rasterfill.cpp
+++ b/alg/rasterfill.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterfill.cpp 26341 2013-08-19 19:23:33Z rouault $
+ * $Id: rasterfill.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Interpolate in nodata areas.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rasterfill.cpp 26341 2013-08-19 19:23:33Z rouault $");
+CPL_CVSID("$Id: rasterfill.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           GDALFilterLine()                           */
diff --git a/alg/thinplatespline.cpp b/alg/thinplatespline.cpp
index dfa7748..79b7a84 100644
--- a/alg/thinplatespline.cpp
+++ b/alg/thinplatespline.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: thinplatespline.cpp 24925 2012-09-16 10:07:00Z rouault $
+ * $Id: thinplatespline.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Warp API
  * Purpose:  Implemenentation of 2D Thin Plate Spline transformer. 
@@ -10,6 +10,7 @@
  * 
  ******************************************************************************
  * Copyright (c) 2004, VIZRT Inc.
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,20 +38,6 @@
 
 #include "thinplatespline.h"
 
-#ifdef HAVE_FLOAT_H
-#  include <float.h>
-#elif defined(HAVE_VALUES_H)
-#  include <values.h>
-#endif
-
-#ifndef FLT_MAX
-#  define FLT_MAX 1e+37
-#  define FLT_MIN 1e-37
-#endif
-
-VizGeorefSpline2D* viz_xy2llz;
-VizGeorefSpline2D* viz_llz2xy;
-
 /////////////////////////////////////////////////////////////////////////////////////
 //// vizGeorefSpline2D
 /////////////////////////////////////////////////////////////////////////////////////
@@ -61,40 +48,31 @@ VizGeorefSpline2D* viz_llz2xy;
 
 #define VIZ_GEOREF_SPLINE_DEBUG 0
 
+#ifndef HAVE_ARMADILLO
 static int matrixInvert( int N, double input[], double output[] );
+#endif
 
 void VizGeorefSpline2D::grow_points()
 
 {
     int new_max = _max_nof_points*2 + 2 + 3;
     int i;
-    
-    if( _max_nof_points == 0 )
-    {
-        x = (double *) VSIMalloc( sizeof(double) * new_max );
-        y = (double *) VSIMalloc( sizeof(double) * new_max );
-        u = (double *) VSIMalloc( sizeof(double) * new_max );
-        unused = (int *) VSIMalloc( sizeof(int) * new_max );
-        index = (int *) VSIMalloc( sizeof(int) * new_max );
-        for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
-        {
-            rhs[i] = (double *) VSICalloc( sizeof(double), new_max );
-            coef[i] = (double *) VSICalloc( sizeof(double), new_max );
-        }
-    }
-    else
+
+    x = (double *) VSIRealloc( x, sizeof(double) * new_max );
+    y = (double *) VSIRealloc( y, sizeof(double) * new_max );
+    u = (double *) VSIRealloc( u, sizeof(double) * new_max );
+    unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
+    index = (int *) VSIRealloc( index, sizeof(int) * new_max );
+    for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
     {
-        x = (double *) VSIRealloc( x, sizeof(double) * new_max );
-        y = (double *) VSIRealloc( y, sizeof(double) * new_max );
-        u = (double *) VSIRealloc( u, sizeof(double) * new_max );
-        unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
-        index = (int *) VSIRealloc( index, sizeof(int) * new_max );
-        for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
+        rhs[i] = (double *) 
+            VSIRealloc( rhs[i], sizeof(double) * new_max );
+        coef[i] = (double *) 
+            VSIRealloc( coef[i], sizeof(double) * new_max );
+        if( _max_nof_points == 0 )
         {
-            rhs[i] = (double *) 
-                VSIRealloc( rhs[i], sizeof(double) * new_max );
-            coef[i] = (double *) 
-                VSIRealloc( coef[i], sizeof(double) * new_max );
+            memset(rhs[i], 0, 3 * sizeof(double));
+            memset(coef[i], 0, 3 * sizeof(double));
         }
     }
 
@@ -119,6 +97,7 @@ int VizGeorefSpline2D::add_point( const double Px, const double Py, const double
     return 1;
 }
 
+#if 0
 bool VizGeorefSpline2D::change_point(int index, double Px, double Py, double* Pvars)
 {
     if ( index < _nof_points )
@@ -172,10 +151,217 @@ int VizGeorefSpline2D::delete_point(const double Px, const double Py )
     }
     return(0);
 }
+#endif
+
+#define SQ(x) ((x)*(x))
+
+static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const double y1,
+                          const double x2, const double y2 )
+{
+    double dist  = SQ( x2 - x1 )  + SQ( y2 - y1 );
+    return dist ? dist * log( dist ) : 0.0;
+}
+
+#if defined(__GNUC__) && defined(__x86_64__)
+
+/* Derived and adapted from code originating from: */
+
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :                  
+ *   1. Argument Reduction: find k and f such that
+ *                      x = 2^k * (1+f),
+ *         where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *      Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *               = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *               = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ *      a polynomial of degree 14 to approximate R The maximum error
+ *      of this polynomial approximation is bounded by 2**-58.45. In
+ *      other words,
+ *                      2      4      6      8      10      12      14
+ *          R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *      (the values of Lg1 to Lg7 are listed in the program)
+ *      and
+ *          |      2          14          |     -58.45
+ *          | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *          |                             |
+ *      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *      In order to guarantee error in log below 1ulp, we compute log
+ *      by
+ *              log(1+f) = f - s*(f - R)        (if f is not too large)
+ *              log(1+f) = f - (hfsq - s*(hfsq+R)).     (better accuracy)
+ *      
+ *      3. Finally,  log(x) = k*ln2 + log(1+f).  
+ *                          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *         Here ln2 is split into two floating point number:
+ *                      ln2_hi + ln2_lo,
+ *         where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *      log(x) is NaN with signal if x < 0 (including -INF) ;
+ *      log(+INF) is +INF; log(0) is -INF with signal;
+ *      log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+typedef double V2DF __attribute__ ((__vector_size__ (16)));
+typedef union
+{
+    V2DF v2;
+    double d[2];
+} v2dfunion;
+
+typedef union
+{
+    int i[2];
+    long long li;
+} i64union;
+
+static const V2DF
+v2_ln2_div_2pow20 = {6.93147180559945286e-01 / 1048576, 6.93147180559945286e-01 / 1048576},
+v2_Lg1 = {6.666666666666735130e-01, 6.666666666666735130e-01},
+v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01}, 
+v2_Lg3 = {2.857142874366239149e-01, 2.857142874366239149e-01},
+v2_Lg4 = {2.222219843214978396e-01, 2.222219843214978396e-01},
+v2_Lg5 = {1.818357216161805012e-01, 1.818357216161805012e-01},
+v2_Lg6 = {1.531383769920937332e-01, 1.531383769920937332e-01},
+/*v2_Lg7 = {1.479819860511658591e-01, 1.479819860511658591e-01}, */
+v2_one = { 1.0, 1.0 },
+v2_const1023_mul_2pow20 = { 1023.0 * 1048576, 1023.0 * 1048576};
+
+#define GET_HIGH_WORD(hx,x) memcpy(&hx,((char*)&x+4),4)
+#define SET_HIGH_WORD(x,hx) memcpy(((char*)&x+4),&hx,4)
+
+#define MAKE_WIDE_CST(x) ((((long long)(x)) << 32) | (x))
+static const long long cst_expmask = MAKE_WIDE_CST(0xfff00000);
+static const long long cst_0x95f64 = MAKE_WIDE_CST(0x00095f64);
+static const long long cst_0x100000 = MAKE_WIDE_CST(0x00100000);
+static const long long cst_0x3ff00000 = MAKE_WIDE_CST(0x3ff00000);
+
+/* Modified version of __ieee754_log(), less precise than log() but a bit */
+/* faste, and computing 4 log() at a time. Assumes that the values are > 0 */
+static void FastApproxLog4Val(v2dfunion* x)
+{
+    V2DF f[2],s[2],z[2],R[2],w[2],t1[2],t2[2];
+    v2dfunion dk[2];
+    i64union k[2], hx[2], i[2];
+
+    GET_HIGH_WORD(hx[0].i[0],x[0].d[0]);
+    GET_HIGH_WORD(hx[0].i[1],x[0].d[1]);
+    k[0].li = hx[0].li & cst_expmask;
+    hx[0].li &= ~cst_expmask;
+    i[0].li = (hx[0].li + cst_0x95f64) & cst_0x100000;
+    hx[0].li |= i[0].li ^ cst_0x3ff00000;
+    SET_HIGH_WORD(x[0].d[0],hx[0].i[0]);     /* normalize x or x/2 */
+    SET_HIGH_WORD(x[0].d[1],hx[0].i[1]);     /* normalize x or x/2 */
+    k[0].li += i[0].li;
+    dk[0].d[0] = (double)k[0].i[0];
+    dk[0].d[1] = (double)k[0].i[1];
+
+    GET_HIGH_WORD(hx[1].i[0],x[1].d[0]);
+    GET_HIGH_WORD(hx[1].i[1],x[1].d[1]);
+    k[1].li = hx[1].li & cst_expmask;
+    hx[1].li &= ~cst_expmask;
+    i[1].li = (hx[1].li + cst_0x95f64) & cst_0x100000;
+    hx[1].li |= i[1].li ^ cst_0x3ff00000;
+    SET_HIGH_WORD(x[1].d[0],hx[1].i[0]);     /* normalize x or x/2 */
+    SET_HIGH_WORD(x[1].d[1],hx[1].i[1]);     /* normalize x or x/2 */
+    k[1].li += i[1].li;
+    dk[1].d[0] = (double)k[1].i[0];
+    dk[1].d[1] = (double)k[1].i[1];
+
+    f[0] = x[0].v2-v2_one;
+    s[0] = f[0]/(x[0].v2+v2_one);
+    z[0] = s[0]*s[0];
+    w[0] = z[0]*z[0];
+    t1[0]= w[0]*(v2_Lg2+w[0]*(v2_Lg4+w[0]*v2_Lg6));
+    t2[0]= z[0]*(v2_Lg1+w[0]*(v2_Lg3+w[0]*(v2_Lg5/*+w[0]*v2_Lg7*/)));
+    R[0] = t2[0]+t1[0];
+    x[0].v2 = ((dk[0].v2 - v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[0]*(f[0]-R[0])-f[0]));
+
+    f[1] = x[1].v2-v2_one;
+    s[1] = f[1]/(x[1].v2+v2_one);
+    z[1] = s[1]*s[1];
+    w[1] = z[1]*z[1];
+    t1[1]= w[1]*(v2_Lg2+w[1]*(v2_Lg4+w[1]*v2_Lg6));
+    t2[1]= z[1]*(v2_Lg1+w[1]*(v2_Lg3+w[1]*(v2_Lg5/*+w[1]*v2_Lg7*/)));
+    R[1] = t2[1]+t1[1];
+    x[1].v2 = ((dk[1].v2- v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[1]*(f[1]-R[1])-f[1]));
+}
+
+static CPL_INLINE void VizGeorefSpline2DBase_func4( double* res,
+                                         const double* pxy,
+                                         const double* xr, const double* yr )
+{
+    v2dfunion x1v, y1v, xv[2], yv[2], dist[2], resv[2];
+    xv[0].d[0] = xr[0];
+    xv[0].d[1] = xr[1];
+    xv[1].d[0] = xr[2];
+    xv[1].d[1] = xr[3];
+    yv[0].d[0] = yr[0];
+    yv[0].d[1] = yr[1];
+    yv[1].d[0] = yr[2];
+    yv[1].d[1] = yr[3];
+    x1v.d[0] = pxy[0];
+    x1v.d[1] = pxy[0];
+    y1v.d[0] = pxy[1];
+    y1v.d[1] = pxy[1];
+    dist[0].v2 = SQ( xv[0].v2 - x1v.v2 ) + SQ( yv[0].v2 - y1v.v2 );
+    dist[1].v2 = SQ( xv[1].v2 - x1v.v2 ) + SQ( yv[1].v2 - y1v.v2 );
+    resv[0] = dist[0];
+    resv[1] = dist[1];
+    FastApproxLog4Val(dist);
+    resv[0].v2 *= dist[0].v2;
+    resv[1].v2 *= dist[1].v2;
+    res[0] = resv[0].d[0];
+    res[1] = resv[0].d[1];
+    res[2] = resv[1].d[0];
+    res[3] = resv[1].d[1];
+}
+#else
+static void VizGeorefSpline2DBase_func4( double* res,
+                                         const double* pxy,
+                                         const double* xr, const double* yr )
+{
+    double dist0  = SQ( xr[0] - pxy[0] ) + SQ( yr[0] - pxy[1] );
+    res[0] = dist0 ? dist0 * log(dist0) : 0.0;
+    double dist1  = SQ( xr[1] - pxy[0] ) + SQ( yr[1] - pxy[1] );
+    res[1] = dist1 ? dist1 * log(dist1) : 0.0;
+    double dist2  = SQ( xr[2] - pxy[0] ) + SQ( yr[2] - pxy[1] );
+    res[2] = dist2 ? dist2 * log(dist2) : 0.0;
+    double dist3  = SQ( xr[3] - pxy[0] ) + SQ( yr[3] - pxy[1] );
+    res[3] = dist3 ? dist3 * log(dist3) : 0.0;
+}
+#endif
 
 int VizGeorefSpline2D::solve(void)
 {
-    int r, c, v;
+    int r, c;
     int p;
 	
     //	No points at all
@@ -280,11 +466,7 @@ int VizGeorefSpline2D::solve(void)
 	
     type = VIZ_GEOREF_SPLINE_FULL;
     // Make the necessary memory allocations
-    if ( _AA )
-        CPLFree(_AA);
-    if ( _Ainv )
-        CPLFree(_Ainv);
-	
+
     _nof_eqs = _nof_points + 3;
     
     if( _nof_eqs > INT_MAX / _nof_eqs )
@@ -293,12 +475,14 @@ int VizGeorefSpline2D::solve(void)
         return 0;
     }
 	
-    _AA = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
-    _Ainv = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
+    double* _AA = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
+    double* _Ainv = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
     
     if( _AA == NULL || _Ainv == NULL )
     {
         fprintf(stderr, "Out-of-memory while allocating temporary arrays. Computation aborted.\n");
+        VSIFree(_AA);
+        VSIFree(_Ainv);
         return 0;
     }
 	
@@ -321,7 +505,7 @@ int VizGeorefSpline2D::solve(void)
     for ( r = 0; r < _nof_points; r++ )
         for ( c = r; c < _nof_points; c++ )
         {
-            A(r+3,c+3) = base_func( x[r], y[r], x[c], y[c] );
+            A(r+3,c+3) = VizGeorefSpline2DBase_func( x[r], y[r], x[c], y[c] );
             if ( r != c )
                 A(c+3,r+3 ) = A(r+3,c+3);
         }
@@ -336,26 +520,53 @@ int VizGeorefSpline2D::solve(void)
     }
 			
 #endif
-			
+
+    int ret  = 4;
+#ifdef HAVE_ARMADILLO
+    try
+    {
+        arma::mat matA(_AA,_nof_eqs,_nof_eqs,false);
+        arma::mat matRHS(_nof_eqs, _nof_vars);
+        int row, col;
+        for(row = 0; row < _nof_eqs; row++)
+            for(col = 0; col < _nof_vars; col++)
+                matRHS.at(row, col) = rhs[col][row];
+        arma::mat matCoefs(arma::solve(matA, matRHS));
+        for(row = 0; row < _nof_eqs; row++)
+            for(col = 0; col < _nof_vars; col++)
+                coef[col][row] = matCoefs.at(row, col);
+    }
+    catch(...)
+    {
+        fprintf(stderr, "There is a problem to invert the interpolation matrix\n");
+        ret = 0;
+    }
+#else
     // Invert the matrix
     int status = matrixInvert( _nof_eqs, _AA, _Ainv );
 			
     if ( !status )
     {
         fprintf(stderr, " There is a problem to invert the interpolation matrix\n");
-        return 0;
+        ret = 0;
     }
-			
-    // calc the coefs
-    for ( v = 0; v < _nof_vars; v++ )
-        for ( r = 0; r < _nof_eqs; r++ )
-        {
-            coef[v][r] = 0.0;
-            for ( c = 0; c < _nof_eqs; c++ )
-                coef[v][r] += Ainv(r,c) * rhs[v][c];
-        }
-				
-    return(4);
+    else
+    {
+        // calc the coefs
+        for ( int v = 0; v < _nof_vars; v++ )
+            for ( r = 0; r < _nof_eqs; r++ )
+            {
+                coef[v][r] = 0.0;
+                for ( c = 0; c < _nof_eqs; c++ )
+                    coef[v][r] += Ainv(r,c) * rhs[v][c];
+            }
+    }
+#endif
+
+    VSIFree(_AA);
+    VSIFree(_Ainv);
+
+    return(ret);
 }
 
 int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars )
@@ -409,16 +620,29 @@ int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars
 			fact * rhs[v][rightP+3];
 		break;
 	case VIZ_GEOREF_SPLINE_FULL :
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
-		
-		for ( r = 0; r < _nof_points; r++ )
-		{
-			tmp = base_func( Px, Py, x[r], y[r] );
-			for ( v= 0; v < _nof_vars; v++ )
-				vars[v] += coef[v][r+3] * tmp;
-		}
-		break;
+    {
+        double Pxy[2] = { Px, Py };
+        for ( v = 0; v < _nof_vars; v++ )
+            vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
+        
+        for ( r = 0; r < (_nof_points & (~3)); r+=4 )
+        {
+            double tmp[4];
+            VizGeorefSpline2DBase_func4( tmp, Pxy, &x[r], &y[r] );
+            for ( v= 0; v < _nof_vars; v++ )
+                vars[v] += coef[v][r+3] * tmp[0] +
+                        coef[v][r+3+1] * tmp[1] +
+                        coef[v][r+3+2] * tmp[2] +
+                        coef[v][r+3+3] * tmp[3];
+        }
+        for ( ; r < _nof_points; r++ )
+        {
+            tmp = VizGeorefSpline2DBase_func( Px, Py, x[r], y[r] );
+            for ( v= 0; v < _nof_vars; v++ )
+                vars[v] += coef[v][r+3] * tmp;
+        }
+        break;
+    }
 	case VIZ_GEOREF_SPLINE_POINT_WAS_ADDED :
 		fprintf(stderr, " A point was added after the last solve\n");
 		fprintf(stderr, " NO interpolation - return values are zero\n");
@@ -440,42 +664,7 @@ int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars
 	return(1);
 }
 
-double VizGeorefSpline2D::base_func( const double x1, const double y1,
-						  const double x2, const double y2 )
-{
-	if ( ( x1 == x2 ) && (y1 == y2 ) )
-		return 0.0;
-	
-	double dist  = ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 );
-	
-	return dist * log( dist );	
-}
-
-#ifdef HAVE_ARMADILLO
-
-static int matrixInvert( int N, double input[], double output[] )
-{
-    try
-    {
-        arma::mat matInput(input,N,N,false);
-        const arma::mat& matInv = arma::inv(matInput);
-        int row, col;
-        for(row = 0; row < N; row++)
-            for(col = 0; col < N; col++)
-                output[row * N + col] = matInv.at(row, col);
-        return true;
-        //arma::mat matInv(output,N,N,false);
-        //return arma::inv(matInv, matInput);
-    }
-    catch(...)
-    {
-        fprintf(stderr, "matrixInvert(): error occured.\n");
-        return false;
-    }
-}
-
-#else
-
+#ifndef HAVE_ARMADILLO
 static int matrixInvert( int N, double input[], double output[] )
 {
     // Receives an array of dimension NxN as input.  This is passed as a one-
diff --git a/alg/thinplatespline.h b/alg/thinplatespline.h
index 38c9358..15da846 100644
--- a/alg/thinplatespline.h
+++ b/alg/thinplatespline.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: thinplatespline.h 20193 2010-08-06 17:12:10Z rouault $
+ * $Id: thinplatespline.h 26650 2013-11-24 14:05:58Z rouault $
  *
  * Project:  GDAL Warp API
  * Purpose:  Declarations for 2D Thin Plate Spline transformer. 
@@ -67,18 +67,11 @@ class VizGeorefSpline2D
         _nof_points = 0;
         _nof_vars = nof_vars;
         _max_nof_points = 0;
-        _AA = NULL;
-        _Ainv = NULL;
         grow_points();
         type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
     }
 
     ~VizGeorefSpline2D(){
-        if ( _AA )
-            CPLFree(_AA);
-        if ( _Ainv )
-            CPLFree(_Ainv);
-
         CPLFree( x );
         CPLFree( y );
         CPLFree( u );
@@ -91,6 +84,7 @@ class VizGeorefSpline2D
         }
     }
 
+#if 0
     int get_nof_points(){
         return _nof_points;
     }
@@ -119,6 +113,7 @@ class VizGeorefSpline2D
                 fprintf(stderr, "\n");
             }
 	}
+	
     int delete_list()
 	{
             _nof_points = 0;
@@ -135,19 +130,20 @@ class VizGeorefSpline2D
             }
             return _nof_points;
 	}
+#endif
 
     void grow_points();
     int add_point( const double Px, const double Py, const double *Pvars );
-    int delete_point(const double Px, const double Py );
     int get_point( const double Px, const double Py, double *Pvars );
+#if 0
+    int delete_point(const double Px, const double Py );
     bool get_xy(int index, double& x, double& y);
     bool change_point(int index, double x, double y, double* Pvars);
     void reset(void) { _nof_points = 0; }
+#endif
     int solve(void);
 
   private:	
-    double base_func( const double x1, const double y1,
-                      const double x2, const double y2 );
 
     vizGeorefInterType type;
 
@@ -171,8 +167,4 @@ class VizGeorefSpline2D
     double *u; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
     int *unused; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
     int *index; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
-	
-    double *_AA, *_Ainv;
 };
-
-
diff --git a/apps/GNUmakefile b/apps/GNUmakefile
index 80566a0..77a44ec 100644
--- a/apps/GNUmakefile
+++ b/apps/GNUmakefile
@@ -20,10 +20,15 @@ BIN_LIST += 	gdal_contour$(EXE) \
 		ogrinfo$(EXE) \
 		ogr2ogr$(EXE) \
 		ogrtindex$(EXE) \
+        ogrlineref$(EXE) \
 		testepsg$(EXE) \
 		gdalbuildvrt$(EXE)
 endif
 
+ifeq ($(HAVE_GEOS),yes)
+CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
+endif
+
 NON_DEFAULT_LIST = 	multireadtest$(EXE) \
 			dumpoverviews$(EXE) gdalwarpsimple$(EXE) gdalflattenmask$(EXE) \
 			gdaltorture$(EXE) gdal2ogr$(EXE) test_ogrsf$(EXE) \
@@ -109,6 +114,9 @@ gdal2ogr$(EXE):	gdal2ogr.$(OBJ_EXT) $(DEP_LIBS)
 ogrinfo$(EXE):	ogrinfo.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT)  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
+ogrlineref$(EXE):	ogrlineref.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT)  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+
 ogr2ogr$(EXE):	ogr2ogr.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
diff --git a/apps/commonutils.cpp b/apps/commonutils.cpp
index 7c5b7e9..4644671 100644
--- a/apps/commonutils.cpp
+++ b/apps/commonutils.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: commonutils.cpp 25416 2012-12-31 20:42:56Z rouault $
+ * $Id: commonutils.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Common utility routines
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: commonutils.cpp 25416 2012-12-31 20:42:56Z rouault $");
+CPL_CVSID("$Id: commonutils.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /*                      CheckExtensionConsistency()                     */
diff --git a/apps/commonutils.h b/apps/commonutils.h
index ff6d58e..bf62d18 100644
--- a/apps/commonutils.h
+++ b/apps/commonutils.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: commonutils.h 25416 2012-12-31 20:42:56Z rouault $
+ * $Id: commonutils.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Common utility routines
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/apps/dumpoverviews.cpp b/apps/dumpoverviews.cpp
index 7669005..0cd97dc 100644
--- a/apps/dumpoverviews.cpp
+++ b/apps/dumpoverviews.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: dumpoverviews.cpp 23484 2011-12-07 03:34:10Z warmerdam $
+ * $Id: dumpoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Dump overviews to external files.
@@ -7,6 +7,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dumpoverviews.cpp 23484 2011-12-07 03:34:10Z warmerdam $");
+CPL_CVSID("$Id: dumpoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hBand,
                       const char *pszName );
diff --git a/apps/gdal2ogr.c b/apps/gdal2ogr.c
index aa4332b..76534ef 100644
--- a/apps/gdal2ogr.c
+++ b/apps/gdal2ogr.c
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/apps/gdal_contour.cpp b/apps/gdal_contour.cpp
index f42a926..41a96ae 100644
--- a/apps/gdal_contour.cpp
+++ b/apps/gdal_contour.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_contour.cpp 25643 2013-02-12 13:50:42Z bishop $
+ * $Id: gdal_contour.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Contour Generator
  * Purpose:  Contour Generator mainline.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Applied Coherent Technology (www.actgate.com). 
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "ogr_api.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdal_contour.cpp 25643 2013-02-12 13:50:42Z bishop $");
+CPL_CVSID("$Id: gdal_contour.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
diff --git a/apps/gdal_grid.cpp b/apps/gdal_grid.cpp
index 7603dc3..c4911ab 100644
--- a/apps/gdal_grid.cpp
+++ b/apps/gdal_grid.cpp
@@ -1,1054 +1,1128 @@
-/* ****************************************************************************
- * $Id: gdal_grid.cpp 25582 2013-01-29 21:13:43Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  GDAL scattered data gridding (interpolation) tool
- * Author:   Andrey Kiselev, dron at ak4719.spb.edu
- *
- * ****************************************************************************
- * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <cstdlib>
-#include <vector>
-#include <algorithm>
-
-#include "cpl_string.h"
-#include "gdal.h"
-#include "gdal_alg.h"
-#include "ogr_spatialref.h"
-#include "ogr_api.h"
-#include "ogrsf_frmts.h"
-#include "gdalgrid.h"
-#include "commonutils.h"
-
-CPL_CVSID("$Id: gdal_grid.cpp 25582 2013-01-29 21:13:43Z rouault $");
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg = NULL)
-
-{
-    printf( 
-        "Usage: gdal_grid [--help-general] [--formats]\n"
-        "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
-        "          CInt16/CInt32/CFloat32/CFloat64}]\n"
-        "    [-of format] [-co \"NAME=VALUE\"]\n"
-        "    [-zfield field_name]\n"
-        "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
-        "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
-        "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
-        "    [-clipsrcwhere expression]\n"
-        "    [-l layername]* [-where expression] [-sql select_statement]\n"
-        "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
-        "    [-a algorithm[:parameter1=value1]*]"
-        "    [-q]\n"
-        "    <src_datasource> <dst_filename>\n"
-        "\n"
-        "Available algorithms and parameters with their's defaults:\n"
-        "    Inverse distance to a power (default)\n"
-        "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
-        "    Moving average\n"
-        "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-        "    Nearest neighbor\n"
-        "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
-        "    Various data metrics\n"
-        "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-        "        possible metrics are:\n"
-        "            minimum\n"
-        "            maximum\n"
-        "            range\n"
-        "            count\n"
-        "            average_distance\n"
-        "            average_distance_pts\n"
-        "\n");
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    GDALDestroyDriverManager();
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                          GetAlgorithmName()                          */
-/*                                                                      */
-/*      Translates algortihm code into mnemonic name.                   */
-/************************************************************************/
-
-static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
-                                      void *pOptions )
-{
-    switch ( eAlgorithm )
-    {
-        case GGA_InverseDistanceToAPower:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameInvDist );
-            printf( "Options are "
-                    "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
-                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
-                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MovingAverage:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverage );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_NearestNeighbor:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameNearest );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricMinimum:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameMinimum );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricMaximum:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameMaximum );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricRange:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameRange );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricCount:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameCount );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricAverageDistance:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistance );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricAverageDistancePts:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistancePts );
-            printf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        default:
-            printf( "Algorithm is unknown.\n" );
-            break;
-    }
-}
-
-/************************************************************************/
-/*                          ProcessGeometry()                           */
-/*                                                                      */
-/*  Extract point coordinates from the geometry reference and set the   */
-/*  Z value as requested. Test whther we are in the clipped region      */
-/*  before processing.                                                  */
-/************************************************************************/
-
-static void ProcessGeometry( OGRPoint *poGeom, OGRGeometry *poClipSrc,
-                             int iBurnField, double dfBurnValue,
-                             std::vector<double> &adfX,
-                             std::vector<double> &adfY,
-                             std::vector<double> &adfZ )
-
-{
-    if ( poClipSrc && !poGeom->Within(poClipSrc) )
-        return;
-
-    adfX.push_back( poGeom->getX() );
-    adfY.push_back( poGeom->getY() );
-    if ( iBurnField < 0 )
-        adfZ.push_back( poGeom->getZ() );
-    else
-        adfZ.push_back( dfBurnValue );
-}
-
-/************************************************************************/
-/*                            ProcessLayer()                            */
-/*                                                                      */
-/*      Process all the features in a layer selection, collecting       */
-/*      geometries and burn values.                                     */
-/************************************************************************/
-
-static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
-                          OGRGeometry *poClipSrc,
-                          GUInt32 nXSize, GUInt32 nYSize, int nBand,
-                          int& bIsXExtentSet, int& bIsYExtentSet,
-                          double& dfXMin, double& dfXMax,
-                          double& dfYMin, double& dfYMax,
-                          const char *pszBurnAttribute,
-                          GDALDataType eType,
-                          GDALGridAlgorithm eAlgorithm, void *pOptions,
-                          int bQuiet, GDALProgressFunc pfnProgress )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Get field index, and check.                                     */
-/* -------------------------------------------------------------------- */
-    int iBurnField = -1;
-
-    if ( pszBurnAttribute )
-    {
-        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
-                                           pszBurnAttribute );
-        if( iBurnField == -1 )
-        {
-            printf( "Failed to find field %s on layer %s, skipping.\n",
-                    pszBurnAttribute, 
-                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
-            return CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Collect the geometries from this layer, and build list of       */
-/*      values to be interpolated.                                      */
-/* -------------------------------------------------------------------- */
-    OGRFeature *poFeat;
-    std::vector<double> adfX, adfY, adfZ;
-
-    OGR_L_ResetReading( hSrcLayer );
-
-    while( (poFeat = (OGRFeature *)OGR_L_GetNextFeature( hSrcLayer )) != NULL )
-    {
-        OGRGeometry *poGeom = poFeat->GetGeometryRef();
-
-        if ( poGeom != NULL )
-        {
-            OGRwkbGeometryType eType = wkbFlatten( poGeom->getGeometryType() );
-            double  dfBurnValue = 0.0;
-
-            if ( iBurnField >= 0 )
-                dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
-
-            if ( eType == wkbMultiPoint )
-            {
-                int iGeom;
-                int nGeomCount = ((OGRMultiPoint *)poGeom)->getNumGeometries();
-
-                for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
-                {
-                    ProcessGeometry( (OGRPoint *)((OGRMultiPoint *)poGeom)->getGeometryRef(iGeom),
-                                     poClipSrc, iBurnField, dfBurnValue,
-                                     adfX, adfY, adfZ);
-                }
-            }
-            else if ( eType == wkbPoint )
-            {
-                ProcessGeometry( (OGRPoint *)poGeom, poClipSrc,
-                                 iBurnField, dfBurnValue, adfX, adfY, adfZ);
-            }
-        }
-
-        OGRFeature::DestroyFeature( poFeat );
-    }
-
-    if ( adfX.size() == 0 )
-    {
-        printf( "No point geometry found on layer %s, skipping.\n",
-                OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
-        return CE_None;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute grid geometry.                                          */
-/* -------------------------------------------------------------------- */
-    if ( !bIsXExtentSet || !bIsYExtentSet )
-    {
-        OGREnvelope sEnvelope;
-        OGR_L_GetExtent( hSrcLayer, &sEnvelope, TRUE );
-
-        if ( !bIsXExtentSet )
-        {
-            dfXMin = sEnvelope.MinX;
-            dfXMax = sEnvelope.MaxX;
-            bIsXExtentSet = TRUE;
-        }
-
-        if ( !bIsYExtentSet )
-        {
-            dfYMin = sEnvelope.MinY;
-            dfYMax = sEnvelope.MaxY;
-            bIsYExtentSet = TRUE;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Perform gridding.                                               */
-/* -------------------------------------------------------------------- */
-
-    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
-    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
-
-    if ( !bQuiet )
-    {
-        printf( "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
-        printf( "Grid size = (%lu %lu).\n",
-                (unsigned long)nXSize, (unsigned long)nYSize );
-        printf( "Corner coordinates = (%f %f)-(%f %f).\n",
-                dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
-                dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
-        printf( "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
-        printf( "Source point count = %lu.\n", (unsigned long)adfX.size() );
-        PrintAlgorithmAndOptions( eAlgorithm, pOptions );
-        printf("\n");
-    }
-
-    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
-
-    if (adfX.size() == 0)
-    {
-        // FIXME: Shoulda' set to nodata value instead
-        GDALFillRaster( hBand, 0.0 , 0.0 );
-        return CE_None;
-    }
-
-    GUInt32 nXOffset, nYOffset;
-    int     nBlockXSize, nBlockYSize;
-    int     nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
-
-    // Try to grow the work buffer up to 16 MB if it is smaller
-    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-    const GUInt32 nDesiredBufferSize = 16*1024*1024;
-    if( (GUInt32)nBlockXSize < nXSize && (GUInt32)nBlockYSize < nYSize &&
-        (GUInt32)nBlockXSize < nDesiredBufferSize / (nBlockYSize * nDataTypeSize) )
-    {
-        int nNewBlockXSize  = nDesiredBufferSize / (nBlockYSize * nDataTypeSize);
-        nBlockXSize = (nNewBlockXSize / nBlockXSize) * nBlockXSize;
-        if( (GUInt32)nBlockXSize > nXSize )
-            nBlockXSize = nXSize;
-    }
-    else if( (GUInt32)nBlockXSize == nXSize && (GUInt32)nBlockYSize < nYSize &&
-             (GUInt32)nBlockYSize < nDesiredBufferSize / (nXSize * nDataTypeSize) )
-    {
-        int nNewBlockYSize = nDesiredBufferSize / (nXSize * nDataTypeSize);
-        nBlockYSize = (nNewBlockYSize / nBlockYSize) * nBlockYSize;
-        if( (GUInt32)nBlockYSize > nYSize )
-            nBlockYSize = nYSize;
-    }
-    CPLDebug("GDAL_GRID", "Work buffer: %d * %d", nBlockXSize, nBlockYSize);
-
-    void    *pData =
-        VSIMalloc3( nBlockXSize, nBlockYSize, nDataTypeSize );
-    if( pData == NULL )
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate work buffer");
-        return CE_Failure;
-    }
-
-    GUInt32 nBlock = 0;
-    GUInt32 nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
-        * ((nYSize + nBlockYSize - 1) / nBlockYSize);
-
-    CPLErr eErr = CE_None;
-    for ( nYOffset = 0; nYOffset < nYSize && eErr == CE_None; nYOffset += nBlockYSize )
-    {
-        for ( nXOffset = 0; nXOffset < nXSize && eErr == CE_None; nXOffset += nBlockXSize )
-        {
-            void *pScaledProgress;
-            pScaledProgress =
-                GDALCreateScaledProgress( (double)nBlock / nBlockCount,
-                                          (double)(nBlock + 1) / nBlockCount,
-                                          pfnProgress, NULL );
-            nBlock ++;
-
-            int nXRequest = nBlockXSize;
-            if (nXOffset + nXRequest > nXSize)
-                nXRequest = nXSize - nXOffset;
-
-            int nYRequest = nBlockYSize;
-            if (nYOffset + nYRequest > nYSize)
-                nYRequest = nYSize - nYOffset;
-
-            eErr = GDALGridCreate( eAlgorithm, pOptions,
-                            adfX.size(), &(adfX[0]), &(adfY[0]), &(adfZ[0]),
-                            dfXMin + dfDeltaX * nXOffset,
-                            dfXMin + dfDeltaX * (nXOffset + nXRequest),
-                            dfYMin + dfDeltaY * nYOffset,
-                            dfYMin + dfDeltaY * (nYOffset + nYRequest),
-                            nXRequest, nYRequest, eType, pData,
-                            GDALScaledProgress, pScaledProgress );
-
-            if( eErr == CE_None )
-                eErr = GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
-                          nXRequest, nYRequest, pData,
-                          nXRequest, nYRequest, eType, 0, 0 );
-
-            GDALDestroyScaledProgress( pScaledProgress );
-        }
-    }
-
-    CPLFree( pData );
-    return eErr;
-}
-
-/************************************************************************/
-/*                            LoadGeometry()                            */
-/*                                                                      */
-/*  Read geometries from the given dataset using specified filters and  */
-/*  returns a collection of read geometries.                            */
-/************************************************************************/
-
-static OGRGeometryCollection* LoadGeometry( const char* pszDS,
-                                            const char* pszSQL,
-                                            const char* pszLyr,
-                                            const char* pszWhere )
-{
-    OGRDataSource       *poDS;
-    OGRLayer            *poLyr;
-    OGRFeature          *poFeat;
-    OGRGeometryCollection *poGeom = NULL;
-        
-    poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
-    if ( poDS == NULL )
-        return NULL;
-
-    if ( pszSQL != NULL )
-        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL ); 
-    else if ( pszLyr != NULL )
-        poLyr = poDS->GetLayerByName( pszLyr );
-    else
-        poLyr = poDS->GetLayer(0);
-        
-    if ( poLyr == NULL )
-    {
-        fprintf( stderr,
-            "FAILURE: Failed to identify source layer from datasource.\n" );
-        OGRDataSource::DestroyDataSource( poDS );
-        return NULL;
-    }
-    
-    if ( pszWhere )
-        poLyr->SetAttributeFilter( pszWhere );
-        
-    while ( (poFeat = poLyr->GetNextFeature()) != NULL )
-    {
-        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
-        if ( poSrcGeom )
-        {
-            OGRwkbGeometryType eType =
-                wkbFlatten( poSrcGeom->getGeometryType() );
-            
-            if ( poGeom == NULL )
-                poGeom = new OGRMultiPolygon();
-
-            if ( eType == wkbPolygon )
-                poGeom->addGeometry( poSrcGeom );
-            else if ( eType == wkbMultiPolygon )
-            {
-                int iGeom;
-                int nGeomCount =
-                    ((OGRMultiPolygon *)poSrcGeom)->getNumGeometries();
-
-                for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
-                {
-                    poGeom->addGeometry(
-                        ((OGRMultiPolygon *)poSrcGeom)->getGeometryRef(iGeom) );
-                }
-            }
-            else
-            {
-                fprintf( stderr, "FAILURE: Geometry not of polygon type.\n" );
-                OGRGeometryFactory::destroyGeometry( poGeom );
-                OGRFeature::DestroyFeature( poFeat );
-                if ( pszSQL != NULL )
-                    poDS->ReleaseResultSet( poLyr );
-                OGRDataSource::DestroyDataSource( poDS );
-                return NULL;
-            }
-        }
-    
-        OGRFeature::DestroyFeature( poFeat );
-    }
-    
-    if( pszSQL != NULL )
-        poDS->ReleaseResultSet( poLyr );
-    OGRDataSource::DestroyDataSource( poDS );
-    
-    return poGeom;
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv )
-{
-    GDALDriverH     hDriver;
-    const char      *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
-    int             bFormatExplicitelySet = FALSE;
-    char            **papszLayers = NULL;
-    const char      *pszBurnAttribute = NULL;
-    const char      *pszWHERE = NULL, *pszSQL = NULL;
-    GDALDataType    eOutputType = GDT_Float64;
-    char            **papszCreateOptions = NULL;
-    GUInt32         nXSize = 0, nYSize = 0;
-    double          dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
-    int             bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
-    GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
-    void            *pOptions = NULL;
-    char            *pszOutputSRS = NULL;
-    int             bQuiet = FALSE;
-    GDALProgressFunc pfnProgress = GDALTermProgress;
-    int             i;
-    OGRGeometry     *poSpatialFilter = NULL;
-    int             bClipSrc = FALSE;
-    OGRGeometry     *poClipSrc = NULL;
-    const char      *pszClipSrcDS = NULL;
-    const char      *pszClipSrcSQL = NULL;
-    const char      *pszClipSrcLayer = NULL;
-    const char      *pszClipSrcWhere = NULL;
-
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(argv[0]))
-        exit(1);
-
-    GDALAllRegister();
-    OGRRegisterAll();
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"--help") )
-            Usage();
-        else if( EQUAL(argv[i],"-of") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFormat = argv[++i];
-            bFormatExplicitelySet = TRUE;
-        }
-
-        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
-        {
-            bQuiet = TRUE;
-            pfnProgress = GDALDummyProgress;
-        }
-
-        else if( EQUAL(argv[i],"-ot") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eOutputType = (GDALDataType) iType;
-                }
-            }
-
-            if( eOutputType == GDT_Unknown )
-            {
-                Usage(CPLSPrintf("Unknown output pixel type: %s.",
-                                 argv[i + 1] ));
-            }
-            i++;
-        }
-
-        else if( EQUAL(argv[i],"-txe") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfXMin = atof(argv[++i]);
-            dfXMax = atof(argv[++i]);
-            bIsXExtentSet = TRUE;
-        }   
-
-        else if( EQUAL(argv[i],"-tye") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfYMin = atof(argv[++i]);
-            dfYMax = atof(argv[++i]);
-            bIsYExtentSet = TRUE;
-        }   
-
-        else if( EQUAL(argv[i],"-outsize") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            nXSize = atoi(argv[++i]);
-            nYSize = atoi(argv[++i]);
-        }   
-
-        else if( EQUAL(argv[i],"-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }   
-
-        else if( EQUAL(argv[i],"-zfield") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszBurnAttribute = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-where") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszWHERE = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-l") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszLayers = CSLAddString( papszLayers, argv[++i] );
-        }
-
-        else if( EQUAL(argv[i],"-sql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSQL = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-spat") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            OGRLinearRing  oRing;
-
-            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
-            oRing.addPoint( atof(argv[i+1]), atof(argv[i+4]) );
-            oRing.addPoint( atof(argv[i+3]), atof(argv[i+4]) );
-            oRing.addPoint( atof(argv[i+3]), atof(argv[i+2]) );
-            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
-
-            poSpatialFilter = new OGRPolygon();
-            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
-            i += 4;
-        }
-
-        else if ( EQUAL(argv[i],"-clipsrc") )
-        {
-            if (i + 1 >= argc)
-                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", argv[i]));
-
-            bClipSrc = TRUE;
-            errno = 0;
-            const double unused = strtod( argv[i + 1], NULL );    // XXX: is it a number or not?
-            if ( errno != 0
-                 && argv[i + 2] != NULL
-                 && argv[i + 3] != NULL
-                 && argv[i + 4] != NULL)
-            {
-                OGRLinearRing  oRing;
-
-                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
-                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 4]) );
-                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 4]) );
-                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 2]) );
-                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
-
-                poClipSrc = new OGRPolygon();
-                ((OGRPolygon *) poClipSrc)->addRing( &oRing );
-                i += 4;
-
-                (void)unused;
-            }
-            else if (EQUALN(argv[i + 1], "POLYGON", 7)
-                     || EQUALN(argv[i + 1], "MULTIPOLYGON", 12))
-            {
-                OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc);
-                if ( poClipSrc == NULL )
-                {
-                    Usage("Invalid geometry. "
-                             "Must be a valid POLYGON or MULTIPOLYGON WKT.");
-                }
-                i++;
-            }
-            else if (EQUAL(argv[i + 1], "spat_extent") )
-            {
-                i++;
-            }
-            else
-            {
-                pszClipSrcDS = argv[i + 1];
-                i++;
-            }
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrcsql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcSQL = argv[i + 1];
-            i++;
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrclayer") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcLayer = argv[i + 1];
-            i++;
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrcwhere") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcWhere = argv[i + 1];
-            i++;
-        }
-
-        else if( EQUAL(argv[i],"-a_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            OGRSpatialReference oOutputSRS;
-
-            if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         argv[i+1] );
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-
-            oOutputSRS.exportToWkt( &pszOutputSRS );
-            i++;
-        }   
-
-        else if( EQUAL(argv[i],"-a") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if ( ParseAlgorithmAndOptions( argv[++i], &eAlgorithm, &pOptions )
-                 != CE_None )
-            {
-                fprintf( stderr,
-                         "Failed to process algorithm name and parameters.\n" );
-                exit( 1 );
-            }
-        }
-
-        else if( argv[i][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
-        }
-
-        else if( pszSource == NULL )
-        {
-            pszSource = argv[i];
-        }
-
-        else if( pszDest == NULL )
-        {
-            pszDest = argv[i];
-        }
-
-        else
-        {
-            Usage("Too many command options.");
-        }
-    }
-
-    if( pszSource == NULL )
-    {
-        Usage("Source datasource is not specified.");
-    }
-    if( pszDest == NULL )
-    {
-        Usage("Target dataset is not specified.");
-    }
-    if( pszSQL == NULL && papszLayers == NULL )
-    {
-        Usage("Neither -sql nor -l are specified.");
-    }
-    
-    if ( bClipSrc && pszClipSrcDS != NULL )
-    {
-        poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL,
-                                  pszClipSrcLayer, pszClipSrcWhere );
-        if ( poClipSrc == NULL )
-        {
-            Usage("Cannot load source clip geometry.");
-        }
-    }
-    else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter )
-    {
-        Usage("-clipsrc must be used with -spat option or \n"
-                 "a bounding box, WKT string or datasource must be "
-                 "specified.");
-    }
-
-    if ( poSpatialFilter )
-    {
-        if ( poClipSrc )
-        {
-            OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc );
-
-            if ( poTemp )
-            {
-                OGRGeometryFactory::destroyGeometry( poSpatialFilter );
-                poSpatialFilter = poTemp;
-            }
-
-            OGRGeometryFactory::destroyGeometry( poClipSrc );
-            poClipSrc = NULL;
-        }
-    }
-    else
-    {
-        if ( poClipSrc )
-        {
-            poSpatialFilter = poClipSrc;
-            poClipSrc = NULL;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDriverByName( pszFormat );
-    if( hDriver == NULL )
-    {
-        int	iDr;
-        
-        fprintf( stderr,
-                 "FAILURE: Output driver `%s' not recognised.\n", pszFormat );
-        fprintf( stderr,
-        "The following format drivers are configured and support output:\n" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
-                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
-                                        NULL ) != NULL )
-            {
-                fprintf( stderr, "  %s: %s\n",
-                         GDALGetDriverShortName( hDriver  ),
-                         GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        printf( "\n" );
-        Usage();
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Open input datasource.                                          */
-/* -------------------------------------------------------------------- */
-    OGRDataSourceH hSrcDS;
-
-    hSrcDS = OGROpen( pszSource, FALSE, NULL );
-    if( hSrcDS == NULL )
-    {
-        fprintf( stderr, "Unable to open input datasource \"%s\".\n",
-                 pszSource );
-        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
-        exit( 3 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create target raster file.                                      */
-/* -------------------------------------------------------------------- */
-    GDALDatasetH    hDstDS;
-    int             nLayerCount = CSLCount(papszLayers);
-    int             nBands = nLayerCount;
-
-    if ( pszSQL )
-        nBands++;
-
-    // FIXME
-    if ( nXSize == 0 )
-        nXSize = 256;
-    if ( nYSize == 0 )
-        nYSize = 256;
-
-    if (!bQuiet && !bFormatExplicitelySet)
-        CheckExtensionConsistency(pszDest, pszFormat);
-
-    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
-                         eOutputType, papszCreateOptions );
-    if ( hDstDS == NULL )
-    {
-        fprintf( stderr, "Unable to create target dataset \"%s\".\n",
-                 pszDest );
-        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
-        exit( 3 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If algorithm was not specified assigh default one.              */
-/* -------------------------------------------------------------------- */
-    if ( !pOptions )
-        ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
-
-/* -------------------------------------------------------------------- */
-/*      Process SQL request.                                            */
-/* -------------------------------------------------------------------- */
-    if( pszSQL != NULL )
-    {
-        OGRLayerH hLayer;
-
-        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL,
-                                    (OGRGeometryH)poSpatialFilter, NULL ); 
-        if( hLayer != NULL )
-        {
-            // Custom layer will be rasterized in the first band.
-            ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1,
-                          bIsXExtentSet, bIsYExtentSet,
-                          dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
-                          eOutputType, eAlgorithm, pOptions,
-                          bQuiet, pfnProgress );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process each layer.                                             */
-/* -------------------------------------------------------------------- */
-    for( i = 0; i < nLayerCount; i++ )
-    {
-        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
-        if( hLayer == NULL )
-        {
-            fprintf( stderr, "Unable to find layer \"%s\", skipping.\n", 
-                     papszLayers[i] );
-            continue;
-        }
-
-        if( pszWHERE )
-        {
-            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
-                break;
-        }
-
-        if ( poSpatialFilter != NULL )
-            OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter );
-
-        // Fetch the first meaningful SRS definition
-        if ( !pszOutputSRS )
-        {
-            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
-            if ( hSRS )
-                OSRExportToWkt( hSRS, &pszOutputSRS );
-        }
-
-        ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize,
-                      i + 1 + nBands - nLayerCount,
-                      bIsXExtentSet, bIsYExtentSet,
-                      dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
-                      eOutputType, eAlgorithm, pOptions,
-                      bQuiet, pfnProgress );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Apply geotransformation matrix.                                 */
-/* -------------------------------------------------------------------- */
-    double  adfGeoTransform[6];
-    adfGeoTransform[0] = dfXMin;
-    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = dfYMin;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
-    GDALSetGeoTransform( hDstDS, adfGeoTransform );
-
-/* -------------------------------------------------------------------- */
-/*      Apply SRS definition if set.                                    */
-/* -------------------------------------------------------------------- */
-    if ( pszOutputSRS )
-    {
-        GDALSetProjection( hDstDS, pszOutputSRS );
-        CPLFree( pszOutputSRS );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    OGR_DS_Destroy( hSrcDS );
-    GDALClose( hDstDS );
-    OGRGeometryFactory::destroyGeometry( poSpatialFilter );
-
-    CPLFree( pOptions );
-    CSLDestroy( papszCreateOptions );
-    CSLDestroy( argv );
-    CSLDestroy( papszLayers );
-
-    OGRCleanupAll();
-
-    GDALDestroyDriverManager();
- 
-    return 0;
-}
-
+/* ****************************************************************************
+ * $Id: gdal_grid.cpp 27128 2014-04-05 12:59:03Z rouault $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL scattered data gridding (interpolation) tool
+ * Author:   Andrey Kiselev, dron at ak4719.spb.edu
+ *
+ * ****************************************************************************
+ * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+#include "gdalgrid.h"
+#include "commonutils.h"
+
+CPL_CVSID("$Id: gdal_grid.cpp 27128 2014-04-05 12:59:03Z rouault $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf( 
+        "Usage: gdal_grid [--help-general] [--formats]\n"
+        "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+        "          CInt16/CInt32/CFloat32/CFloat64}]\n"
+        "    [-of format] [-co \"NAME=VALUE\"]\n"
+        "    [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]\n"
+        "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
+        "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
+        "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
+        "    [-clipsrcwhere expression]\n"
+        "    [-l layername]* [-where expression] [-sql select_statement]\n"
+        "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
+        "    [-a algorithm[:parameter1=value1]*]"
+        "    [-q]\n"
+        "    <src_datasource> <dst_filename>\n"
+        "\n"
+        "Available algorithms and parameters with their's defaults:\n"
+        "    Inverse distance to a power (default)\n"
+        "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
+        "    Moving average\n"
+        "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "    Nearest neighbor\n"
+        "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
+        "    Various data metrics\n"
+        "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "        possible metrics are:\n"
+        "            minimum\n"
+        "            maximum\n"
+        "            range\n"
+        "            count\n"
+        "            average_distance\n"
+        "            average_distance_pts\n"
+        "\n");
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    GDALDestroyDriverManager();
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                          GetAlgorithmName()                          */
+/*                                                                      */
+/*      Translates algortihm code into mnemonic name.                   */
+/************************************************************************/
+
+static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
+                                      void *pOptions )
+{
+    switch ( eAlgorithm )
+    {
+        case GGA_InverseDistanceToAPower:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameInvDist );
+            printf( "Options are "
+                    "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
+                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MovingAverage:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverage );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_NearestNeighbor:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameNearest );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMinimum:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameMinimum );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMaximum:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameMaximum );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricRange:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameRange );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricCount:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameCount );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricAverageDistance:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistance );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricAverageDistancePts:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistancePts );
+            printf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        default:
+            printf( "Algorithm is unknown.\n" );
+            break;
+    }
+}
+
+/************************************************************************/
+/*                          ProcessGeometry()                           */
+/*                                                                      */
+/*  Extract point coordinates from the geometry reference and set the   */
+/*  Z value as requested. Test whther we are in the clipped region      */
+/*  before processing.                                                  */
+/************************************************************************/
+
+static void ProcessGeometry( OGRPoint *poGeom, OGRGeometry *poClipSrc,
+                             int iBurnField, double dfBurnValue,
+                             const double dfIncreaseBurnValue,
+                             const double dfMultiplyBurnValue,
+                             std::vector<double> &adfX,
+                             std::vector<double> &adfY,
+                             std::vector<double> &adfZ )
+
+{
+    if ( poClipSrc && !poGeom->Within(poClipSrc) )
+        return;
+
+    adfX.push_back( poGeom->getX() );
+    adfY.push_back( poGeom->getY() );
+    if ( iBurnField < 0 )
+        adfZ.push_back(  (poGeom->getZ() + dfIncreaseBurnValue) * dfMultiplyBurnValue  );
+    else
+        adfZ.push_back( (dfBurnValue + dfIncreaseBurnValue) * dfMultiplyBurnValue );
+}
+
+/************************************************************************/
+/*                       ProcessCommonGeometry()                        */
+/*                                                                      */
+/*  Process recursivelly geometry and extract points                    */
+/************************************************************************/
+
+static void ProcessCommonGeometry(OGRGeometry* poGeom, OGRGeometry *poClipSrc,
+                                int iBurnField, double dfBurnValue,
+                                const double dfIncreaseBurnValue,
+                                const double dfMultiplyBurnValue,
+                                std::vector<double> &adfX,
+                                std::vector<double> &adfY,
+                                std::vector<double> &adfZ)
+{
+    if (NULL == poGeom)
+        return;
+
+    OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch (eType)
+    {
+    case wkbPoint:
+        return ProcessGeometry((OGRPoint *)poGeom, poClipSrc,
+            iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+    case wkbLinearRing:
+    case wkbLineString:
+        {
+            OGRLineString *poLS = (OGRLineString*)poGeom;
+            OGRPoint point;
+            for (int pointIndex = 0; pointIndex < poLS->getNumPoints(); pointIndex++)
+            {
+                poLS->getPoint(pointIndex, &point);
+                ProcessCommonGeometry((OGRGeometry*)&point, poClipSrc,
+                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+            }
+        }
+        break;
+    case wkbPolygon:
+        {
+            int nRings(0);
+            OGRPolygon* poPoly = (OGRPolygon*)poGeom;
+            OGRLinearRing* poRing = poPoly->getExteriorRing();
+            ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
+                iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+
+            nRings = poPoly->getNumInteriorRings();
+            if (nRings > 0)
+            {
+                for (int ir = 0; ir < nRings; ++ir)
+                {
+                    OGRLinearRing* poRing = poPoly->getInteriorRing(ir);
+                    ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
+                        iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+                }
+            }
+        }
+        break;
+    case wkbMultiPoint:
+    case wkbMultiPolygon:
+    case wkbMultiLineString:
+    case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* pOGRGeometryCollection = (OGRGeometryCollection*)poGeom;
+            for (int i = 0; i < pOGRGeometryCollection->getNumGeometries(); ++i)
+            {
+                ProcessCommonGeometry(pOGRGeometryCollection->getGeometryRef(i), poClipSrc,
+                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+            }
+        }
+        break;
+    case wkbUnknown:
+    case wkbNone:
+    default:
+        break;
+    }
+}
+
+/************************************************************************/
+/*                            ProcessLayer()                            */
+/*                                                                      */
+/*      Process all the features in a layer selection, collecting       */
+/*      geometries and burn values.                                     */
+/************************************************************************/
+
+static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
+                          OGRGeometry *poClipSrc,
+                          GUInt32 nXSize, GUInt32 nYSize, int nBand,
+                          int& bIsXExtentSet, int& bIsYExtentSet,
+                          double& dfXMin, double& dfXMax,
+                          double& dfYMin, double& dfYMax,
+                          const char *pszBurnAttribute,
+                          const double dfIncreaseBurnValue,
+                          const double dfMultiplyBurnValue,
+                          GDALDataType eType,
+                          GDALGridAlgorithm eAlgorithm, void *pOptions,
+                          int bQuiet, GDALProgressFunc pfnProgress )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Get field index, and check.                                     */
+/* -------------------------------------------------------------------- */
+    int iBurnField = -1;
+
+    if ( pszBurnAttribute )
+    {
+        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
+                                           pszBurnAttribute );
+        if( iBurnField == -1 )
+        {
+            printf( "Failed to find field %s on layer %s, skipping.\n",
+                    pszBurnAttribute, 
+                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+            return CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      values to be interpolated.                                      */
+/* -------------------------------------------------------------------- */
+    OGRFeature *poFeat;
+    std::vector<double> adfX, adfY, adfZ;
+
+    OGR_L_ResetReading( hSrcLayer );
+
+    while( (poFeat = (OGRFeature *)OGR_L_GetNextFeature( hSrcLayer )) != NULL )
+    {
+        OGRGeometry *poGeom = poFeat->GetGeometryRef();
+        double  dfBurnValue = 0.0;
+
+        if ( iBurnField >= 0 )
+            dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
+
+        ProcessCommonGeometry(poGeom, poClipSrc, iBurnField, dfBurnValue,
+            dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+
+        OGRFeature::DestroyFeature( poFeat );
+    }
+
+    if ( adfX.size() == 0 )
+    {
+        printf( "No point geometry found on layer %s, skipping.\n",
+                OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+        return CE_None;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute grid geometry.                                          */
+/* -------------------------------------------------------------------- */
+    if ( !bIsXExtentSet || !bIsYExtentSet )
+    {
+        OGREnvelope sEnvelope;
+        OGR_L_GetExtent( hSrcLayer, &sEnvelope, TRUE );
+
+        if ( !bIsXExtentSet )
+        {
+            dfXMin = sEnvelope.MinX;
+            dfXMax = sEnvelope.MaxX;
+            bIsXExtentSet = TRUE;
+        }
+
+        if ( !bIsYExtentSet )
+        {
+            dfYMin = sEnvelope.MinY;
+            dfYMax = sEnvelope.MaxY;
+            bIsYExtentSet = TRUE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Perform gridding.                                               */
+/* -------------------------------------------------------------------- */
+
+    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
+    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+
+    if ( !bQuiet )
+    {
+        printf( "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
+        printf( "Grid size = (%lu %lu).\n",
+                (unsigned long)nXSize, (unsigned long)nYSize );
+        printf( "Corner coordinates = (%f %f)-(%f %f).\n",
+                dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
+                dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
+        printf( "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
+        printf( "Source point count = %lu.\n", (unsigned long)adfX.size() );
+        PrintAlgorithmAndOptions( eAlgorithm, pOptions );
+        printf("\n");
+    }
+
+    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
+
+    if (adfX.size() == 0)
+    {
+        // FIXME: Shoulda' set to nodata value instead
+        GDALFillRaster( hBand, 0.0 , 0.0 );
+        return CE_None;
+    }
+
+    GUInt32 nXOffset, nYOffset;
+    int     nBlockXSize, nBlockYSize;
+    int     nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
+
+    // Try to grow the work buffer up to 16 MB if it is smaller
+    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+    const GUInt32 nDesiredBufferSize = 16*1024*1024;
+    if( (GUInt32)nBlockXSize < nXSize && (GUInt32)nBlockYSize < nYSize &&
+        (GUInt32)nBlockXSize < nDesiredBufferSize / (nBlockYSize * nDataTypeSize) )
+    {
+        int nNewBlockXSize  = nDesiredBufferSize / (nBlockYSize * nDataTypeSize);
+        nBlockXSize = (nNewBlockXSize / nBlockXSize) * nBlockXSize;
+        if( (GUInt32)nBlockXSize > nXSize )
+            nBlockXSize = nXSize;
+    }
+    else if( (GUInt32)nBlockXSize == nXSize && (GUInt32)nBlockYSize < nYSize &&
+             (GUInt32)nBlockYSize < nDesiredBufferSize / (nXSize * nDataTypeSize) )
+    {
+        int nNewBlockYSize = nDesiredBufferSize / (nXSize * nDataTypeSize);
+        nBlockYSize = (nNewBlockYSize / nBlockYSize) * nBlockYSize;
+        if( (GUInt32)nBlockYSize > nYSize )
+            nBlockYSize = nYSize;
+    }
+    CPLDebug("GDAL_GRID", "Work buffer: %d * %d", nBlockXSize, nBlockYSize);
+
+    void    *pData =
+        VSIMalloc3( nBlockXSize, nBlockYSize, nDataTypeSize );
+    if( pData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate work buffer");
+        return CE_Failure;
+    }
+
+    GUInt32 nBlock = 0;
+    GUInt32 nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
+        * ((nYSize + nBlockYSize - 1) / nBlockYSize);
+
+    CPLErr eErr = CE_None;
+    for ( nYOffset = 0; nYOffset < nYSize && eErr == CE_None; nYOffset += nBlockYSize )
+    {
+        for ( nXOffset = 0; nXOffset < nXSize && eErr == CE_None; nXOffset += nBlockXSize )
+        {
+            void *pScaledProgress;
+            pScaledProgress =
+                GDALCreateScaledProgress( (double)nBlock / nBlockCount,
+                                          (double)(nBlock + 1) / nBlockCount,
+                                          pfnProgress, NULL );
+            nBlock ++;
+
+            int nXRequest = nBlockXSize;
+            if (nXOffset + nXRequest > nXSize)
+                nXRequest = nXSize - nXOffset;
+
+            int nYRequest = nBlockYSize;
+            if (nYOffset + nYRequest > nYSize)
+                nYRequest = nYSize - nYOffset;
+
+            eErr = GDALGridCreate( eAlgorithm, pOptions,
+                            adfX.size(), &(adfX[0]), &(adfY[0]), &(adfZ[0]),
+                            dfXMin + dfDeltaX * nXOffset,
+                            dfXMin + dfDeltaX * (nXOffset + nXRequest),
+                            dfYMin + dfDeltaY * nYOffset,
+                            dfYMin + dfDeltaY * (nYOffset + nYRequest),
+                            nXRequest, nYRequest, eType, pData,
+                            GDALScaledProgress, pScaledProgress );
+
+            if( eErr == CE_None )
+                eErr = GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
+                          nXRequest, nYRequest, pData,
+                          nXRequest, nYRequest, eType, 0, 0 );
+
+            GDALDestroyScaledProgress( pScaledProgress );
+        }
+    }
+
+    CPLFree( pData );
+    return eErr;
+}
+
+/************************************************************************/
+/*                            LoadGeometry()                            */
+/*                                                                      */
+/*  Read geometries from the given dataset using specified filters and  */
+/*  returns a collection of read geometries.                            */
+/************************************************************************/
+
+static OGRGeometryCollection* LoadGeometry( const char* pszDS,
+                                            const char* pszSQL,
+                                            const char* pszLyr,
+                                            const char* pszWhere )
+{
+    OGRDataSource       *poDS;
+    OGRLayer            *poLyr;
+    OGRFeature          *poFeat;
+    OGRGeometryCollection *poGeom = NULL;
+        
+    poDS = OGRSFDriverRegistrar::Open( pszDS, FALSE );
+    if ( poDS == NULL )
+        return NULL;
+
+    if ( pszSQL != NULL )
+        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL ); 
+    else if ( pszLyr != NULL )
+        poLyr = poDS->GetLayerByName( pszLyr );
+    else
+        poLyr = poDS->GetLayer(0);
+        
+    if ( poLyr == NULL )
+    {
+        fprintf( stderr,
+            "FAILURE: Failed to identify source layer from datasource.\n" );
+        OGRDataSource::DestroyDataSource( poDS );
+        return NULL;
+    }
+    
+    if ( pszWhere )
+        poLyr->SetAttributeFilter( pszWhere );
+        
+    while ( (poFeat = poLyr->GetNextFeature()) != NULL )
+    {
+        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
+        if ( poSrcGeom )
+        {
+            OGRwkbGeometryType eType =
+                wkbFlatten( poSrcGeom->getGeometryType() );
+            
+            if ( poGeom == NULL )
+                poGeom = new OGRMultiPolygon();
+
+            if ( eType == wkbPolygon )
+                poGeom->addGeometry( poSrcGeom );
+            else if ( eType == wkbMultiPolygon )
+            {
+                int iGeom;
+                int nGeomCount =
+                    ((OGRMultiPolygon *)poSrcGeom)->getNumGeometries();
+
+                for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+                {
+                    poGeom->addGeometry(
+                        ((OGRMultiPolygon *)poSrcGeom)->getGeometryRef(iGeom) );
+                }
+            }
+            else
+            {
+                fprintf( stderr, "FAILURE: Geometry not of polygon type.\n" );
+                OGRGeometryFactory::destroyGeometry( poGeom );
+                OGRFeature::DestroyFeature( poFeat );
+                if ( pszSQL != NULL )
+                    poDS->ReleaseResultSet( poLyr );
+                OGRDataSource::DestroyDataSource( poDS );
+                return NULL;
+            }
+        }
+    
+        OGRFeature::DestroyFeature( poFeat );
+    }
+    
+    if( pszSQL != NULL )
+        poDS->ReleaseResultSet( poLyr );
+    OGRDataSource::DestroyDataSource( poDS );
+    
+    return poGeom;
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (i + nExtraArg >= argc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+
+int main( int argc, char ** argv )
+{
+    GDALDriverH     hDriver;
+    const char      *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    int             bFormatExplicitelySet = FALSE;
+    char            **papszLayers = NULL;
+    const char      *pszBurnAttribute = NULL;
+    double          dfIncreaseBurnValue = 0.0;
+    double          dfMultiplyBurnValue = 1.0;
+    const char      *pszWHERE = NULL, *pszSQL = NULL;
+    GDALDataType    eOutputType = GDT_Float64;
+    char            **papszCreateOptions = NULL;
+    GUInt32         nXSize = 0, nYSize = 0;
+    double          dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
+    int             bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
+    GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
+    void            *pOptions = NULL;
+    char            *pszOutputSRS = NULL;
+    int             bQuiet = FALSE;
+    GDALProgressFunc pfnProgress = GDALTermProgress;
+    int             i;
+    OGRGeometry     *poSpatialFilter = NULL;
+    int             bClipSrc = FALSE;
+    OGRGeometry     *poClipSrc = NULL;
+    const char      *pszClipSrcDS = NULL;
+    const char      *pszClipSrcSQL = NULL;
+    const char      *pszClipSrcLayer = NULL;
+    const char      *pszClipSrcWhere = NULL;
+
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    GDALAllRegister();
+    OGRRegisterAll();
+
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for( i = 1; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+            Usage();
+        else if( EQUAL(argv[i],"-of") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
+        }
+
+        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
+        {
+            bQuiet = TRUE;
+            pfnProgress = GDALDummyProgress;
+        }
+
+        else if( EQUAL(argv[i],"-ot") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            int	iType;
+            
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             argv[i+1]) )
+                {
+                    eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( eOutputType == GDT_Unknown )
+            {
+                Usage(CPLSPrintf("Unknown output pixel type: %s.",
+                                 argv[i + 1] ));
+            }
+            i++;
+        }
+
+        else if( EQUAL(argv[i],"-txe") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
+            dfXMin = atof(argv[++i]);
+            dfXMax = atof(argv[++i]);
+            bIsXExtentSet = TRUE;
+        }   
+
+        else if( EQUAL(argv[i],"-tye") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
+            dfYMin = atof(argv[++i]);
+            dfYMax = atof(argv[++i]);
+            bIsYExtentSet = TRUE;
+        }   
+
+        else if( EQUAL(argv[i],"-outsize") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
+            nXSize = atoi(argv[++i]);
+            nYSize = atoi(argv[++i]);
+        }   
+
+        else if( EQUAL(argv[i],"-co") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
+        }   
+
+        else if( EQUAL(argv[i],"-zfield") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszBurnAttribute = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-z_increase") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfIncreaseBurnValue = atof(argv[++i]);
+        }
+
+        else if( EQUAL(argv[i],"-z_multiply") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfMultiplyBurnValue = atof(argv[++i]);
+        }
+
+        else if( EQUAL(argv[i],"-where") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszWHERE = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-l") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszLayers = CSLAddString( papszLayers, argv[++i] );
+        }
+
+        else if( EQUAL(argv[i],"-sql") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszSQL = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-spat") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
+            OGRLinearRing  oRing;
+
+            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
+            oRing.addPoint( atof(argv[i+1]), atof(argv[i+4]) );
+            oRing.addPoint( atof(argv[i+3]), atof(argv[i+4]) );
+            oRing.addPoint( atof(argv[i+3]), atof(argv[i+2]) );
+            oRing.addPoint( atof(argv[i+1]), atof(argv[i+2]) );
+
+            poSpatialFilter = new OGRPolygon();
+            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
+            i += 4;
+        }
+
+        else if ( EQUAL(argv[i],"-clipsrc") )
+        {
+            if (i + 1 >= argc)
+                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", argv[i]));
+
+            bClipSrc = TRUE;
+            errno = 0;
+            const double unused = strtod( argv[i + 1], NULL );    // XXX: is it a number or not?
+            if ( errno != 0
+                 && argv[i + 2] != NULL
+                 && argv[i + 3] != NULL
+                 && argv[i + 4] != NULL)
+            {
+                OGRLinearRing  oRing;
+
+                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
+                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 4]) );
+                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 4]) );
+                oRing.addPoint( atof(argv[i + 3]), atof(argv[i + 2]) );
+                oRing.addPoint( atof(argv[i + 1]), atof(argv[i + 2]) );
+
+                poClipSrc = new OGRPolygon();
+                ((OGRPolygon *) poClipSrc)->addRing( &oRing );
+                i += 4;
+
+                (void)unused;
+            }
+            else if (EQUALN(argv[i + 1], "POLYGON", 7)
+                     || EQUALN(argv[i + 1], "MULTIPOLYGON", 12))
+            {
+                OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc);
+                if ( poClipSrc == NULL )
+                {
+                    Usage("Invalid geometry. "
+                             "Must be a valid POLYGON or MULTIPOLYGON WKT.");
+                }
+                i++;
+            }
+            else if (EQUAL(argv[i + 1], "spat_extent") )
+            {
+                i++;
+            }
+            else
+            {
+                pszClipSrcDS = argv[i + 1];
+                i++;
+            }
+        }
+
+        else if ( EQUAL(argv[i], "-clipsrcsql") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszClipSrcSQL = argv[i + 1];
+            i++;
+        }
+
+        else if ( EQUAL(argv[i], "-clipsrclayer") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszClipSrcLayer = argv[i + 1];
+            i++;
+        }
+
+        else if ( EQUAL(argv[i], "-clipsrcwhere") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszClipSrcWhere = argv[i + 1];
+            i++;
+        }
+
+        else if( EQUAL(argv[i],"-a_srs") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            OGRSpatialReference oOutputSRS;
+
+            if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
+            {
+                fprintf( stderr, "Failed to process SRS definition: %s\n", 
+                         argv[i+1] );
+                GDALDestroyDriverManager();
+                exit( 1 );
+            }
+
+            oOutputSRS.exportToWkt( &pszOutputSRS );
+            i++;
+        }   
+
+        else if( EQUAL(argv[i],"-a") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            if ( ParseAlgorithmAndOptions( argv[++i], &eAlgorithm, &pOptions )
+                 != CE_None )
+            {
+                fprintf( stderr,
+                         "Failed to process algorithm name and parameters.\n" );
+                exit( 1 );
+            }
+        }
+
+        else if( argv[i][0] == '-' )
+        {
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
+        }
+
+        else if( pszSource == NULL )
+        {
+            pszSource = argv[i];
+        }
+
+        else if( pszDest == NULL )
+        {
+            pszDest = argv[i];
+        }
+
+        else
+        {
+            Usage("Too many command options.");
+        }
+    }
+
+    if( pszSource == NULL )
+    {
+        Usage("Source datasource is not specified.");
+    }
+    if( pszDest == NULL )
+    {
+        Usage("Target dataset is not specified.");
+    }
+    if( pszSQL == NULL && papszLayers == NULL )
+    {
+        Usage("Neither -sql nor -l are specified.");
+    }
+    
+    if ( bClipSrc && pszClipSrcDS != NULL )
+    {
+        poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL,
+                                  pszClipSrcLayer, pszClipSrcWhere );
+        if ( poClipSrc == NULL )
+        {
+            Usage("Cannot load source clip geometry.");
+        }
+    }
+    else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter )
+    {
+        Usage("-clipsrc must be used with -spat option or \n"
+                 "a bounding box, WKT string or datasource must be "
+                 "specified.");
+    }
+
+    if ( poSpatialFilter )
+    {
+        if ( poClipSrc )
+        {
+            OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc );
+
+            if ( poTemp )
+            {
+                OGRGeometryFactory::destroyGeometry( poSpatialFilter );
+                poSpatialFilter = poTemp;
+            }
+
+            OGRGeometryFactory::destroyGeometry( poClipSrc );
+            poClipSrc = NULL;
+        }
+    }
+    else
+    {
+        if ( poClipSrc )
+        {
+            poSpatialFilter = poClipSrc;
+            poClipSrc = NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL )
+    {
+        int	iDr;
+        
+        fprintf( stderr,
+                 "FAILURE: Output driver `%s' not recognised.\n", pszFormat );
+        fprintf( stderr,
+        "The following format drivers are configured and support output:\n" );
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
+                                        NULL ) != NULL )
+            {
+                fprintf( stderr, "  %s: %s\n",
+                         GDALGetDriverShortName( hDriver  ),
+                         GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        printf( "\n" );
+        Usage();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open input datasource.                                          */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hSrcDS;
+
+    hSrcDS = OGROpen( pszSource, FALSE, NULL );
+    if( hSrcDS == NULL )
+    {
+        fprintf( stderr, "Unable to open input datasource \"%s\".\n",
+                 pszSource );
+        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
+        exit( 3 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create target raster file.                                      */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH    hDstDS;
+    int             nLayerCount = CSLCount(papszLayers);
+    int             nBands = nLayerCount;
+
+    if ( pszSQL )
+        nBands++;
+
+    // FIXME
+    if ( nXSize == 0 )
+        nXSize = 256;
+    if ( nYSize == 0 )
+        nYSize = 256;
+
+    if (!bQuiet && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDest, pszFormat);
+
+    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
+                         eOutputType, papszCreateOptions );
+    if ( hDstDS == NULL )
+    {
+        fprintf( stderr, "Unable to create target dataset \"%s\".\n",
+                 pszDest );
+        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
+        exit( 3 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If algorithm was not specified assigh default one.              */
+/* -------------------------------------------------------------------- */
+    if ( !pOptions )
+        ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
+
+/* -------------------------------------------------------------------- */
+/*      Process SQL request.                                            */
+/* -------------------------------------------------------------------- */
+    if( pszSQL != NULL )
+    {
+        OGRLayerH hLayer;
+
+        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL,
+                                    (OGRGeometryH)poSpatialFilter, NULL ); 
+        if( hLayer != NULL )
+        {
+            // Custom layer will be rasterized in the first band.
+            ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1,
+                          bIsXExtentSet, bIsYExtentSet,
+                          dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
+                          dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
+                          bQuiet, pfnProgress );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each layer.                                             */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < nLayerCount; i++ )
+    {
+        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i]);
+        if( hLayer == NULL )
+        {
+            fprintf( stderr, "Unable to find layer \"%s\", skipping.\n", 
+                     papszLayers[i] );
+            continue;
+        }
+
+        if( pszWHERE )
+        {
+            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
+                break;
+        }
+
+        if ( poSpatialFilter != NULL )
+            OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter );
+
+        // Fetch the first meaningful SRS definition
+        if ( !pszOutputSRS )
+        {
+            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
+            if ( hSRS )
+                OSRExportToWkt( hSRS, &pszOutputSRS );
+        }
+
+        ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize,
+                      i + 1 + nBands - nLayerCount,
+                      bIsXExtentSet, bIsYExtentSet,
+                      dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
+                      dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
+                      bQuiet, pfnProgress );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Apply geotransformation matrix.                                 */
+/* -------------------------------------------------------------------- */
+    double  adfGeoTransform[6];
+    adfGeoTransform[0] = dfXMin;
+    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = dfYMin;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
+    GDALSetGeoTransform( hDstDS, adfGeoTransform );
+
+/* -------------------------------------------------------------------- */
+/*      Apply SRS definition if set.                                    */
+/* -------------------------------------------------------------------- */
+    if ( pszOutputSRS )
+    {
+        GDALSetProjection( hDstDS, pszOutputSRS );
+        CPLFree( pszOutputSRS );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    OGR_DS_Destroy( hSrcDS );
+    GDALClose( hDstDS );
+    OGRGeometryFactory::destroyGeometry( poSpatialFilter );
+
+    CPLFree( pOptions );
+    CSLDestroy( papszCreateOptions );
+    CSLDestroy( argv );
+    CSLDestroy( papszLayers );
+
+    OGRCleanupAll();
+
+    GDALDestroyDriverManager();
+ 
+    return 0;
+}
+
diff --git a/apps/gdal_rasterize.cpp b/apps/gdal_rasterize.cpp
index 9882186..263861c 100644
--- a/apps/gdal_rasterize.cpp
+++ b/apps/gdal_rasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rasterize.cpp 24682 2012-07-20 15:14:28Z rouault $
+ * $Id: gdal_rasterize.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Rasterize OGR shapes into a GDAL raster.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "commonutils.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdal_rasterize.cpp 24682 2012-07-20 15:14:28Z rouault $");
+CPL_CVSID("$Id: gdal_rasterize.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -755,7 +756,7 @@ int main( int argc, char ** argv )
     {
         if( dfXRes == 0 && dfYRes == 0 && nXSize == 0 && nYSize == 0 )
         {
-            fprintf( stderr, "'-tr xres yes' or '-ts xsize ysize' is required.\n\n" );
+            fprintf( stderr, "'-tr xres yres' or '-ts xsize ysize' is required.\n\n" );
             Usage();
         }
     
diff --git a/apps/gdal_translate.cpp b/apps/gdal_translate.cpp
index bed36c0..4acebd9 100644
--- a/apps/gdal_translate.cpp
+++ b/apps/gdal_translate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_translate.cpp 26091 2013-06-18 19:24:25Z rouault $
+ * $Id: gdal_translate.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2002, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "vrt/vrtdataset.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdal_translate.cpp 26091 2013-06-18 19:24:25Z rouault $");
+CPL_CVSID("$Id: gdal_translate.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int ArgIsNumeric( const char * );
 static void AttachMetadata( GDALDatasetH, char ** );
@@ -57,12 +58,12 @@ static void Usage(const char* pszErrorMsg = NULL, int bShort = TRUE)
             "             CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n"
             "       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n"
             "       [-outsize xsize[%%] ysize[%%]]\n"
-            "       [-unscale] [-scale [src_min src_max [dst_min dst_max]]]\n"
+            "       [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*\n"
             "       [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry] [-epo] [-eco]\n"
             "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
             "       [-gcp pixel line easting northing [elevation]]*\n" 
             "       [-mo \"META-TAG=VALUE\"]* [-q] [-sds]\n"
-            "       [-co \"NAME=VALUE\"]* [-stats]\n"
+            "       [-co \"NAME=VALUE\"]* [-stats] [-norat]\n"
             "       src_dataset dst_dataset\n" );
 
     if( !bShort )
@@ -261,6 +262,15 @@ enum
     do { if (i + nExtraArg >= argc) \
         Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
 
+
+typedef struct
+{
+    int     bScale;
+    int     bHaveScaleSrc;
+    double  dfScaleSrcMin, dfScaleSrcMax;
+    double  dfScaleDstMin, dfScaleDstMax;
+} ScaleParams;
+
 static int ProxyMain( int argc, char ** argv )
 
 {
@@ -279,9 +289,15 @@ static int ProxyMain( int argc, char ** argv )
     char                **papszCreateOptions = NULL;
     int                 anSrcWin[4], bStrict = FALSE;
     const char          *pszProjection;
-    int                 bScale = FALSE, bHaveScaleSrc = FALSE, bUnscale=FALSE;
-    double	        dfScaleSrcMin=0.0, dfScaleSrcMax=255.0;
-    double              dfScaleDstMin=0.0, dfScaleDstMax=255.0;
+
+    int                 bUnscale=FALSE;
+    int                 nScaleRepeat = 0;
+    ScaleParams        *pasScaleParams = NULL;
+    int                 bHasUsedExplictScaleBand = FALSE;
+    int                 nExponentRepeat = 0;
+    double             *padfExponent = NULL;
+    int                 bHasUsedExplictExponentBand = FALSE;
+
     double              dfULX, dfULY, dfLRX, dfLRY;
     char                **papszMetadataOptions = NULL;
     char                *pszOutputSRS = NULL;
@@ -302,6 +318,7 @@ static int ProxyMain( int argc, char ** argv )
     int                 bStats = FALSE, bApproxStats = FALSE;
     int                 bErrorOnPartiallyOutside = FALSE;
     int                 bErrorOnCompletelyOutside = FALSE;
+    int                 bNoRAT = FALSE;
 
 
     anSrcWin[0] = 0;
@@ -515,28 +532,90 @@ static int ProxyMain( int argc, char ** argv )
             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
         }   
 
-        else if( EQUAL(argv[i],"-scale") )
+        else if( EQUAL(argv[i],"-scale") || EQUALN(argv[i],"-scale_", 7) )
         {
-            bScale = TRUE;
+            int nIndex = 0;
+            if( EQUALN(argv[i],"-scale_", 7) )
+            {
+                if( !bHasUsedExplictScaleBand && nScaleRepeat != 0 )
+                    Usage("Cannot mix -scale and -scale_XX syntax");
+                bHasUsedExplictScaleBand = TRUE;
+                nIndex = atoi(argv[i] + 7);
+                if( nIndex <= 0 || nIndex > 65535 )
+                    Usage(CPLSPrintf( "Invalid parameter name: %s", argv[i] ));
+                nIndex --;
+            }
+            else
+            {
+                if( bHasUsedExplictScaleBand )
+                    Usage("Cannot mix -scale and -scale_XX syntax");
+                nIndex = nScaleRepeat;
+            }
+
+            if( nIndex >= nScaleRepeat )
+            {
+                pasScaleParams = (ScaleParams*)CPLRealloc(pasScaleParams,
+                    (nIndex + 1) * sizeof(ScaleParams));
+                if( nIndex > nScaleRepeat )
+                    memset(pasScaleParams + nScaleRepeat, 0,
+                        sizeof(ScaleParams) * (nIndex - nScaleRepeat));
+                nScaleRepeat = nIndex + 1;
+            }
+            pasScaleParams[nIndex].bScale = TRUE;
             if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
             {
-                bHaveScaleSrc = TRUE;
-                dfScaleSrcMin = CPLAtofM(argv[i+1]);
-                dfScaleSrcMax = CPLAtofM(argv[i+2]);
+                pasScaleParams[nIndex].bHaveScaleSrc = TRUE;
+                pasScaleParams[nIndex].dfScaleSrcMin = CPLAtofM(argv[i+1]);
+                pasScaleParams[nIndex].dfScaleSrcMax = CPLAtofM(argv[i+2]);
                 i += 2;
             }
-            if( i < argc-2 && bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
+            if( i < argc-2 && pasScaleParams[nIndex].bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
             {
-                dfScaleDstMin = CPLAtofM(argv[i+1]);
-                dfScaleDstMax = CPLAtofM(argv[i+2]);
+                pasScaleParams[nIndex].dfScaleDstMin = CPLAtofM(argv[i+1]);
+                pasScaleParams[nIndex].dfScaleDstMax = CPLAtofM(argv[i+2]);
                 i += 2;
             }
             else
             {
-                dfScaleDstMin = 0.0;
-                dfScaleDstMax = 255.999;
+                pasScaleParams[nIndex].dfScaleDstMin = 0.0;
+                pasScaleParams[nIndex].dfScaleDstMax = 255.999;
             }
-        }   
+        }
+
+        else if( EQUAL(argv[i],"-exponent") || EQUALN(argv[i],"-exponent_",10) )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+
+            int nIndex = 0;
+            if( EQUALN(argv[i],"-exponent_", 10) )
+            {
+                if( !bHasUsedExplictExponentBand && nExponentRepeat != 0 )
+                    Usage("Cannot mix -exponent and -exponent_XX syntax");
+                bHasUsedExplictExponentBand = TRUE;
+                nIndex = atoi(argv[i] + 10);
+                if( nIndex <= 0 || nIndex > 65535 )
+                    Usage(CPLSPrintf( "Invalid parameter name: %s", argv[i] ));
+                nIndex --;
+            }
+            else
+            {
+                if( bHasUsedExplictExponentBand )
+                    Usage("Cannot mix -exponent and -exponent_XX syntax");
+                nIndex = nExponentRepeat;
+            }
+
+            if( nIndex >= nExponentRepeat )
+            {
+                padfExponent = (double*)CPLRealloc(padfExponent,
+                    (nIndex + 1) * sizeof(double));
+                if( nIndex > nExponentRepeat )
+                    memset(padfExponent + nExponentRepeat, 0,
+                        sizeof(double) * (nIndex - nExponentRepeat));
+                nExponentRepeat = nIndex + 1;
+            }
+            double dfExponent = CPLAtofM(argv[++i]);
+            padfExponent[nIndex] = dfExponent;
+        }
 
         else if( EQUAL(argv[i], "-unscale") )
         {
@@ -630,10 +709,13 @@ static int ProxyMain( int argc, char ** argv )
             bStats = TRUE;
             bApproxStats = TRUE;
         }
-
+        else if( EQUAL(argv[i], "-norat") )
+        {
+            bNoRAT = TRUE;
+        }
         else if( argv[i][0] == '-' )
         {
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         }
         else if( pszSource == NULL )
         {
@@ -713,6 +795,25 @@ static int ProxyMain( int argc, char ** argv )
         char** papszDupArgv = CSLDuplicate(argv);
         int nRet = 0;
 
+        CPLString osPath = CPLGetPath(pszDest);
+        CPLString osBasename = CPLGetBasename(pszDest);
+        CPLString osExtension = CPLGetExtension(pszDest);
+        CPLString osTemp;
+
+        const char* pszFormat = NULL;
+        if ( CSLCount(papszSubdatasets)/2 < 10 )
+        {
+            pszFormat = "%s_%d";
+        }
+        else if ( CSLCount(papszSubdatasets)/2 < 100 )
+        {
+            pszFormat = "%s_%002d";
+        }
+        else
+        {
+            pszFormat = "%s_%003d";
+        }
+
         CPLFree(papszDupArgv[iDstFileArg]);
         papszDupArgv[iDstFileArg] = pszSubDest;
         bSubCall = TRUE;
@@ -720,13 +821,15 @@ static int ProxyMain( int argc, char ** argv )
         {
             CPLFree(papszDupArgv[iSrcFileArg]);
             papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
-            sprintf( pszSubDest, "%s%d", pszDest, i/2 + 1 );
+            osTemp = CPLSPrintf( pszFormat, osBasename.c_str(), i/2 + 1 );
+            osTemp = CPLFormFilename( osPath, osTemp, osExtension ); 
+            strcpy( pszSubDest, osTemp.c_str() );
             nRet = ProxyMain( argc, papszDupArgv );
             if (nRet != 0)
                 break;
         }
         CSLDestroy(papszDupArgv);
-        
+
         bSubCall = bOldSubCall;
         CSLDestroy(argv);
 
@@ -790,6 +893,21 @@ static int ProxyMain( int argc, char ** argv )
             bDefBands = FALSE;
     }
 
+    if( nScaleRepeat > nBandCount )
+    {
+        if( !bHasUsedExplictScaleBand )
+            Usage("-scale has been specified more times than the number of output bands");
+        else
+            Usage("-scale_XX has been specified with XX greater than the number of output bands");
+    }
+
+    if( nExponentRepeat > nBandCount )
+    {
+        if( !bHasUsedExplictExponentBand )
+            Usage("-exponent has been specified more times than the number of output bands");
+        else
+            Usage("-exponent_XX has been specified with XX greater than the number of output bands");
+    }
 /* -------------------------------------------------------------------- */
 /*      Compute the source window from the projected source window      */
 /*      if the projected coordinates were provided.  Note that the      */
@@ -816,9 +934,9 @@ static int ProxyMain( int argc, char ** argv )
         }
 
         anSrcWin[0] = (int) 
-            ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
+            floor((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
         anSrcWin[1] = (int) 
-            ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
+            floor((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
 
         anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
         anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);
@@ -925,13 +1043,13 @@ static int ProxyMain( int argc, char ** argv )
         && pszOXSize == NULL && pszOYSize == NULL );
 
     if( eOutputType == GDT_Unknown 
-        && !bScale && !bUnscale
+        && nScaleRepeat == 0 && nExponentRepeat == 0 && !bUnscale
         && CSLCount(papszMetadataOptions) == 0 && bDefBands 
         && eMaskMode == MASK_AUTO
         && bSpatialArrangementPreserved
         && nGCPCount == 0 && !bGotBounds
         && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
-        && nRGBExpand == 0 && !bStats )
+        && nRGBExpand == 0 && !bStats && !bNoRAT )
     {
         
         hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
@@ -1080,7 +1198,7 @@ static int ProxyMain( int argc, char ** argv )
 /*      Transfer generally applicable metadata.                         */
 /* -------------------------------------------------------------------- */
     char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
-    if ( bScale || bUnscale || eOutputType != GDT_Unknown )
+    if ( nScaleRepeat > 0 || bUnscale || eOutputType != GDT_Unknown )
     {
         /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
         /* if the data range may change because of options */
@@ -1152,7 +1270,7 @@ static int ProxyMain( int argc, char ** argv )
             for( nColor = 0; nColor < nColorCount; nColor++ )
             {
                 const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
-                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
+                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c3)
                 {
                     fprintf(stderr, "Warning : color table contains non gray levels colors\n");
                     break;
@@ -1172,7 +1290,7 @@ static int ProxyMain( int argc, char ** argv )
     }
 
     int bFilterOutStatsMetadata =
-        (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
+        (nScaleRepeat > 0 || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
 
 /* ==================================================================== */
 /*      Process all bands.                                              */
@@ -1227,6 +1345,46 @@ static int ProxyMain( int argc, char ** argv )
 /*      Do we need to collect scaling information?                      */
 /* -------------------------------------------------------------------- */
         double dfScale=1.0, dfOffset=0.0;
+        int    bScale = FALSE, bHaveScaleSrc = FALSE;
+        double dfScaleSrcMin = 0.0, dfScaleSrcMax = 0.0;
+        double dfScaleDstMin = 0.0, dfScaleDstMax = 0.0;
+        int    bExponentScaling = FALSE;
+        double dfExponent = 0.0;
+
+        if( i < nScaleRepeat && pasScaleParams[i].bScale )
+        {
+            bScale = pasScaleParams[i].bScale;
+            bHaveScaleSrc = pasScaleParams[i].bHaveScaleSrc;
+            dfScaleSrcMin = pasScaleParams[i].dfScaleSrcMin;
+            dfScaleSrcMax = pasScaleParams[i].dfScaleSrcMax;
+            dfScaleDstMin = pasScaleParams[i].dfScaleDstMin;
+            dfScaleDstMax = pasScaleParams[i].dfScaleDstMax;
+        }
+        else if( nScaleRepeat == 1 && !bHasUsedExplictScaleBand )
+        {
+            bScale = pasScaleParams[0].bScale;
+            bHaveScaleSrc = pasScaleParams[0].bHaveScaleSrc;
+            dfScaleSrcMin = pasScaleParams[0].dfScaleSrcMin;
+            dfScaleSrcMax = pasScaleParams[0].dfScaleSrcMax;
+            dfScaleDstMin = pasScaleParams[0].dfScaleDstMin;
+            dfScaleDstMax = pasScaleParams[0].dfScaleDstMax;
+        }
+
+        if( i < nExponentRepeat && padfExponent[i] != 0.0 )
+        {
+            bExponentScaling = TRUE;
+            dfExponent = padfExponent[i];
+        }
+        else if( nExponentRepeat == 1 && !bHasUsedExplictExponentBand )
+        {
+            bExponentScaling = TRUE;
+            dfExponent = padfExponent[0];
+        }
+
+        if( bExponentScaling && !bScale )
+        {
+            Usage(CPLSPrintf("For band %d, -scale should be specified when -exponent is specified.", i + 1));
+        }
 
         if( bScale && !bHaveScaleSrc )
         {
@@ -1238,14 +1396,16 @@ static int ProxyMain( int argc, char ** argv )
 
         if( bScale )
         {
+            /* To avoid a divide by zero */
             if( dfScaleSrcMax == dfScaleSrcMin )
                 dfScaleSrcMax += 0.1;
-            if( dfScaleDstMax == dfScaleDstMin )
-                dfScaleDstMax += 0.1;
 
-            dfScale = (dfScaleDstMax - dfScaleDstMin) 
-                / (dfScaleSrcMax - dfScaleSrcMin);
-            dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
+            if( !bExponentScaling )
+            {
+                dfScale = (dfScaleDstMax - dfScaleDstMin) 
+                    / (dfScaleSrcMax - dfScaleSrcMin);
+                dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
+            }
         }
 
         if( bUnscale )
@@ -1260,14 +1420,35 @@ static int ProxyMain( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
         if( bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand) )
         {
-            poVRTBand->AddComplexSource( poSrcBand,
-                                         anSrcWin[0], anSrcWin[1],
-                                         anSrcWin[2], anSrcWin[3],
-                                         anDstWin[0], anDstWin[1],
-                                         anDstWin[2], anDstWin[3],
-                                         dfOffset, dfScale,
-                                         VRT_NODATA_UNSET,
-                                         nComponent );
+            VRTComplexSource* poSource = new VRTComplexSource();
+            poVRTBand->ConfigureSource( poSource,
+                                        poSrcBand,
+                                        FALSE,
+                                        anSrcWin[0], anSrcWin[1],
+                                        anSrcWin[2], anSrcWin[3],
+                                        anDstWin[0], anDstWin[1],
+                                        anDstWin[2], anDstWin[3] );
+
+        /* -------------------------------------------------------------------- */
+        /*      Set complex parameters.                                         */
+        /* -------------------------------------------------------------------- */
+
+            if( dfOffset != 0.0 || dfScale != 1.0 )
+            {
+                poSource->SetLinearScaling(dfOffset, dfScale);
+            }
+            else if( bExponentScaling )
+            {
+                poSource->SetPowerScaling(dfExponent,
+                                          dfScaleSrcMin,
+                                          dfScaleSrcMax,
+                                          dfScaleDstMin,
+                                          dfScaleDstMax);
+            }
+
+            poSource->SetColorTableComponent(nComponent);
+
+            poVRTBand->AddSource( poSource );
         }
         else
             poVRTBand->AddSimpleSource( poSrcBand,
@@ -1444,6 +1625,8 @@ static int ProxyMain( int argc, char ** argv )
     GDALClose( hDataset );
 
     CPLFree( panBandList );
+    CPLFree( pasScaleParams );
+    CPLFree( padfExponent );
     
     CPLFree( pszOutputSRS );
 
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index 6f6721c..36d2314 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 25825 2013-04-01 08:45:42Z dron $ */
+/* $Id: gdal_utilities.dox 27110 2014-03-28 21:29:20Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*! 
@@ -33,8 +33,10 @@ The following utility programs are distributed with GDAL.
 <li> \ref gdalsrsinfo - Report a given SRS in different formats.  (GDAL >= 1.9.0)
 <li> \ref gdalmove - Transform the coordinate system of a file (GDAL >= 1.10)
 <li> \ref gdal_edit - Edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata)
+<li> \ref gdal_calc - Command line raster calculator with numpy syntax
 <li> \ref gdal-config - Get options required to build software using GDAL.
 <li> \ref gdalmanage - Identify, copy, rename and delete raster.
+<li> \ref gdalcompare - Compare two images and report on differences.
 </ul>
 
 \section gdal_utilities_creating Creating New Files
@@ -171,7 +173,7 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 25825 2013-04-01 08:45:42Z dron $
+$Id: gdal_utilities.dox 27110 2014-03-28 21:29:20Z rouault $
 </p>
 \endhtmlonly
 */
@@ -185,8 +187,9 @@ lists information about a raster dataset
 
 \verbatim
 gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
-         [-norat] [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*
-	 [-sd subdataset] datasetname
+         [-norat] [-noct] [-nofl] [-checksum] [-proj4]
+         [-listmdd] [-mdd domain|`all`]*
+         [-sd subdataset] datasetname
 \endverbatim
 
 \section gdalinfo_description DESCRIPTION
@@ -210,7 +213,9 @@ of metadata strings.</dd>
 <dt> <b>-nrat</b></dt><dd> Suppress printing of raster attribute table.</dd>
 <dt> <b>-noct</b></dt><dd> Suppress printing of color table.</dd>
 <dt> <b>-checksum</b></dt><dd> Force computation of the checksum for each band in the dataset.</dd>
-<dt> <b>-mdd domain</b></dt><dd> Report metadata for the specified domain</dd>
+<dt> <b>-listmdd</b></dt><dd> (GDAL >= 1.11) List all metadata domains available for the dataset.</dd>
+<dt> <b>-mdd domain</b></dt><dd> Report metadata for the specified domain. Starting with GDAL 1.11,
+"all" can be used to report metadata in all domains</dd>
 <dt> <b>-nofl</b></dt><dd> (GDAL >= 1.9.0) Only display the first file of the
 file list.</dd>
 <dt> <b>-sd</b> <i>subdataset</i></dt><dd> (GDAL >= 1.9.0) If the input
@@ -294,12 +299,12 @@ gdal_translate [--help-general]
              CInt16/CInt32/CFloat32/CFloat64}] [-strict]
        [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]
        [-outsize xsize[%] ysize[%]]
-       [-unscale] [-scale [src_min src_max [dst_min dst_max]]]
+       [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*
        [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry] [-epo] [-eco]
        [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]
        [-gcp pixel line easting northing [elevation]]*
        [-mo "META-TAG=VALUE"]* [-q] [-sds]
-       [-co "NAME=VALUE"]* [-stats]
+       [-co "NAME=VALUE"]* [-stats] [-norat]
        src_dataset dst_dataset
 \endverbatim
 
@@ -341,7 +346,24 @@ is as a fraction of the input image size.</dd>
 input pixels values from the range <i>src_min</i> to <i>src_max</i> to
 the range <i>dst_min</i> to <i>dst_max</i>.  If omitted the output range is
 0 to 255.  If omitted the input range is automatically computed from the
-source data.</dd>
+source data.
+Before GDAL 1.11, it can be specified only once, and in that case, it applies to
+all bands of the output dataset.
+Starting with GDAL 1.11, -scale can be repeated several times (if specified only once,
+it also applies to all bands of the output dataset), so as to specify per band parameters.
+It is also possible to use the "-scale_bn" syntax where bn is a band number
+(e.g. "-scale_2" for the 2nd band of the output dataset) to specify the parameters of
+one or several specific bands.
+</dd>
+<dt> <b>-exponent</b> <i> exp_val</i>:</dt><dd> (From GDAL 1.11) To apply non-linear scaling
+with a power function. exp_val is the exponent of the power function (must be postive). This option
+must be used with the -scale option.
+If specified only once, -exponent applies to all bands of the output image.
+It can be repeated several times so as to specify per band parameters.
+It is also possible to use the "-exponent_bn" syntax where bn is a band number
+(e.g. "-exponent_2" for the 2nd band of the output dataset) to specify the parameters of
+one or several specific bands.
+</dd>
 <dt> <b>-unscale</b>:</dt><dd> Apply the scale/offset metadata for the bands
 to convert scaled values to unscaled values.  It is also often necessary to 
 reset the output datatype with the <b>-ot</b> switch.</dd>
@@ -380,8 +402,10 @@ may be provided multiple times to provide a set of GCPs.
 <dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
 output.</dd>
 <dt> <b>-sds</b>:</dt><dd> Copy all subdatasets of this file to individual 
-output files.  Use with formats like HDF or OGDI that have subdatasets.</dd>
+output files.  Use with formats like HDF or OGDI that have subdatasets.
+The output file naming scheme has changed in GDAL 1.11 (e.g. ofile_1.tif, ofile_2.tif).</dd>
 <dt> <b>-stats</b>:</dt><dd> (GDAL >= 1.8.0) Force (re)computation of statistics.</dd>
+<dt> <b>-norat</b></dt><dd> (GDAL >= 1.11) Do not copy source RAT into destination dataset.</dd>
 <dt> <i>src_dataset</i>:</dt><dd>The source dataset name. It can be either
 file name, URL of data source or subdataset name for multi-dataset files.</dd>
 <dt> <i>dst_dataset</i>:</dt><dd> The destination file name.</dd>
@@ -553,12 +577,15 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 *******************************************************************************
 /*! \page gdaltindex gdaltindex
 
-builds a shapefile as a raster tileindex
+Builds a shapefile as a raster tileindex
 
 \section gdaltindex_synopsis SYNOPSIS
 
 \verbatim
-gdaltindex [-tileindex field_name] [-write_absolute_path] [-skip_different_projection] [-t_srs target_srs] index_file [gdal_file]*
+gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path]
+           [-skip_different_projection] [-t_srs target_srs]
+           [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]
+           [-lyr_name name] index_file [gdal_file]*
 \endverbatim
 
 \section gdaltindex_description DESCRIPTION
@@ -568,31 +595,61 @@ an attribute containing the filename, and a polygon geometry outlining the
 raster.  This output is suitable for use with <a href="http://mapserver.org/">MapServer</a> as a raster 
 tileindex. 
 
-<ul>
-<li> The shapefile (index_file) will be created if it doesn't already exist, 
-otherwise it will append to the existing file.
-<li> The default tile index field is 'location'.
-<li> Raster filenames will be put in the file exactly as they are specified
-on the commandline unless the option -write_absolute_path is used.
-<li> If -skip_different_projection is specified, only files with same projection ref
-as files already inserted in the tileindex will be inserted (unless t_srs is specified).
-<li> If -t_srs is specified, geometries of input files will be transformed to the desired
-target coordinate reference system. 
-Note that using this option generates files that are NOT compatible with MapServer.
-<li> Simple rectangular polygons are generated in the same coordinate reference system
-as the rasters, or in target reference system if the -t_srs option is used.
-</ul>
+<dl>
+<dt><b>-f</b> format:</dt><dd> (GDAL >= 1.11)
+<p>The OGR format of the output tile index file. Default is Esri Shapefile.</p>
+</dd>
+<dt><b>-tileindex</b> field_name:</dt>
+<dd><p>The output field name to hold the file path/location to the indexed rasters. The default tile index field name is <code>location</code>.</p>
+</dd>
+<dt><b>-write_absolute_path</b>:</dt>
+<dd><p>The absolute path to the raster files is stored in the tile index file. By default the raster filenames will be put in the file exactly as they are specified on the command line.</p>
+</dd>
+<dt><b>-skip_different_projection</b>:</dt>
+<dd><p>Only files with same projection as files already inserted in the tileindex will be inserted (unless <code>-t_srs</code> is specified). Default does not check projection and accepts all inputs.</p>
+</dd>
+<dt><b>-t_srs</b> target_srs:</dt>
+<dd><p>Geometries of input files will be transformed to the desired target coordinate reference system. Using this option generates files that are not compatible with MapServer < 6.4. Default creates simple rectangular polygons in the same coordinate reference system as the input rasters.</p>
+</dd>
+<dt><b>-src_srs_name</b> field_name:</dt><dd> (GDAL >= 1.11) 
+<p>The name of the field to store the SRS of each tile. This field name can be used as the value of the TILESRS keyword in MapServer >= 6.4.</p>
+</dd>
+<dt><b>-src_srs_format</b> type:</dt><dd> (GDAL >= 1.11) 
+<p>The format in which the SRS of each tile must be written. Types can be AUTO, WKT, EPSG, PROJ.</p>
+</dd>
+<dt><b>-lyr_name</b> name:</dt>
+<dd><p>Layer name to create/append to in the output tile index file.</p>
+</dd>
+<dt><b>index_file</b>:</dt>
+<dd><p>The name of the output file to create/append to. The default shapefile will be created if it doesn't already exist, otherwise it will append to the existing file.</p>
+</dd>
+<dt><b>gdal_file</b>:</dt>
+<dd><p>The input GDAL raster files, can be multiple files separated by spaces. Wildcards my also be used. Stores the file locations in the same style as specified here, unless <code>-write_absolute_path</code> option is also used.</p>
+</dd>
+</dl>
 
-\section gdaltindex_example EXAMPLE
+\section gdaltindex_example EXAMPLES
 
 \htmlonly
-Example:
+Examples:
 \endhtmlonly
 
+Produce a shapefile (<code>doq_index.shp</code>) with a record for every 
+image that the utility found in the <code>doq</code> folder. Each record holds 
+information that points to the location of the image and also a bounding rectangle 
+shape showing the bounds of the image:
+
 \verbatim
 gdaltindex doq_index.shp doq/*.tif
 \endverbatim
 
+The <code>-t_srs</code> option can also be used to transform all input rasters
+into the same output projection:
+
+\verbatim
+gdaltindex -t_srs EPSG:4326 -src_srs_name src_srs tile_index_mixed_srs.shp *.tif
+\endverbatim
+
 \if man
 \section gdaltindex_author AUTHOR
 Frank Warmerdam <warmerdam at pobox.com>
@@ -1624,7 +1681,7 @@ creates regular grid from the scattered data
 gdal_grid [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
           CInt16/CInt32/CFloat32/CFloat64}]
 	  [-of format] [-co "NAME=VALUE"]
-	  [-zfield field_name]
+	  [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]
 	  [-a_srs srs_def] [-spat xmin ymin xmax ymax]
           [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]
           [-clipsrcsql sql_statement] [-clipsrclayer layer]
@@ -1673,6 +1730,15 @@ read from feature geometry record (naturally, if you have a Z value in
 geometry, otherwise you have no choice and should specify a field name
 containing Z value).</dd>
 
+<dt> <b>-z_increase</b> <i>increase_value</i>:</dt><dd> Addition to the attribute field
+on the features to be used to get a Z value from. The addition should be the same
+unit as Z value. The result value will be Z value + Z increase value. The default value is 0.</dd>
+
+<dt> <b>-z_multiply</b> <i>multiply_value</i>:</dt><dd> This is multiplication 
+ratio for Z field. This can be used for shift from e.g. foot to meters or from 
+elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value. 
+The default value is 1.</dd>
+
 <dt> <b>-a</b> <i>[algorithm[:parameter1=value1][:parameter2=value2]...]</i>:
 </dt><dd> Set the interpolation algorithm or data metric name and (optionally)
 its parameters. See \ref gdal_grid_algorithms and \ref gdal_grid_metrics
@@ -1982,8 +2048,14 @@ Usage:
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
 
 Notes :
-  Scale is the ratio of vertical units to horizontal
-   for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120)
+  gdaldem generally assumes that x, y and z units are identical.  If x (east-west)
+  and y (north-south) units are identical, but z (elevation) units are different, the
+  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For 
+  LatLong projections near the equator, where units of latitude and units of 
+  longitude are similar, elevation (z) units can be converted to be compatible
+  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in 
+  meters).  For locations not near the equator, it would be best to reproject your
+  grid using gdalwarp before using gdaldem.
 
 \endverbatim
 \if man
diff --git a/apps/gdaladdo.cpp b/apps/gdaladdo.cpp
index 9a89bc8..c804663 100644
--- a/apps/gdaladdo.cpp
+++ b/apps/gdaladdo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaladdo.cpp 25586 2013-01-30 20:26:44Z rouault $
+ * $Id: gdaladdo.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to build overviews. 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaladdo.cpp 25586 2013-01-30 20:26:44Z rouault $");
+CPL_CVSID("$Id: gdaladdo.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -153,7 +154,7 @@ int main( int nArgc, char ** papszArgv )
             panBandList[nBandCount-1] = nBand;
         }
         else if( papszArgv[iArg][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
         else if( pszFilename == NULL )
             pszFilename = papszArgv[iArg];
         else if( atoi(papszArgv[iArg]) > 0 )
diff --git a/apps/gdalbuildvrt.cpp b/apps/gdalbuildvrt.cpp
index fa074e3..890aa5b 100644
--- a/apps/gdalbuildvrt.cpp
+++ b/apps/gdalbuildvrt.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gdalbuildvrt.cpp 25846 2013-04-03 06:13:31Z dron $
+ * $Id: gdalbuildvrt.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to build VRT datasets from raster products or content of SHP tile index
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 #endif
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdalbuildvrt.cpp 25846 2013-04-03 06:13:31Z dron $");
+CPL_CVSID("$Id: gdalbuildvrt.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define GEOTRSFRM_TOPLEFT_X            0
 #define GEOTRSFRM_WE_RES               1
@@ -80,6 +80,16 @@ typedef struct
 } BandProperty;
 
 /************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+/************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
 
@@ -1026,7 +1036,15 @@ int VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressData)
             nSrcNoDataCount = CSLCount(papszTokens);
             padfSrcNoData = (double *) CPLMalloc(sizeof(double) * nSrcNoDataCount);
             for(i=0;i<nSrcNoDataCount;i++)
+            {
+                if( !ArgIsNumeric(papszTokens[i]) )
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -srcnodata value");
+                    CSLDestroy(papszTokens);
+                    return CE_Failure;
+                }
                 padfSrcNoData[i] = CPLAtofM(papszTokens[i]);
+            }
             CSLDestroy(papszTokens);
         }
     }
@@ -1043,7 +1061,15 @@ int VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressData)
             nVRTNoDataCount = CSLCount(papszTokens);
             padfVRTNoData = (double *) CPLMalloc(sizeof(double) * nVRTNoDataCount);
             for(i=0;i<nVRTNoDataCount;i++)
+            {
+                if( !ArgIsNumeric(papszTokens[i]) )
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -vrtnodata value");
+                    CSLDestroy(papszTokens);
+                    return CE_Failure;
+                }
                 padfVRTNoData[i] = CPLAtofM(papszTokens[i]);
+            }
             CSLDestroy(papszTokens);
         }
     }
@@ -1271,6 +1297,8 @@ int main( int nArgc, char ** papszArgv )
     int *panBandList = NULL;
     int nBandCount = 0;
     int nMaxBandNo = 0;
+    int nRet;
+
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
         exit(1);
@@ -1427,7 +1455,7 @@ int main( int nArgc, char ** papszArgv )
         }
         else if ( papszArgv[iArg][0] == '-' )
         {
-            Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
         }
         else if( pszOutputFilename == NULL )
         {
@@ -1519,7 +1547,7 @@ int main( int nArgc, char ** papszArgv )
                         bSeparate, bAllowProjectionDifference, bAddAlpha, bHideNoData, nSubdataset,
                         pszSrcNoData, pszVRTNoData, pszOutputSRS);
 
-    oBuilder.Build(pfnProgress, NULL);
+    nRet = (oBuilder.Build(pfnProgress, NULL) == CE_None) ? 0 : 1;
     
     for(i=0;i<nInputFiles;i++)
     {
@@ -1535,5 +1563,5 @@ int main( int nArgc, char ** papszArgv )
     OGRCleanupAll();
 #endif
 
-    return 0;
+    return nRet;
 }
diff --git a/apps/gdaldem.cpp b/apps/gdaldem.cpp
index daa7113..4d70825 100644
--- a/apps/gdaldem.cpp
+++ b/apps/gdaldem.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldem.cpp 26358 2013-08-21 20:12:38Z rouault $
+ * $Id: gdaldem.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL DEM Utilities
  * Purpose:  
@@ -10,7 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, 2009 Matthew Perry 
- * Copyright (c) 2009 Even Rouault
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Portions derived from GRASS 4.1 (public domain) See 
  * http://trac.osgeo.org/gdal/ticket/2975 for more information regarding 
  * history of this code
@@ -91,7 +91,7 @@
 #include "gdal_priv.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdaldem.cpp 26358 2013-08-21 20:12:38Z rouault $");
+CPL_CVSID("$Id: gdaldem.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef M_PI
 # define M_PI  3.1415926535897932384626433832795
@@ -2184,6 +2184,15 @@ double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
 }
 
 /************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -2303,7 +2312,10 @@ int main( int argc, char ** argv )
             (EQUAL(argv[i], "--z") || EQUAL(argv[i], "-z")))
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            z = atof(argv[++i]);
+            ++i;
+            if( !ArgIsNumeric(argv[i]) )
+                Usage();
+            z = atof(argv[i]);
         }
         else if ( eUtilityMode == SLOPE && EQUAL(argv[i], "-p"))
         {
@@ -2345,7 +2357,10 @@ int main( int argc, char ** argv )
           )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            scale = atof(argv[++i]);
+            ++i;
+            if( !ArgIsNumeric(argv[i]) )
+                Usage();
+            scale = atof(argv[i]);
         }
         else if( eUtilityMode == HILL_SHADE &&
             (EQUAL(argv[i], "--az") || 
@@ -2355,7 +2370,10 @@ int main( int argc, char ** argv )
           )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            az = atof(argv[++i]);
+            ++i;
+            if( !ArgIsNumeric(argv[i]) )
+                Usage();
+            az = atof(argv[i]);
         }
         else if( eUtilityMode == HILL_SHADE &&
             (EQUAL(argv[i], "--alt") || 
@@ -2365,7 +2383,10 @@ int main( int argc, char ** argv )
           )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            alt = atof(argv[++i]);
+            ++i;
+            if( !ArgIsNumeric(argv[i]) )
+                Usage();
+            alt = atof(argv[i]);
         }
         else if( eUtilityMode == HILL_SHADE &&
             (EQUAL(argv[i], "-combined") || 
@@ -2409,7 +2430,7 @@ int main( int argc, char ** argv )
         }
         else if( argv[i][0] == '-' )
         {
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         }
         else if( pszSrcFilename == NULL )
         {
diff --git a/apps/gdalenhance.cpp b/apps/gdalenhance.cpp
index 7e4f25b..f2baca4 100644
--- a/apps/gdalenhance.cpp
+++ b/apps/gdalenhance.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalenhance.cpp 22783 2011-07-23 19:28:16Z rouault $
+ * $Id: gdalenhance.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to do image enhancement. 
@@ -7,6 +7,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "vrt/vrtdataset.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdalenhance.cpp 22783 2011-07-23 19:28:16Z rouault $");
+CPL_CVSID("$Id: gdalenhance.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int
 ComputeEqualizationLUTs( GDALDatasetH hDataset,  int nLUTBins,
diff --git a/apps/gdalflattenmask.c b/apps/gdalflattenmask.c
index 350d5bc..397545e 100644
--- a/apps/gdalflattenmask.c
+++ b/apps/gdalflattenmask.c
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/apps/gdalinfo.c b/apps/gdalinfo.c
index a5e25c4..a4e3f94 100644
--- a/apps/gdalinfo.c
+++ b/apps/gdalinfo.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.c 25582 2013-01-29 21:13:43Z rouault $
+ * $Id: gdalinfo.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to list info about a file.
@@ -7,6 +7,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_multiproc.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdalinfo.c 25582 2013-01-29 21:13:43Z rouault $");
+CPL_CVSID("$Id: gdalinfo.c 27044 2014-03-16 23:41:27Z rouault $");
 
 static int 
 GDALInfoReportCorner( GDALDatasetH hDataset, 
@@ -51,7 +52,8 @@ void Usage(const char* pszErrorMsg)
 
 {
     printf( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
-            "                [-norat] [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*\n"
+            "                [-norat] [-noct] [-nofl] [-checksum] [-proj4]\n"
+            "                [-listmdd] [-mdd domain|`all`]*\n"
             "                [-sd subdataset] datasetname\n" );
 
     if( pszErrorMsg != NULL )
@@ -86,6 +88,7 @@ int main( int argc, char ** argv )
     int                 nSubdataset = -1;
     const char          *pszFilename = NULL;
     char              **papszExtraMDDomains = NULL, **papszFileList;
+    int                 bListMDD = FALSE;
     const char  *pszProjection = NULL;
     OGRCoordinateTransformationH hTransform = NULL;
     int             bShowFileList = TRUE;
@@ -148,6 +151,8 @@ int main( int argc, char ** argv )
             bShowRAT = FALSE;
         else if( EQUAL(argv[i], "-noct") )
             bShowColorTable = FALSE;
+        else if( EQUAL(argv[i], "-listmdd") )
+            bListMDD = TRUE;
         else if( EQUAL(argv[i], "-mdd") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -162,7 +167,7 @@ int main( int argc, char ** argv )
             nSubdataset = atoi(argv[++i]);
         }
         else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         else if( pszFilename == NULL )
             pszFilename = argv[i];
         else
@@ -382,6 +387,25 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Report metadata.                                                */
 /* -------------------------------------------------------------------- */
+
+    if( bListMDD )
+    {
+        char** papszMDDList = GDALGetMetadataDomainList( hDataset );
+        char** papszIter = papszMDDList;
+
+        if( papszMDDList != NULL )
+            printf( "Metadata domains:\n" );
+        while( papszIter != NULL && *papszIter != NULL )
+        {
+            if( EQUAL(*papszIter, "") )
+                printf( "  (default)\n");
+            else
+                printf( "  %s\n", *papszIter );
+            papszIter ++;
+        }
+        CSLDestroy(papszMDDList);
+    }
+
     papszMetadata = (bShowMetadata) ? GDALGetMetadata( hDataset, NULL ) : NULL;
     if( bShowMetadata && CSLCount(papszMetadata) > 0 )
     {
@@ -392,6 +416,30 @@ int main( int argc, char ** argv )
         }
     }
 
+    if( papszExtraMDDomains != NULL && EQUAL(papszExtraMDDomains[0], "all") &&
+        papszExtraMDDomains[1] == NULL )
+    {
+        char** papszMDDList = GDALGetMetadataDomainList( hDataset );
+        char** papszIter = papszMDDList;
+
+        CSLDestroy(papszExtraMDDomains);
+        papszExtraMDDomains = NULL;
+
+        while( papszIter != NULL && *papszIter != NULL )
+        {
+            if( !EQUAL(*papszIter, "") &&
+                !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
+                !EQUAL(*papszIter, "SUBDATASETS") &&
+                !EQUAL(*papszIter, "GEOLOCATION") &&
+                !EQUAL(*papszIter, "RPC") )
+            {
+                papszExtraMDDomains = CSLAddString(papszExtraMDDomains, *papszIter);
+            }
+            papszIter ++;
+        }
+        CSLDestroy(papszMDDList);
+    }
+
     for( iMDD = 0; bShowMetadata && iMDD < CSLCount(papszExtraMDDomains); iMDD++ )
     {
         papszMetadata = GDALGetMetadata( hDataset, papszExtraMDDomains[iMDD] );
@@ -739,6 +787,23 @@ int main( int argc, char ** argv )
                     GDALGetRasterOffset( hBand, &bSuccess ),
                     GDALGetRasterScale( hBand, &bSuccess ) );
 
+        if( bListMDD )
+        {
+            char** papszMDDList = GDALGetMetadataDomainList( hBand );
+            char** papszIter = papszMDDList;
+            if( papszMDDList != NULL )
+                printf( "  Metadata domains:\n" );
+            while( papszIter != NULL && *papszIter != NULL )
+            {
+                if( EQUAL(*papszIter, "") )
+                    printf( "    (default)\n");
+                else
+                    printf( "    %s\n", *papszIter );
+                papszIter ++;
+            }
+            CSLDestroy(papszMDDList);
+        }
+
         papszMetadata = (bShowMetadata) ? GDALGetMetadata( hBand, NULL ) : NULL;
         if( bShowMetadata && CSLCount(papszMetadata) > 0 )
         {
diff --git a/apps/gdallocationinfo.cpp b/apps/gdallocationinfo.cpp
index 577983f..d1ae8be 100644
--- a/apps/gdallocationinfo.cpp
+++ b/apps/gdallocationinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdallocationinfo.cpp 23726 2012-01-07 22:57:12Z rouault $
+ * $Id: gdallocationinfo.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Commandline raster query tool.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_minixml.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdallocationinfo.cpp 23726 2012-01-07 22:57:12Z rouault $");
+CPL_CVSID("$Id: gdallocationinfo.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /******************************************************************************/
 /*! \page gdallocationinfo gdallocationinfo
@@ -364,9 +365,16 @@ int main( int argc, char ** argv )
             double adfGeoTransform[6], adfInvGeoTransform[6];
     
             if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) != CE_None )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot get geotransform");
                 exit( 1 );
+            }
     
-            GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform );
+            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
+                exit( 1 );
+            }
     
             iPixel = (int) floor(
                 adfInvGeoTransform[0] 
diff --git a/apps/gdalmanage.cpp b/apps/gdalmanage.cpp
index 73c871c..aa0b0af 100644
--- a/apps/gdalmanage.cpp
+++ b/apps/gdalmanage.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmanage.cpp 21425 2011-01-07 19:36:23Z warmerdam $
+ * $Id: gdalmanage.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline utility for GDAL identify, delete, rename and copy 
@@ -8,6 +8,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 2007, Frank Warmerdam
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdalmanage.cpp 21425 2011-01-07 19:36:23Z warmerdam $");
+CPL_CVSID("$Id: gdalmanage.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
diff --git a/apps/gdalserver.c b/apps/gdalserver.c
index da61891..ee55c90 100644
--- a/apps/gdalserver.c
+++ b/apps/gdalserver.c
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gdalserver.c 25684 2013-02-25 15:40:26Z rouault $
+ * $Id: gdalserver.c 27142 2014-04-09 11:14:35Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Server application that is forked by libgdal
  * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2013, Even Rouault, <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,12 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#if defined(__STDC_VERSION__)
+#define _XOPEN_SOURCE
+#endif
+
 #include "cpl_port.h"
 
 #ifdef WIN32
-  #ifndef _WIN32_WINNT
-    #define _WIN32_WINNT 0x0501
+  #ifdef _WIN32_WINNT
+    #undef _WIN32_WINNT
   #endif
+  #define _WIN32_WINNT 0x0501
   #include <winsock2.h>
   #include <ws2tcpip.h>
   typedef SOCKET CPL_SOCKET;
@@ -72,7 +77,7 @@ int CPL_DLL GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout);
 int CPL_DLL GDALServerLoopSocket(CPL_SOCKET nSocket);
 CPL_C_END
 
-CPL_CVSID("$Id: gdalserver.c 25684 2013-02-25 15:40:26Z rouault $");
+CPL_CVSID("$Id: gdalserver.c 27142 2014-04-09 11:14:35Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -574,7 +579,7 @@ int main(int argc, char* argv[])
         else if( EQUAL(argv[i], "-daemonize") )
             ;
         else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         else
             Usage("Too many command options.");
     }
diff --git a/apps/gdalsrsinfo.cpp b/apps/gdalsrsinfo.cpp
index a267dba..55e17f4 100644
--- a/apps/gdalsrsinfo.cpp
+++ b/apps/gdalsrsinfo.cpp
@@ -9,6 +9,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -211,8 +212,7 @@ int main( int argc, char ** argv )
             bValidate = TRUE;
         else if( argv[i][0] == '-' )
         {
-            CSLDestroy( argv );
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         }
         else  
             pszInput = argv[i];
@@ -326,8 +326,10 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
     int            bGotSRS = FALSE;
     VSILFILE      *fp = NULL;
     GDALDataset	  *poGDALDS = NULL; 
+#ifdef OGR_ENABLED
     OGRDataSource *poOGRDS = NULL;
     OGRLayer      *poLayer = NULL;
+#endif
     char           *pszProjection = NULL;
     CPLErrorHandler oErrorHandler = NULL;
     int bIsFile = FALSE;
@@ -348,8 +350,12 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
     } 
        
     /* try to open with GDAL */
-    CPLDebug( "gdalsrsinfo", "trying to open with GDAL" );
-    poGDALDS = (GDALDataset *) GDALOpen( pszInput, GA_ReadOnly );
+    if( strncmp(pszInput, "http://spatialreference.org/",
+                strlen("http://spatialreference.org/")) != 0 )
+    {
+        CPLDebug( "gdalsrsinfo", "trying to open with GDAL" );
+        poGDALDS = (GDALDataset *) GDALOpen( pszInput, GA_ReadOnly );
+    }
     if ( poGDALDS != NULL && poGDALDS->GetProjectionRef( ) != NULL ) {
         pszProjection = (char *) poGDALDS->GetProjectionRef( );
         if( oSRS.importFromWkt( &pszProjection ) == CE_None ) {
@@ -364,8 +370,12 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
 #ifdef OGR_ENABLED
     /* if unsuccessful, try to open with OGR */
     if ( ! bGotSRS ) {
-        CPLDebug( "gdalsrsinfo", "trying to open with OGR" );
-        poOGRDS = OGRSFDriverRegistrar::Open( pszInput, FALSE, NULL );
+        if( strncmp(pszInput, "http://spatialreference.org/",
+                    strlen("http://spatialreference.org/")) != 0 )
+        {
+            CPLDebug( "gdalsrsinfo", "trying to open with OGR" );
+            poOGRDS = OGRSFDriverRegistrar::Open( pszInput, FALSE, NULL );
+        }
         if( poOGRDS != NULL ) {
             poLayer = poOGRDS->GetLayer( 0 );
             if ( poLayer != NULL ) {
diff --git a/apps/gdaltindex.c b/apps/gdaltindex.c
index 4a40ca0..ddcca6c 100644
--- a/apps/gdaltindex.c
+++ b/apps/gdaltindex.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltindex.c 26095 2013-06-18 23:09:35Z rouault $
+ * $Id: gdaltindex.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  MapServer
  * Purpose:  Commandline App to build tile index for raster files.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam, DM Solutions Group Inc
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaltindex.c 26095 2013-06-18 23:09:35Z rouault $");
+CPL_CVSID("$Id: gdaltindex.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -45,9 +46,10 @@ static void Usage(const char* pszErrorMsg)
 {
     fprintf(stdout, "%s", 
             "\n"
-            "Usage: gdaltindex [-tileindex field_name] [-write_absolute_path] \n"
+            "Usage: gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path] \n"
             "                  [-skip_different_projection] [-t_srs target_srs]\n"
-            "                  index_file [gdal_file]*\n"
+            "                  [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]\n"
+            "                  [-lyr_name name] index_file [gdal_file]*\n"
             "\n"
             "eg.\n"
             "  % gdaltindex doq_index.shp doq/*.tif\n" 
@@ -61,7 +63,7 @@ static void Usage(const char* pszErrorMsg)
             "    as files already inserted in the tileindex will be inserted (unless t_srs is specified).\n"
             "  o If -t_srs is specified, geometries of input files will be transformed to the desired\n"
             "    target coordinate reference system.\n"
-            "    Note that using this option generates files that are NOT compatible with MapServer.\n"
+            "    Note that using this option generates files that are NOT compatible with MapServer < 6.4.\n"
             "  o Simple rectangular polygons are generated in the same coordinate reference system\n"
             "    as the rasters, or in target reference system if the -t_srs option is used.\n");
 
@@ -79,10 +81,21 @@ static void Usage(const char* pszErrorMsg)
     do { if (i_arg + nExtraArg >= argc) \
         Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i_arg], nExtraArg)); } while(0)
 
+typedef enum
+{
+    FORMAT_AUTO,
+    FORMAT_WKT,
+    FORMAT_EPSG,
+    FORMAT_PROJ
+} SrcSRSFormat;
+
 int main(int argc, char *argv[])
 {
+    const char* pszIndexLayerName = NULL;
     const char *index_filename = NULL;
     const char *tile_index = "location";
+    const char* pszDriverName = "ESRI Shapefile";
+    int nMaxFieldSize = 254;
     int		i_arg, ti_field;
     OGRDataSourceH hTileIndexDS;
     OGRLayerH hLayer = NULL;
@@ -95,12 +108,13 @@ int main(int argc, char *argv[])
     char** existingFilesTab = NULL;
     int alreadyExistingProjectionRefValid = FALSE;
     char* alreadyExistingProjectionRef = NULL;
-    char* index_filename_mod;
-    int bExists;
-    VSIStatBuf sStatBuf;
     const char *pszTargetSRS = "";
     int bSetTargetSRS = FALSE;
     OGRSpatialReferenceH hTargetSRS = NULL;
+    const char* pszSrcSRSName = NULL;
+    int i_SrcSRSName = -1;
+    int bSrcSRSFormatSpecified = FALSE;
+    SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO;
 
     /* Check that we are running against at least GDAL 1.4 */
     /* Note to developers : if we use newer API, please change the requirement */
@@ -131,6 +145,18 @@ int main(int argc, char *argv[])
         }
         else if( EQUAL(argv[i_arg],"--help") )
             Usage(NULL);
+        else if( strcmp(argv[i_arg],"-f") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszDriverName = argv[++i_arg];
+            if( !EQUAL(pszDriverName, "ESRI Shapefile") )
+                nMaxFieldSize = 0;
+        }
+        else if( strcmp(argv[i_arg],"-lyr_name") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszIndexLayerName = argv[++i_arg];
+        }
         else if( strcmp(argv[i_arg],"-tileindex") == 0 )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -150,8 +176,28 @@ int main(int argc, char *argv[])
         {
             skip_different_projection = TRUE;
         }
+        else if( strcmp(argv[i_arg], "-src_srs_name") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszSrcSRSName = argv[++i_arg];
+        }
+        else if( strcmp(argv[i_arg], "-src_srs_format") == 0 )
+        {
+            const char* pszFormat;
+            bSrcSRSFormatSpecified = TRUE;
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = argv[++i_arg];
+            if( EQUAL(pszFormat, "AUTO") )
+                eSrcSRSFormat = FORMAT_AUTO;
+            else if( EQUAL(pszFormat, "WKT") )
+                eSrcSRSFormat = FORMAT_WKT;
+            else if( EQUAL(pszFormat, "EPSG") )
+                eSrcSRSFormat = FORMAT_EPSG;
+            else if( EQUAL(pszFormat, "PROJ") )
+                eSrcSRSFormat = FORMAT_PROJ;
+        }
         else if( argv[i_arg][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i_arg]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i_arg]));
         else if( index_filename == NULL )
         {
             index_filename = argv[i_arg];
@@ -164,6 +210,8 @@ int main(int argc, char *argv[])
         Usage("No index filename specified.");
     if( i_arg == argc )
         Usage("No file to index specified.");
+    if( bSrcSRSFormatSpecified && pszSrcSRSName == NULL )
+        Usage("-src_srs_name must be specified when -src_srs_format is specified.");
 
 /* -------------------------------------------------------------------- */
 /*      Create and validate target SRS if given.                        */
@@ -187,31 +235,28 @@ int main(int argc, char *argv[])
    }
 
 /* -------------------------------------------------------------------- */
-/*      Open or create the target shapefile and DBF file.               */
+/*      Open or create the target datasource                            */
 /* -------------------------------------------------------------------- */
-    index_filename_mod = CPLStrdup(CPLResetExtension(index_filename, "shp"));
-
-    bExists = (VSIStat(index_filename_mod, &sStatBuf) == 0);
-    if (!bExists)
-    {
-        CPLFree(index_filename_mod);
-        index_filename_mod = CPLStrdup(CPLResetExtension(index_filename, "SHP"));
-        bExists = (VSIStat(index_filename_mod, &sStatBuf) == 0);
-    }
-    CPLFree(index_filename_mod);
-
-    if (bExists)
+    hTileIndexDS = OGROpen( index_filename, TRUE, NULL );
+    if (hTileIndexDS != NULL)
     {
-        hTileIndexDS = OGROpen( index_filename, TRUE, NULL );
-        if (hTileIndexDS != NULL)
-        {
+        if( OGR_DS_GetLayerCount(hTileIndexDS) == 1 )
             hLayer = OGR_DS_GetLayer(hTileIndexDS, 0);
+        else
+        {
+            if( pszIndexLayerName == NULL )
+            {
+                printf( "-lyr_name must be specified.\n" );
+                exit( 1 );
+            }
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            hLayer = OGR_DS_GetLayerByName(hTileIndexDS, pszIndexLayerName);
+            CPLPopErrorHandler();
         }
     }
     else
     {
         OGRSFDriverH hDriver;
-        const char* pszDriverName = "ESRI Shapefile";
 
         printf( "Creating new index file...\n" );
         hDriver = OGRGetDriverByName( pszDriverName );
@@ -222,40 +267,64 @@ int main(int argc, char *argv[])
         }
 
         hTileIndexDS = OGR_Dr_CreateDataSource( hDriver, index_filename, NULL );
-        if (hTileIndexDS)
-        {
-            char* pszLayerName = CPLStrdup(CPLGetBasename(index_filename));
+    }
 
-            /* get spatial reference for output file from target SRS (if set) */
-            /* or from first input file */
-            OGRSpatialReferenceH hSpatialRef = NULL;
-            if( bSetTargetSRS )
+    if( hTileIndexDS != NULL && hLayer == NULL )
+    {
+        OGRSpatialReferenceH hSpatialRef = NULL;
+        char* pszLayerName;
+        if( pszIndexLayerName == NULL )
+        {
+            VSIStatBuf sStat;
+            if( EQUAL(pszDriverName, "ESRI Shapefile") ||
+                VSIStat(index_filename, &sStat) == 0 )
+                pszLayerName = CPLStrdup(CPLGetBasename(index_filename));
+            else
             {
-                hSpatialRef = OSRClone( hTargetSRS );
+                printf( "-lyr_name must be specified.\n" );
+                exit( 1 );
             }
-            else
+        }
+        else
+            pszLayerName = CPLStrdup(pszIndexLayerName);
+
+        /* get spatial reference for output file from target SRS (if set) */
+        /* or from first input file */
+        if( bSetTargetSRS )
+        {
+            hSpatialRef = OSRClone( hTargetSRS );
+        }
+        else
+        {
+            GDALDatasetH hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
+            if (hDS)
             {
-                GDALDatasetH hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
-                if (hDS)
+                const char* pszWKT = GDALGetProjectionRef(hDS);
+                if (pszWKT != NULL && pszWKT[0] != '\0')
                 {
-                    const char* pszWKT = GDALGetProjectionRef(hDS);
-                    if (pszWKT != NULL && pszWKT[0] != '\0')
-                    {
-                        hSpatialRef = OSRNewSpatialReference(pszWKT);
-                    }
-                    GDALClose(hDS);
+                    hSpatialRef = OSRNewSpatialReference(pszWKT);
                 }
+                GDALClose(hDS);
             }
+        }
 
-            hLayer = OGR_DS_CreateLayer( hTileIndexDS, pszLayerName, hSpatialRef, wkbPolygon, NULL );
-            CPLFree(pszLayerName);
-            if (hSpatialRef)
-                OSRRelease(hSpatialRef);
+        hLayer = OGR_DS_CreateLayer( hTileIndexDS, pszLayerName, hSpatialRef, wkbPolygon, NULL );
+        CPLFree(pszLayerName);
+        if (hSpatialRef)
+            OSRRelease(hSpatialRef);
 
-            if (hLayer)
+        if (hLayer)
+        {
+            OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
+            if( nMaxFieldSize )
+                OGR_Fld_SetWidth( hFieldDefn, nMaxFieldSize);
+            OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
+            OGR_Fld_Destroy(hFieldDefn);
+            if( pszSrcSRSName != NULL )
             {
-                OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
-                OGR_Fld_SetWidth( hFieldDefn, 254);
+                hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString );
+                if( nMaxFieldSize )
+                    OGR_Fld_SetWidth( hFieldDefn, nMaxFieldSize);
                 OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
                 OGR_Fld_Destroy(hFieldDefn);
             }
@@ -271,23 +340,22 @@ int main(int argc, char *argv[])
 
     hFDefn = OGR_L_GetLayerDefn(hLayer);
 
-    for( ti_field = 0; ti_field < OGR_FD_GetFieldCount(hFDefn); ti_field++ )
-    {
-        OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, ti_field );
-        if( strcmp(OGR_Fld_GetNameRef(hFieldDefn), tile_index) == 0 )
-            break;
-    }
-
-    if( ti_field == OGR_FD_GetFieldCount(hFDefn) )
+    ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index );
+    if( ti_field < 0 )
     {
-        fprintf( stderr, "Unable to find field `%s' in DBF file `%s'.\n", 
+        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n", 
                  tile_index, index_filename );
         exit(2);
     }
+    
+    if( pszSrcSRSName != NULL )
+        i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName );
 
     /* Load in memory existing file names in SHP */
     nExistingFiles = OGR_L_GetFeatureCount(hLayer, FALSE);
-    if (nExistingFiles)
+    if( nExistingFiles < 0)
+        nExistingFiles = 0;
+    if (nExistingFiles > 0)
     {
         OGRFeatureH hFeature;
         existingFilesTab = (char**)CPLMalloc(nExistingFiles * sizeof(char*));
@@ -335,6 +403,7 @@ int main(int argc, char *argv[])
         int k;
         OGRFeatureH hFeature;
         OGRGeometryH hPoly, hRing;
+        OGRSpatialReferenceH hSourceSRS = NULL;
 
         /* Make sure it is a file before building absolute path name */
         if (write_absolute_path && CPLIsFilenameRelative( argv[i_arg] ) &&
@@ -461,12 +530,13 @@ int main(int argc, char *argv[])
             + 0 * adfGeoTransform[4] 
             + 0 * adfGeoTransform[5];
 
+        if( (bSetTargetSRS || i_SrcSRSName >= 0) && projectionRef != NULL && projectionRef[0] != '\0' )
+            hSourceSRS = OSRNewSpatialReference( projectionRef );
+
         /* if set target srs, do the forward transformation of all points */
-        if( bSetTargetSRS )
+        if( bSetTargetSRS && projectionRef != NULL && projectionRef[0] != '\0' )
         {
-            OGRSpatialReferenceH hSourceSRS = NULL;
             OGRCoordinateTransformationH hCT = NULL;
-            hSourceSRS = OSRNewSpatialReference( projectionRef );
             if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) )
             {
                 hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
@@ -485,13 +555,58 @@ int main(int argc, char *argv[])
                 if ( hCT ) 
                     OCTDestroyCoordinateTransformation( hCT );
             }
-            if ( hSourceSRS )
-                OSRDestroySpatialReference( hSourceSRS );
         }
 
         hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) );
         OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite );
 
+        if( i_SrcSRSName >= 0 && hSourceSRS != NULL )
+        {
+            const char* pszAuthorityCode = OSRGetAuthorityCode(hSourceSRS, NULL);
+            const char* pszAuthorityName = OSRGetAuthorityName(hSourceSRS, NULL);
+            if( eSrcSRSFormat == FORMAT_AUTO )
+            {
+                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
+                                        CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) );
+                else if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize )
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
+                else
+                {
+                    char* pszProj4 = NULL;
+                    if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
+                    {
+                        OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
+                        CPLFree(pszProj4);
+                    }
+                    else
+                        OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
+                }
+            }
+            else if( eSrcSRSFormat == FORMAT_WKT )
+            {
+                if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize )
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
+            }
+            else if( eSrcSRSFormat == FORMAT_PROJ )
+            {
+                char* pszProj4 = NULL;
+                if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
+                {
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
+                    CPLFree(pszProj4);
+                }
+            }
+            else if( eSrcSRSFormat == FORMAT_EPSG )
+            {
+                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
+                                        CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) );
+            }
+        }
+        if( hSourceSRS )
+            OSRDestroySpatialReference( hSourceSRS );
+
         hPoly = OGR_G_CreateGeometry(wkbPolygon);
         hRing = OGR_G_CreateGeometry(wkbLinearRing);
         for(k=0;k<5;k++)
diff --git a/apps/gdaltorture.cpp b/apps/gdaltorture.cpp
index a00079c..b2ca20c 100644
--- a/apps/gdaltorture.cpp
+++ b/apps/gdaltorture.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/apps/gdaltransform.cpp b/apps/gdaltransform.cpp
index 91ed857..dced22a 100644
--- a/apps/gdaltransform.cpp
+++ b/apps/gdaltransform.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -202,7 +203,7 @@ int main( int argc, char ** argv )
         }   
 
         else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
 
         else if( pszSrcFilename == NULL )
             pszSrcFilename = argv[i];
diff --git a/apps/gdalwarp.cpp b/apps/gdalwarp.cpp
index 75a7166..a917f7a 100644
--- a/apps/gdalwarp.cpp
+++ b/apps/gdalwarp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarp.cpp 26006 2013-05-16 15:00:44Z etourigny $
+ * $Id: gdalwarp.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -8,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 2002, i3 - information integration and imaging 
  *                          Fort Collin, CO
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "commonutils.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdalwarp.cpp 26006 2013-05-16 15:00:44Z etourigny $");
+CPL_CVSID("$Id: gdalwarp.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void
 LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
@@ -167,7 +168,8 @@ for output bands (different values can be supplied for each band).  If more
 than one value is supplied all values should be quoted to keep them together
 as a single operating system argument.  New files will be initialized to this
 value and if possible the nodata value will be recorded in the output
-file.</dd>
+file. Use a value of <tt>None</tt> to ensure that nodata is not defined (GDAL>=2.0).
+If this argument is not used then nodata values will be copied from the source dataset (GDAL>=2.0).</dd>
 <dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify 
 nodata (unset/transparent) pixels. </dd>
 <dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
@@ -209,8 +211,8 @@ use the -overwrite option.
 
 Polygon cutlines may be used as a mask to restrict the area of the destination file
 that may be updated, including blending.  If the OGR layer containing the cutline
-features has no explicit SRS, the cutline features must be in the georeferenced
-units of the destination file. When outputing to a not yet existing target dataset,
+features has no explicit SRS, the cutline features must be in the SRS of the
+destination file. When outputing to a not yet existing target dataset,
 its extent will be the one of the original raster unless -te or -crop_to_cutline are
 specified.
 
@@ -690,7 +692,7 @@ int main( int argc, char ** argv )
             bSetColorInterpretation = TRUE;
 
         else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
 
         else 
             papszSrcFiles = CSLAddString( papszSrcFiles, argv[i] );
@@ -891,6 +893,10 @@ int main( int argc, char ** argv )
     void* hUniqueTransformArg = NULL;
     GDALDatasetH hUniqueSrcDS = NULL;
 
+    const char* pszWarpThreads = CSLFetchNameValue(papszWarpOptions, "NUM_THREADS");
+    if( pszWarpThreads != NULL )
+        papszTO = CSLSetNameValue(papszTO, "NUM_THREADS", pszWarpThreads);
+
     if( hDstDS == NULL )
     {
         if (!bQuiet && !bFormatExplicitelySet)
@@ -987,10 +993,20 @@ int main( int argc, char ** argv )
                     {
                         hSrcBand = GDALGetRasterBand( hSrcDS, iBand + 1 );
                         hDstBand = GDALGetRasterBand( hDstDS, iBand + 1 );
-                        /* copy metadata */
+                        /* copy metadata, except stats (#5319) */
                         papszMetadata = GDALGetMetadata( hSrcBand, NULL);              
                         if ( CSLCount(papszMetadata) > 0 )
-                            GDALSetMetadata( hDstBand, papszMetadata, NULL );
+                        {
+                            //GDALSetMetadata( hDstBand, papszMetadata, NULL );       
+                            char** papszMetadataNew = NULL;
+                            for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
+                            {
+                                if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
+                                    papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
+                            }
+                            GDALSetMetadata( hDstBand, papszMetadataNew, NULL );
+                            CSLDestroy(papszMetadataNew);
+                        }
                         /* copy other info (Description, Unit Type) - what else? */
                         if ( bCopyBandInfo ) {
                             pszSrcInfo = GDALGetDescription( hSrcBand );
@@ -1167,7 +1183,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Setup NODATA options.                                           */
 /* -------------------------------------------------------------------- */
-        if( pszSrcNodata != NULL && !EQUALN(pszSrcNodata,"n",1) )
+        if( pszSrcNodata != NULL && !EQUAL(pszSrcNodata,"none") )
         {
             char **papszTokens = CSLTokenizeString( pszSrcNodata );
             int  nTokenCount = CSLCount(papszTokens);
@@ -1218,10 +1234,10 @@ int main( int argc, char ** argv )
                 if( !bQuiet )
                 {
                     if (CPLIsNan(dfReal))
-                        printf( "Using internal nodata values (eg. nan) for image %s.\n",
+                        printf( "Using internal nodata values (e.g. nan) for image %s.\n",
                                 papszSrcFiles[iSrc] );
                     else
-                        printf( "Using internal nodata values (eg. %g) for image %s.\n",
+                        printf( "Using internal nodata values (e.g. %g) for image %s.\n",
                                 dfReal, papszSrcFiles[iSrc] );
                 }
                 psWO->padfSrcNoDataReal = (double *) 
@@ -1257,6 +1273,7 @@ int main( int argc, char ** argv )
         {
             char **papszTokens = CSLTokenizeString( pszDstNodata );
             int  nTokenCount = CSLCount(papszTokens);
+            int bDstNoDataNone = TRUE;
 
             psWO->padfDstNoDataReal = (double *) 
                 CPLMalloc(psWO->nBandCount*sizeof(double));
@@ -1267,14 +1284,37 @@ int main( int argc, char ** argv )
             {
                 if( i < nTokenCount )
                 {
+                    if ( papszTokens[i] != NULL && EQUAL(papszTokens[i],"none") )
+                    {
+                        CPLDebug( "WARP", "dstnodata of band %d not set", i );
+                        bDstNoDataNone = TRUE;
+                        continue;
+                    }
+                    else if ( papszTokens[i] == NULL ) // this shouldn't happen, but just in case
+                    {
+                        fprintf( stderr, "Error parsing dstnodata arg #%d\n", i );
+                        bDstNoDataNone = TRUE;
+                        continue;
+                    }
                     CPLStringToComplex( papszTokens[i], 
                                         psWO->padfDstNoDataReal + i,
                                         psWO->padfDstNoDataImag + i );
+                    bDstNoDataNone = FALSE;
+                    CPLDebug( "WARP", "dstnodata of band %d set to %f", i, psWO->padfDstNoDataReal[i] );
                 }
                 else
                 {
-                    psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
-                    psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
+                    if ( ! bDstNoDataNone )
+                    {                    
+                        psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
+                        psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
+                        CPLDebug( "WARP", "dstnodata of band %d set from previous band", i );
+                    }
+                    else
+                    {
+                        CPLDebug( "WARP", "dstnodata value of band %d not set", i );
+                        continue;
+                    }
                 }
                 
                 GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
@@ -1336,6 +1376,44 @@ int main( int argc, char ** argv )
 
             CSLDestroy( papszTokens );
         }
+        /* else try to fill dstNoData from source bands */
+        else if ( psWO->padfSrcNoDataReal != NULL )
+        {
+            psWO->padfDstNoDataReal = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfDstNoDataImag = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            if( !bQuiet )
+                printf( "Copying nodata values from source %s to destination %s.\n",
+                        papszSrcFiles[iSrc], pszDstFilename );
+
+            for( i = 0; i < psWO->nBandCount; i++ )
+            {
+                int bHaveNodata = FALSE;
+                
+                GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, i+1 );
+                GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+
+                CPLDebug("WARP", "band=%d bHaveNodata=%d", i, bHaveNodata);
+                if( bHaveNodata )
+                {
+                    psWO->padfDstNoDataReal[i] = psWO->padfSrcNoDataReal[i];
+                    psWO->padfDstNoDataImag[i] = psWO->padfSrcNoDataImag[i];
+                    CPLDebug("WARP", "srcNoData=%f dstNoData=%f", 
+                             psWO->padfSrcNoDataReal[i], psWO->padfDstNoDataReal[i] );
+                }
+
+                if( bCreateOutput )
+                {
+                    CPLDebug("WARP", "calling GDALSetRasterNoDataValue() for band#%d", i );
+                    GDALSetRasterNoDataValue( 
+                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
+                        psWO->padfDstNoDataReal[i] );
+                }
+            }
+
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If we have a cutline, transform it into the source              */
@@ -1424,7 +1502,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
     GDALFlushCache( hDstDS );
-    if( CPLGetLastErrorType() != CE_None )
+    if( CPLGetLastErrorType() == CE_Failure )
         bHasGotErr = TRUE;
     GDALClose( hDstDS );
     
@@ -2230,16 +2308,20 @@ RemoveConflictingMetadata( GDALMajorObjectH hObj, char **papszMetadata,
     int nCount = CSLCount( papszMetadataRef ); 
 
     for( int i = 0; i < nCount; i++ ) 
-    { 
+    {
+        pszKey = NULL;
         pszValueRef = CPLParseNameValue( papszMetadataRef[i], &pszKey ); 
-        pszValueComp = GDALGetMetadataItem( hObj, pszKey, NULL );
-        if ( ( pszValueRef == NULL || pszValueComp == NULL ||
-               ! EQUAL( pszValueRef, pszValueComp ) ) &&
-             ( pszValueComp == NULL ||
-               ! EQUAL( pszValueComp, pszValueConflict ) ) ) {
-            GDALSetMetadataItem( hObj, pszKey, pszValueConflict, NULL ); 
-        }
-        CPLFree( pszKey ); 
+        if( pszKey != NULL )
+        {
+            pszValueComp = GDALGetMetadataItem( hObj, pszKey, NULL );
+            if ( ( pszValueRef == NULL || pszValueComp == NULL ||
+                ! EQUAL( pszValueRef, pszValueComp ) ) &&
+                ( pszValueComp == NULL ||
+                ! EQUAL( pszValueComp, pszValueConflict ) ) ) {
+                GDALSetMetadataItem( hObj, pszKey, pszValueConflict, NULL ); 
+            }
+            CPLFree( pszKey );
+        }
     } 
 
     CSLDestroy( papszMetadataRef );
diff --git a/apps/makefile.vc b/apps/makefile.vc
index a82ccb3..864847a 100644
--- a/apps/makefile.vc
+++ b/apps/makefile.vc
@@ -5,13 +5,13 @@ XTRAOBJ =	$(SETARGV)
 
 LIBS	=	$(GDAL_ROOT)\gdal_i.lib
 
-XTRAFLAGS =	-I..\frmts -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts
+XTRAFLAGS =	-I..\frmts -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS)
 
 !INCLUDE ..\nmake.opt
 
 !IFDEF INCLUDE_OGR_FRMTS
 OGR_PROGRAMS =	gdal_contour.exe gdaltindex.exe gdal_rasterize.exe \
-		gdal_grid.exe ogrinfo.exe ogr2ogr.exe ogrtindex.exe \
+		gdal_grid.exe ogrinfo.exe ogr2ogr.exe ogrtindex.exe ogrlineref.exe\
 		gdalbuildvrt.exe testepsg.exe
 !ENDIF
 
@@ -137,6 +137,11 @@ ogrtindex.exe:	ogrtindex.cpp $(GDALLIB) $(XTRAOBJ)
 	$(CC) $(CFLAGS) $(XTRAFLAGS) ogrtindex.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
+
+ogrlineref.exe:	ogrlineref.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) ogrlineref.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+		/link $(LINKER_FLAGS)
+	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 testepsg.exe:	testepsg.cpp $(GDALLIB) $(XTRAOBJ) 
 	$(CC) $(CFLAGS) $(XTRAFLAGS) testepsg.cpp $(XTRAOBJ) $(LIBS) \
diff --git a/apps/nearblack.cpp b/apps/nearblack.cpp
index 24e987b..bcc2b44 100644
--- a/apps/nearblack.cpp
+++ b/apps/nearblack.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nearblack.cpp 25582 2013-01-29 21:13:43Z rouault $
+ * $Id: nearblack.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Convert nearly black or nearly white border to exact black/white.
@@ -7,6 +7,7 @@
  *
  * ****************************************************************************
  * Copyright (c) 2006, MapShots Inc (www.mapshots.com)
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include <vector>
 #include "commonutils.h"
 
-CPL_CVSID("$Id: nearblack.cpp 25582 2013-01-29 21:13:43Z rouault $");
+CPL_CVSID("$Id: nearblack.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef std::vector<int> Color;
 typedef std::vector< Color > Colors;
@@ -222,7 +223,7 @@ int main( int argc, char ** argv )
             papszCreationOptions = CSLAddString(papszCreationOptions, argv[++i]);
         }
         else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         else if( pszInFile == NULL )
             pszInFile = argv[i];
         else
diff --git a/apps/ogr2ogr.cpp b/apps/ogr2ogr.cpp
index 02f4b52..9271fae 100644
--- a/apps/ogr2ogr.cpp
+++ b/apps/ogr2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.cpp 26349 2013-08-20 18:23:51Z rouault $
+ * $Id: ogr2ogr.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,14 +37,17 @@
 #include "gdal_alg.h"
 #include "commonutils.h"
 #include <map>
+#include <vector>
 
-CPL_CVSID("$Id: ogr2ogr.cpp 26349 2013-08-20 18:23:51Z rouault $");
+CPL_CVSID("$Id: ogr2ogr.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int bSkipFailures = FALSE;
-static int nGroupTransactions = 200;
+static int nGroupTransactions = 20000;
 static int bPreserveFID = FALSE;
 static int nFIDToFetch = OGRNullFID;
 
+#define COORD_DIM_LAYER_DIM -2
+
 static void Usage(int bShort = TRUE);
 static void Usage(const char* pszAdditionalMsg, int bShort = TRUE);
 
@@ -59,10 +63,11 @@ typedef struct
     GIntBig      nFeaturesRead;
     int          bPerFeatureCT;
     OGRLayer    *poDstLayer;
-    OGRCoordinateTransformation *poCT;
-    char       **papszTransformOptions;
+    OGRCoordinateTransformation **papoCT; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
+    char       ***papapszTransformOptions; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
     int         *panMap;
     int          iSrcZField;
+    int          iRequestedSrcGeomField;
 } TargetLayerInfo;
 
 typedef struct
@@ -79,14 +84,16 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
                                                 OGRSpatialReference *poOutputSRS,
                                                 int bNullifyOutputSRS,
                                                 char **papszSelFields,
-                                                int bAppend, int eGType,
+                                                int bAppend, int bAddMissingFields, int eGType,
                                                 int bPromoteToMulti,
                                                 int nCoordDim, int bOverwrite,
                                                 char** papszFieldTypesToString,
+                                                int bUnsetFieldWidth,
                                                 int bExplodeCollections,
                                                 const char* pszZField,
                                                 char **papszFieldMap,
-                                                const char* pszWHERE );
+                                                const char* pszWHERE,
+                                                int bExactFieldNameMatch );
 
 static void FreeTargetLayerInfo(TargetLayerInfo* psInfo);
 
@@ -349,12 +356,24 @@ class OGRSplitListFieldLayer : public OGRLayer
         poSrcLayer->SetSpatialFilter(poGeom);
     }
 
+    virtual void                 SetSpatialFilter( int iGeom, OGRGeometry *poGeom )
+    {
+        poSrcLayer->SetSpatialFilter(iGeom, poGeom);
+    }
+
     virtual void                 SetSpatialFilterRect( double dfMinX, double dfMinY,
                                                        double dfMaxX, double dfMaxY )
     {
         poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
     }
 
+    virtual void                 SetSpatialFilterRect( int iGeom,
+                                                       double dfMinX, double dfMinY,
+                                                       double dfMaxX, double dfMaxY )
+    {
+        poSrcLayer->SetSpatialFilterRect(iGeom, dfMinX, dfMinY, dfMaxX, dfMaxY);
+    }
+
     virtual OGRErr               SetAttributeFilter( const char *pszFilter )
     {
         return poSrcLayer->SetAttributeFilter(pszFilter);
@@ -491,7 +510,12 @@ int  OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
     poFeatureDefn =
             OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( poSrcFieldDefn->GetGeomType() );
+    poFeatureDefn->SetGeomType( wkbNone );
+    
+    for(i=0;i<poSrcFieldDefn->GetGeomFieldCount();i++)
+    {
+        poFeatureDefn->AddGeomFieldDefn(poSrcFieldDefn->GetGeomFieldDefn(i));
+    }
 
     int iListField = 0;
     for(i=0;i<nSrcFields;i++)
@@ -552,7 +576,10 @@ OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
 
     OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
     poFeature->SetFID(poSrcFeature->GetFID());
-    poFeature->SetGeometryDirectly(poSrcFeature->StealGeometry());
+    for(int i=0;i<poFeature->GetGeomFieldCount();i++)
+    {
+        poFeature->SetGeomFieldDirectly(i, poSrcFeature->StealGeometry(i));
+    }
     poFeature->SetStyleString(poFeature->GetStyleString());
 
     OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
@@ -793,6 +820,29 @@ public:
 };
 
 /************************************************************************/
+/*                        ApplySpatialFilter()                          */
+/************************************************************************/
+
+void ApplySpatialFilter(OGRLayer* poLayer, OGRGeometry* poSpatialFilter,
+                        const char* pszGeomField)
+{
+    if( poSpatialFilter != NULL )
+    {
+        if( pszGeomField != NULL )
+        {
+            int iGeomField = poLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
+            if( iGeomField >= 0 )
+                poLayer->SetSpatialFilter( iGeomField, poSpatialFilter );
+            else
+                printf("WARNING: Cannot find geometry field %s.\n",
+                    pszGeomField);
+        }
+        else
+            poLayer->SetSpatialFilter( poSpatialFilter );
+    }
+}
+
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -813,14 +863,17 @@ int main( int nArgc, char ** papszArgv )
     char        **papszDSCO = NULL, **papszLCO = NULL;
     int         bTransform = FALSE;
     int         bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
+    int         bAddMissingFields = FALSE;
     const char  *pszOutputSRSDef = NULL;
     const char  *pszSourceSRSDef = NULL;
     OGRSpatialReference *poOutputSRS = NULL;
     int         bNullifyOutputSRS = FALSE;
+    int         bExactFieldNameMatch = TRUE;
     OGRSpatialReference *poSourceSRS = NULL;
     char        *pszNewLayerName = NULL;
     const char  *pszWHERE = NULL;
     OGRGeometry *poSpatialFilter = NULL;
+    const char  *pszGeomField = NULL;
     const char  *pszSelect;
     char        **papszSelFields = NULL;
     const char  *pszSQLStatement = NULL;
@@ -830,6 +883,7 @@ int main( int nArgc, char ** papszArgv )
     GeomOperation eGeomOp = NONE;
     double       dfGeomOpParam = 0;
     char        **papszFieldTypesToString = NULL;
+    int          bUnsetFieldWidth = FALSE;
     int          bDisplayProgress = FALSE;
     GDALProgressFunc pfnProgress = NULL;
     void        *pProgressArg = NULL;
@@ -931,10 +985,20 @@ int main( int nArgc, char ** papszArgv )
             bOverwrite = TRUE;
             bUpdate = TRUE;
         }
+        else if( EQUAL(papszArgv[iArg],"-addfields") )
+        {
+            bAddMissingFields = TRUE;
+            bAppend = TRUE;
+            bUpdate = TRUE;
+        }
         else if( EQUAL(papszArgv[iArg],"-update") )
         {
             bUpdate = TRUE;
         }
+        else if( EQUAL(papszArgv[iArg],"-relaxedFieldNameMatch") )
+        {
+            bExactFieldNameMatch = FALSE;
+        }
         else if( EQUAL(papszArgv[iArg],"-fid") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -990,12 +1054,17 @@ int main( int nArgc, char ** papszArgv )
         else if( EQUAL(papszArgv[iArg],"-dim")  )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nCoordDim = atoi(papszArgv[iArg+1]);
-            if( nCoordDim != 2 && nCoordDim != 3 )
+            if( EQUAL(papszArgv[iArg+1], "layer_dim") )
+                nCoordDim = COORD_DIM_LAYER_DIM;
+            else
             {
-                fprintf( stderr, "-dim %s: value not handled.\n",
-                        papszArgv[iArg+1] );
-                exit( 1 );
+                nCoordDim = atoi(papszArgv[iArg+1]);
+                if( nCoordDim != 2 && nCoordDim != 3 )
+                {
+                    fprintf( stderr, "-dim %s: value not handled.\n",
+                            papszArgv[iArg+1] );
+                    exit( 1 );
+                }
             }
             iArg ++;
         }
@@ -1042,6 +1111,11 @@ int main( int nArgc, char ** papszArgv )
             ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
             iArg += 4;
         }
+        else if( EQUAL(papszArgv[iArg],"-geomfield") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszGeomField = papszArgv[++iArg];
+        }
         else if( EQUAL(papszArgv[iArg],"-where") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -1103,6 +1177,10 @@ int main( int nArgc, char ** papszArgv )
                 iter ++;
             }
         }
+        else if( EQUAL(papszArgv[iArg],"-unsetFieldWidth") )
+        {
+            bUnsetFieldWidth = TRUE;
+        }
         else if( EQUAL(papszArgv[iArg],"-progress") )
         {
             bDisplayProgress = TRUE;
@@ -1309,7 +1387,7 @@ int main( int nArgc, char ** papszArgv )
         }
         else if( papszArgv[iArg][0] == '-' )
         {
-            Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
         }
         else if( pszDestDataSource == NULL )
             pszDestDataSource = papszArgv[iArg];
@@ -1337,6 +1415,16 @@ int main( int nArgc, char ** papszArgv )
         Usage("if -fieldmap is specified, -append must also be specified");
     }
 
+    if (pszFieldMap && bAddMissingFields)
+    {
+        Usage("if -addfields is specified, -fieldmap cannot be used.");
+    }
+
+    if( pszSourceSRSDef != NULL && pszOutputSRSDef == NULL )
+    {
+        Usage("if -s_srs is specified, -t_srs must also be specified");
+    }
+
     if( bClipSrc && pszClipSrcDS != NULL)
     {
         poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
@@ -1613,11 +1701,22 @@ int main( int nArgc, char ** papszArgv )
         if( CSLCount(papszLayers) > 0 )
             fprintf( stderr,  "layer names ignored in combination with -sql.\n" );
         
-        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+        poResultSet = poDS->ExecuteSQL( pszSQLStatement,
+                                        (pszGeomField == NULL) ? poSpatialFilter : NULL, 
                                         pszDialect );
 
         if( poResultSet != NULL )
         {
+            if( poSpatialFilter != NULL && pszGeomField != NULL )
+            {
+                int iGeomField = poResultSet->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
+                if( iGeomField >= 0 )
+                    poResultSet->SetSpatialFilter( iGeomField, poSpatialFilter );
+                else
+                    printf("WARNING: Cannot find geometry field %s.\n",
+                           pszGeomField);
+            }
+
             long nCountLayerFeatures = 0;
             if (bDisplayProgress)
             {
@@ -1670,14 +1769,16 @@ int main( int nArgc, char ** papszArgv )
                                                 poOutputSRS,
                                                 bNullifyOutputSRS,
                                                 papszSelFields,
-                                                bAppend, eGType,
+                                                bAppend, bAddMissingFields, eGType,
                                                 bPromoteToMulti,
                                                 nCoordDim, bOverwrite,
                                                 papszFieldTypesToString,
+                                                bUnsetFieldWidth,
                                                 bExplodeCollections,
                                                 pszZField,
                                                 papszFieldMap,
-                                                pszWHERE );
+                                                pszWHERE,
+                                                bExactFieldNameMatch );
 
             poPassedLayer->ResetReading();
 
@@ -1699,7 +1800,7 @@ int main( int nArgc, char ** papszArgv )
                           "Terminating translation prematurely after failed\n"
                           "translation from sql statement." );
 
-                exit( 1 );
+                nRetCode = 1;
             }
 
             FreeTargetLayerInfo(psInfo);
@@ -1814,8 +1915,7 @@ int main( int nArgc, char ** papszArgv )
                     }
                 }
 
-                if( poSpatialFilter != NULL )
-                    poLayer->SetSpatialFilter( poSpatialFilter );
+                ApplySpatialFilter(poLayer, poSpatialFilter, pszGeomField);
 
                 TargetLayerInfo* psInfo = SetupTargetLayer( poDS,
                                                     poLayer,
@@ -1825,14 +1925,16 @@ int main( int nArgc, char ** papszArgv )
                                                     poOutputSRS,
                                                     bNullifyOutputSRS,
                                                     papszSelFields,
-                                                    bAppend, eGType,
+                                                    bAppend, bAddMissingFields, eGType,
                                                     bPromoteToMulti,
                                                     nCoordDim, bOverwrite,
                                                     papszFieldTypesToString,
+                                                    bUnsetFieldWidth,
                                                     bExplodeCollections,
                                                     pszZField,
                                                     papszFieldMap,
-                                                    pszWHERE );
+                                                    pszWHERE,
+						    bExactFieldNameMatch );
 
                 if( psInfo == NULL && !bSkipFailures )
                     exit(1);
@@ -1881,7 +1983,8 @@ int main( int nArgc, char ** papszArgv )
                                 "translation of layer %s (use -skipfailures to skip errors)\n",
                                 poLayer->GetName() );
 
-                        exit( 1 );
+                        nRetCode = 1;
+                        break;
                     }
                 }
                 else
@@ -1902,6 +2005,11 @@ int main( int nArgc, char ** papszArgv )
         }
         while( bHasLayersNonEmpty );
 
+        if (pfnProgress)
+        {
+            pfnProgress(1.0, "", pProgressArg);
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
@@ -2006,8 +2114,7 @@ int main( int nArgc, char ** papszArgv )
                 }
             }
 
-            if( poSpatialFilter != NULL )
-                poLayer->SetSpatialFilter( poSpatialFilter );
+            ApplySpatialFilter(poLayer, poSpatialFilter, pszGeomField);
 
             if (bDisplayProgress && !bSrcIsOSM)
             {
@@ -2026,7 +2133,7 @@ int main( int nArgc, char ** papszArgv )
 
         /* Second pass to do the real job */
         for( iLayer = 0; 
-            iLayer < nLayerCount; 
+            iLayer < nLayerCount && nRetCode == 0; 
             iLayer++ )
         {
             OGRLayer        *poLayer = papoLayers[iLayer];
@@ -2094,14 +2201,16 @@ int main( int nArgc, char ** papszArgv )
                                                 poOutputSRS,
                                                 bNullifyOutputSRS,
                                                 papszSelFields,
-                                                bAppend, eGType,
+                                                bAppend, bAddMissingFields, eGType,
                                                 bPromoteToMulti,
                                                 nCoordDim, bOverwrite,
                                                 papszFieldTypesToString,
+                                                bUnsetFieldWidth,
                                                 bExplodeCollections,
                                                 pszZField,
                                                 papszFieldMap,
-                                                pszWHERE );
+                                                pszWHERE,
+						bExactFieldNameMatch );
 
             poPassedLayer->ResetReading();
 
@@ -2125,7 +2234,7 @@ int main( int nArgc, char ** papszArgv )
                         "translation of layer %s (use -skipfailures to skip errors)\n", 
                         poLayer->GetName() );
 
-                exit( 1 );
+                nRetCode = 1;
             }
 
             FreeTargetLayerInfo(psInfo);
@@ -2204,11 +2313,11 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
             "               [-select field_list] [-where restricted_where]\n"
             "               [-progress] [-sql <sql statement>] [-dialect dialect]\n"
             "               [-preserve_fid] [-fid FID]\n"
-            "               [-spat xmin ymin xmax ymax]\n"
+            "               [-spat xmin ymin xmax ymax] [-geomfield field]\n"
             "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
             "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
             "               dst_datasource_name src_datasource_name\n"
-            "               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3] [layer [layer ...]]\n"
+            "               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3|layer_dim] [layer [layer ...]]\n"
             "\n"
             "Advanced options :\n"
             "               [-gt n]\n"
@@ -2220,7 +2329,9 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
             "               [-clipdstwhere expression]\n"
             "               [-wrapdateline][-datelineoffset val]\n"
             "               [[-simplify tolerance] | [-segmentize max_dist]]\n"
-            "               [-fieldTypeToString All|(type1[,type2]*)]\n"
+            "               [-addfields]\n"
+            "               [-relaxedFieldNameMatch]\n"
+            "               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]\n"
             "               [-fieldmap identity | index1[,index2]*]\n"
             "               [-splitlistfields] [-maxsubfields val]\n"
             "               [-explodecollections] [-zfield field_name]\n"
@@ -2260,7 +2371,7 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
             " -sql statement: Execute given SQL statement and save result.\n"
             " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
             " -skipfailures: skip features or layers that fail to convert\n"
-            " -gt n: group n features per transaction (default 200)\n"
+            " -gt n: group n features per transaction (default 20000)\n"
             " -spat xmin ymin xmax ymax: spatial query extents\n"
             " -simplify tolerance: distance tolerance for simplification.\n"
             " -segmentize max_dist: maximum distance between 2 nodes.\n"
@@ -2351,6 +2462,20 @@ static void SetZ (OGRGeometry* poGeom, double dfZ )
 }
 
 /************************************************************************/
+/*                       ForceCoordDimension()                          */
+/************************************************************************/
+
+static int ForceCoordDimension(int eGType, int nCoordDim)
+{
+    if( nCoordDim == 2 && eGType != wkbNone )
+        return eGType & ~wkb25DBit;
+    else if( nCoordDim == 3 && eGType != wkbNone )
+        return eGType | wkb25DBit;
+    else
+        return eGType;
+}
+
+/************************************************************************/
 /*                         SetupTargetLayer()                           */
 /************************************************************************/
 
@@ -2362,14 +2487,16 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
                                                 OGRSpatialReference *poOutputSRS,
                                                 int bNullifyOutputSRS,
                                                 char **papszSelFields,
-                                                int bAppend, int eGType,
+                                                int bAppend, int bAddMissingFields, int eGType,
                                                 int bPromoteToMulti,
                                                 int nCoordDim, int bOverwrite,
                                                 char** papszFieldTypesToString,
+                                                int bUnsetFieldWidth,
                                                 int bExplodeCollections,
                                                 const char* pszZField,
                                                 char **papszFieldMap,
-                                                const char* pszWHERE )
+                                                const char* pszWHERE,
+                                                int bExactFieldNameMatch )
 {
     OGRLayer    *poDstLayer;
     OGRFeatureDefn *poSrcFDefn;
@@ -2383,8 +2510,61 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
 /* -------------------------------------------------------------------- */
     poSrcFDefn = poSrcLayer->GetLayerDefn();
 
+/* -------------------------------------------------------------------- */
+/*      Find requested geometry fields.                                 */
+/* -------------------------------------------------------------------- */
+    std::vector<int> anRequestedGeomFields;
+    int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
+    if (papszSelFields && !bAppend )
+    {
+        for( int iField=0; papszSelFields[iField] != NULL; iField++)
+        {
+            int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
+            if (iSrcField >= 0)
+            {
+                /* do nothing */
+            }
+            else
+            {
+                iSrcField = poSrcFDefn->GetGeomFieldIndex(papszSelFields[iField]);
+                if( iSrcField >= 0)
+                {
+                    anRequestedGeomFields.push_back(iSrcField);
+                }
+                else
+                {
+                    fprintf( stderr, "Field '%s' not found in source layer.\n",
+                            papszSelFields[iField] );
+                    if( !bSkipFailures )
+                        return NULL;
+                }
+            }
+        }
+
+        if( anRequestedGeomFields.size() > 1 &&
+            !poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            fprintf( stderr, "Several geometry fields requested, but output "
+                                "datasource does not support multiple geometry "
+                                "fields.\n" );
+            if( !bSkipFailures )
+                return NULL;
+            else
+                anRequestedGeomFields.resize(0);
+        }
+    }
+
     if( poOutputSRS == NULL && !bNullifyOutputSRS )
-        poOutputSRS = poSrcLayer->GetSpatialRef();
+    {
+        if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.size() == 0 )
+            poOutputSRS = poSrcLayer->GetSpatialRef();
+        else if( anRequestedGeomFields.size() == 1 )
+        {
+            int iSrcGeomField = anRequestedGeomFields[0];
+            poOutputSRS = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->
+                GetSpatialRef();
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Find the layer.                                                 */
@@ -2436,9 +2616,28 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( poDstLayer == NULL )
     {
+        if( !poDstDS->TestCapability( ODsCCreateLayer ) )
+        {
+            fprintf( stderr,
+              "Layer %s not found, and CreateLayer not supported by driver.\n",
+                     pszNewLayerName );
+            return NULL;
+        }
+
+        int bForceGType = ( eGType != -2 );
         if( eGType == -2 )
         {
-            eGType = poSrcFDefn->GetGeomType();
+            if( anRequestedGeomFields.size() == 0 )
+            {
+                eGType = poSrcFDefn->GetGeomType();
+            }
+            else if( anRequestedGeomFields.size() == 1  )
+            {
+                int iSrcGeomField = anRequestedGeomFields[0];
+                eGType = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->GetType();
+            }
+            else
+                eGType = wkbNone;
 
             int n25DBit = eGType & wkb25DBit;
             if ( bPromoteToMulti )
@@ -2469,32 +2668,75 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
                 }
             }
 
-            if ( pszZField )
+            if ( pszZField && eGType != wkbNone )
                 eGType |= wkb25DBit;
         }
 
-        if( nCoordDim == 2 )
-            eGType &= ~wkb25DBit;
-        else if( nCoordDim == 3 )
-            eGType |= wkb25DBit;
+        eGType = ForceCoordDimension(eGType, nCoordDim);
 
-        if( !poDstDS->TestCapability( ODsCCreateLayer ) )
+        CPLErrorReset();
+
+        int eGCreateLayerType = eGType;
+        if( anRequestedGeomFields.size() == 0 &&
+            nSrcGeomFieldCount > 1 &&
+            poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
         {
-            fprintf( stderr,
-              "Layer %s not found, and CreateLayer not supported by driver.\n",
-                     pszNewLayerName );
-            return NULL;
+            eGCreateLayerType = wkbNone;
+        }
+        else if( anRequestedGeomFields.size() == 1 &&
+                 poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            eGCreateLayerType = wkbNone;
         }
-
-        CPLErrorReset();
 
         poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
-                                           (OGRwkbGeometryType) eGType,
+                                           (OGRwkbGeometryType) eGCreateLayerType,
                                            papszLCO );
 
         if( poDstLayer == NULL )
             return NULL;
 
+        if( anRequestedGeomFields.size() == 0 &&
+            nSrcGeomFieldCount > 1 &&
+            poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            for(int i = 0; i < nSrcGeomFieldCount; i ++)
+            {
+                anRequestedGeomFields.push_back(i);
+            }
+        }
+
+        if( anRequestedGeomFields.size() > 1 ||
+            (anRequestedGeomFields.size() == 1 &&
+                 poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer)) )
+        {
+            for(int i = 0; i < (int)anRequestedGeomFields.size(); i ++)
+            {
+                int iSrcGeomField = anRequestedGeomFields[i];
+                OGRGeomFieldDefn oGFldDefn
+                    (poSrcFDefn->GetGeomFieldDefn(iSrcGeomField));
+                if( poOutputSRS != NULL )
+                    oGFldDefn.SetSpatialRef(poOutputSRS);
+                if( bForceGType )
+                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
+                else
+                {
+                    eGType = oGFldDefn.GetType();
+                    int n25DBit = eGType & wkb25DBit;
+                    if ( bPromoteToMulti )
+                    {
+                        if (wkbFlatten(eGType) == wkbLineString)
+                            eGType = wkbMultiLineString | n25DBit;
+                        else if (wkbFlatten(eGType) == wkbPolygon)
+                            eGType = wkbMultiPolygon | n25DBit;
+                    }
+                    eGType = ForceCoordDimension(eGType, nCoordDim);
+                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
+                }
+                poDstLayer->CreateGeomField(&oGFldDefn);
+            }
+        }
+
         bAppend = FALSE;
     }
 
@@ -2504,7 +2746,7 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
     else if( !bAppend )
     {
         fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
-                "        Consider using -append, or -overwrite.\n",
+                         "        Consider using -append, or -overwrite.\n",
                 pszNewLayerName );
         return NULL;
     }
@@ -2513,7 +2755,7 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
         if( CSLCount(papszLCO) > 0 )
         {
             fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
-                    "         being appended to.\n" );
+                             "         being appended to.\n" );
         }
     }
 
@@ -2548,7 +2790,8 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
             bIdentity = TRUE;
         else if (CSLCount(papszFieldMap) != nSrcFieldCount)
         {
-            fprintf( stderr, "Field map should contain the value 'identity' or the same number of integer values as the source field count.\n");
+            fprintf( stderr, "Field map should contain the value 'identity' or "
+                    "the same number of integer values as the source field count.\n");
             VSIFree(panMap);
             return NULL;
         }
@@ -2584,6 +2827,11 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
                 {
                     oFieldDefn.SetType(OFTString);
                 }
+                if( bUnsetFieldWidth )
+                {
+                    oFieldDefn.SetWidth(0);
+                    oFieldDefn.SetPrecision(0);
+                }
 
                 /* The field may have been already created at layer creation */
                 int iDstField = -1;
@@ -2614,16 +2862,6 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
                     }
                 }
             }
-            else
-            {
-                fprintf( stderr, "Field '%s' not found in source layer.\n",
-                        papszSelFields[iField] );
-                if( !bSkipFailures )
-                {
-                    VSIFree(panMap);
-                    return NULL;
-                }
-            }
         }
 
         /* -------------------------------------------------------------------- */
@@ -2676,7 +2914,7 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
             CSLDestroy(papszWHEREUsedFields);
         }
     }
-    else if( !bAppend )
+    else if( !bAppend || bAddMissingFields )
     {
         int nDstFieldCount = 0;
         if (poDstFDefn)
@@ -2710,6 +2948,11 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
             {
                 oFieldDefn.SetType(OFTString);
             }
+            if( bUnsetFieldWidth )
+            {
+                oFieldDefn.SetWidth(0);
+                oFieldDefn.SetPrecision(0);
+            }
 
             /* The field may have been already created at layer creation */
             std::map<CPLString, int>::iterator oIter =
@@ -2789,7 +3032,7 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
         for( iField = 0; iField < nSrcFieldCount; iField++ )
         {
             OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
-            int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
+            int iDstField = poDstLayer->FindFieldIndex(poSrcFieldDefn->GetNameRef(), bExactFieldNameMatch);
             if (iDstField >= 0)
                 panMap[iField] = iDstField;
             else
@@ -2809,10 +3052,18 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS,
     psInfo->nFeaturesRead = 0;
     psInfo->bPerFeatureCT = FALSE;
     psInfo->poDstLayer = poDstLayer;
-    psInfo->poCT = NULL;
-    psInfo->papszTransformOptions = NULL;
+    psInfo->papoCT = (OGRCoordinateTransformation**)
+        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
+                  sizeof(OGRCoordinateTransformation*));
+    psInfo->papapszTransformOptions = (char***)
+        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
+                  sizeof(char**));
     psInfo->panMap = panMap;
     psInfo->iSrcZField = iSrcZField;
+    if( anRequestedGeomFields.size() == 1 )
+        psInfo->iRequestedSrcGeomField = anRequestedGeomFields[0];
+    else
+        psInfo->iRequestedSrcGeomField = -1;
 
     return psInfo;
 }
@@ -2825,13 +3076,175 @@ static void FreeTargetLayerInfo(TargetLayerInfo* psInfo)
 {
     if( psInfo == NULL )
         return;
-    delete psInfo->poCT;
-    CSLDestroy(psInfo->papszTransformOptions);
+    for(int i=0;i<psInfo->poDstLayer->GetLayerDefn()->GetGeomFieldCount();i++)
+    {
+        delete psInfo->papoCT[i];
+        CSLDestroy(psInfo->papapszTransformOptions[i]);
+    }
+    CPLFree(psInfo->papoCT);
+    CPLFree(psInfo->papapszTransformOptions);
     CPLFree(psInfo->panMap);
     CPLFree(psInfo);
 }
 
 /************************************************************************/
+/*                               SetupCT()                              */
+/************************************************************************/
+
+static int SetupCT( TargetLayerInfo* psInfo,
+                    OGRLayer* poSrcLayer,
+                    int bTransform,
+                    int bWrapDateline,
+                    const char* pszDateLineOffset,
+                    OGRSpatialReference* poUserSourceSRS,
+                    OGRFeature* poFeature,
+                    OGRSpatialReference* poOutputSRS,
+                    OGRCoordinateTransformation* poGCPCoordTrans)
+{
+    OGRLayer    *poDstLayer = psInfo->poDstLayer;
+    int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
+    for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Setup coordinate transformation if we need it.                  */
+/* -------------------------------------------------------------------- */
+        OGRSpatialReference* poSourceSRS = NULL;
+        OGRCoordinateTransformation* poCT = NULL;
+        char** papszTransformOptions = NULL;
+        
+        int iSrcGeomField;
+        if( psInfo->iRequestedSrcGeomField >= 0 )
+            iSrcGeomField = psInfo->iRequestedSrcGeomField;
+        else
+        {
+            iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
+                poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetNameRef());
+            if( iSrcGeomField < 0 )
+            {
+                if( nDstGeomFieldCount == 1 && 
+                    poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
+                {
+                    iSrcGeomField = 0;
+                }
+                else
+                    continue;
+            }
+        }
+        
+        if( bTransform || bWrapDateline )
+        {
+            if( psInfo->nFeaturesRead == 0 )
+            {
+                poSourceSRS = poUserSourceSRS;
+                if( poSourceSRS == NULL )
+                {
+                    if( iSrcGeomField > 0 )
+                        poSourceSRS = poSrcLayer->GetLayerDefn()->
+                            GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
+                    else
+                        poSourceSRS = poSrcLayer->GetSpatialRef();
+                }
+            }
+            if( poSourceSRS == NULL )
+            {
+                OGRGeometry* poSrcGeometry =
+                    poFeature->GetGeomFieldRef(iSrcGeomField);
+                if( poSrcGeometry )
+                    poSourceSRS = poSrcGeometry->getSpatialReference();
+                psInfo->bPerFeatureCT = TRUE;
+            }
+        }
+
+        if( bTransform )
+        {
+            if( poSourceSRS == NULL )
+            {
+                fprintf( stderr, "Can't transform coordinates, source layer has no\n"
+                        "coordinate system.  Use -s_srs to set one.\n" );
+
+                return FALSE;
+            }
+
+            CPLAssert( NULL != poSourceSRS );
+            CPLAssert( NULL != poOutputSRS );
+
+            if( psInfo->papoCT[iGeom] != NULL &&
+                psInfo->papoCT[iGeom]->GetSourceCS() == poSourceSRS )
+            {
+                poCT = psInfo->papoCT[iGeom];
+            }
+            else
+            {
+                poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
+                if( poCT == NULL )
+                {
+                    char        *pszWKT = NULL;
+
+                    fprintf( stderr, "Failed to create coordinate transformation between the\n"
+                        "following coordinate systems.  This may be because they\n"
+                        "are not transformable, or because projection services\n"
+                        "(PROJ.4 DLL/.so) could not be loaded.\n" );
+
+                    poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                    fprintf( stderr,  "Source:\n%s\n", pszWKT );
+                    CPLFree(pszWKT);
+
+                    poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                    fprintf( stderr,  "Target:\n%s\n", pszWKT );
+                    CPLFree(pszWKT);
+
+                    return FALSE;
+                }
+                if( poGCPCoordTrans != NULL )
+                    poCT = new CompositeCT( poGCPCoordTrans, poCT );
+            }
+
+            if( poCT != psInfo->papoCT[iGeom] )
+            {
+                delete psInfo->papoCT[iGeom];
+                psInfo->papoCT[iGeom] = poCT;
+            }
+        }
+        else
+        {
+            poCT = poGCPCoordTrans;
+        }
+
+        if (bWrapDateline)
+        {
+            if (bTransform && poCT != NULL && poOutputSRS != NULL && poOutputSRS->IsGeographic())
+            {
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
+                CPLString soOffset("DATELINEOFFSET=");
+                soOffset += pszDateLineOffset;
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, soOffset);
+            }
+            else if (poSourceSRS != NULL && poSourceSRS->IsGeographic())
+            {
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
+                CPLString soOffset("DATELINEOFFSET=");
+                soOffset += pszDateLineOffset;
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, soOffset);
+            }
+            else
+            {
+                static int bHasWarned = FALSE;
+                if( !bHasWarned )
+                    fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
+                bHasWarned = TRUE;
+            }
+
+            CSLDestroy(psInfo->papapszTransformOptions[iGeom]);
+            psInfo->papapszTransformOptions[iGeom] = papszTransformOptions;
+        }
+    }
+    return TRUE;
+}
+/************************************************************************/
 /*                           TranslateLayer()                           */
 /************************************************************************/
 
@@ -2865,17 +3278,28 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
     int         bForceToPolygon = FALSE;
     int         bForceToMultiPolygon = FALSE;
     int         bForceToMultiLineString = FALSE;
-    char**      papszTransformOptions = NULL;
-    OGRCoordinateTransformation *poCT = NULL;
     int         *panMap = NULL;
     int         iSrcZField;
 
     poDstLayer = psInfo->poDstLayer;
     panMap = psInfo->panMap;
     iSrcZField = psInfo->iSrcZField;
+    int nSrcGeomFieldCount = poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
+    int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
 
     if( poOutputSRS == NULL && !bNullifyOutputSRS )
-        poOutputSRS = poSrcLayer->GetSpatialRef();
+    {
+        if( nSrcGeomFieldCount == 1 )
+        {
+            poOutputSRS = poSrcLayer->GetSpatialRef();
+        }
+        else if( psInfo->iRequestedSrcGeomField > 0 )
+        {
+            poOutputSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(
+                psInfo->iRequestedSrcGeomField)->GetSpatialRef();
+        }
+
+    }
     
     if( wkbFlatten(eGType) == wkbPolygon )
         bForceToPolygon = TRUE;
@@ -2883,6 +3307,11 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
         bForceToMultiPolygon = TRUE;
     else if( wkbFlatten(eGType) == wkbMultiLineString )
         bForceToMultiLineString = TRUE;
+    
+    if( bExplodeCollections && nDstGeomFieldCount > 1 )
+    {
+        bExplodeCollections = FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Transfer features.                                              */
@@ -2915,133 +3344,13 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
 
         if( psInfo->nFeaturesRead == 0 || psInfo->bPerFeatureCT )
         {
-        /* -------------------------------------------------------------------- */
-        /*      Setup coordinate transformation if we need it.                  */
-        /* -------------------------------------------------------------------- */
-            OGRSpatialReference* poSourceSRS = NULL;
-
-            poCT = NULL;
-            papszTransformOptions = NULL;
-
-            if( bTransform )
-            {
-                if( psInfo->nFeaturesRead == 0 )
-                {
-                    poSourceSRS = poUserSourceSRS;
-                    if( poSourceSRS == NULL )
-                        poSourceSRS = poSrcLayer->GetSpatialRef();
-                }
-                if( poSourceSRS == NULL )
-                {
-                    OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
-                    if( poSrcGeometry )
-                        poSourceSRS = poSrcGeometry->getSpatialReference();
-                    psInfo->bPerFeatureCT = TRUE;
-                }
-
-                if( poSourceSRS == NULL )
-                {
-                    fprintf( stderr, "Can't transform coordinates, source layer has no\n"
-                            "coordinate system.  Use -s_srs to set one.\n" );
-                    OGRFeature::DestroyFeature( poFeature );
-                    return FALSE;
-                }
-
-                CPLAssert( NULL != poSourceSRS );
-                CPLAssert( NULL != poOutputSRS );
-
-                if( psInfo->poCT != NULL &&
-                    psInfo->poCT->GetSourceCS() == poSourceSRS )
-                {
-                    poCT = psInfo->poCT;
-                }
-                else
-                {
-                    poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
-                    if( poCT == NULL )
-                    {
-                        char        *pszWKT = NULL;
-
-                        fprintf( stderr, "Failed to create coordinate transformation between the\n"
-                            "following coordinate systems.  This may be because they\n"
-                            "are not transformable, or because projection services\n"
-                            "(PROJ.4 DLL/.so) could not be loaded.\n" );
-
-                        poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
-                        fprintf( stderr,  "Source:\n%s\n", pszWKT );
-                        CPLFree(pszWKT);
-
-                        poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
-                        fprintf( stderr,  "Target:\n%s\n", pszWKT );
-                        CPLFree(pszWKT);
-
-                        OGRFeature::DestroyFeature( poFeature );
-                        return FALSE;
-                    }
-                    if( poGCPCoordTrans != NULL )
-                        poCT = new CompositeCT( poGCPCoordTrans, poCT );
-                }
-
-                if( poCT != psInfo->poCT )
-                {
-                    delete psInfo->poCT;
-                    psInfo->poCT = poCT;
-                }
-            }
-            else
+            if( !SetupCT( psInfo, poSrcLayer, bTransform, bWrapDateline,
+                          pszDateLineOffset, poUserSourceSRS,
+                          poFeature, poOutputSRS, poGCPCoordTrans) )
             {
-                poCT = poGCPCoordTrans;
-            }
-
-            if (bWrapDateline)
-            {
-                if( poSourceSRS == NULL )
-                {
-                    if( psInfo->nFeaturesRead == 0 )
-                    {
-                        poSourceSRS = poUserSourceSRS;
-                        if( poSourceSRS == NULL )
-                            poSourceSRS = poSrcLayer->GetSpatialRef();
-                    }
-                    if( poSourceSRS == NULL )
-                    {
-                        OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
-                        if( poSrcGeometry )
-                            poSourceSRS = poSrcGeometry->getSpatialReference();
-                        psInfo->bPerFeatureCT = TRUE;
-                    }
-                }
-
-                if (bTransform && poCT != NULL && poOutputSRS != NULL && poOutputSRS->IsGeographic())
-                {
-                    papszTransformOptions =
-                        CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                    CPLString soOffset("DATELINEOFFSET=");
-                    soOffset += pszDateLineOffset;
-                    papszTransformOptions =
-                        CSLAddString(papszTransformOptions, soOffset);
-                }
-                else if (poSourceSRS != NULL && poSourceSRS->IsGeographic())
-                {
-                    papszTransformOptions =
-                        CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                    CPLString soOffset("DATELINEOFFSET=");
-                    soOffset += pszDateLineOffset;
-                    papszTransformOptions =
-                        CSLAddString(papszTransformOptions, soOffset);
-                }
-                else
-                {
-                    static int bHasWarned = FALSE;
-                    if( !bHasWarned )
-                        fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
-                    bHasWarned = TRUE;
-                }
-
-                CSLDestroy(psInfo->papszTransformOptions);
-                psInfo->papszTransformOptions = papszTransformOptions;
+                OGRFeature::DestroyFeature( poFeature );
+                return FALSE;
             }
-
         }
 
         psInfo->nFeaturesRead ++;
@@ -3050,7 +3359,12 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
         int nIters = 1;
         if (bExplodeCollections)
         {
-            OGRGeometry* poSrcGeometry = poFeature->GetGeometryRef();
+            OGRGeometry* poSrcGeometry;
+            if( psInfo->iRequestedSrcGeomField >= 0 )
+                poSrcGeometry = poFeature->GetGeomFieldRef(
+                                        psInfo->iRequestedSrcGeomField);
+            else
+                poSrcGeometry = poFeature->GetGeometryRef();
             if (poSrcGeometry)
             {
                 switch (wkbFlatten(poSrcGeometry->getGeometryType()))
@@ -3083,9 +3397,18 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
 
             /* Optimization to avoid duplicating the source geometry in the */
             /* target feature : we steal it from the source feature for now... */
-            OGRGeometry* poStealedGeometry = NULL;
-            if( !bExplodeCollections )
-                poStealedGeometry = poFeature->StealGeometry();
+            OGRGeometry* poStolenGeometry = NULL;
+            if( !bExplodeCollections && nSrcGeomFieldCount == 1 &&
+                nDstGeomFieldCount == 1 )
+            {
+                poStolenGeometry = poFeature->StealGeometry();
+            }
+            else if( !bExplodeCollections &&
+                     psInfo->iRequestedSrcGeomField >= 0 )
+            {
+                poStolenGeometry = poFeature->StealGeometry(
+                    psInfo->iRequestedSrcGeomField);
+            }
 
             if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
             {
@@ -3098,26 +3421,31 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
 
                 OGRFeature::DestroyFeature( poFeature );
                 OGRFeature::DestroyFeature( poDstFeature );
-                OGRGeometryFactory::destroyGeometry( poStealedGeometry );
+                OGRGeometryFactory::destroyGeometry( poStolenGeometry );
                 return FALSE;
             }
 
-            /* ... and now we can attach the stealed geometry */
-            if( poStealedGeometry )
-                poDstFeature->SetGeometryDirectly(poStealedGeometry);
+            /* ... and now we can attach the stolen geometry */
+            if( poStolenGeometry )
+            {
+                poDstFeature->SetGeometryDirectly(poStolenGeometry);
+            }
 
             if( bPreserveFID )
                 poDstFeature->SetFID( poFeature->GetFID() );
-
-            OGRGeometry* poDstGeometry = poDstFeature->GetGeometryRef();
-            if (poDstGeometry != NULL)
+            
+            for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
             {
+                OGRGeometry* poDstGeometry = poDstFeature->GetGeomFieldRef(iGeom);
+                if (poDstGeometry == NULL)
+                    continue;
+
                 if (nParts > 0)
                 {
                     /* For -explodecollections, extract the iPart(th) of the geometry */
                     OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
                     ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
-                    poDstFeature->SetGeometryDirectly(poPart);
+                    poDstFeature->SetGeomFieldDirectly(iGeom, poPart);
                     poDstGeometry = poPart;
                 }
 
@@ -3126,12 +3454,15 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                     SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
                     /* This will correct the coordinate dimension to 3 */
                     OGRGeometry* poDupGeometry = poDstGeometry->clone();
-                    poDstFeature->SetGeometryDirectly(poDupGeometry);
+                    poDstFeature->SetGeomFieldDirectly(iGeom, poDupGeometry);
                     poDstGeometry = poDupGeometry;
                 }
 
                 if (nCoordDim == 2 || nCoordDim == 3)
                     poDstGeometry->setCoordinateDimension( nCoordDim );
+                else if ( nCoordDim == COORD_DIM_LAYER_DIM )
+                    poDstGeometry->setCoordinateDimension(
+                        (poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetType() & wkb25DBit) ? 3 : 2 );
 
                 if (eGeomOp == SEGMENTIZE)
                 {
@@ -3145,7 +3476,7 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                         OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
                         if (poNewGeom)
                         {
-                            poDstFeature->SetGeometryDirectly(poNewGeom);
+                            poDstFeature->SetGeomFieldDirectly(iGeom, poNewGeom);
                             poDstGeometry = poNewGeom;
                         }
                     }
@@ -3159,9 +3490,14 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                         OGRGeometryFactory::destroyGeometry(poClipped);
                         goto end_loop;
                     }
-                    poDstFeature->SetGeometryDirectly(poClipped);
+                    poDstFeature->SetGeomFieldDirectly(iGeom, poClipped);
                     poDstGeometry = poClipped;
                 }
+                
+                OGRCoordinateTransformation* poCT = psInfo->papoCT[iGeom];
+                if( !bTransform )
+                    poCT = poGCPCoordTrans;
+                char** papszTransformOptions = psInfo->papapszTransformOptions[iGeom];
 
                 if( poCT != NULL || papszTransformOptions != NULL)
                 {
@@ -3182,7 +3518,7 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                         }
                     }
 
-                    poDstFeature->SetGeometryDirectly(poReprojectedGeom);
+                    poDstFeature->SetGeomFieldDirectly(iGeom, poReprojectedGeom);
                     poDstGeometry = poReprojectedGeom;
                 }
                 else if (poOutputSRS != NULL)
@@ -3199,29 +3535,29 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                         goto end_loop;
                     }
 
-                    poDstFeature->SetGeometryDirectly(poClipped);
+                    poDstFeature->SetGeomFieldDirectly(iGeom, poClipped);
                     poDstGeometry = poClipped;
                 }
 
                 if( bForceToPolygon )
                 {
-                    poDstFeature->SetGeometryDirectly(
+                    poDstFeature->SetGeomFieldDirectly(iGeom, 
                         OGRGeometryFactory::forceToPolygon(
-                            poDstFeature->StealGeometry() ) );
+                            poDstFeature->StealGeometry(iGeom) ) );
                 }
                 else if( bForceToMultiPolygon ||
                         (bPromoteToMulti && wkbFlatten(poDstGeometry->getGeometryType()) == wkbPolygon) )
                 {
-                    poDstFeature->SetGeometryDirectly(
+                    poDstFeature->SetGeomFieldDirectly(iGeom, 
                         OGRGeometryFactory::forceToMultiPolygon(
-                            poDstFeature->StealGeometry() ) );
+                            poDstFeature->StealGeometry(iGeom) ) );
                 }
                 else if ( bForceToMultiLineString ||
                         (bPromoteToMulti && wkbFlatten(poDstGeometry->getGeometryType()) == wkbLineString) )
                 {
-                    poDstFeature->SetGeometryDirectly(
+                    poDstFeature->SetGeomFieldDirectly(iGeom, 
                         OGRGeometryFactory::forceToMultiLineString(
-                            poDstFeature->StealGeometry() ) );
+                            poDstFeature->StealGeometry(iGeom) ) );
                 }
             }
 
@@ -3235,10 +3571,19 @@ static int TranslateLayer( TargetLayerInfo* psInfo,
                 if( nGroupTransactions )
                     poDstLayer->RollbackTransaction();
 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to write feature %ld from layer %s.\n",
+                        poFeature->GetFID(), poSrcLayer->GetName() );
+
                 OGRFeature::DestroyFeature( poFeature );
                 OGRFeature::DestroyFeature( poDstFeature );
                 return FALSE;
             }
+            else
+            {
+                CPLDebug( "OGR2OGR", "Unable to write feature %ld into layer %s.\n",
+                           poFeature->GetFID(), poSrcLayer->GetName() );
+            }
 
 end_loop:
             OGRFeature::DestroyFeature( poDstFeature );
diff --git a/apps/ogr_utilities.dox b/apps/ogr_utilities.dox
index 696f80d..94b46cc 100644
--- a/apps/ogr_utilities.dox
+++ b/apps/ogr_utilities.dox
@@ -7,6 +7,7 @@ toolkit:
 <li> \ref ogrinfo - Lists information about an OGR supported data source
 <li> \ref ogr2ogr - Converts simple features data between file formats
 <li> \ref ogrtindex - Creates a tileindex
+<li> \ref ogrlineref - Create linear reference and provide some calculations using it
 </ul>
 
 */
@@ -23,7 +24,7 @@ Usage:
 
 \verbatim
 ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]
-        [-spat xmin ymin xmax ymax] [-fid fid]
+        [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
         [-sql statement] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
         [-geom={YES/NO/SUMMARY}][--formats]
         datasource_name [layer [layer ...]]
@@ -53,6 +54,8 @@ and return the result.</dd>
 Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasource.</dd>
 <dt> <b>-spat</b> <i>xmin ymin xmax ymax</i>:</dt><dd> The area of interest.  Only
 features within the rectangle will be reported.</dd>
+<dt> <b>-geomfield</b> <i>field</i>:</dt><dd> (OGR >= 1.11) Name of the geometry field
+on which the spatial filter operates on.</dd>
 <dt> <b>-fid</b> <i>fid</i>:</dt><dd> If provided, only the feature with this feature
 id will be reported.  Operates exclusive of the spatial or attribute 
 queries. Note: if you want to select several features based on their feature id, you can
@@ -171,11 +174,11 @@ Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
                [-select field_list] [-where restricted_where] 
                [-progress] [-sql <sql statement>] [-dialect dialect]
                [-preserve_fid] [-fid FID]
-               [-spat xmin ymin xmax ymax]
+               [-spat xmin ymin xmax ymax] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
                [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
                dst_datasource_name src_datasource_name
-               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3] [layer [layer ...]]
+               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
                [-gt n]
@@ -187,7 +190,8 @@ Advanced options :
                [-clipdstwhere expression]
                [-wrapdateline] [-datelineoffset val]
                [[-simplify tolerance] | [-segmentize max_dist]]
-               [-fieldTypeToString All|(type1[,type2]*)]
+               [-addfields]
+               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]
                [-fieldmap identity | index1[,index2]*]
                [-splitlistfields] [-maxsubfields val]
                [-explodecollections] [-zfield field_name]
@@ -220,7 +224,8 @@ new</dd>
 fields from input layer to copy to the new layer. A field is skipped if
 mentioned previously in the list even if the input layer has duplicate field
 names.  (Defaults to all; any field is skipped if a subsequent field with
-same name is found.)</dd>
+same name is found.) Starting with OGR 1.11, geometry fields can also be specified
+in the list.</dd>
 <dt> <b>-progress</b>:</dt><dd> (starting with GDAL 1.7.0) Display progress on terminal. Only works if input layers have the "fast feature count" capability.</dd>
 <dt> <b>-sql</b> <em>sql_statement</em>:</dt><dd> SQL statement to execute.
 The resulting table/layer will be saved to the output.</dd>
@@ -230,6 +235,8 @@ Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasour
 <dt> <b>-skipfailures</b>:</dt><dd>Continue after a failure, skipping the failed feature.</dd>
 <dt> <b>-spat</b><em> xmin ymin xmax ymax</em>:</dt><dd> spatial query extents. Only features
 whose geometry intersects the extents will be selected. The geometries will not be clipped unless -clipsrc is specified</dd>
+<dt> <b>-geomfield</b> <i>field</i>:</dt><dd> (OGR >= 1.11) Name of the geometry field
+on which the spatial filter operates on.</dd>
 <dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option (format specific)</dd>
 <dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option (format specific)</dd>
 <dt> <b>-nln</b><em> name</em>:</dt><dd> Assign an alternate name to the new layer</dd>
@@ -242,7 +249,10 @@ that mix polygon or multipolygons to multipolygons, and layers that mix linestri
 multilinestrings to multilinestrings. Can be usefull when converting shapefiles to PostGIS
 (and other target drivers) that implements strict checks for geometry type.</dd>
 <dt> <b>-dim</b><em> val</em>:</dt><dd>(starting with GDAL 1.10) Force the coordinate dimension to val (valid values are 2 or 3).
-This affects both the layer geometry type, and feature geometries.</dd>
+This affects both the layer geometry type, and feature geometries.
+Starting with GDAL 1.11, the value can be set to "layer_dim" to instruct feature geometries to be promoted
+to the coordinate dimension declared by the layer.
+</dd>
 <dt> <b>-a_srs</b><em> srs_def</em>:</dt><dd> Assign an output SRS</dd>
 <dt> <b>-t_srs</b><em> srs_def</em>:</dt><dd> Reproject/transform to this SRS on output</dd>
 <dt> <b>-s_srs</b><em> srs_def</em>:</dt><dd> Override source SRS</dd>
@@ -260,7 +270,7 @@ known definition (ie. EPSG:4326) or a file with a WKT definition.
 Advanced options :
 
 <dl>
-<dt> <b>-gt</b> <em>n</em>:</dt><dd> group <em>n</em> features per transaction (default 200). Increase the value
+<dt> <b>-gt</b> <em>n</em>:</dt><dd> group <em>n</em> features per transaction (default 20000 in OGR 1.11, 200 in previous releases). Increase the value
 for better performance when writing into DBMS drivers that have transaction support.</dd>
 <dt> <b>-clipsrc</b><em> [xmin ymin xmax ymax]|WKT|datasource|spat_extent</em>:
 </dt><dd> (starting with GDAL 1.7.0) clip geometries to the specified bounding
@@ -288,6 +298,7 @@ Used to create intermediate points</dd>
 specified type to a field of type string in the destination layer. Valid types are : Integer, Real, String, Date, Time,
 DateTime, Binary, IntegerList, RealList, StringList. Special value <b>All</b> can be used to convert all fields to strings.
 This is an alternate way to using the CAST operator of OGR SQL, that may avoid typing a long SQL query.</dd>
+<dt> <b>-unsetFieldWidth</b>:</dt><dd> (starting with GDAL 1.11) set field width and precision to 0.</dd>
 <dt> <b>-splitlistfields</b>:</dt><dd>(starting with GDAL 1.8.0) split fields of type StringList, RealList or IntegerList into as many fields of type String, Real or Integer as necessary.</dd>
 <dt> <b>-maxsubfields</b> <em>val</em>:</dt><dd>To be combined with -splitlistfields to limit the number of subfields created for each split field.</dd>
 <dt> <b>-explodecollections</b>:</dt><dd>(starting with GDAL 1.8.0) produce one feature for each geometry in any kind of geometry collection in the source file</dd>
@@ -306,6 +317,11 @@ target layer definition in which the n(th) field of the source layer must be cop
 zero. There must be exactly as many values in the list as the count of the fields in the source layer. 
 We can use the 'identity' setting to specify that the fields should be transferred by using the same order. 
 This setting should be used along with the -append setting.</dd>
+<dt> <b>-addfields</b>:</dt><dd>(starting with GDAL 1.11) This is a specialized version of
+-append. Contrary to -append, -addfields has the effect of adding, to existing target layers,
+the new fields found in source layers. This option is usefull when merging files that have non-strictly
+identical structures.
+This might not work for output formats that don't support adding fields to existing non-empty layers.</dd>
 </dl>
 
 \section ogr2ogr_performance PERFORMANCE HINTS
@@ -314,8 +330,7 @@ When writing into transactional DBMS (SQLite/PostgreSQL,MySQL, etc...),
 it might be beneficial to increase the number
 of INSERT statements executed between BEGIN TRANSACTION and COMMIT TRANSACTION statements.
 This number is specified with the -gt option. For example, for SQLite, explicitly defining
-<b>-gt 1024</b> usually ensures a noticeable performance boost;
-defining an even bigger <b>-gt 65536</b> ensures optimal performance while
+<b>-gt 65536</b> ensures optimal performance while
 populating some table containing many hundredth thousand or million rows. However, note that
 if there are failed insertions, the scope of -skipfailures is a whole transaction.
 
@@ -419,3 +434,97 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 
 */
+
+/*! \page ogrlineref ogrlineref
+
+The utility can be used for:
+- create linear reference file from input data
+- return the "linear referenced" distance for the projection of the input coordinates (point) on the path
+- return the coordinates (point) on the path according to the "linear referenced" distance 
+- return the portion of the path according to the "linear referenced" begin and end distances
+
+\section ogrlineref_synopsis SYNOPSIS
+
+\htmlonly
+Usage:
+\endhtmlonly
+
+\verbatim
+ogrlineref [--help-general] [-progress] [-quiet]
+           [-f format_name] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE]...]
+           [-create]
+           [-l src_line_datasource_name] [-ln layer_name] [-lf field_name]
+           [-p src_repers_datasource_name] [-pn layer_name] [-pm pos_field_name] [-pf field_name]
+           [-r src_parts_datasource_name] [-rn layer_name]
+           [-o dst_datasource_name] [-on layer_name]  [-of field_name] [-s step]
+           [-get_pos] [-x long] [-y lat]
+           [-get_coord] [-m position]
+           [-get_subline] [-mb position] [-me position]
+\endverbatim
+
+\section ogrlineref_description DESCRIPTION
+
+The ogrlineref program can be used to create a linear reference - a file containing
+a segments of special length (e.g. 1 km in reference units) and get coordinates, 
+linear referenced distances or sublines (subpaths) from this file. The utility not
+required the M or Z values in geometry. The results can be stored in any OGR supported 
+format. Also some information writed to the stdout.  
+
+<dl>
+<dt><b>--help-general</b>:</dt><dd> Show the usage.</dd>
+<dt><b>-progress</b>:</dt><dd> Show progress.</dd>
+<dt><b>-quiet</b>:</dt><dd> Supress all messages except errors and results.</dd>
+<dt><b>-f</b> <em>format_name</em>:</dt><dd> Select an output format name.
+    The default is to create a shapefile.</dd>
+<dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option 
+    (format specific)</dd>
+<dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option 
+    (format specific)</dd>
+<dt><b>-create</b>:</dt><dd> Create the linear reference file (linestring of parts).</dd>
+<dt> <b>-l</b><em>src_line_datasource_name</em>:</dt><dd> The path to input linestring 
+    datasource (e.g. the road)</dd>
+<dt> <b>-ln</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
+<dt> <b>-lf</b><em>field_name</em>:</dt><dd> The field name of uniq values to 
+    separate the input lines (e.g. the set of roads)</dd>
+<dt> <b>-p</b><em>src_repers_datasource_name</em>:</dt><dd> The path to linear 
+    references points (e.g. the road mile-stones)</dd>
+<dt> <b>-pn</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
+<dt> <b>-pm</b><em>pos_field_name</em>:</dt><dd> The field name of distances 
+    along path (e.g. mile-stones values)</dd>
+<dt> <b>-pf</b><em>field_name</em>:</dt><dd> The field name of uniq values to 
+    map input reference points to lines</dd>
+<dt> <b>-r</b><em>src_parts_datasource_name</em>:</dt><dd> The path to linear 
+    reference file</dd>
+<dt> <b>-rn</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
+<dt> <b>-o</b><em>dst_datasource_name</em>:</dt><dd> The path to output linear 
+    reference file (linestring datasource)</dd>
+<dt> <b>-on</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
+<dt> <b>-of</b><em>field_name</em>:</dt><dd> The field name for storing the 
+    uniq values of input lines</dd>
+<dt> <b>-s</b><em>step</em>:</dt><dd> The part size in linear units</dd>
+<dt> <b>-get_pos</b>:</dt><dd> Return linear referenced postion for input X, Y</dd>
+<dt> <b>-x</b><em>long</em>:</dt><dd> Input X coordinate</dd>
+<dt> <b>-y</b><em>lat</em>:</dt><dd> Input Y coordinate</dd>
+<dt> <b>-get_coord</b>:</dt><dd> Return point on path for input linear distance</dd>
+<dt> <b>-m</b><em>position</em>:</dt><dd> The input linear distance</dd>
+<dt> <b>-get_subline</b>:</dt><dd> Return the portion of the input path from and to 
+    input linear positions</dd>
+<dt> <b>-mb</b><em>position</em>:</dt><dd> The input begin linear distance</dd>
+<dt> <b>-me</b><em>position</em>:</dt><dd> The input end linear distance</dd>
+</dl>
+
+\section ogrlineref_example EXAMPLE
+
+This example would create a shapefile (parts.shp) containing a data needed
+for linear referencing (1 km parts):
+\verbatim
+% ogrlineref -create -l roads.shp -p references.shp -pm dist -o parts.shp -s 1000 -progress
+\endverbatim
+
+\if man
+\section ogrlineref_author AUTHORS
+Dmitry Baryshnikov <polimax at mail.ru>
+
+\endif
+
+*/
\ No newline at end of file
diff --git a/apps/ogrinfo.cpp b/apps/ogrinfo.cpp
index f92edec..94b748d 100644
--- a/apps/ogrinfo.cpp
+++ b/apps/ogrinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.cpp 25582 2013-01-29 21:13:43Z rouault $
+ * $Id: ogrinfo.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing OGR driver data.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_multiproc.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: ogrinfo.cpp 25582 2013-01-29 21:13:43Z rouault $");
+CPL_CVSID("$Id: ogrinfo.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -45,7 +46,8 @@ char**  papszOptions = NULL;
 
 static void Usage(const char* pszErrorMsg = NULL);
 
-static void ReportOnLayer( OGRLayer *, const char *, OGRGeometry * );
+static void ReportOnLayer( OGRLayer *, const char *, const char* pszGeomField, 
+                           OGRGeometry * );
 
 /************************************************************************/
 /*                                main()                                */
@@ -66,6 +68,7 @@ int main( int nArgc, char ** papszArgv )
     const char  *pszSQLStatement = NULL;
     const char  *pszDialect = NULL;
     int          nRet = 0;
+    const char* pszGeomField = NULL;
     
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
@@ -120,6 +123,11 @@ int main( int nArgc, char ** papszArgv )
             ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
             iArg += 4;
         }
+        else if( EQUAL(papszArgv[iArg],"-geomfield") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszGeomField = papszArgv[++iArg];
+        }
         else if( EQUAL(papszArgv[iArg],"-where") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -165,7 +173,7 @@ int main( int nArgc, char ** papszArgv )
         }
         else if( papszArgv[iArg][0] == '-' )
         {
-            Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
         }
         else if( pszDataSource == NULL )
             pszDataSource = papszArgv[iArg];
@@ -245,7 +253,8 @@ int main( int nArgc, char ** papszArgv )
         if( CSLCount(papszLayers) > 0 )
             printf( "layer names ignored in combination with -sql.\n" );
         
-        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+        poResultSet = poDS->ExecuteSQL( pszSQLStatement,
+                                        (pszGeomField == NULL) ? poSpatialFilter: NULL, 
                                         pszDialect );
 
         if( poResultSet != NULL )
@@ -259,7 +268,10 @@ int main( int nArgc, char ** papszArgv )
                 }
             }
 
-            ReportOnLayer( poResultSet, NULL, NULL );
+            if( pszGeomField != NULL )
+                ReportOnLayer( poResultSet, NULL, pszGeomField, poSpatialFilter );
+            else
+                ReportOnLayer( poResultSet, NULL, NULL, NULL );
             poDS->ReleaseResultSet( poResultSet );
         }
     }
@@ -290,7 +302,24 @@ int main( int nArgc, char ** papszArgv )
                             iLayer+1,
                             poLayer->GetName() );
 
-                    if( poLayer->GetGeomType() != wkbUnknown )
+                    int nGeomFieldCount =
+                        poLayer->GetLayerDefn()->GetGeomFieldCount();
+                    if( nGeomFieldCount > 1 )
+                    {
+                        printf( " (");
+                        for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+                        {
+                            if( iGeom > 0 )
+                                printf(", ");
+                            OGRGeomFieldDefn* poGFldDefn =
+                                poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                            printf( "%s", 
+                                OGRGeometryTypeToName( 
+                                    poGFldDefn->GetType() ) );
+                        }
+                        printf( ")");
+                    }
+                    else if( poLayer->GetGeomType() != wkbUnknown )
                         printf( " (%s)", 
                                 OGRGeometryTypeToName( 
                                     poLayer->GetGeomType() ) );
@@ -302,7 +331,7 @@ int main( int nArgc, char ** papszArgv )
                     if( iRepeat != 0 )
                         poLayer->ResetReading();
 
-                    ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
+                    ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter );
                 }
             }
         }
@@ -326,7 +355,7 @@ int main( int nArgc, char ** papszArgv )
                 if( iRepeat != 0 )
                     poLayer->ResetReading();
 
-                ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
+                ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter );
             }
         }
     }
@@ -355,7 +384,7 @@ static void Usage(const char* pszErrorMsg)
 
 {
     printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]\n"
-            "               [-spat xmin ymin xmax ymax] [-fid fid]\n"
+            "               [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]\n"
             "               [-sql statement] [-dialect sql_dialect] [-al] [-so] [-fields={YES/NO}]\n"
             "               [-geom={YES/NO/SUMMARY}][--formats]\n"
             "               datasource_name [layer [layer ...]]\n");
@@ -370,7 +399,8 @@ static void Usage(const char* pszErrorMsg)
 /*                           ReportOnLayer()                            */
 /************************************************************************/
 
-static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE, 
+static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
+                           const char* pszGeomField, 
                            OGRGeometry *poSpatialFilter )
 
 {
@@ -389,7 +419,19 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
     }
 
     if( poSpatialFilter != NULL )
-        poLayer->SetSpatialFilter( poSpatialFilter );
+    {
+        if( pszGeomField != NULL )
+        {
+            int iGeomField = poDefn->GetGeomFieldIndex(pszGeomField);
+            if( iGeomField >= 0 )
+                poLayer->SetSpatialFilter( iGeomField, poSpatialFilter );
+            else
+                printf("WARNING: Cannot find geometry field %s.\n",
+                       pszGeomField);
+        }
+        else
+            poLayer->SetSpatialFilter( poSpatialFilter );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Report various overall information.                             */
@@ -400,13 +442,42 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
 
     if( bVerbose )
     {
-        printf( "Geometry: %s\n", 
-                OGRGeometryTypeToName( poLayer->GetGeomType() ) );
+        int nGeomFieldCount =
+            poLayer->GetLayerDefn()->GetGeomFieldCount();
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                OGRGeomFieldDefn* poGFldDefn =
+                    poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                printf( "Geometry (%s): %s\n", poGFldDefn->GetNameRef(), 
+                    OGRGeometryTypeToName( poGFldDefn->GetType() ) );
+            }
+        }
+        else
+        {
+            printf( "Geometry: %s\n", 
+                    OGRGeometryTypeToName( poLayer->GetGeomType() ) );
+        }
         
         printf( "Feature Count: %d\n", poLayer->GetFeatureCount() );
         
         OGREnvelope oExt;
-        if (poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                if (poLayer->GetExtent(iGeom, &oExt, TRUE) == OGRERR_NONE)
+                {
+                    OGRGeomFieldDefn* poGFldDefn =
+                        poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                    printf("Extent (%s): (%f, %f) - (%f, %f)\n",
+                           poGFldDefn->GetNameRef(),
+                           oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
+                }
+            }
+        }
+        else if (poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
         {
             printf("Extent: (%f, %f) - (%f, %f)\n", 
                    oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
@@ -414,21 +485,53 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
 
         char    *pszWKT;
         
-        if( poLayer->GetSpatialRef() == NULL )
-            pszWKT = CPLStrdup( "(unknown)" );
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                OGRGeomFieldDefn* poGFldDefn =
+                    poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                OGRSpatialReference* poSRS = poGFldDefn->GetSpatialRef();
+                if( poSRS == NULL )
+                    pszWKT = CPLStrdup( "(unknown)" );
+                else
+                {
+                    poSRS->exportToPrettyWkt( &pszWKT );
+                }
+
+                printf( "SRS WKT (%s):\n%s\n",
+                        poGFldDefn->GetNameRef(), pszWKT );
+                CPLFree( pszWKT );
+            }
+        }
         else
         {
-            poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
-        }            
+            if( poLayer->GetSpatialRef() == NULL )
+                pszWKT = CPLStrdup( "(unknown)" );
+            else
+            {
+                poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
+            }            
 
-        printf( "Layer SRS WKT:\n%s\n", pszWKT );
-        CPLFree( pszWKT );
+            printf( "Layer SRS WKT:\n%s\n", pszWKT );
+            CPLFree( pszWKT );
+        }
     
         if( strlen(poLayer->GetFIDColumn()) > 0 )
             printf( "FID Column = %s\n", 
                     poLayer->GetFIDColumn() );
     
-        if( strlen(poLayer->GetGeometryColumn()) > 0 )
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                OGRGeomFieldDefn* poGFldDefn =
+                    poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                printf( "Geometry Column %d = %s\n", iGeom + 1,
+                        poGFldDefn->GetNameRef() );
+            }
+        }
+        else if( strlen(poLayer->GetGeometryColumn()) > 0 )
             printf( "Geometry Column = %s\n", 
                     poLayer->GetGeometryColumn() );
 
diff --git a/apps/ogrlineref.cpp b/apps/ogrlineref.cpp
new file mode 100644
index 0000000..f07845a
--- /dev/null
+++ b/apps/ogrlineref.cpp
@@ -0,0 +1,1733 @@
+/******************************************************************************
+ * Project:  ogr linear referencing utility
+ * Purpose:  main source file
+ * Author:   Dmitry Baryshnikov (aka Bishop), polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (C) 2014 NextGIS
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsf_frmts.h"
+#include "ogr_p.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_api.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "commonutils.h"
+#include <map>
+#include <vector>
+#include <set>
+#include <limits>
+#include "cpl_error.h"
+#include "ogr_geos.h"
+
+#define FIELD_START "beg"
+#define FIELD_FINISH "end"
+#define FIELD_SCALE_FACTOR "scale"
+#define DELTA 0.00000001 //- delta
+
+#if defined(HAVE_GEOS)
+#if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2)
+#define HAVE_GEOS_PROJECT
+#endif
+#endif
+
+enum operation
+{
+    op_unknown = 0,
+    op_create,
+    op_get_pos,
+    op_get_coord,
+    op_get_subline
+};
+
+typedef struct _curve_data
+{
+    OGRLineString* pPart;
+    double dfBeg, dfEnd, dfFactor;
+    bool IsInside(const double& dfDist) const{ return (dfDist + DELTA >= dfBeg) && (dfDist - DELTA <= dfEnd); }
+} CURVE_DATA;
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+static void Usage(const char* pszAdditionalMsg, int bShort = TRUE)
+{
+    OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+
+    printf("Usage: ogrlineref [--help-general] [-progress] [-quiet]\n"
+        "               [-f format_name] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE]...]\n"
+        "               [-create]\n"
+        "               [-l src_line_datasource_name] [-ln layer_name] [-lf field_name]\n"
+        "               [-p src_repers_datasource_name] [-pn layer_name] [-pm pos_field_name] [-pf field_name]\n"
+        "               [-r src_parts_datasource_name] [-rn layer_name]\n"
+        "               [-o dst_datasource_name] [-on layer_name]  [-of field_name] [-s step]\n"
+        "               [-get_pos] [-x long] [-y lat]\n"
+        "               [-get_coord] [-m position] \n"
+        "               [-get_subline] [-mb position] [-me position]\n");
+
+    if (bShort)
+    {
+        printf("\nNote: ogrlineref --long-usage for full help.\n");
+        if (pszAdditionalMsg)
+            fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+        exit(1);
+    }
+
+    printf("\n -f format_name: output file format name, possible values are:\n");
+
+    for (int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
+    {
+        OGRSFDriver *poDriver = poR->GetDriver(iDriver);
+
+        if (poDriver->TestCapability(ODrCCreateDataSource))
+            printf("     -f \"%s\"\n", poDriver->GetName());
+    }
+
+    printf(" -progress: Display progress on terminal. Only works if input layers have the \n"
+        "                                          \"fast feature count\" capability\n"
+        " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
+        " -lco  NAME=VALUE: Layer creation option (format specific)\n"
+        " -l src_line_datasource_name: Datasource of line path name\n"
+        " -ln layer_name: Layer name in datasource (optional)\n"
+        " -lf field_name: Field name for uniq paths in layer (optional)\n"
+        " -p src_repers_datasource_name: Datasource of repers name\n"
+        " -pn layer_name: Layer name in datasource (optional)\n"
+        " -pm pos_field_name: Line postion field name\n"
+        " -pf field_name: Field name for correspondence repers of separate paths in layer (optional)\n"
+        " -r src_parts_datasource_name: Parts datasource name\n"
+        " -rn layer_name: Layer name in datasource (optional)\n"
+        " -o dst_datasource_name: Parts datasource name\n"
+        " -on layer_name: Layer name in datasource (optional)\n"
+        " -of field_name: Field name for correspondence parts of separate paths in layer (optional)\n"
+        " -s step: part size in m\n"
+        );
+
+    if (pszAdditionalMsg)
+        fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+
+    exit(1);
+}
+
+static void Usage(int bShort = TRUE)
+{
+    Usage(NULL, bShort);
+}
+
+/************************************************************************/
+/*                         SetupTargetLayer()                           */
+/************************************************************************/
+
+static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, OGRDataSource *poDstDS, char **papszLCO, const char *pszNewLayerName, const char* pszOutputSepFieldName = NULL)
+{
+    OGRLayer    *poDstLayer;
+    OGRFeatureDefn *poSrcFDefn;
+    OGRSpatialReference *poOutputSRS;
+
+    CPLString szLayerName;
+    
+    if (pszNewLayerName == NULL)
+    {
+        szLayerName = CPLGetBasename(poDstDS->GetName());
+    }
+    else
+    {
+        szLayerName = pszNewLayerName;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Get other info.                                                 */
+    /* -------------------------------------------------------------------- */
+    poSrcFDefn = poSrcLayer->GetLayerDefn();
+
+    /* -------------------------------------------------------------------- */
+    /*      Find requested geometry fields.                                 */
+    /* -------------------------------------------------------------------- */
+
+    poOutputSRS = poSrcLayer->GetSpatialRef();
+
+    /* -------------------------------------------------------------------- */
+    /*      Find the layer.                                                 */
+    /* -------------------------------------------------------------------- */
+
+    /* GetLayerByName() can instanciate layers that would have been */
+    /* 'hidden' otherwise, for example, non-spatial tables in a */
+    /* Postgis-enabled database, so this apparently useless command is */
+    /* not useless... (#4012) */
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    poDstLayer = poDstDS->GetLayerByName(szLayerName);
+    CPLPopErrorHandler();
+    CPLErrorReset();
+
+    int iLayer = -1;
+    if (poDstLayer != NULL)
+    {
+        int nLayerCount = poDstDS->GetLayerCount();
+        for (iLayer = 0; iLayer < nLayerCount; iLayer++)
+        {
+            OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
+            if (poLayer == poDstLayer)
+                break;
+        }
+
+        if (iLayer == nLayerCount)
+            /* shouldn't happen with an ideal driver */
+            poDstLayer = NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      If the layer does not exist, then create it.                    */
+    /* -------------------------------------------------------------------- */
+    if (poDstLayer == NULL)
+    {
+        if (!poDstDS->TestCapability(ODsCCreateLayer))
+        {
+            fprintf(stderr,
+                "Layer %s not found, and CreateLayer not supported by driver.\n",
+                pszNewLayerName);
+            return NULL;
+        }
+
+        OGRwkbGeometryType eGType = wkbLineString;
+
+        CPLErrorReset();
+
+        if (poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
+        {
+            eGType = wkbNone;
+        }
+
+        poDstLayer = poDstDS->CreateLayer(pszNewLayerName, poOutputSRS,
+            (OGRwkbGeometryType)eGType,
+            papszLCO);
+
+        if (poDstLayer == NULL)
+            return NULL;
+
+        if (poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
+        {
+            OGRGeomFieldDefn oGFldDefn(poSrcFDefn->GetGeomFieldDefn(0));
+            if (poOutputSRS != NULL)
+                oGFldDefn.SetSpatialRef(poOutputSRS);
+            oGFldDefn.SetType(wkbLineString);
+            poDstLayer->CreateGeomField(&oGFldDefn);
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Otherwise we will append to it, if append was requested.        */
+    /* -------------------------------------------------------------------- */
+    else
+    {
+        fprintf(stderr, "FAILED: Layer %s already exists.\n",
+            pszNewLayerName);
+        return NULL;
+    }
+
+    //create beg, end, scale factor fields
+    OGRFieldDefn oFieldDefn_Beg = OGRFieldDefn(FIELD_START, OFTReal);
+    if (poDstLayer->CreateField(&oFieldDefn_Beg) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
+            oFieldDefn_Beg.GetNameRef());
+        return NULL;
+    }
+
+    OGRFieldDefn oFieldDefn_End = OGRFieldDefn(FIELD_FINISH, OFTReal);
+    if (poDstLayer->CreateField(&oFieldDefn_End) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
+            oFieldDefn_End.GetNameRef());
+        return NULL;
+    }
+
+    OGRFieldDefn oFieldDefn_SF = OGRFieldDefn(FIELD_SCALE_FACTOR, OFTReal);
+    if (poDstLayer->CreateField(&oFieldDefn_SF) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
+            oFieldDefn_SF.GetNameRef());
+        return NULL;
+    }
+
+    if (pszOutputSepFieldName != NULL)
+    {
+        OGRFieldDefn  oSepField(pszOutputSepFieldName, OFTString);
+        oSepField.SetWidth(255);
+        if (poDstLayer->CreateField(&oSepField) != OGRERR_NONE)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
+                oSepField.GetNameRef());
+            return NULL;
+        }
+    }
+
+    /* now that we've created a field, GetLayerDefn() won't return NULL */
+    OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
+
+    /* Sanity check : if it fails, the driver is buggy */
+    if (poDstFDefn != NULL && poDstFDefn->GetFieldCount() != 3)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+            "The output driver has claimed to have added the %s field, but it did not!",
+            oFieldDefn_Beg.GetNameRef());
+    }
+
+    return poDstLayer;
+}
+
+/* -------------------------------------------------------------------- */
+/*                  CheckDestDataSourceNameConsistency()                */
+/* -------------------------------------------------------------------- */
+
+static
+void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
+                                        const char* pszDriverName)
+{
+    int i;
+    char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
+
+    /* TODO: Would be good to have driver metadata like for GDAL drivers ! */
+    static const char* apszExtensions[][2] = { { "shp"    , "ESRI Shapefile" },
+                                               { "dbf"    , "ESRI Shapefile" },
+                                               { "sqlite" , "SQLite" },
+                                               { "db"     , "SQLite" },
+                                               { "mif"    , "MapInfo File" },
+                                               { "tab"    , "MapInfo File" },
+                                               { "s57"    , "S57" },
+                                               { "bna"    , "BNA" },
+                                               { "csv"    , "CSV" },
+                                               { "gml"    , "GML" },
+                                               { "kml"    , "KML/LIBKML" },
+                                               { "kmz"    , "LIBKML" },
+                                               { "json"   , "GeoJSON" },
+                                               { "geojson", "GeoJSON" },
+                                               { "dxf"    , "DXF" },
+                                               { "gdb"    , "FileGDB" },
+                                               { "pix"    , "PCIDSK" },
+                                               { "sql"    , "PGDump" },
+                                               { "gtm"    , "GPSTrackMaker" },
+                                               { "gmt"    , "GMT" },
+                                               { "pdf"    , "PDF" },
+                                               { NULL, NULL }
+                                              };
+    static const char* apszBeginName[][2] =  { { "PG:"      , "PG" },
+                                               { "MySQL:"   , "MySQL" },
+                                               { "CouchDB:" , "CouchDB" },
+                                               { "GFT:"     , "GFT" },
+                                               { "MSSQL:"   , "MSSQLSpatial" },
+                                               { "ODBC:"    , "ODBC" },
+                                               { "OCI:"     , "OCI" },
+                                               { "SDE:"     , "SDE" },
+                                               { "WFS:"     , "WFS" },
+                                               { NULL, NULL }
+                                             };
+
+    for(i=0; apszExtensions[i][0] != NULL; i++)
+    {
+        if (EQUAL(pszDestExtension, apszExtensions[i][0]) && !EQUAL(pszDriverName, apszExtensions[i][1]))
+        {
+            fprintf(stderr,
+                    "Warning: The target file has a '%s' extension, which is normally used by the %s driver,\n"
+                    "but the requested output driver is %s. Is it really what you want ?\n",
+                    pszDestExtension,
+                    apszExtensions[i][1],
+                    pszDriverName);
+            break;
+        }
+    }
+
+    for(i=0; apszBeginName[i][0] != NULL; i++)
+    {
+        if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
+            !EQUAL(pszDriverName, apszBeginName[i][1]))
+        {
+            fprintf(stderr,
+                    "Warning: The target file has a name which is normally recognized by the %s driver,\n"
+                    "but the requested output driver is %s. Is it really what you want ?\n",
+                    apszBeginName[i][1],
+                    pszDriverName);
+            break;
+        }
+    }
+
+    CPLFree(pszDestExtension);
+}
+
+//------------------------------------------------------------------------
+// AddFeature
+//------------------------------------------------------------------------
+
+OGRErr AddFeature(OGRLayer* const poOutLayer, OGRLineString* pPart, double dfFrom, double dfTo, double dfScaleFactor, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+{
+    OGRFeature *poFeature;
+
+    poFeature = OGRFeature::CreateFeature(poOutLayer->GetLayerDefn());
+
+    poFeature->SetField(FIELD_START, dfFrom);
+    poFeature->SetField(FIELD_FINISH, dfTo);
+    poFeature->SetField(FIELD_SCALE_FACTOR, dfScaleFactor);
+
+    if (pszOutputSepFieldName != NULL)
+    {
+        poFeature->SetField(pszOutputSepFieldName, pszOutputSepFieldValue);
+    }
+
+    poFeature->SetGeometryDirectly(pPart);
+
+    if (poOutLayer->CreateFeature(poFeature) != OGRERR_NONE)
+    {
+        if (!bQuiet)
+            printf("Failed to create feature in shapefile.\n");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFeature::DestroyFeature(poFeature);
+
+    return OGRERR_NONE;
+}
+
+//------------------------------------------------------------------------
+// CreateSubline
+//------------------------------------------------------------------------
+OGRErr CreateSubline(OGRLayer* const poPkLayer, double dfPosBeg, double dfPosEnd, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet)
+{
+    OGRFeature* pFeature = NULL;
+    double dfBeg, dfEnd, dfStep;
+    //get step
+    poPkLayer->ResetReading();
+    pFeature = poPkLayer->GetNextFeature();
+    if (NULL != pFeature)
+    {
+        dfBeg = pFeature->GetFieldAsDouble(FIELD_START);
+        dfEnd = pFeature->GetFieldAsDouble(FIELD_FINISH);
+        OGRFeature::DestroyFeature(pFeature);
+    }
+    else
+    {
+        fprintf(stderr, "Get step for positions %f - %f failed\n", dfPosBeg, dfPosEnd);
+        return OGRERR_FAILURE;
+    }
+    //get second part
+    pFeature = poPkLayer->GetNextFeature();
+    if (NULL != pFeature)
+    {
+        dfBeg = pFeature->GetFieldAsDouble(FIELD_START);
+        dfEnd = pFeature->GetFieldAsDouble(FIELD_FINISH);
+        OGRFeature::DestroyFeature(pFeature);
+    }
+    else
+    {
+        fprintf(stderr, "Get step for positions %f - %f failed\n", dfPosBeg, dfPosEnd);
+        return OGRERR_FAILURE;
+    }
+    dfStep = dfEnd - dfBeg;
+
+    //round input to step
+    CPLString szAttributeFilter;
+    double dfPosBegLow = floor(dfPosBeg / dfStep) * dfStep;
+    double dfPosEndHigh = ceil(dfPosEnd / dfStep) * dfStep;
+
+    szAttributeFilter.Printf("%s >= %f AND %s <= %f", FIELD_START, dfPosBegLow, FIELD_FINISH, dfPosEndHigh);
+    poPkLayer->SetAttributeFilter(szAttributeFilter); //TODO: ExecuteSQL should be faster
+    poPkLayer->ResetReading();
+
+    std::map<double, OGRFeature *> moParts;
+    
+    while ((pFeature = poPkLayer->GetNextFeature()) != NULL)
+    {
+        double dfStart = pFeature->GetFieldAsDouble(FIELD_START);
+        moParts[dfStart] = pFeature;
+    }
+
+    OGRLineString SubLine;
+    
+    if (moParts.size() == 0)
+    {
+        fprintf(stderr, "Get parts for positions %f - %f failed\n", dfPosBeg, dfPosEnd);
+        return OGRERR_FAILURE;
+    }
+    else if (moParts.size() == 1)
+    {
+        std::map<double, OGRFeature *>::iterator IT = moParts.begin();
+        double dfStart = IT->first;
+        double dfPosBegCorr = dfPosBeg - dfStart;
+        double dfSF = IT->second->GetFieldAsDouble(FIELD_SCALE_FACTOR);
+        dfPosBegCorr *= dfSF;
+
+        double dfPosEndCorr = dfPosEnd - dfStart;
+        dfPosEndCorr *= dfSF;
+
+        OGRLineString *pLine = (OGRLineString*)IT->second->GetGeometryRef();
+
+        OGRLineString *pSubLine = pLine->getSubLine(dfPosBegCorr, dfPosEndCorr, FALSE);
+
+        OGRFeature::DestroyFeature(IT->second);
+        //store
+        return AddFeature(poOutLayer, pSubLine, dfPosBeg, dfPosEnd, 1.0, bQuiet);
+    }
+    else
+    {
+        int nCounter = moParts.size();
+        std::map<double, OGRFeature *>::iterator IT = moParts.begin();
+        OGRLineString *pOutLine = new OGRLineString();
+        //get first part
+        double dfStart = IT->first;
+        double dfPosBegCorr = dfPosBeg - dfStart;
+        double dfSF = IT->second->GetFieldAsDouble(FIELD_SCALE_FACTOR);
+        dfPosBegCorr *= dfSF;
+
+        OGRLineString *pLine = (OGRLineString*)IT->second->GetGeometryRef();
+
+        OGRLineString *pSubLine = pLine->getSubLine(dfPosBegCorr, pLine->get_Length(), FALSE);
+
+        pOutLine->addSubLineString(pSubLine);
+        OGRFeature::DestroyFeature(IT->second);
+
+        ++IT;
+        nCounter--;
+
+        while (nCounter > 1)
+        {
+            pLine = (OGRLineString*)IT->second->GetGeometryRef();
+            pOutLine->addSubLineString(pLine);
+            OGRFeature::DestroyFeature(IT->second);
+            ++IT;
+            nCounter--;
+        }
+
+        //get last part
+        double dfPosEndCorr = dfPosEnd - IT->first;
+        dfSF = IT->second->GetFieldAsDouble(FIELD_SCALE_FACTOR);
+        dfPosEndCorr *= dfSF;
+
+        pLine = (OGRLineString*)IT->second->GetGeometryRef();
+
+        pSubLine = pLine->getSubLine(0, dfPosEndCorr, FALSE);
+
+        pOutLine->addSubLineString(pSubLine);
+
+        OGRFeature::DestroyFeature(IT->second);
+        //store
+        return AddFeature(poOutLayer, pOutLine, dfPosBeg, dfPosEnd, 1.0, bQuiet);
+    }
+
+    //should never reach here
+    return OGRERR_NONE;
+}
+
+
+
+//------------------------------------------------------------------------
+// CreatePartsFromLineString
+//------------------------------------------------------------------------
+
+OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+{
+    //check repers type
+    OGRwkbGeometryType eGeomType = poPkLayer->GetGeomType();
+    if (wkbFlatten(eGeomType) != wkbPoint)
+    {
+        fprintf(stderr, "Unsupported geometry type %s for path\n", OGRGeometryTypeToName(eGeomType));
+        return OGRERR_FAILURE;
+    }
+
+    //create sorted list of repers
+    std::map<double, OGRPoint*> moRepers;
+    poPkLayer->ResetReading();
+    OGRFeature* pReperFeature = NULL;
+    double dfTestDistance = 0;
+    while ((pReperFeature = poPkLayer->GetNextFeature()) != NULL)
+    {
+        double dfReperPos = pReperFeature->GetFieldAsDouble(nMValField);
+        OGRGeometry* pGeom = pReperFeature->GetGeometryRef();
+        if (NULL != pGeom)
+        {
+            OGRPoint* pPt = (OGRPoint*)pGeom->clone();
+            if (!bQuiet)
+            {
+                if (moRepers.find(dfReperPos) != moRepers.end())
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                        "The distance %f is already present in repers file!", dfReperPos);
+                }
+            }
+            //check if reper incide path
+            dfTestDistance = pPathGeom->Project(pPt);
+            if (dfTestDistance == 0 || dfTestDistance == pPathGeom->get_Length())
+            {
+                if (!bQuiet)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                        "The distance %f is out of path!", dfReperPos);
+                }
+            }
+            else
+            {
+                moRepers[dfReperPos] = pPt;
+            }           
+        }
+        OGRFeature::DestroyFeature(pReperFeature);
+    }
+
+    if (moRepers.size() < 2)
+    {
+        fprintf(stderr, "Not enough repers to proceed\n");
+        return OGRERR_FAILURE;
+    }
+
+    //check direction
+    if (!bQuiet)
+    {
+        fprintf(stdout, "Check path direction\n");
+    }
+
+    //get distance along path from pt1 and pt2. If pt1 distance > pt2 distance, reverse path
+    OGRPoint *pt1, *pt2;
+    std::map<double, OGRPoint*>::const_iterator IT;
+    IT = moRepers.begin();
+    double dfPosition = IT->first;
+    double dfBeginPosition = IT->first;
+    pt1 = IT->second;
+    ++IT;
+    pt2 = IT->second;
+
+    double dfDistance1 = pPathGeom->Project(pt1);
+    double dfDistance2 = pPathGeom->Project(pt2);
+
+    if (dfDistance1 > dfDistance2)
+    {
+        if (!bQuiet)
+        {
+            fprintf(stderr, "Warning: The path is opposite the repers direction. Let's reverse path\n");
+        }
+        pPathGeom->reversePoints();
+
+        dfDistance1 = pPathGeom->Project(pt1);
+        dfDistance2 = pPathGeom->Project(pt2);
+    }
+
+    OGRLineString* pPart = NULL;
+
+    std::vector<CURVE_DATA> astSubLines;
+
+    if (!bQuiet)
+    {
+        fprintf(stdout, "Create parts\n");
+    }
+
+    //get first part 
+    //If first point is not at the beginning of the path
+    //The first part should be from the beginning of the path to the first point. length == part.getLength
+    OGRPoint *pPtBeg(NULL), *pPtEnd(NULL);
+    double dfPtBegPosition, dfPtEndPosition;
+
+    if (dfDistance1 > DELTA)
+    {
+        pPart = pPathGeom->getSubLine(0, dfDistance1, FALSE);
+        if (NULL != pPart)
+        {
+            OGRSpatialReference* pSpaRef = pPathGeom->getSpatialReference();
+            double dfLen = pPart->get_Length();
+            if (pSpaRef->IsGeographic())
+            {
+                //convert to UTM/WGS84
+                OGRPoint pt;
+                pPart->Value(dfLen / 2, &pt);
+                int nZoneEnv = 30 + (pt.getX() + 3.0) / 6.0 + 0.5;
+                int nEPSG;
+                if (pt.getY() > 0)
+                {
+                    nEPSG = 32600 + nZoneEnv;
+                }
+                else
+                {
+                    nEPSG = 32700 + nZoneEnv;
+                }
+                OGRSpatialReference SpatRef;
+                SpatRef.importFromEPSG(nEPSG);
+                OGRGeometry *pTransformPart = pPart->clone();
+                if (pTransformPart->transformTo(&SpatRef) == OGRERR_NONE)
+                {
+                    OGRLineString* pTransformPartLS = (OGRLineString*)pTransformPart;
+                    dfLen = pTransformPartLS->get_Length();
+                }
+
+                CURVE_DATA data = { pPart, dfPosition - dfLen, dfPosition, pPart->get_Length() / dfLen };
+                astSubLines.push_back(data);
+
+                pPtBeg = new OGRPoint();
+                pPart->getPoint(0, pPtBeg);
+                dfPtBegPosition = dfPosition - dfLen;
+
+                //AddFeature(poOutLayer, pPart, dfPosition - dfLen, dfPosition, pPart->get_Length() / dfLen, bQuiet);
+                delete pTransformPart;
+            }
+            else
+            {
+                CURVE_DATA data = { pPart, dfPosition - dfLen, dfPosition, 1.0 };
+                astSubLines.push_back(data);
+                //AddFeature(poOutLayer, pPart, dfPosition - dfLen, dfPosition, 1.0, bQuiet);
+                pPtBeg = new OGRPoint();
+                pPart->getPoint(0, pPtBeg);
+                dfPtBegPosition = dfPosition - dfLen;
+            }
+        }
+    }
+
+    pPart = pPathGeom->getSubLine(dfDistance1, dfDistance2, FALSE);
+    if (NULL != pPart)
+    {
+        CURVE_DATA data = { pPart, dfPosition, IT->first, pPart->get_Length() / (IT->first - dfPosition) };
+        astSubLines.push_back(data);
+//        AddFeature(poOutLayer, pPart, dfPosition, IT->first, pPart->get_Length() / (IT->first - dfPosition), bQuiet);
+    }
+
+    GDALProgressFunc pfnProgress = NULL;
+    void        *pProgressArg = NULL;
+
+    double dfFactor = 1.0 / moRepers.size();
+    if (bDisplayProgress)
+    {
+        pfnProgress = GDALScaledProgress;
+        pProgressArg = GDALCreateScaledProgress(0.0, 1.0, GDALTermProgress, NULL);
+    }
+
+    int nCount = 2;
+    dfDistance1 = dfDistance2;
+    dfPosition = IT->first;
+    ++IT;//get third point    
+
+    double dfEndPosition;
+    while (IT != moRepers.end())
+    {
+        if (bDisplayProgress)
+        {
+            pfnProgress(nCount * dfFactor, "", pProgressArg);
+            nCount++;
+        }
+
+        dfEndPosition = IT->first;
+
+        dfDistance2 = pPathGeom->Project(IT->second);
+
+        pPart = pPathGeom->getSubLine(dfDistance1, dfDistance2, FALSE);
+        if (NULL != pPart)
+        {
+            CURVE_DATA data = { pPart, dfPosition, IT->first, pPart->get_Length() / (IT->first - dfPosition) };
+            astSubLines.push_back(data);
+//            AddFeature(poOutLayer, pPart, dfPosition, IT->first, pPart->get_Length() / (IT->first - dfPosition), bQuiet);
+            dfDistance1 = dfDistance2;
+            dfPosition = IT->first;
+        }
+
+        ++IT;
+    }
+
+    //get last part
+    pPart = pPathGeom->getSubLine(dfDistance1, pPathGeom->get_Length(), FALSE);
+    if (NULL != pPart)
+    {
+        OGRSpatialReference* pSpaRef = pPathGeom->getSpatialReference();
+        double dfLen = pPart->get_Length();
+        if (pSpaRef->IsGeographic())
+        {
+            //convert to UTM/WGS84
+            OGRPoint pt;
+            pPart->Value(dfLen / 2, &pt);
+            int nZoneEnv = 30 + (pt.getX() + 3.0) / 6.0 + 0.5;
+            int nEPSG;
+            if (pt.getY() > 0)
+            {
+                nEPSG = 32600 + nZoneEnv;
+            }
+            else
+            {
+                nEPSG = 32700 + nZoneEnv;
+            }
+            OGRSpatialReference SpatRef;
+            SpatRef.importFromEPSG(nEPSG);
+            OGRGeometry *pTransformPart = pPart->clone();
+            if (pTransformPart->transformTo(&SpatRef) == OGRERR_NONE)
+            {
+                OGRLineString* pTransformPartLS = (OGRLineString*)pTransformPart;
+                dfLen = pTransformPartLS->get_Length();
+            }
+            CURVE_DATA data = { pPart, dfPosition, dfPosition + dfLen, pPart->get_Length() / dfLen };
+            astSubLines.push_back(data);
+            //AddFeature(poOutLayer, pPart, dfPosition, dfPosition + dfLen, pPart->get_Length() / dfLen, bQuiet);
+
+            pPtEnd = new OGRPoint();
+            pPart->getPoint(pPart->getNumPoints() - 1, pPtEnd);
+            dfPtEndPosition = dfPosition + dfLen;
+
+            delete pTransformPart;
+        }
+        else
+        {
+            CURVE_DATA data = { pPart, dfPosition, dfPosition + dfLen, 1.0 };
+            astSubLines.push_back(data);
+            //AddFeature(poOutLayer, pPart, dfPosition - dfLen, dfPosition, 1.0, bQuiet);
+            pPtEnd = new OGRPoint();
+            pPart->getPoint(pPart->getNumPoints() - 1, pPtEnd);
+            dfPtEndPosition = dfPosition + dfLen;
+        }
+    }
+
+    //create pickets
+    if (!bQuiet)
+    {
+        fprintf(stdout, "\nCreate pickets\n");
+    }
+
+    long nBegin = 0;
+    
+    if (pPtBeg != NULL)
+        nBegin = ceil(dfPtBegPosition / dfStep) * dfStep;
+    else
+        nBegin = ceil(dfBeginPosition / dfStep) * dfStep;
+
+    double dfRoundBeg = nBegin;
+
+    if (pPtEnd != NULL)
+        dfEndPosition = dfPtEndPosition;
+
+    dfFactor = dfStep / (dfEndPosition - dfRoundBeg);
+    nCount = 0;
+    moRepers.clear();
+
+    if (pPtBeg != NULL)
+        moRepers[dfPtBegPosition] = pPtBeg;
+    if (pPtEnd != NULL)
+        moRepers[dfPtEndPosition] = pPtEnd;
+
+    for (double dfDist = dfRoundBeg; dfDist <= dfEndPosition; dfDist += dfStep)
+    {
+        if (bDisplayProgress)
+        {
+            pfnProgress(nCount * dfFactor, "", pProgressArg);
+            nCount++;
+        }
+
+        for (int j = 0; j < (int)astSubLines.size(); j++)
+        {
+            if (astSubLines[j].IsInside(dfDist))
+            {
+                double dfRealDist = (dfDist - astSubLines[j].dfBeg) * astSubLines[j].dfFactor;
+                OGRPoint *pReperPoint = new OGRPoint();
+                astSubLines[j].pPart->Value(dfRealDist, pReperPoint);
+
+                moRepers[dfDist] = pReperPoint;
+                break;
+            }
+        }
+    }
+
+    if (!bQuiet)
+    {
+        fprintf(stdout, "\nCreate sublines\n");
+    }
+
+    IT = moRepers.begin();
+    dfFactor = 1.0 / moRepers.size();
+    nCount = 0;
+    dfDistance1 = 0;
+    dfPosition = IT->first;
+
+    while (IT != moRepers.end())
+    {
+        if (bDisplayProgress)
+        {
+            pfnProgress(nCount * dfFactor, "", pProgressArg);
+            nCount++;
+        }
+
+        dfDistance2 = pPathGeom->Project(IT->second);
+
+        if (dfDistance1 != dfDistance2)
+        {
+            pPart = pPathGeom->getSubLine(dfDistance1, dfDistance2, FALSE);
+            if (NULL != pPart)
+            {
+                AddFeature(poOutLayer, pPart, dfPosition, IT->first, pPart->get_Length() / (IT->first - dfPosition), bQuiet, pszOutputSepFieldName, pszOutputSepFieldValue);
+                dfDistance1 = dfDistance2;
+                dfPosition = IT->first;
+            }
+        }
+
+        ++IT;
+    }
+
+    if (!bQuiet)
+    {
+        fprintf(stdout, "\nSuccess!\n\n");
+    }
+    
+    if (NULL != pProgressArg)
+    {
+        GDALDestroyScaledProgress(pProgressArg);
+    }
+
+
+    return OGRERR_NONE;
+}
+
+//------------------------------------------------------------------------
+// CreateParts
+//------------------------------------------------------------------------
+OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+{
+    OGRErr eRetCode = OGRERR_FAILURE;
+
+    //check path and get first line
+    OGRwkbGeometryType eGeomType = poLnLayer->GetGeomType();
+    if (wkbFlatten(eGeomType) != wkbLineString && wkbFlatten(eGeomType) != wkbMultiLineString)
+    {
+        fprintf(stderr, "Unsupported geometry type %s for path\n", OGRGeometryTypeToName(eGeomType));
+        return eRetCode;
+    }
+
+    poLnLayer->ResetReading();
+    //get first geometry
+    //TODO: attruibute filter for path geometry 
+    OGRFeature* pPathFeature = poLnLayer->GetNextFeature();
+    if (NULL != pPathFeature)
+    {
+        OGRGeometry* pGeom = pPathFeature->GetGeometryRef();
+
+        if (wkbFlatten(pGeom->getGeometryType()) == wkbMultiLineString)
+        {
+            if (!bQuiet)
+            {
+                fprintf(stdout, "\nThe geometry %ld is wkbMultiLineString type\n", pPathFeature->GetFID());
+            }
+
+            OGRGeometryCollection* pGeomColl = (OGRGeometryCollection*)pGeom;
+            for (int i = 0; i < pGeomColl->getNumGeometries(); ++i)
+            {
+                OGRLineString* pPath = (OGRLineString*)pGeomColl->getGeometryRef(i)->clone();
+                pPath->assignSpatialReference(pGeomColl->getSpatialReference());
+                eRetCode = CreatePartsFromLineString(pPath, poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet, pszOutputSepFieldName, pszOutputSepFieldValue);
+
+                if (eRetCode != OGRERR_NONE)
+                {
+                    OGRFeature::DestroyFeature(pPathFeature);
+                    return eRetCode;
+                }
+            }
+        }
+        else
+        {
+            if (NULL != pGeom)
+            {
+                eRetCode = CreatePartsFromLineString((OGRLineString*)pGeom->clone(), poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet, pszOutputSepFieldName, pszOutputSepFieldValue);
+            }
+        }
+
+        OGRFeature::DestroyFeature(pPathFeature);
+    }
+
+    return eRetCode;
+}
+
+//------------------------------------------------------------------------
+// CreatePartsMultiple
+//------------------------------------------------------------------------
+OGRErr CreatePartsMultiple(OGRLayer* const poLnLayer, const char* pszLineSepFieldName, OGRLayer* const poPkLayer, const char* pszPicketsSepFieldName, int nMValField, double dfStep, OGRLayer* const poOutLayer, const char* pszOutputSepFieldName, int bDisplayProgress, int bQuiet)
+{
+    //read all sep field values into array
+    std::set<CPLString> asIDs;
+
+    OGRFeatureDefn *pDefn = poLnLayer->GetLayerDefn();
+    int nLineSepFieldInd = pDefn->GetFieldIndex(pszLineSepFieldName);
+    if (nLineSepFieldInd == -1)
+    {
+        fprintf(stderr, "The field %s not found\n", pszLineSepFieldName);
+        return OGRERR_FAILURE;
+    }
+
+    poLnLayer->ResetReading();
+    OGRFeature* pFeature = NULL;
+    while ((pFeature = poLnLayer->GetNextFeature()) != NULL)
+    {
+        CPLString sID = pFeature->GetFieldAsString(nLineSepFieldInd);
+        asIDs.insert(sID);
+
+        OGRFeature::DestroyFeature(pFeature);
+    }
+
+    for (std::set<CPLString>::const_iterator it = asIDs.begin(); it != asIDs.end(); ++it)
+    {
+        //create select clause
+        CPLString sLineWhere;
+        sLineWhere.Printf("%s = \"%s\"", pszLineSepFieldName, it->c_str());
+        poLnLayer->SetAttributeFilter(sLineWhere);
+
+        CPLString sPkWhere;
+        sPkWhere.Printf("%s = \"%s\"", pszPicketsSepFieldName, it->c_str());
+        poPkLayer->SetAttributeFilter(sPkWhere);
+
+        if (!bQuiet)
+        {
+            fprintf(stdout, "The %s %s\n", pszPicketsSepFieldName, it->c_str());
+        }
+
+        //don't check success as we want to try all paths
+        CreateParts(poLnLayer, poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet, pszOutputSepFieldName, *it);
+    }
+
+    return OGRERR_NONE;
+}
+
+//------------------------------------------------------------------------
+// GetPosition
+//------------------------------------------------------------------------
+OGRErr GetPosition(OGRLayer* const poPkLayer, double dfX, double dfY, int bDisplayProgress, int bQuiet)
+{
+    //create point
+    OGRPoint pt;
+    pt.setX(dfX);
+    pt.setY(dfY);
+    pt.assignSpatialReference(poPkLayer->GetSpatialRef());
+
+    poPkLayer->ResetReading();
+    OGRLineString *pCloserPart = NULL;
+    double dfBeg, dfScale;
+    double dfMinDistance = std::numeric_limits<double>::max();
+    OGRFeature* pFeature = NULL;
+    while ((pFeature = poPkLayer->GetNextFeature()) != NULL)
+    {
+        OGRGeometry* pCurrentGeom = pFeature->GetGeometryRef();
+        if (pCurrentGeom != NULL)
+        {
+            double dfCurrentDistance = pCurrentGeom->Distance(&pt);
+            if (dfCurrentDistance < dfMinDistance)
+            {
+                dfMinDistance = dfCurrentDistance;
+                if (pCloserPart != NULL)
+                    delete pCloserPart;
+                pCloserPart = (OGRLineString*)pFeature->StealGeometry();
+                dfBeg = pFeature->GetFieldAsDouble(FIELD_START);
+                dfScale = pFeature->GetFieldAsDouble(FIELD_SCALE_FACTOR);
+            }
+        }
+        OGRFeature::DestroyFeature(pFeature);
+    }
+
+    if(NULL == pCloserPart)
+    {
+        fprintf(stderr, "Filed to find closest part\n");
+        return OGRERR_FAILURE;
+    }
+    //now we have closest part
+    //get real distance
+    double dfRealDist = pCloserPart->Project(&pt);
+    //compute reference distance
+    double dfRefDist = dfBeg + dfRealDist / dfScale;
+    if (bQuiet == TRUE)
+    {
+        fprintf(stdout, "%f\n", dfRefDist);
+    }
+    else
+    {
+        fprintf(stdout, "The position for coordinates lat:%f, long:%f is %f\n", dfY, dfX, dfRefDist);
+    }
+
+    return OGRERR_NONE;
+}
+
+//------------------------------------------------------------------------
+// GetCoordinates
+//------------------------------------------------------------------------
+OGRErr GetCoordinates(OGRLayer* const poPkLayer, double dfPos, int bDisplayProgress, int bQuiet)
+{
+    CPLString szAttributeFilter;
+    szAttributeFilter.Printf("%s < %f AND %s > %f", FIELD_START, dfPos, FIELD_FINISH, dfPos);
+    poPkLayer->SetAttributeFilter(szAttributeFilter); //TODO: ExecuteSQL should be faster
+    poPkLayer->ResetReading();
+
+    bool bHaveCoords = false;
+    OGRFeature* pFeature = NULL;
+    while ((pFeature = poPkLayer->GetNextFeature()) != NULL)
+    {
+        bHaveCoords = true;
+        double dfStart = pFeature->GetFieldAsDouble(FIELD_START);
+        double dfPosCorr = dfPos - dfStart;
+        double dfSF = pFeature->GetFieldAsDouble(FIELD_SCALE_FACTOR);
+        dfPosCorr *= dfSF;
+        OGRLineString *pLine = (OGRLineString*)pFeature->GetGeometryRef();
+
+        OGRPoint pt;
+        pLine->Value(dfPosCorr, &pt);
+
+        if (bQuiet == TRUE)
+        {
+            fprintf(stdout, "%f,%f,%f\n", pt.getX(), pt.getY(), pt.getZ());
+        }
+        else
+        {
+            fprintf(stdout, "The position for distance %f is lat:%f, long:%f, height:%f\n", dfPos, pt.getY(), pt.getX(), pt.getZ());
+        }
+        OGRFeature::DestroyFeature(pFeature);
+    }
+
+    if (bHaveCoords)
+    {
+        return OGRERR_NONE;
+    }
+    else
+    {
+        fprintf(stderr, "Get coordinates for position %f failed\n", dfPos);
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (iArg + nExtraArg >= nArgc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+
+int main( int nArgc, char ** papszArgv )
+
+{
+    OGRErr       eErr = OGRERR_NONE;
+    int          bQuiet = FALSE;
+    const char  *pszFormat = "ESRI Shapefile";
+
+    const char  *pszOutputDataSource = NULL;
+    const char  *pszLineDataSource = NULL;
+    const char  *pszPicketsDataSource = NULL;
+    const char  *pszPartsDataSource = NULL;
+    char  *pszOutputLayerName = NULL;
+    const char  *pszLineLayerName = NULL;
+    const char  *pszPicketsLayerName = NULL;
+    const char  *pszPicketsMField = NULL;
+    const char  *pszPartsLayerName = NULL;
+
+    const char  *pszLineSepFieldName = NULL;
+    const char  *pszPicketsSepFieldName = NULL;
+    const char  *pszOutputSepFieldName = "uniq_uid";
+    
+    char        **papszDSCO = NULL, **papszLCO = NULL;
+    
+    operation stOper = op_unknown;
+    double dfX(-100000000), dfY(-100000000), dfPos(-100000000);
+
+    int bDisplayProgress = FALSE;
+    
+    double dfPosBeg(-100000000), dfPosEnd(-100000000);
+    double dfStep(-100000000);
+
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(papszArgv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(nArgc, papszArgv);
+
+/* -------------------------------------------------------------------- */
+/*      Register format(s).                                             */
+/* -------------------------------------------------------------------- */
+    OGRRegisterAll();
+
+/* -------------------------------------------------------------------- */
+/*      Processing command line arguments.                              */
+/* -------------------------------------------------------------------- */
+    nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
+    
+    if( nArgc < 1 )
+        exit( -nArgc );
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
+    {
+        if( EQUAL(papszArgv[iArg], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            return 0;
+        }
+        else if( EQUAL(papszArgv[iArg],"--help") )
+            Usage();
+        else if ( EQUAL(papszArgv[iArg], "--long-usage") )
+        {
+            Usage(FALSE);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+        {
+            bQuiet = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-f") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            //bFormatExplicitelySet = TRUE;
+            pszFormat = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-dsco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
+        }
+        else if( EQUAL(papszArgv[iArg],"-lco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
+        }        
+        else if( EQUAL(papszArgv[iArg],"-create") )
+        {
+            stOper = op_create;
+        }
+        else if( EQUAL(papszArgv[iArg],"-get_pos") )
+        {
+            stOper = op_get_pos;
+        }        
+        else if( EQUAL(papszArgv[iArg],"-get_coord") )
+        {
+            stOper = op_get_coord;
+        }        
+        else if( EQUAL(papszArgv[iArg],"-get_subline") )
+        {
+            stOper = op_get_subline;
+        }        
+        else if( EQUAL(papszArgv[iArg],"-l") )
+        {
+             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+           pszLineDataSource = papszArgv[++iArg];
+        }        
+        else if( EQUAL(papszArgv[iArg],"-ln") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszLineLayerName = papszArgv[++iArg];
+        }    
+        else if (EQUAL(papszArgv[iArg], "-lf"))
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszLineSepFieldName = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-p") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszPicketsDataSource = papszArgv[++iArg];
+        }        
+        else if( EQUAL(papszArgv[iArg],"-pn") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszPicketsLayerName = papszArgv[++iArg];
+        }    
+        else if( EQUAL(papszArgv[iArg],"-pm") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszPicketsMField = papszArgv[++iArg];
+        }
+        else if (EQUAL(papszArgv[iArg], "-pf"))
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszPicketsSepFieldName = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-r") )
+        {
+             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+           pszPartsDataSource = papszArgv[++iArg];
+        }        
+        else if( EQUAL(papszArgv[iArg],"-rn") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszPartsLayerName = papszArgv[++iArg];
+        }         
+        else if( EQUAL(papszArgv[iArg],"-o") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszOutputDataSource = papszArgv[++iArg];
+        }   
+        else if( EQUAL(papszArgv[iArg],"-on") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszOutputLayerName = CPLStrdup(papszArgv[++iArg]);
+        }        
+        else if (EQUAL(papszArgv[iArg], "-of"))
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszOutputSepFieldName = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-x") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfX = CPLAtofM(papszArgv[++iArg]);
+        } 
+        else if( EQUAL(papszArgv[iArg],"-y") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfY = CPLAtofM(papszArgv[++iArg]);
+        } 
+        else if( EQUAL(papszArgv[iArg],"-m") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfPos = CPLAtofM(papszArgv[++iArg]);
+        }  
+        else if( EQUAL(papszArgv[iArg],"-mb") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfPosBeg = CPLAtofM(papszArgv[++iArg]);
+        }  
+        else if( EQUAL(papszArgv[iArg],"-me") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfPosEnd = CPLAtofM(papszArgv[++iArg]);
+        }  
+        else if( EQUAL(papszArgv[iArg],"-s") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfStep = CPLAtofM(papszArgv[++iArg]);
+        }  
+        else if( EQUAL(papszArgv[iArg],"-progress") )
+        {
+            bDisplayProgress = TRUE;
+        }
+        else if( papszArgv[iArg][0] == '-' )
+        {
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
+        }
+    }
+
+    
+    if(stOper == op_create)
+    {
+#ifdef HAVE_GEOS_PROJECT
+        if( pszOutputDataSource == NULL)
+            Usage("no output datasource provided");
+        else if(pszLineDataSource == NULL)
+            Usage("no path datasource provided");
+        else  if(pszPicketsDataSource == NULL)
+            Usage("no repers datasource provided");
+        else  if(pszPicketsMField == NULL)
+            Usage("no position field provided");
+        else  if (dfStep == -100000000)
+            Usage("no step provided");
+            
+    /* -------------------------------------------------------------------- */
+    /*      Open data source.                                               */
+    /* -------------------------------------------------------------------- */
+        OGRDataSource       *poLnDS;
+        OGRDataSource       *poODS = NULL;
+        OGRSFDriver         *poDriver = NULL;
+        OGRDataSource *poPkDS = NULL;
+        OGRLayer *poPkLayer = NULL;
+
+        poLnDS = OGRSFDriverRegistrar::Open( pszLineDataSource, FALSE );
+
+    /* -------------------------------------------------------------------- */
+    /*      Report failure                                                  */
+    /* -------------------------------------------------------------------- */
+        if( poLnDS == NULL )
+        {
+            OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+            
+            fprintf( stderr, "FAILURE:\n"
+                    "Unable to open path datasource `%s' with the following drivers.\n",
+                    pszLineDataSource);
+
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+            }
+
+            exit( 1 );
+        }
+        
+        poPkDS = OGRSFDriverRegistrar::Open( pszPicketsDataSource, FALSE );
+    /* -------------------------------------------------------------------- */
+    /*      Report failure                                                  */
+    /* -------------------------------------------------------------------- */
+        if( poPkDS == NULL )
+        {
+            OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+            
+            fprintf( stderr, "FAILURE:\n"
+                    "Unable to open repers datasource `%s' with the following drivers.\n",
+                    pszPicketsDataSource);
+
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+            }
+
+            exit( 1 );
+        }
+    
+    
+    /* -------------------------------------------------------------------- */
+    /*      Find the output driver.                                         */
+    /* -------------------------------------------------------------------- */
+
+        if (!bQuiet)
+            CheckDestDataSourceNameConsistency(pszOutputDataSource, pszFormat);
+
+        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+        int                  iDriver;
+
+        poDriver = poR->GetDriverByName(pszFormat);
+        if( poDriver == NULL )
+        {
+            fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
+            fprintf( stderr,  "The following drivers are available:\n" );
+        
+            for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
+            }
+            exit( 1 );
+        }
+
+        if( !poDriver->TestCapability( ODrCCreateDataSource ) )
+        {
+            fprintf( stderr,  "%s driver does not support data source creation.\n",
+                    pszFormat );
+            exit( 1 );
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the output data source.                                  */
+    /* -------------------------------------------------------------------- */
+        poODS = poDriver->CreateDataSource( pszOutputDataSource, papszDSCO );
+        if( poODS == NULL )
+        {
+            fprintf( stderr,  "%s driver failed to create %s\n", 
+                    pszFormat, pszOutputDataSource );
+            exit( 1 );
+        }
+
+        OGRLayer *poLnLayer, *poOutLayer;
+
+        if(pszLineLayerName == NULL)
+        {
+            poLnLayer = poLnDS->GetLayer(0);
+        }
+        else
+        {
+            poLnLayer = poLnDS->GetLayerByName(pszLineLayerName);
+        }
+        
+        if(poLnLayer == NULL)
+        {
+            fprintf( stderr, "Get path layer failed.\n" );
+            exit( 1 );
+        }   
+        
+        if(pszPicketsLayerName == NULL)
+        {
+            poPkLayer = poPkDS->GetLayer(0);
+        }
+        else
+        {
+            poPkLayer = poPkDS->GetLayerByName(pszPicketsLayerName);
+        }
+        
+        if(poPkLayer == NULL)
+        {
+            fprintf( stderr, "Get repers layer failed.\n" );
+            exit( 1 );    
+        }
+                 
+        OGRFeatureDefn *poPkFDefn = poPkLayer->GetLayerDefn();
+        int nMValField = poPkFDefn->GetFieldIndex( pszPicketsMField );
+
+        if (pszLineSepFieldName != NULL && pszPicketsSepFieldName != NULL)
+        {
+            poOutLayer = SetupTargetLayer(poLnLayer, poODS, papszLCO, pszOutputLayerName, pszOutputSepFieldName);
+            if(poOutLayer == NULL)
+            {
+                fprintf( stderr, "Create output layer failed.\n" );
+                exit( 1 );    
+            }    
+
+            //do the work
+            eErr = CreatePartsMultiple(poLnLayer, pszLineSepFieldName, poPkLayer, pszPicketsSepFieldName, nMValField, dfStep, poOutLayer, pszOutputSepFieldName, bDisplayProgress, bQuiet);
+        }
+        else
+        {
+            poOutLayer = SetupTargetLayer(poLnLayer, poODS, papszLCO, pszOutputLayerName);
+            if(poOutLayer == NULL)
+            {
+                fprintf( stderr, "Create output layer failed.\n" );
+                exit( 1 );    
+            }     
+        
+            //do the work
+            eErr = CreateParts(poLnLayer, poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet);
+        }
+        
+        //clean up        
+        OGRDataSource::DestroyDataSource(poLnDS);
+        OGRDataSource::DestroyDataSource(poPkDS);
+        OGRDataSource::DestroyDataSource(poODS);
+            
+        if (NULL != pszOutputLayerName)
+            CPLFree(pszOutputLayerName);
+#else //HAVE_GEOS_PROJECT
+        fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+        exit( 1 );       
+#endif //HAVE_GEOS_PROJECT            
+    }
+    else if(stOper == op_get_pos)
+    {
+#ifdef HAVE_GEOS_PROJECT    
+        OGRDataSource *poPartsDS = NULL;
+        OGRLayer *poPartsLayer = NULL;
+
+        if (pszPartsDataSource == NULL)
+            Usage("no parts datasource provided");
+        else if(dfX == -100000000 || dfY == -100000000)
+            Usage("no coordinates provided");
+            
+        poPartsDS = OGRSFDriverRegistrar::Open( pszPartsDataSource, FALSE );
+    /* -------------------------------------------------------------------- */
+    /*      Report failure                                                  */
+    /* -------------------------------------------------------------------- */
+        if (poPartsDS == NULL)
+        {
+            OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+            
+            fprintf( stderr, "FAILURE:\n"
+                    "Unable to open parts datasource `%s' with the following drivers.\n",
+                    pszPicketsDataSource);
+
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+            }
+
+            exit( 1 );
+        }
+            
+        if(pszPartsLayerName == NULL)
+        {
+            poPartsLayer = poPartsDS->GetLayer(0);
+        }
+        else
+        {
+            poPartsLayer = poPartsDS->GetLayerByName(pszPartsLayerName);
+        }
+        
+        if (poPartsLayer == NULL)
+        {
+            fprintf( stderr, "Get parts layer failed.\n" );
+            exit( 1 );    
+        }  
+
+        //do the work
+        eErr = GetPosition(poPartsLayer, dfX, dfY, bDisplayProgress, bQuiet);
+
+        //clean up
+        OGRDataSource::DestroyDataSource(poPartsDS);
+#else //HAVE_GEOS_PROJECT
+        fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+        exit( 1 );       
+#endif //HAVE_GEOS_PROJECT            
+    }
+    else if(stOper == op_get_coord)
+    {
+        OGRDataSource *poPartsDS = NULL;
+        OGRLayer *poPartsLayer = NULL;
+
+        if (pszPartsDataSource == NULL)
+            Usage("no parts datasource provided");
+        else if(dfPos == -100000000)
+            Usage("no position provided");
+            
+        poPartsDS = OGRSFDriverRegistrar::Open(pszPartsDataSource, FALSE);
+    /* -------------------------------------------------------------------- */
+    /*      Report failure                                                  */
+    /* -------------------------------------------------------------------- */
+        if (poPartsDS == NULL)
+        {
+            OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+            
+            fprintf( stderr, "FAILURE:\n"
+                    "Unable to open parts datasource `%s' with the following drivers.\n",
+                    pszPicketsDataSource);
+
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+            }
+
+            exit( 1 );
+        }
+            
+        if(pszPartsLayerName == NULL)
+        {
+            poPartsLayer = poPartsDS->GetLayer(0);
+        }
+        else
+        {
+            poPartsLayer = poPartsDS->GetLayerByName(pszPartsLayerName);
+        }
+        
+        if (poPartsLayer == NULL)
+        {
+            fprintf( stderr, "Get parts layer failed.\n" );
+            exit( 1 );    
+        }     
+        //do the work
+        eErr = GetCoordinates(poPartsLayer, dfPos, bDisplayProgress, bQuiet);
+
+        //clean up
+        OGRDataSource::DestroyDataSource(poPartsDS);
+    }
+    else if (stOper == op_get_subline)
+    {
+        if (pszOutputDataSource == NULL)
+            Usage("no output datasource provided");
+        else if (pszPartsDataSource == NULL)
+            Usage("no parts datasource provided");
+        else  if (dfPosBeg == -100000000)
+            Usage("no begin position provided");
+        else  if (dfPosEnd == -100000000)
+            Usage("no end position provided");
+
+        /* -------------------------------------------------------------------- */
+        /*      Open data source.                                               */
+        /* -------------------------------------------------------------------- */
+        OGRDataSource       *poPartsDS;
+        OGRDataSource       *poODS = NULL;
+        OGRSFDriver         *poDriver = NULL;
+
+        poPartsDS = OGRSFDriverRegistrar::Open(pszPartsDataSource, FALSE);
+
+        /* -------------------------------------------------------------------- */
+        /*      Report failure                                                  */
+        /* -------------------------------------------------------------------- */
+        if (poPartsDS == NULL)
+        {
+            OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+            fprintf(stderr, "FAILURE:\n"
+                "Unable to open parts datasource `%s' with the following drivers.\n",
+                pszLineDataSource);
+
+            for (int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
+            {
+                fprintf(stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName());
+            }
+
+            exit(1);
+        }
+
+        /* -------------------------------------------------------------------- */
+        /*      Find the output driver.                                         */
+        /* -------------------------------------------------------------------- */
+
+        if (!bQuiet)
+            CheckDestDataSourceNameConsistency(pszOutputDataSource, pszFormat);
+
+        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+        int                  iDriver;
+
+        poDriver = poR->GetDriverByName(pszFormat);
+        if (poDriver == NULL)
+        {
+            fprintf(stderr, "Unable to find driver `%s'.\n", pszFormat);
+            fprintf(stderr, "The following drivers are available:\n");
+
+            for (iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
+            {
+                fprintf(stderr, "  -> `%s'\n", poR->GetDriver(iDriver)->GetName());
+            }
+            exit(1);
+        }
+
+        if (!poDriver->TestCapability(ODrCCreateDataSource))
+        {
+            fprintf(stderr, "%s driver does not support data source creation.\n",
+                pszFormat);
+            exit(1);
+        }
+
+        /* -------------------------------------------------------------------- */
+        /*      Create the output data source.                                  */
+        /* -------------------------------------------------------------------- */
+        poODS = poDriver->CreateDataSource(pszOutputDataSource, papszDSCO);
+        if (poODS == NULL)
+        {
+            fprintf(stderr, "%s driver failed to create %s\n",
+                pszFormat, pszOutputDataSource);
+            exit(1);
+        }
+
+        OGRLayer *poPartsLayer, *poOutLayer;
+
+        if (pszLineLayerName == NULL)
+        {
+            poPartsLayer = poPartsDS->GetLayer(0);
+        }
+        else
+        {
+            poPartsLayer = poPartsDS->GetLayerByName(pszLineLayerName);
+        }
+
+        if (poPartsLayer == NULL)
+        {
+            fprintf(stderr, "Get parts layer failed.\n");
+            exit(1);
+        }
+
+        poOutLayer = SetupTargetLayer(poPartsLayer, poODS, papszLCO, pszOutputLayerName);
+        if (poOutLayer == NULL)
+        {
+            fprintf(stderr, "Create output layer failed.\n");
+            exit(1);
+        }
+
+        //do the work
+        eErr = CreateSubline(poPartsLayer, dfPosBeg, dfPosEnd, poOutLayer, bDisplayProgress, bQuiet);
+
+        //clean up        
+        OGRDataSource::DestroyDataSource(poPartsDS);
+        OGRDataSource::DestroyDataSource(poODS);
+
+        if (NULL != pszOutputLayerName)
+            CPLFree(pszOutputLayerName);
+    }
+    else
+    {
+        Usage("no operation provided");
+    }  
+    
+/* -------------------------------------------------------------------- */
+/*      Close down.                                                     */
+/* -------------------------------------------------------------------- */
+
+    CSLDestroy( papszArgv );
+    CSLDestroy( papszDSCO );
+    CSLDestroy( papszLCO );
+
+    OGRCleanupAll();
+
+#ifdef DBMALLOC
+    malloc_dump(1);
+#endif
+    
+    return eErr == OGRERR_NONE ? 0 : 1;
+}
+
diff --git a/apps/ogrtindex.cpp b/apps/ogrtindex.cpp
index 7ee2d03..4a9e5b3 100644
--- a/apps/ogrtindex.cpp
+++ b/apps/ogrtindex.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtindex.cpp 19803 2010-06-05 11:05:38Z rouault $
+ * $Id: ogrtindex.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Program to generate a UMN MapServer compatible tile index for a
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 
 #include <cassert>
 
-CPL_CVSID("$Id: ogrtindex.cpp 19803 2010-06-05 11:05:38Z rouault $");
+CPL_CVSID("$Id: ogrtindex.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void Usage();
 
diff --git a/apps/test_ogrsf.cpp b/apps/test_ogrsf.cpp
index 1375fb6..f0dd14c 100644
--- a/apps/test_ogrsf.cpp
+++ b/apps/test_ogrsf.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: test_ogrsf.cpp 25490 2013-01-12 23:43:30Z rouault $
+ * $Id: test_ogrsf.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Formal test harnass for OGRLayer implementations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,16 +30,30 @@
 
 #include "ogrsf_frmts.h"
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
 #include "ogr_api.h"
 #include "ogr_p.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: test_ogrsf.cpp 25490 2013-01-12 23:43:30Z rouault $");
+CPL_CVSID("$Id: test_ogrsf.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
+const char  *pszDataSource = NULL;
+char** papszLayers = NULL;
+const char  *pszSQLStatement = NULL;
+const char  *pszDialect = NULL;
+int nLoops = 1;
+
+typedef struct
+{
+    void* hThread;
+    int bRet;
+} ThreadContext;
 
 static void Usage();
+static void ThreadFunction( void* user_data );
+static void ThreadFunctionInternal( ThreadContext* psContext );
 static int TestOGRLayer( OGRDataSource * poDS, OGRLayer * poLayer, int bIsSQLLayer );
 static int TestInterleavedReading( const char* pszDataSource, char** papszLayers );
 static int TestDSErrorConditions( OGRDataSource * poDS );
@@ -50,11 +65,8 @@ static int TestDSErrorConditions( OGRDataSource * poDS );
 int main( int nArgc, char ** papszArgv )
 
 {
-    const char  *pszDataSource = NULL;
-    char** papszLayers = NULL;
-    const char  *pszSQLStatement = NULL;
-    const char  *pszDialect = NULL;
     int bRet = TRUE;
+    int nThreads = 1;
 
     EarlySetConfigOptions(nArgc, papszArgv);
 
@@ -92,6 +104,14 @@ int main( int nArgc, char ** papszArgv )
         {
             pszDialect = papszArgv[++iArg];
         }
+        else if( EQUAL(papszArgv[iArg],"-threads") && iArg + 1 < nArgc)
+        {
+            nThreads = atoi(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-loops") && iArg + 1 < nArgc)
+        {
+            nLoops = atoi(papszArgv[++iArg]);
+        }
         else if( papszArgv[iArg][0] == '-' )
         {
             Usage();
@@ -104,6 +124,70 @@ int main( int nArgc, char ** papszArgv )
 
     if( pszDataSource == NULL )
         Usage();
+    if( nThreads > 1 && !bReadOnly )
+    {
+        fprintf(stderr, "-theads must be used with -ro option.\n");
+        exit(1);
+    }
+
+    if( nThreads == 1 )
+    {
+        ThreadContext sContext;
+        ThreadFunction(&sContext);
+        bRet = sContext.bRet;
+    }
+    else if( nThreads > 1 )
+    {
+        int i;
+        ThreadContext* pasContext = new ThreadContext[nThreads];
+        for(i = 0; i < nThreads; i ++ )
+        {
+            pasContext[i].hThread = CPLCreateJoinableThread(
+                ThreadFunction, &(pasContext[i]));
+        }
+        for(i = 0; i < nThreads; i ++ )
+        {
+            CPLJoinThread(pasContext[i].hThread);
+            bRet &= pasContext[i].bRet;
+        }
+        delete[] pasContext;
+    }
+
+    OGRCleanupAll();
+
+    CSLDestroy(papszLayers);
+    CSLDestroy(papszArgv);
+    
+#ifdef DBMALLOC
+    malloc_dump(1);
+#endif
+    
+    return (bRet) ? 0 : 1;
+}
+
+/************************************************************************/
+/*                        ThreadFunction()                              */
+/************************************************************************/
+
+static void ThreadFunction( void* user_data )
+
+{
+    ThreadContext* psContext = (ThreadContext* )user_data;
+    psContext->bRet = TRUE;
+    for( int iLoop = 0; psContext->bRet && iLoop < nLoops; iLoop ++ )
+    {
+        ThreadFunctionInternal(psContext);
+    }
+}
+
+/************************************************************************/
+/*                     ThreadFunctionInternal()                         */
+/************************************************************************/
+
+static void ThreadFunctionInternal( ThreadContext* psContext )
+
+{
+    int bRet = TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Open data source.                                               */
@@ -138,7 +222,8 @@ int main( int nArgc, char ** papszArgv )
             printf( "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
         }
 
-        exit( 1 );
+        psContext->bRet = FALSE;
+        return;
     }
 
 /* -------------------------------------------------------------------- */
@@ -162,10 +247,17 @@ int main( int nArgc, char ** papszArgv )
     {
         OGRLayer  *poResultSet = poDS->ExecuteSQL(pszSQLStatement, NULL, pszDialect);
         if (poResultSet == NULL)
-            exit(1);
-            
-        printf( "INFO: Testing layer %s.\n",
-                    poResultSet->GetName() );
+        {
+            OGRDataSource::DestroyDataSource(poDS);
+            psContext->bRet = FALSE;
+            return;
+        }
+
+        if( bVerbose )
+        {
+            printf( "INFO: Testing layer %s.\n",
+                        poResultSet->GetName() );
+        }
         bRet = TestOGRLayer( poDS, poResultSet, TRUE );
         
         poDS->ReleaseResultSet(poResultSet);
@@ -185,11 +277,16 @@ int main( int nArgc, char ** papszArgv )
             {
                 printf( "FAILURE: Couldn't fetch advertised layer %d!\n",
                         iLayer );
-                exit( 1 );
+                OGRDataSource::DestroyDataSource(poDS);
+                psContext->bRet = FALSE;
+                return;
             }
 
-            printf( "INFO: Testing layer %s.\n",
-                    poLayer->GetName() );
+            if( bVerbose )
+            {
+                printf( "INFO: Testing layer %s.\n",
+                        poLayer->GetName() );
+            }
             bRet &= TestOGRLayer( poDS, poLayer, FALSE );
         }
 
@@ -216,11 +313,16 @@ int main( int nArgc, char ** papszArgv )
             {
                 printf( "FAILURE: Couldn't fetch requested layer %s!\n",
                         *papszLayerIter );
-                exit( 1 );
+                OGRDataSource::DestroyDataSource(poDS);
+                psContext->bRet = FALSE;
+                return;
             }
             
-            printf( "INFO: Testing layer %s.\n",
-                    poLayer->GetName() );
+            if( bVerbose )
+            {
+                printf( "INFO: Testing layer %s.\n",
+                        poLayer->GetName() );
+            }
             bRet &= TestOGRLayer( poDS, poLayer, FALSE );
             
             papszLayerIter ++;
@@ -241,16 +343,7 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     OGRDataSource::DestroyDataSource(poDS);
 
-    OGRCleanupAll();
-
-    CSLDestroy(papszLayers);
-    CSLDestroy(papszArgv);
-    
-#ifdef DBMALLOC
-    malloc_dump(1);
-#endif
-    
-    return (bRet) ? 0 : 1;
+    psContext->bRet = bRet;
 }
 
 /************************************************************************/
@@ -260,7 +353,7 @@ int main( int nArgc, char ** papszArgv )
 static void Usage()
 
 {
-    printf( "Usage: test_ogrsf [-ro] [-q] datasource_name \n"
+    printf( "Usage: test_ogrsf [-ro] [-q] [-threads N] [-loops M] datasource_name \n"
             "                  [[layer1_name, layer2_name, ...] | [-sql statement] [-dialect dialect]]\n" );
     exit( 1 );
 }
@@ -275,23 +368,74 @@ static int TestBasic( OGRLayer *poLayer )
 
     const char* pszLayerName = poLayer->GetName();
     OGRwkbGeometryType eGeomType = poLayer->GetGeomType();
+    OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
-    if( strcmp(poLayer->GetName(), poLayer->GetLayerDefn()->GetName()) != 0 )
+    if( strcmp(pszLayerName, poFDefn->GetName()) != 0 )
     {
         bRet = FALSE;
-        printf( "ERROR: poLayer->GetName() and poLayer->GetLayerDefn()->GetName() differ.\n"
+        printf( "ERROR: poLayer->GetName() and poFDefn>GetName() differ.\n"
                 "poLayer->GetName() = %s\n"
-                "poLayer->GetLayerDefn()->GetName() = %s\n",
-                    pszLayerName, poLayer->GetLayerDefn()->GetName());
+                "poFDefn->GetName() = %s\n",
+                    pszLayerName, poFDefn->GetName());
     }
 
-    if( eGeomType != poLayer->GetLayerDefn()->GetGeomType() )
+    if( eGeomType != poFDefn->GetGeomType() )
     {
         bRet = FALSE;
-        printf( "ERROR: poLayer->GetGeomType() and poLayer->GetLayerDefn()->GetGeomType() differ.\n"
+        printf( "ERROR: poLayer->GetGeomType() and poFDefn->GetGeomType() differ.\n"
                 "poLayer->GetGeomType() = %d\n"
-                "poLayer->GetLayerDefn()->GetGeomType() = %d\n",
-                    eGeomType, poLayer->GetLayerDefn()->GetGeomType());
+                "poFDefn->GetGeomType() = %d\n",
+                    eGeomType, poFDefn->GetGeomType());
+    }
+
+    if( poLayer->GetFIDColumn() == NULL )
+    {
+        bRet = FALSE;
+        printf( "ERROR: poLayer->GetFIDColumn() returned NULL.\n" );
+    }
+
+    if( poLayer->GetGeometryColumn() == NULL )
+    {
+        bRet = FALSE;
+        printf( "ERROR: poLayer->GetGeometryColumn() returned NULL.\n" );
+    }
+
+    if( poFDefn->GetGeomFieldCount() > 0 )
+    {
+        if( eGeomType != poFDefn->GetGeomFieldDefn(0)->GetType() )
+        {
+            bRet = FALSE;
+            printf( "ERROR: poLayer->GetGeomType() and poFDefn->GetGeomFieldDefn(0)->GetType() differ.\n"
+                    "poLayer->GetGeomType() = %d\n"
+                    "poFDefn->GetGeomFieldDefn(0)->GetType() = %d\n",
+                        eGeomType, poFDefn->GetGeomFieldDefn(0)->GetType());
+        }
+
+        if( !EQUAL(poLayer->GetGeometryColumn(),
+                   poFDefn->GetGeomFieldDefn(0)->GetNameRef()) )
+        {
+            if( poFDefn->GetGeomFieldCount() > 1 )
+                bRet = FALSE;
+            printf( "%s: poLayer->GetGeometryColumn() and poFDefn->GetGeomFieldDefn(0)->GetNameRef() differ.\n"
+                    "poLayer->GetGeometryColumn() = %s\n"
+                    "poFDefn->GetGeomFieldDefn(0)->GetNameRef() = %s\n",
+                     ( poFDefn->GetGeomFieldCount() == 1 ) ? "WARNING" : "ERROR",
+                    poLayer->GetGeometryColumn(),
+                     poFDefn->GetGeomFieldDefn(0)->GetNameRef());
+        }
+
+        if( poLayer->GetSpatialRef() !=
+                   poFDefn->GetGeomFieldDefn(0)->GetSpatialRef() )
+        {
+            if( poFDefn->GetGeomFieldCount() > 1 )
+                bRet = FALSE;
+            printf( "%s: poLayer->GetSpatialRef() and poFDefn->GetGeomFieldDefn(0)->GetSpatialRef() differ.\n"
+                    "poLayer->GetSpatialRef() = %p\n"
+                    "poFDefn->GetGeomFieldDefn(0)->GetSpatialRef() = %p\n",
+                     ( poFDefn->GetGeomFieldCount() == 1 ) ? "WARNING" : "ERROR",
+                     poLayer->GetSpatialRef(),
+                     poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
+        }
     }
 
     return bRet;
@@ -424,11 +568,12 @@ static int TestOGRLayerFeatureCount( OGRDataSource* poDS, OGRLayer *poLayer, int
     int bRet = TRUE;
     int         nFC = 0, nClaimedFC = poLayer->GetFeatureCount();
     OGRFeature  *poFeature;
-    OGRSpatialReference * poSRS = poLayer->GetSpatialRef();
     int         bWarnAboutSRS = FALSE;
     OGRFeatureDefn* poLayerDefn = poLayer->GetLayerDefn();
+    int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
 
     poLayer->ResetReading();
+    CPLErrorReset();
 
     while( (poFeature = poLayer->GetNextFeature()) != NULL )
     {
@@ -443,38 +588,57 @@ static int TestOGRLayerFeatureCount( OGRDataSource* poDS, OGRLayer *poLayer, int
                      poFeature->GetDefnRef(), poLayerDefn);
         }
 
-        if( poFeature->GetGeometryRef() != NULL
-            && poFeature->GetGeometryRef()->getSpatialReference() != poSRS
-            && !bWarnAboutSRS )
+        for( int iGeom = 0; iGeom < nGeomFieldCount; iGeom ++ )
         {
-            char        *pszLayerSRSWKT, *pszFeatureSRSWKT;
-            
-            bWarnAboutSRS = TRUE;
+            OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeom);
+            OGRSpatialReference * poGFldSRS =
+                poLayerDefn->GetGeomFieldDefn(iGeom)->GetSpatialRef();
 
-            if( poSRS != NULL )
-                poSRS->exportToWkt( &pszLayerSRSWKT );
-            else
-                pszLayerSRSWKT = CPLStrdup("(NULL)");
+            // Compatibility with old drivers anterior to RFC 41
+            if( iGeom == 0 && nGeomFieldCount == 1 && poGFldSRS == NULL )
+                poGFldSRS = poLayer->GetSpatialRef();
 
-            if( poFeature->GetGeometryRef()->getSpatialReference() != NULL )
-                poFeature->GetGeometryRef()->
-                    getSpatialReference()->exportToWkt( &pszFeatureSRSWKT );
-            else
-                pszFeatureSRSWKT = CPLStrdup("(NULL)");
+            if( poGeom != NULL
+                && poGeom->getSpatialReference() != poGFldSRS
+                && !bWarnAboutSRS )
+            {
+                char        *pszLayerSRSWKT, *pszFeatureSRSWKT;
+                
+                bWarnAboutSRS = TRUE;
 
-            bRet = FALSE;
-            printf( "ERROR: Feature SRS differs from layer SRS.\n"
-                    "Feature SRS = %s (%p)\n"
-                    "Layer SRS = %s (%p)\n",
-                    pszFeatureSRSWKT, poFeature->GetGeometryRef()->getSpatialReference(),
-                    pszLayerSRSWKT, poSRS );
-            CPLFree( pszLayerSRSWKT );
-            CPLFree( pszFeatureSRSWKT );
+                if( poGFldSRS != NULL )
+                    poGFldSRS->exportToWkt( &pszLayerSRSWKT );
+                else
+                    pszLayerSRSWKT = CPLStrdup("(NULL)");
+
+                if( poGeom->getSpatialReference() != NULL )
+                    poGeom->
+                        getSpatialReference()->exportToWkt( &pszFeatureSRSWKT );
+                else
+                    pszFeatureSRSWKT = CPLStrdup("(NULL)");
+
+                bRet = FALSE;
+                printf( "ERROR: Feature SRS differs from layer SRS.\n"
+                        "Feature SRS = %s (%p)\n"
+                        "Layer SRS = %s (%p)\n",
+                        pszFeatureSRSWKT, poGeom->getSpatialReference(),
+                        pszLayerSRSWKT, poGFldSRS );
+                CPLFree( pszLayerSRSWKT );
+                CPLFree( pszFeatureSRSWKT );
+            }
         }
         
         OGRFeature::DestroyFeature(poFeature);
     }
 
+    /* mapogr.cpp doesn't like errors after GetNextFeature() */
+    if (CPLGetLastErrorType() != CE_None )
+    {
+        bRet = FALSE;
+        printf( "ERROR: An error was reported : %s\n",
+                CPLGetLastErrorMsg());
+    }
+
     if( nFC != nClaimedFC )
     {
         bRet = FALSE;
@@ -604,7 +768,7 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
 /*      Test feature 5.                                                 */
 /* -------------------------------------------------------------------- */
     poFeature = poLayer->GetFeature( papoFeatures[4]->GetFID() );
-    if( !poFeature->Equal( papoFeatures[4] ) )
+    if( poFeature == NULL || !poFeature->Equal( papoFeatures[4] ) )
     {
         bRet = FALSE;
         printf( "ERROR: Attempt to randomly read feature %ld appears to\n"
@@ -684,7 +848,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     }
     
     poFeature = poLayer->GetNextFeature();
-    if( !poFeature->Equal( papoFeatures[1] ) )
+    if( poFeature == NULL || !poFeature->Equal( papoFeatures[1] ) )
     {
         bRet = FALSE;
         printf( "ERROR: Attempt to read feature at index %d appears to\n"
@@ -698,7 +862,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     OGRFeature::DestroyFeature(poFeature);
     
     poFeature = poLayer->GetNextFeature();
-    if( !poFeature->Equal( papoFeatures[2] ) )
+    if( poFeature == NULL || !poFeature->Equal( papoFeatures[2] ) )
     {
         bRet = FALSE;
         printf( "ERROR: Attempt to read feature after feature at index %d appears to\n"
@@ -855,9 +1019,11 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
     if( !poFeature->Equal(papoFeatures[1]) )
     {
         bRet = FALSE;
+        poFeature->DumpReadable(stderr);
+        papoFeatures[1]->DumpReadable(stderr);
         printf( "ERROR: Written feature didn't seem to retain value.\n" );
     }
-    else
+    else if( bVerbose )
     {
         printf( "INFO: Random write test passed.\n" );
     }
@@ -892,6 +1058,15 @@ end:
     return bRet;
 }
 
+#ifndef INFINITY
+    static CPL_INLINE double CPLInfinity(void)
+    {
+        static double ZERO = 0;
+        return 1.0 / ZERO; /* MSVC doesn't like 1.0 / 0.0 */
+    }
+    #define INFINITY CPLInfinity()
+#endif
+
 /************************************************************************/
 /*                         TestSpatialFilter()                          */
 /*                                                                      */
@@ -902,7 +1077,7 @@ end:
 /*      filter that doesn't include this feature, and test again.       */
 /************************************************************************/
 
-static int TestSpatialFilter( OGRLayer *poLayer )
+static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
 
 {
     int bRet = TRUE;
@@ -920,36 +1095,53 @@ static int TestSpatialFilter( OGRLayer *poLayer )
 
     if( poTargetFeature == NULL )
     {
-        printf( "INFO: Skipping Spatial Filter test for %s.\n"
-                "      No features in layer.\n",
-                poLayer->GetName() );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Spatial Filter test for %s.\n"
+                    "      No features in layer.\n",
+                    poLayer->GetName() );
+        }
         return bRet;
     }
 
-    if( poTargetFeature->GetGeometryRef() == NULL )
+    OGRGeometry* poGeom = poTargetFeature->GetGeomFieldRef(iGeomField);
+    if( poGeom == NULL || poGeom->IsEmpty() )
     {
-        printf( "INFO: Skipping Spatial Filter test for %s,\n"
-                "      target feature has no geometry.\n",
-                poTargetFeature->GetDefnRef()->GetName() );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Spatial Filter test for %s,\n"
+                    "      target feature has no geometry.\n",
+                    poTargetFeature->GetDefnRef()->GetName() );
+        }
         OGRFeature::DestroyFeature(poTargetFeature);
         return bRet;
     }
 
-    poTargetFeature->GetGeometryRef()->getEnvelope( &sEnvelope );
+    poGeom->getEnvelope( &sEnvelope );
+
+    OGREnvelope sLayerExtent;
+    double epsilon = 10.0;
+    if( poLayer->TestCapability( OLCFastGetExtent ) &&
+        poLayer->GetExtent(iGeomField, &sLayerExtent) == OGRERR_NONE &&
+        sLayerExtent.MinX < sLayerExtent.MaxX &&
+        sLayerExtent.MinY < sLayerExtent.MaxY )
+    {
+        epsilon = MIN( sLayerExtent.MaxX - sLayerExtent.MinX, sLayerExtent.MaxY - sLayerExtent.MinY ) / 10.0;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Construct inclusive filter.                                     */
 /* -------------------------------------------------------------------- */
     
-    oRing.setPoint( 0, sEnvelope.MinX - 20.0, sEnvelope.MinY - 20.0 );
-    oRing.setPoint( 1, sEnvelope.MinX - 20.0, sEnvelope.MaxY + 10.0 );
-    oRing.setPoint( 2, sEnvelope.MaxX + 10.0, sEnvelope.MaxY + 10.0 );
-    oRing.setPoint( 3, sEnvelope.MaxX + 10.0, sEnvelope.MinY - 20.0 );
-    oRing.setPoint( 4, sEnvelope.MinX - 20.0, sEnvelope.MinY - 20.0 );
+    oRing.setPoint( 0, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
+    oRing.setPoint( 1, sEnvelope.MinX - 2 * epsilon, sEnvelope.MaxY + 1 * epsilon );
+    oRing.setPoint( 2, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MaxY + 1 * epsilon );
+    oRing.setPoint( 3, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MinY - 2 * epsilon );
+    oRing.setPoint( 4, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
     
     oInclusiveFilter.addRing( &oRing );
 
-    poLayer->SetSpatialFilter( &oInclusiveFilter );
+    poLayer->SetSpatialFilter( iGeomField, &oInclusiveFilter );
 
 /* -------------------------------------------------------------------- */
 /*      Verify that we can find the target feature.                     */
@@ -970,7 +1162,8 @@ static int TestSpatialFilter( OGRLayer *poLayer )
     if( poFeature == NULL )
     {
         bRet = FALSE;
-        printf( "ERROR: Spatial filter eliminated a feature unexpectedly!\n");
+        printf( "ERROR: Spatial filter (%d) eliminated a feature unexpectedly!\n",
+                iGeomField);
     }
     else if( bVerbose )
     {
@@ -982,15 +1175,15 @@ static int TestSpatialFilter( OGRLayer *poLayer )
 /* -------------------------------------------------------------------- */
 /*      Construct exclusive filter.                                     */
 /* -------------------------------------------------------------------- */
-    oRing.setPoint( 0, sEnvelope.MinX - 20.0, sEnvelope.MinY - 20.0 );
-    oRing.setPoint( 1, sEnvelope.MinX - 10.0, sEnvelope.MinY - 20.0 );
-    oRing.setPoint( 2, sEnvelope.MinX - 10.0, sEnvelope.MinY - 10.0 );
-    oRing.setPoint( 3, sEnvelope.MinX - 20.0, sEnvelope.MinY - 10.0 );
-    oRing.setPoint( 4, sEnvelope.MinX - 20.0, sEnvelope.MinY - 20.0 );
+    oRing.setPoint( 0, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
+    oRing.setPoint( 1, sEnvelope.MinX - 1 * epsilon, sEnvelope.MinY - 2 * epsilon );
+    oRing.setPoint( 2, sEnvelope.MinX - 1 * epsilon, sEnvelope.MinY - 1 * epsilon );
+    oRing.setPoint( 3, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 1 * epsilon );
+    oRing.setPoint( 4, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
     
     oExclusiveFilter.addRing( &oRing );
 
-    poLayer->SetSpatialFilter( &oExclusiveFilter );
+    poLayer->SetSpatialFilter( iGeomField, &oExclusiveFilter );
 
 /* -------------------------------------------------------------------- */
 /*      Verify that we can find the target feature.                     */
@@ -1011,24 +1204,200 @@ static int TestSpatialFilter( OGRLayer *poLayer )
     if( poFeature != NULL )
     {
         bRet = FALSE;
-        printf( "ERROR: Spatial filter failed to eliminate"
-                "a feature unexpectedly!\n");
+        printf( "ERROR: Spatial filter (%d) failed to eliminate"
+                "a feature unexpectedly!\n",
+                iGeomField);
     }
     else if( poLayer->GetFeatureCount() >= nInclusiveCount )
     {
         bRet = FALSE;
         printf( "ERROR: GetFeatureCount() may not be taking spatial "
-                "filter into account.\n" );
+                "filter (%d) into account.\n" ,
+                iGeomField);
     }
     else if( bVerbose )
     {
         printf( "INFO: Spatial filter exclusion seems to work.\n" );
     }
 
+    // Check that GetFeature() ignores the spatial filter
+    poFeature = poLayer->GetFeature( poTargetFeature->GetFID() );
+    if( poFeature == NULL || !poFeature->Equal(poTargetFeature) )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Spatial filter has been taken into account by GetFeature()\n");
+    }
+    else if( bVerbose )
+    {
+        printf( "INFO: Spatial filter is ignored by GetFeature() as expected.\n");
+    }
+    if( poFeature != NULL )
+        OGRFeature::DestroyFeature(poFeature);
+
+    if( bRet )
+    {
+        poLayer->ResetReading();
+        while( (poFeature = poLayer->GetNextFeature()) != NULL )
+        {
+            if( poFeature->Equal(poTargetFeature) )
+            {
+                OGRFeature::DestroyFeature(poFeature);
+                break;
+            }
+            else
+                OGRFeature::DestroyFeature(poFeature);
+        }
+        if( poFeature != NULL )
+        {
+            bRet = FALSE;
+            printf( "ERROR: Spatial filter has not been restored correctly after GetFeature()\n");
+        }
+    }
+
     OGRFeature::DestroyFeature(poTargetFeature);
 
+/* -------------------------------------------------------------------- */
+/*     Test infinity envelope                                           */
+/* -------------------------------------------------------------------- */
+
+#define NEG_INF -INFINITY
+#define POS_INF INFINITY
+
+    oRing.setPoint( 0, NEG_INF, NEG_INF );
+    oRing.setPoint( 1, NEG_INF, POS_INF );
+    oRing.setPoint( 2, POS_INF, POS_INF );
+    oRing.setPoint( 3, POS_INF, NEG_INF );
+    oRing.setPoint( 4, NEG_INF, NEG_INF );
+
+    OGRPolygon oInfinityFilter;
+    oInfinityFilter.addRing( &oRing );
+
+    poLayer->SetSpatialFilter( iGeomField, &oInfinityFilter );
+    poLayer->ResetReading();
+    int nCountInf = 0;
+    while( (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        if( poFeature->GetGeomFieldRef(iGeomField) != NULL )
+            nCountInf ++;
+        delete poFeature;
+    }
+
+/* -------------------------------------------------------------------- */
+/*     Test envelope with huge coords                                   */
+/* -------------------------------------------------------------------- */
+
+#define HUGE_COORDS (1e300)
+
+    oRing.setPoint( 0, -HUGE_COORDS, -HUGE_COORDS );
+    oRing.setPoint( 1, -HUGE_COORDS, HUGE_COORDS );
+    oRing.setPoint( 2, HUGE_COORDS, HUGE_COORDS );
+    oRing.setPoint( 3, HUGE_COORDS, -HUGE_COORDS );
+    oRing.setPoint( 4, -HUGE_COORDS, -HUGE_COORDS );
+
+    OGRPolygon oHugeFilter;
+    oHugeFilter.addRing( &oRing );
+
+    poLayer->SetSpatialFilter( iGeomField, &oHugeFilter );
+    poLayer->ResetReading();
+    int nCountHuge = 0;
+    while( (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        if( poFeature->GetGeomFieldRef(iGeomField) != NULL )
+            nCountHuge ++;
+        delete poFeature;
+    }
+
+/* -------------------------------------------------------------------- */
+/*     Reset spatial filter                                             */
+/* -------------------------------------------------------------------- */
     poLayer->SetSpatialFilter( NULL );
 
+    int nExpected = 0;
+    poLayer->ResetReading();
+    while( (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        if( poFeature->GetGeomFieldRef(iGeomField) != NULL )
+            nExpected ++;
+        delete poFeature;
+    }
+    poLayer->ResetReading();
+
+    if( nCountInf != nExpected )
+    {
+        /*bRet = FALSE; */
+        printf( "WARNING: Infinity spatial filter returned %d features instead of %d\n",
+                nCountInf, nExpected );
+    }
+    else if( bVerbose )
+    {
+        printf( "INFO: Infinity spatial filter works as expected.\n");
+    }
+
+    if( nCountHuge != nExpected )
+    {
+        /* bRet = FALSE; */
+        printf( "WARNING: Huge coords spatial filter returned %d features instead of %d\n",
+                nCountHuge, nExpected );
+    }
+    else if( bVerbose )
+    {
+        printf( "INFO: Huge coords spatial filter works as expected.\n");
+    }
+
+    return bRet;
+}
+
+static int TestSpatialFilter( OGRLayer *poLayer )
+{
+/* -------------------------------------------------------------------- */
+/*      Read the target feature.                                        */
+/* -------------------------------------------------------------------- */
+    poLayer->ResetReading();
+    OGRFeature* poTargetFeature = poLayer->GetNextFeature();
+
+    if( poTargetFeature == NULL )
+    {
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Spatial Filter test for %s.\n"
+                    "      No features in layer.\n",
+                    poLayer->GetName() );
+        }
+        return TRUE;
+    }
+    OGRFeature::DestroyFeature(poTargetFeature);
+
+    if( poLayer->GetLayerDefn()->GetGeomFieldCount() == 0 )
+    {
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Spatial Filter test for %s,\n"
+                    "      target feature has no geometry.\n",
+                    poLayer->GetName() );
+        }
+        return TRUE;
+    }
+
+    int bRet = TRUE;
+    int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();
+    for( int iGeom = 0; iGeom < nGeomFieldCount; iGeom ++ )
+        bRet &= TestSpatialFilter(poLayer, iGeom);
+    
+    OGRPolygon oPolygon;
+    CPLErrorReset();
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    poLayer->SetSpatialFilter(-1, &oPolygon);
+    CPLPopErrorHandler();
+    if( CPLGetLastErrorType() == 0 )
+        printf( "WARNING: poLayer->SetSpatialFilter(-1) should emit an error.\n" );
+
+    CPLErrorReset();
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    poLayer->SetSpatialFilter(nGeomFieldCount, &oPolygon);
+    CPLPopErrorHandler();
+    if( CPLGetLastErrorType() == 0 )
+        printf( "WARNING: poLayer->SetSpatialFilter(nGeomFieldCount) should emit an error.\n" );
+
     return bRet;
 }
 
@@ -1047,7 +1416,7 @@ static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
 
 {
     int bRet = TRUE;
-    OGRFeature  *poFeature, *poTargetFeature;
+    OGRFeature  *poFeature, *poFeature2, *poFeature3, *poTargetFeature;
     int         nInclusiveCount, nExclusiveCount, nTotalCount;
     CPLString osAttributeFilter;
 
@@ -1059,9 +1428,12 @@ static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
 
     if( poTargetFeature == NULL )
     {
-        printf( "INFO: Skipping Attribute Filter test for %s.\n"
-                "      No features in layer.\n",
-                poLayer->GetName() );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Attribute Filter test for %s.\n"
+                    "      No features in layer.\n",
+                    poLayer->GetName() );
+        }
         return bRet;
     }
 
@@ -1078,15 +1450,20 @@ static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
     }
     if( i == poTargetFeature->GetFieldCount() )
     {
-        printf( "INFO: Skipping Attribute Filter test for %s.\n"
-                "      Could not find non NULL field.\n",
-                poLayer->GetName() );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping Attribute Filter test for %s.\n"
+                    "      Could not find non NULL field.\n",
+                    poLayer->GetName() );
+        }
         OGRFeature::DestroyFeature(poTargetFeature);
         return bRet;
     }
 
     const char* pszFieldName = poTargetFeature->GetFieldDefnRef(i)->GetNameRef();
     CPLString osValue = poTargetFeature->GetFieldAsString(i);
+    if( eType == OFTReal )
+        osValue.Printf("%.18g", poTargetFeature->GetFieldAsDouble(i));
 
 /* -------------------------------------------------------------------- */
 /*      Construct inclusive filter.                                     */
@@ -1197,6 +1574,21 @@ static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
 
     nExclusiveCount = poLayer->GetFeatureCount();
 
+    // Check that GetFeature() ignores the attribute filter
+    poFeature2 = poLayer->GetFeature( poTargetFeature->GetFID() );
+
+    poLayer->ResetReading();
+    while( (poFeature3 = poLayer->GetNextFeature()) != NULL )
+    {
+        if( poFeature3->Equal(poTargetFeature) )
+        {
+            OGRFeature::DestroyFeature(poFeature3);
+            break;
+        }
+        else
+            OGRFeature::DestroyFeature(poFeature3);
+    }
+
     poLayer->SetAttributeFilter( NULL );
 
     nTotalCount = poLayer->GetFeatureCount();
@@ -1221,6 +1613,25 @@ static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
     {
         printf( "INFO: Attribute filter exclusion seems to work.\n" );
     }
+    
+    if( poFeature2 == NULL || !poFeature2->Equal(poTargetFeature) )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attribute filter has been taken into account by GetFeature()\n");
+    }
+    else if( bVerbose )
+    {
+        printf( "INFO: Attribute filter is ignored by GetFeature() as expected.\n");
+    }
+
+    if( poFeature3 != NULL )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attribute filter has not been restored correctly after GetFeature()\n");
+    }
+
+    if( poFeature2 != NULL )
+        OGRFeature::DestroyFeature(poFeature2);
 
     OGRFeature::DestroyFeature(poTargetFeature);
 
@@ -1298,7 +1709,7 @@ static int TestOGRLayerUTF8 ( OGRLayer *poLayer )
     if (!bFoundString)
     {
     }
-    else if (bCanAdvertizeUTF8)
+    else if (bCanAdvertizeUTF8 && bVerbose)
     {
         if (bIsAdvertizedAsUTF8)
         {
@@ -1323,7 +1734,7 @@ static int TestOGRLayerUTF8 ( OGRLayer *poLayer )
             }
         }
     }
-    else
+    else if( bVerbose )
     {
         printf( "INFO: Layer has non UTF-8 content (and is consistently declared as not being UTF-8 compatible).\n" );
     }
@@ -1335,7 +1746,7 @@ static int TestOGRLayerUTF8 ( OGRLayer *poLayer )
 /*                         TestGetExtent()                              */
 /************************************************************************/
 
-static int TestGetExtent ( OGRLayer *poLayer )
+static int TestGetExtent ( OGRLayer *poLayer, int iGeomField )
 {
     int bRet = TRUE;
 
@@ -1346,23 +1757,29 @@ static int TestGetExtent ( OGRLayer *poLayer )
     OGREnvelope sExtent;
     OGREnvelope sExtentSlow;
 
-    OGRErr eErr = poLayer->GetExtent(&sExtent, TRUE);
-    OGRErr eErr2 = poLayer->OGRLayer::GetExtent(&sExtentSlow, TRUE);
+    OGRErr eErr = poLayer->GetExtent(iGeomField, &sExtent, TRUE);
+    OGRErr eErr2 = poLayer->OGRLayer::GetExtent(iGeomField, &sExtentSlow, TRUE);
 
     if (eErr != eErr2)
     {
         if (eErr == OGRERR_NONE && eErr2 != OGRERR_NONE)
         {
             /* with the LIBKML driver and test_ogrsf ../autotest/ogr/data/samples.kml "Styles and Markup" */
-            printf("INFO: GetExtent() succeeded but OGRLayer::GetExtent() failed.\n");
+            if( bVerbose )
+            {
+                printf("INFO: GetExtent() succeeded but OGRLayer::GetExtent() failed.\n");
+            }
         }
         else
         {
             bRet = FALSE;
-            printf("ERROR: GetExtent() failed but OGRLayer::GetExtent() succeeded.\n");
+            if( bVerbose )
+            {
+                printf("ERROR: GetExtent() failed but OGRLayer::GetExtent() succeeded.\n");
+            }
         }
     }
-    else if (eErr == OGRERR_NONE)
+    else if (eErr == OGRERR_NONE && bVerbose)
     {
         if (fabs(sExtentSlow.MinX - sExtent.MinX) < 1e-10 &&
             fabs(sExtentSlow.MinY - sExtent.MinY) < 1e-10 &&
@@ -1399,6 +1816,36 @@ static int TestGetExtent ( OGRLayer *poLayer )
     return bRet;
 }
 
+static int TestGetExtent ( OGRLayer *poLayer )
+{
+    int bRet = TRUE;
+    int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();
+    for( int iGeom = 0; iGeom < nGeomFieldCount; iGeom ++ )
+        bRet &= TestGetExtent(poLayer, iGeom);
+
+    OGREnvelope sExtent;
+    
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    OGRErr eErr = poLayer->GetExtent(-1, &sExtent, TRUE);
+    CPLPopErrorHandler();
+    if( eErr != OGRERR_FAILURE )
+    {
+        printf("ERROR: poLayer->GetExtent(-1) should fail.\n");
+        bRet = FALSE;
+    }
+    
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    eErr = poLayer->GetExtent(nGeomFieldCount, &sExtent, TRUE);
+    CPLPopErrorHandler();
+    if( eErr != OGRERR_FAILURE )
+    {
+        printf("ERROR: poLayer->GetExtent(nGeomFieldCount) should fail.\n");
+        bRet = FALSE;
+    }
+
+    return bRet;
+}
+
 /*************************************************************************/
 /*             TestOGRLayerDeleteAndCreateFeature()                      */
 /*                                                                       */
@@ -1473,7 +1920,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
         bRet = FALSE;
         printf( "ERROR: The feature was not deleted.\n" );
     }
-    else
+    else if( bVerbose )
     {
         printf( "INFO: Delete Feature test passed.\n" );
     }
@@ -1492,7 +1939,10 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
     {
         /* Case of shapefile driver for example that will not try to */
         /* reuse the existing FID, but will assign a new one */
-        printf( "INFO: Feature was created, but with not its original FID.\n" );
+        if( bVerbose )
+        {
+            printf( "INFO: Feature was created, but with not its original FID.\n" );
+        }
         nFID = poFeature->GetFID();
     }
 
@@ -1505,7 +1955,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
         bRet = FALSE;
         printf( "ERROR: The feature was not created.\n" );
     }
-    else
+    else if( bVerbose )
     {
         printf( "INFO: Create Feature test passed.\n" );
     }
@@ -1541,8 +1991,11 @@ static int TestTransactions( OGRLayer *poLayer )
             {
                 /* The default implementation has a dummy StartTransaction(), but RollbackTransaction() returns */
                 /* OGRERR_UNSUPPORTED_OPERATION */
-                printf( "INFO: Transactions test skipped due to lack of transaction support.\n" );
-                return FALSE;
+                if( bVerbose )
+                {
+                    printf( "INFO: Transactions test skipped due to lack of transaction support.\n" );
+                }
+                return TRUE;
             }
             else
             {
@@ -1604,9 +2057,12 @@ static int TestTransactions( OGRLayer *poLayer )
 
     if (eErr == OGRERR_FAILURE)
     {
-        printf("INFO: CreateFeature() failed. Exiting this test now.\n");
+        if( bVerbose )
+        {
+            printf("INFO: CreateFeature() failed. Exiting this test now.\n");
+        }
         poLayer->RollbackTransaction();
-        return FALSE;
+        return TRUE;
     }
 
     eErr = poLayer->RollbackTransaction();
@@ -1618,7 +2074,7 @@ static int TestTransactions( OGRLayer *poLayer )
 
     if (poLayer->GetFeatureCount() != nInitialFeatureCount)
     {
-        printf("INFO: GetFeatureCount() should have returned its initial value after RollbackTransaction().\n");
+        printf("ERROR: GetFeatureCount() should have returned its initial value after RollbackTransaction().\n");
         poLayer->RollbackTransaction();
         return FALSE;
     }
@@ -1644,7 +2100,7 @@ static int TestTransactions( OGRLayer *poLayer )
 
         if (eErr == OGRERR_FAILURE)
         {
-            printf("INFO: CreateFeature() failed. Exiting this test now.\n");
+            printf("ERROR: CreateFeature() failed. Exiting this test now.\n");
             poLayer->RollbackTransaction();
             return FALSE;
         }
@@ -1658,7 +2114,7 @@ static int TestTransactions( OGRLayer *poLayer )
 
         if (poLayer->GetFeatureCount() != nInitialFeatureCount + 1)
         {
-            printf("INFO: GetFeatureCount() should have returned its initial value + 1 after CommitTransaction().\n");
+            printf("ERROR: GetFeatureCount() should have returned its initial value + 1 after CommitTransaction().\n");
             poLayer->RollbackTransaction();
             return FALSE;
         }
@@ -1672,7 +2128,7 @@ static int TestTransactions( OGRLayer *poLayer )
 
         if (poLayer->GetFeatureCount() != nInitialFeatureCount)
         {
-            printf("INFO: GetFeatureCount() should have returned its initial value after DeleteFeature().\n");
+            printf("ERROR: GetFeatureCount() should have returned its initial value after DeleteFeature().\n");
             poLayer->RollbackTransaction();
             return FALSE;
         }
@@ -1680,7 +2136,10 @@ static int TestTransactions( OGRLayer *poLayer )
 
     /* ---------------- */
 
-    printf( "INFO: Transactions test passed.\n" );
+    if( bVerbose )
+    {
+        printf( "INFO: Transactions test passed.\n" );
+    }
 
     return TRUE;
 }
@@ -1730,7 +2189,10 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
 
     if( iFieldNonEmpty < 0 && bGeomNonEmpty == FALSE )
     {
-        printf( "INFO: IgnoreFields test skipped.\n" );
+        if( bVerbose )
+        {
+            printf( "INFO: IgnoreFields test skipped.\n" );
+        }
         return TRUE;
     }
 
@@ -1788,7 +2250,10 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
 
     poLayer->SetIgnoredFields(NULL);
 
-    printf( "INFO: IgnoreFields test passed.\n" );
+    if( bVerbose )
+    {
+        printf( "INFO: IgnoreFields test passed.\n" );
+    }
 
     return TRUE;
 }
@@ -1833,39 +2298,70 @@ static int TestLayerSQL( OGRDataSource* poDS, OGRLayer * poLayer )
         }
         else if( poLayerFeat != NULL && poSQLFeat != NULL )
         {
-            OGRGeometry* poLayerFeatGeom = poLayerFeat->GetGeometryRef();
-            OGRGeometry* poSQLFeatGeom = poSQLFeat->GetGeometryRef();
-            if( poLayerFeatGeom == NULL && poSQLFeatGeom != NULL )
+            if( poLayer->GetLayerDefn()->GetGeomFieldCount() !=
+                poSQLLyr->GetLayerDefn()->GetGeomFieldCount() )
             {
-                printf( "ERROR: poLayerFeatGeom == NULL && poSQLFeatGeom != NULL.\n" );
+                printf( "ERROR: poLayer->GetLayerDefn()->GetGeomFieldCount() != poSQLLyr->GetLayerDefn()->GetGeomFieldCount().\n" );
                 bRet = FALSE;
             }
-            else if( poLayerFeatGeom != NULL && poSQLFeatGeom == NULL )
-            {
-                printf( "ERROR: poLayerFeatGeom != NULL && poSQLFeatGeom == NULL.\n" );
-                bRet = FALSE;
-            }
-            else if( poLayerFeatGeom != NULL && poSQLFeatGeom != NULL )
+            else
             {
-                OGRSpatialReference* poLayerFeatSRS = poLayerFeatGeom->getSpatialReference();
-                OGRSpatialReference* poSQLFeatSRS = poSQLFeatGeom->getSpatialReference();
-                if( poLayerFeatSRS == NULL && poSQLFeatSRS != NULL )
+                int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();
+                for(int i = 0; i < nGeomFieldCount; i++ )
                 {
-                    printf( "ERROR: poLayerFeatSRS == NULL && poSQLFeatSRS != NULL.\n" );
-                    bRet = FALSE;
-                }
-                else if( poLayerFeatSRS != NULL && poSQLFeatSRS == NULL )
-                {
-                    printf( "ERROR: poLayerFeatSRS != NULL && poSQLFeatSRS == NULL.\n" );
-                    bRet = FALSE;
-                }
-                else if( poLayerFeatSRS != NULL && poSQLFeatSRS != NULL )
-                {
-                    if( !(poLayerFeatSRS->IsSame(poSQLFeatSRS)) )
+                    int iOtherI;
+                    if( nGeomFieldCount != 1 )
+                    {
+                        OGRGeomFieldDefn* poGFldDefn =
+                            poLayer->GetLayerDefn()->GetGeomFieldDefn(i);
+                        iOtherI = poSQLLyr->GetLayerDefn()->
+                            GetGeomFieldIndex(poGFldDefn->GetNameRef());
+                        if( iOtherI == -1 )
+                        {
+                            printf( "ERROR: Cannot find geom field in SQL matching %s.\n",
+                                    poGFldDefn->GetNameRef() );
+                            break;
+                        }
+                    }
+                    else
+                        iOtherI = 0;
+                    OGRGeometry* poLayerFeatGeom = poLayerFeat->GetGeomFieldRef(i);
+                    OGRGeometry* poSQLFeatGeom = poSQLFeat->GetGeomFieldRef(iOtherI);
+                    if( poLayerFeatGeom == NULL && poSQLFeatGeom != NULL )
+                    {
+                        printf( "ERROR: poLayerFeatGeom[%d] == NULL && poSQLFeatGeom[%d] != NULL.\n",
+                                i, iOtherI );
+                        bRet = FALSE;
+                    }
+                    else if( poLayerFeatGeom != NULL && poSQLFeatGeom == NULL )
                     {
-                        printf( "ERROR: !(poLayerFeatSRS->IsSame(poSQLFeatSRS)).\n" );
+                        printf( "ERROR: poLayerFeatGeom[%d] != NULL && poSQLFeatGeom[%d] == NULL.\n",
+                                i, iOtherI );
                         bRet = FALSE;
                     }
+                    else if( poLayerFeatGeom != NULL && poSQLFeatGeom != NULL )
+                    {
+                        OGRSpatialReference* poLayerFeatSRS = poLayerFeatGeom->getSpatialReference();
+                        OGRSpatialReference* poSQLFeatSRS = poSQLFeatGeom->getSpatialReference();
+                        if( poLayerFeatSRS == NULL && poSQLFeatSRS != NULL )
+                        {
+                            printf( "ERROR: poLayerFeatSRS == NULL && poSQLFeatSRS != NULL.\n" );
+                            bRet = FALSE;
+                        }
+                        else if( poLayerFeatSRS != NULL && poSQLFeatSRS == NULL )
+                        {
+                            printf( "ERROR: poLayerFeatSRS != NULL && poSQLFeatSRS == NULL.\n" );
+                            bRet = FALSE;
+                        }
+                        else if( poLayerFeatSRS != NULL && poSQLFeatSRS != NULL )
+                        {
+                            if( !(poLayerFeatSRS->IsSame(poSQLFeatSRS)) )
+                            {
+                                printf( "ERROR: !(poLayerFeatSRS->IsSame(poSQLFeatSRS)).\n" );
+                                bRet = FALSE;
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -1902,7 +2398,7 @@ static int TestLayerSQL( OGRDataSource* poDS, OGRLayer * poLayer )
         bRet = FALSE;
     }
     
-    if( bRet )
+    if( bRet && bVerbose )
         printf("INFO: TestLayerSQL passed.\n");
 
     return bRet;
@@ -2044,7 +2540,10 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
     poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, NULL );
     if (poDS == NULL)
     {
-        printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        }
         goto bye;
     }
 
@@ -2053,7 +2552,10 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
     if (poLayer1 == NULL || poLayer2 == NULL ||
         poLayer1->GetFeatureCount() < 2 || poLayer2->GetFeatureCount() < 2)
     {
-        printf( "INFO: Skipping TestInterleavedReading(). Test conditions are not met\n" );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping TestInterleavedReading(). Test conditions are not met\n" );
+        }
         goto bye;
     }
 
@@ -2063,7 +2565,10 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
     poDS2 = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, NULL );
     if (poDS == NULL || poDS2 == NULL)
     {
-        printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        if( bVerbose )
+        {
+            printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        }
         goto bye;
     }
 
diff --git a/apps/testreprojmulti.cpp b/apps/testreprojmulti.cpp
index b919e58..95b7010 100644
--- a/apps/testreprojmulti.cpp
+++ b/apps/testreprojmulti.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: testreprojmulti.cpp 20592 2010-09-12 17:28:30Z rouault $
+ * $Id: testreprojmulti.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Test multi-threaded reprojection
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "cpl_multiproc.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: testreprojmulti.cpp 20592 2010-09-12 17:28:30Z rouault $");
+CPL_CVSID("$Id: testreprojmulti.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 double* padfRefX;
 double* padfRefY;
diff --git a/configure b/configure
index 1c4f8fb..1bcff74 100755
--- a/configure
+++ b/configure
@@ -1,11 +1,9 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68.
+# Generated by GNU Autoconf 2.69.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -134,6 +132,31 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -167,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -220,21 +244,25 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-	# neutralization value for shells without unset; and this also
-	# works around shells that cannot unset nonexistent variables.
-	# Preserve -v and -x to the replacement shell.
-	BASH_ENV=/dev/null
-	ENV=/dev/null
-	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-	export CONFIG_SHELL
-	case $- in # ((((
-	  *v*x* | *x*v* ) as_opts=-vx ;;
-	  *v* ) as_opts=-v ;;
-	  *x* ) as_opts=-x ;;
-	  * ) as_opts= ;;
-	esac
-	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -336,6 +364,14 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -457,6 +493,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -491,16 +531,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -512,28 +552,8 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -641,6 +661,8 @@ POPPLER_BASE_STREAM_HAS_TWO_ARGS
 POPPLER_HAS_OPTCONTENT
 HAVE_POPPLER
 PAM_SETTING
+JSON_INCLUDE
+LIBJSONC_SETTING
 FREEXL_INCLUDE
 HAVE_FREEXL
 OPENCL_LIB
@@ -665,6 +687,7 @@ SQLITE_INC
 SQLITE3_LDFLAGS
 SQLITE3_CFLAGS
 SQLITE3_VERSION
+SPATIALITE_412_OR_LATER
 SPATIALITE_AMALGAMATION
 SPATIALITE_INC
 HAVE_SPATIALITE
@@ -700,6 +723,7 @@ INGRES_INC
 INGRES_LIB
 II_SYSTEM
 HAVE_INGRES
+MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION
 MYSQL_LIB
 MYSQL_INC
 HAVE_MYSQL
@@ -734,6 +758,9 @@ HDF5_INCLUDE
 HAVE_HDF5
 HDF4_INCLUDE
 HAVE_HDF4
+SOSI_INC
+SOSI_LIB
+SOSI_ENABLED
 X_FME_HOME
 OGDI_INCLUDE
 HAVE_OGDI
@@ -769,6 +796,8 @@ LIBZ_SETTING
 RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
 RENAME_INTERNAL_LIBTIFF_SYMBOLS
 HAVE_HIDE_INTERNAL_SYMBOLS
+HAVE_AVX_AT_COMPILE_TIME
+AVXFLAGS
 HAVE_GCC_ATOMIC_BUILTINS
 HAVE_LIBTOOL
 SO_EXT
@@ -872,6 +901,7 @@ with_ld_shared
 with_unix_stdio_64
 enable_debug
 with_sse
+with_avx
 with_hide_internal_symbols
 with_rename_internal_libtiff_symbols
 with_rename_internal_libgeotiff_symbols
@@ -897,6 +927,7 @@ with_jpeg12
 with_gif
 with_ogdi
 with_fme
+with_sosi
 with_hdf4
 with_hdf5
 with_netcdf
@@ -944,6 +975,7 @@ with_opencl
 with_opencl_include
 with_opencl_lib
 with_freexl
+with_libjson_c
 with_pam
 with_poppler
 with_podofo
@@ -1431,8 +1463,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1609,6 +1639,7 @@ Optional Packages:
   --without-ld-shared   Disable shared library support
   --with-unix-stdio-64=ARG Utilize 64 stdio api (yes/no)
   --with-sse=ARG        Detect SSE availability for some optimized routines (ARG=yes(default), no)
+  --with-avx=ARG        Detect AVX availability for some optimized routines (ARG=yes(default), no)
   --with-hide-internal-symbols=ARG Try to hide internal symbols (ARG=yes/no)
   --with-rename-internal-libtiff-symbols=ARG Prefix internal libtiff symbols with gdal_ (ARG=yes/no)
   --with-rename-internal-libgeotiff-symbols=ARG Prefix internal libgeotiff symbols with gdal_ (ARG=yes/no)
@@ -1636,6 +1667,7 @@ Optional Packages:
   --with-gif=ARG        Include GIF support (ARG=internal, no or path)
   --with-ogdi=ARG       Include OGDI support (ARG=path)
   --with-fme=ARG        Include FMEObjects support (ARG=FME_HOME path)
+  --with-sosi=ARG        Include SOSI support (ARG=SOSI lib Path, yes or no)
   --with-hdf4=ARG       Include HDF4 support (ARG=path)
   --with-hdf5=ARG       Include HDF5 support (ARG=path)
   --with-netcdf=ARG     Include netCDF support (ARG=no or netCDF tree prefix)
@@ -1692,6 +1724,7 @@ Optional Packages:
   --with-opencl-include=ARG OpenCL Include directory (with a CL subdirectory)
   --with-opencl-lib=ARG   OpenCL Link Flags (ie. -L/xxx -lOpenCL)
   --with-freexl=ARG    Include freexl support (ARG=no, yes (default) or libfreexl install path)
+  --with-libjson-c=ARG       Include libjson-c support (ARG=internal or libjson-c directory)
   --without-pam         Disable PAM (.aux.xml) support
   --with-poppler=ARG    Include poppler(for PDF) support (ARG=no(default), yes or poppler install path)
   --with-podofo=ARG    Include podofo(for PDF) support (ARG=no(default), yes or podofo install path)
@@ -1791,9 +1824,9 @@ test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 configure
-generated by GNU Autoconf 2.68
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1907,7 +1940,7 @@ $as_echo "$ac_try_echo"; } >&5
 	 test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
 	 test "$cross_compiling" = yes ||
-	 $as_test_x conftest$ac_exeext
+	 test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2167,7 +2200,7 @@ $as_echo "$ac_try_echo"; } >&5
 	 test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
 	 test "$cross_compiling" = yes ||
-	 $as_test_x conftest$ac_exeext
+	 test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2290,7 +2323,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) >= 0)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -2306,7 +2340,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -2332,7 +2367,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) < 0)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -2348,7 +2384,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) >= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -2382,7 +2419,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -2555,7 +2593,7 @@ This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -3016,7 +3054,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3056,7 +3094,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3109,7 +3147,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3150,7 +3188,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -3208,7 +3246,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3252,7 +3290,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3698,8 +3736,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3877,7 +3914,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3921,7 +3958,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4198,7 +4235,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4238,7 +4275,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4291,7 +4328,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4332,7 +4369,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -4390,7 +4427,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4434,7 +4471,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4630,8 +4667,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -4744,7 +4780,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4788,7 +4824,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4994,7 +5030,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AS="${ac_tool_prefix}as"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5034,7 +5070,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AS="as"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5086,7 +5122,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5126,7 +5162,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DLLTOOL="dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5178,7 +5214,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5218,7 +5254,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OBJDUMP="objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5392,7 +5428,7 @@ do
     for ac_prog in sed gsed; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+      as_fn_executable_p "$ac_path_SED" || continue
 # Check for GNU ac_path_SED and select it if it is found.
   # Check for GNU $ac_path_SED
 case `"$ac_path_SED" --version 2>&1` in
@@ -5468,7 +5504,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -5534,7 +5570,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -5601,7 +5637,7 @@ do
     for ac_prog in fgrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+      as_fn_executable_p "$ac_path_FGREP" || continue
 # Check for GNU ac_path_FGREP and select it if it is found.
   # Check for GNU $ac_path_FGREP
 case `"$ac_path_FGREP" --version 2>&1` in
@@ -5857,7 +5893,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5901,7 +5937,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6320,7 +6356,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6360,7 +6396,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OBJDUMP="objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6663,7 +6699,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6703,7 +6739,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DLLTOOL="dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6803,7 +6839,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6847,7 +6883,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6972,7 +7008,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7012,7 +7048,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7071,7 +7107,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7111,7 +7147,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7215,7 +7251,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AWK="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7788,7 +7824,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7828,7 +7864,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7908,7 +7944,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7948,7 +7984,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8000,7 +8036,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8040,7 +8076,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_NMEDIT="nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8092,7 +8128,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8132,7 +8168,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_LIPO="lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8184,7 +8220,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8224,7 +8260,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL="otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8276,7 +8312,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -8316,7 +8352,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL64="otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -15992,7 +16028,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -16032,7 +16068,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -17366,29 +17402,29 @@ if test "${with_sse+set}" = set; then :
 fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSE is available" >&5
-$as_echo_n "checking whether SSE is available... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSE is available at compile time" >&5
+$as_echo_n "checking whether SSE is available at compile time... " >&6; }
 
 if test "$with_sse" = "yes" -o "$with_sse" = ""; then
 
     rm -f detectsse.cpp
     echo '#ifdef __SSE__' > detectsse.cpp
     echo '#include <xmmintrin.h>' >> detectsse.cpp
-    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); } ' >> detectsse.cpp
+    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); }  int main() { return 0; }' >> detectsse.cpp
     echo '#else' >> detectsse.cpp
     echo 'some_error' >> detectsse.cpp
     echo '#endif' >> detectsse.cpp
-    if test -z "`${CXX} -c detectsse.cpp 2>&1`" ; then
+    if test -z "`${CXX} ${CXXFLAGS} -o detectsse detectsse.cpp 2>&1`" ; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-        CFLAGS="$CFLAGS -DHAVE_SSE_AT_COMPILE_TIME"
-        CXXFLAGS="$CXXFLAGS -DHAVE_SSE_AT_COMPILE_TIME"
+        SSEFLAGS="-DHAVE_SSE_AT_COMPILE_TIME"
+        HAVE_SSE_AT_COMPILE_TIME=yes
     else
-        if test -z "`${CXX} -msse -c detectsse.cpp 2>&1`" ; then
+        if test -z "`${CXX} ${CXXFLAGS} -msse -o detectsse detectsse.cpp 2>&1`" ; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-            CFLAGS="$CFLAGS -msse -DHAVE_SSE_AT_COMPILE_TIME"
-            CXXFLAGS="$CXXFLAGS -msse -DHAVE_SSE_AT_COMPILE_TIME"
+            SSEFLAGS="-msse -DHAVE_SSE_AT_COMPILE_TIME"
+            HAVE_SSE_AT_COMPILE_TIME=yes
         else
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -17397,13 +17433,116 @@ $as_echo "no" >&6; }
             fi
         fi
     fi
-    rm -f detectsse.*
+
+                    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSE is available and needed at runtime" >&5
+$as_echo_n "checking whether SSE is available and needed at runtime... " >&6; }
+           if ./detectsse; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+           else
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+             if test "$with_sse" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling SSE as it is not explicitely required"
+               HAVE_SSE_AT_COMPILE_TIME=""
+               SSEFLAGS=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+      CFLAGS="$CFLAGS $SSEFLAGS"
+      CXXFLAGS="$CXXFLAGS $SSEFLAGS"
+    fi
+
+    rm -f detectsse*
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
+
+# Check whether --with-avx was given.
+if test "${with_avx+set}" = set; then :
+  withval=$with_avx;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AVX is available at compile time" >&5
+$as_echo_n "checking whether AVX is available at compile time... " >&6; }
+
+if test "$with_avx" = "yes" -o "$with_avx" = ""; then
+
+    rm -f detectavx.cpp
+    echo '#ifdef __AVX__' > detectavx.cpp
+    echo '#include <immintrin.h>' >> detectavx.cpp
+    echo 'void foo() { unsigned int nXCRLow, nXCRHigh; __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0)); float fEpsilon = 0.0000000000001f; __m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon); } int main() { return 0; }' >> detectavx.cpp
+    echo '#else' >> detectavx.cpp
+    echo 'some_error' >> detectavx.cpp
+    echo '#endif' >> detectavx.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectavx detectavx.cpp 2>&1`" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        AVXFLAGS=""
+        HAVE_AVX_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -mavx -o detectavx detectavx.cpp 2>&1`" ; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+            AVXFLAGS="-mavx"
+            HAVE_AVX_AT_COMPILE_TIME=yes
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+            if test "$with_avx" = "yes"; then
+                as_fn_error $? "--with-avx was requested, but AVX is not available" "$LINENO" 5
+            fi
+        fi
+    fi
+
+                    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AVX is available and needed at runtime" >&5
+$as_echo_n "checking whether AVX is available and needed at runtime... " >&6; }
+           if ./detectavx; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+           else
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+             if test "$with_avx" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling AVX as it is not explicitely required"
+               AVXFLAGS=""
+               HAVE_AVX_AT_COMPILE_TIME=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    rm -f detectavx*
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+AVXFLAGS=$AVXFLAGS
+
+HAVE_AVX_AT_COMPILE_TIME=$HAVE_AVX_AT_COMPILE_TIME
+
+
+
 echo "#include <winsock2.h>" > test_ws2_32.c
 echo "#include <ws2tcpip.h>" >> test_ws2_32.c
 echo "void foo() {}" >> test_ws2_32.c
@@ -18932,7 +19071,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -19175,7 +19314,50 @@ fi
 # TODO: separate libs for rasters and vectors
 if test "$with_grass" != "yes" -a "$with_grass" != "no" ; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_asprintf in -lgrass_gis" >&5
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_is_initialized in -lgrass_gis" >&5
+$as_echo_n "checking for G_is_initialized in -lgrass_gis... " >&6; }
+if ${ac_cv_lib_grass_gis_G_is_initialized+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgrass_gis -L$with_grass/lib -lgrass_datetime $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char G_is_initialized ();
+int
+main ()
+{
+return G_is_initialized ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_grass_gis_G_is_initialized=yes
+else
+  ac_cv_lib_grass_gis_G_is_initialized=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_grass_gis_G_is_initialized" >&5
+$as_echo "$ac_cv_lib_grass_gis_G_is_initialized" >&6; }
+if test "x$ac_cv_lib_grass_gis_G_is_initialized" = xyes; then :
+  GRASS_SETTING=grass70+
+else
+  GRASS_SETTING=no
+fi
+
+  if test "$GRASS_SETTING" = "no" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_asprintf in -lgrass_gis" >&5
 $as_echo_n "checking for G_asprintf in -lgrass_gis... " >&6; }
 if ${ac_cv_lib_grass_gis_G_asprintf+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -19217,11 +19399,18 @@ else
   GRASS_SETTING=no
 fi
 
+  fi
 
-  if test "$GRASS_SETTING" = "grass57+" ; then
-    G_RASTLIBS="-lgrass_I"
-    G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
-    LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+  if test "$GRASS_SETTING" != "no" ; then
+    if test "$GRASS_SETTING" = "grass70+" ; then
+      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
+      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    else
+      G_RASTLIBS="-lgrass_I"
+      G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    fi
     GRASS_INCLUDE="-I$with_grass/include"
     GRASS_GISBASE="$with_grass"
     HAVE_GRASS=yes
@@ -20810,6 +20999,77 @@ X_FME_HOME=$X_FME_HOME
 
 
 
+
+# Check whether --with-sosi was given.
+if test "${with_sosi+set}" = set; then :
+  withval=$with_sosi;
+fi
+
+
+if test -z "$with_sosi" -o "$with_sosi" = "no" ; then
+
+  SOSI_ENABLED=no
+
+  echo "SOSI support disabled."
+
+elif test "$with_sosi" = "yes" -o "$with_sosi" = "" ; then
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib" >&5
+$as_echo_n "checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib... " >&6; }
+    if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+        SOSI_ENABLED=yes
+        SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
+    else
+        as_fn_error $? "not found." "$LINENO" 5
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba" >&5
+$as_echo_n "checking for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba... " >&6; }
+    if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+        SOSI_ENABLED=yes
+        SOSI_INC="-I/usr/local/include/fyba"
+    else
+        as_fn_error $? "not found." "$LINENO" 5
+    fi
+
+else
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib" >&5
+$as_echo_n "checking for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib... " >&6; }
+  if test -r $with_sosi/lib/libfyba.a -a -r $with_sosi/lib/libfygm.a -a -r $with_sosi/lib/libfyut.a ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    SOSI_LIB="$with_sosi/lib/libfyba.a $with_sosi/lib/libfygm.a $with_sosi/lib/libfyut.a"
+    SOSI_ENABLED=yes
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fyba.h in $with_sosi/include/fyba" >&5
+$as_echo_n "checking for fyba.h in $with_sosi/include/fyba... " >&6; }
+  if test -r $with_sosi/include/fyba/fyba.h -a -r $with_sosi/include/fyba/fygm.h -a -r $with_sosi/include/fyba/fyut.h ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    SOSI_INC="-I$with_sosi/include/fyba"
+    SOSI_ENABLED=yes
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+fi
+
+SOSI_ENABLED=$SOSI_ENABLED
+
+SOSI_LIB=$SOSI_LIB
+
+SOSI_INC=$SOSI_INC
+
+
+
 HDF4_INCLUDE=""
 
 
@@ -21312,7 +21572,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_NETCDF_NCCONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -21355,7 +21615,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_NETCDF_NCCONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -22032,11 +22292,11 @@ $as_echo_n "checking for FileGDBAPI... " >&6; }
     echo "#include <FileGDBAPI.h>" > testfgdb.cpp
     echo "using namespace FileGDBAPI;" >> testfgdb.cpp
     echo "int main() { Geodatabase oDB; std::wstring osStr; ::OpenGeodatabase(osStr, oDB); return 0; }" >> testfgdb.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -o testfgdb 2>&1`" ; then
+    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -lfgdbunixrtl -o testfgdb 2>&1`" ; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: FileGDBAPI found" >&5
 $as_echo "FileGDBAPI found" >&6; }
         FGDB_ENABLED="yes"
-        FGDB_LIB="-lFileGDBAPI"
+        FGDB_LIB="-lFileGDBAPI -lfgdbunixrtl"
     else
         if test "$with_fgdb" = "yes"; then
             as_fn_error $? "FileGDBAPI not found." "$LINENO" 5
@@ -22053,10 +22313,14 @@ else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libFileGDBAPI.so in in $with_fgdb/lib" >&5
 $as_echo_n "checking for libFileGDBAPI.so in in $with_fgdb/lib... " >&6; }
   FGDB_ENABLED=yes
-  if test -r $with_fgdb/lib/libFileGDBAPI.so ; then
+  if test -r $with_fgdb/lib/libFileGDBAPI.so -a -r $with_fgdb/lib/libfgdbunixrtl.so ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
 $as_echo "found." >&6; }
-    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI"
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
+  elif test -r $with_fgdb/lib/libFileGDBAPI.dylib -a -r $with_fgdb/lib/libfgdbunixrtl.dylib ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
   else
     as_fn_error $? "not found." "$LINENO" 5
   fi
@@ -22199,7 +22463,18 @@ fi
       ECW_LIBS="-lecwj2 $CARBON_FRAMEWORK"
     fi
   fi
-
+  # ECWJP2 SDK 5.1 style
+  if test "$ECW_SETTING" = "no" ; then
+        if test -r /Intergraph/ERDASEcwJpeg2000SDK5.1/lib/libEcwJp2SDK.a; then
+                ECW_LIBDIR=/Intergraph/ERDASEcwJpeg2000SDK5.1/lib
+                ECW_INCLUDE=-I/Intergraph/ERDASEcwJpeg2000SDK5.1/include
+                ECW_LIBS="-L$ECW_LIBDIR -lEcwJp2SDK -framework Cocoa"
+                ECW_SETTING=yes
+                ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph ERDAS EcwJpeg2000 SDK 5.1 in /Intergraph/ERDASEcwJpeg2000SDK5.1/." >&5
+$as_echo "found Intergraph ERDAS EcwJpeg2000 SDK 5.1 in /Intergraph/ERDASEcwJpeg2000SDK5.1/." >&6; }
+        fi
+  fi
 else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libNCSEcw.so or libecwj2" >&5
@@ -22233,7 +22508,15 @@ $as_echo "found libecwj2 in $with_ecw/lib." >&6; }
     ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw"
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.x+ SDK in ${ECW_LIBDIR}." >&5
 $as_echo "found Intergraph 5.x+ SDK in ${ECW_LIBDIR}." >&6; }
-  else
+ # ECWJP2 SDK 5.1 style
+  elif test -r $with_ecw/lib/libEcwJp2SDK.a; then
+        ECW_LIBDIR=$with_ecw/lib
+        ECW_INCLUDE=-I$with_ecw/include
+        ECW_LIBS="-L$ECW_LIBDIR -lEcwJp2SDK -framework Cocoa"
+        ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.1+ SDK in $ {with_ecw}." >&5
+$as_echo "found Intergraph 5.1+ SDK in $ {with_ecw}." >&6; }
+ else
     as_fn_error $? "not found in $with_ecw/lib or $with_ecw/bin." "$LINENO" 5
   fi
 
@@ -22395,7 +22678,16 @@ $as_echo "no encoding support." >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MrSID JPEG2000 support" >&5
 $as_echo_n "checking for MrSID JPEG2000 support... " >&6; }
     if test "x$with_jp2mrsid" = "xyes" -a "$HAVE_KAKADU" = "yes" ; then
-      as_fn_error $? "MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu" "$LINENO" 5
+      # SDK v8 or later don't seem to conflict with Kakadu
+      major_version=`cat $with_mrsid/include/lti_version.h | grep MAJOR | sed 's/#define LTI_SDK_MAJOR[ ]*\(.*\)/\1/'`
+      if test "x$major_version" != "x"; then
+        if test "$major_version" -ge 8; then
+            V8_OR_LATER=yes
+        fi
+      fi
+      if test "x$V8_OR_LATER" = "x"; then
+        as_fn_error $? "MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu" "$LINENO" 5
+      fi
     fi
 
     MRSID_KAKADU_LIB=""
@@ -22977,7 +23269,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MYSQL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -23045,6 +23337,34 @@ $as_echo "no, mysql is pre-4.x" >&6; }
       MYSQL_INC="`$MYSQL_CONFIG --include`"
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+
+      # Check if mysql headers declare load_defaults
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking load_defaults() in MySQL" >&5
+$as_echo_n "checking load_defaults() in MySQL... " >&6; }
+      rm -f testmysql.*
+      echo '#include "my_global.h"' > testmysql.cpp
+      echo '#include "my_sys.h"' >> testmysql.cpp
+      echo 'int main(int argc, char** argv) { load_defaults(0, 0, 0, 0); return 0; } ' >> testmysql.cpp
+      if test -z "`${CXX} ${CXXFLAGS} ${MYSQL_INC} -o testmysql testmysql.cpp ${MYSQL_LIB} 2>&1`" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, found in my_sys.h" >&5
+$as_echo "yes, found in my_sys.h" >&6; }
+      else
+        echo 'extern "C" void load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv);' > testmysql.cpp
+        echo 'int main(int argc, char** argv) { load_defaults(0, 0, 0, 0); return 0; } ' >> testmysql.cpp
+        if test -z "`${CXX} ${CXXFLAGS} ${MYSQL_INC} -o testmysql testmysql.cpp ${MYSQL_LIB} 2>&1`" ; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, found in library but not in header" >&5
+$as_echo "yes, found in library but not in header" >&6; }
+            MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION=yes
+        else
+            HAVE_MYSQL=no
+            MYSQL_LIB=
+            MYSQL_INC=
+            as_fn_error $? "Cannot find load_defaults()" "$LINENO" 5
+        fi
+      fi
+      rm -f testmysql.*
+      rm -f testmysql
+
 	;;
   esac
 fi
@@ -23055,6 +23375,8 @@ MYSQL_INC=$MYSQL_INC
 
 MYSQL_LIB=$MYSQL_LIB
 
+MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION=$MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION
+
 
 
 
@@ -23080,8 +23402,6 @@ else
   HAVE_INGRES=yes
   II_SYSTEM=$with_ingres
   INGRES_LIB="-L$II_SYSTEM/ingres/lib \
-	$II_SYSTEM/ingres/lib/iiclsadt.o \
-	$II_SYSTEM/ingres/lib/iiuseradt.o \
 	-liiapi.1 -lcompat.1 -lq.1 -lframe.1"
   INGRES_INC=-I$II_SYSTEM/ingres/files
 fi
@@ -24657,7 +24977,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_LIBCURL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -24785,7 +25105,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_LIBXML2_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -24948,7 +25268,8 @@ fi
 
             if test "$SPATIALITE_INIT_FOUND" = "yes"; then
                 HAVE_SPATIALITE=yes
-                LIBS="$LIBS -lspatialite"
+                SPATIALITE_LIBS="-lspatialite -lsqlite3"
+                LIBS="$LIBS $SPATIALITE_LIBS"
                 HAVE_SQLITE3=yes
             fi
         else
@@ -25013,7 +25334,8 @@ $as_echo "enabled" >&6; }
         # as there's a spatialite.h file in it, which we don't want to include.
         # We want to include include/spatialite.h instead !
         SQLITE3_CFLAGS="-I$with_spatialite/include"
-        LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+        LIBS="$LIBS $SPATIALITE_LIBS"
         HAVE_SQLITE3=yes
 
     elif test -f "$with_spatialite/include/spatialite.h" -a \
@@ -25035,7 +25357,8 @@ done
 $as_echo "enabled" >&6; }
             SPATIALITE_INC="-I$with_spatialite/include"
             HAVE_SPATIALITE=yes
-            LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite -lsqlite3"
+            LIBS="$LIBS $SPATIALITE_LIBS"
             HAVE_SQLITE3=yes
         fi
     else
@@ -25044,12 +25367,62 @@ $as_echo "disabled" >&6; }
     fi
 fi
 
+if test "$HAVE_SPATIALITE" = "yes"; then
+    ax_save_LIBS="${LIBS}"
+    LIBS="$SPATIALITE_LIBS"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_target_cpu in -lspatialite" >&5
+$as_echo_n "checking for spatialite_target_cpu in -lspatialite... " >&6; }
+if ${ac_cv_lib_spatialite_spatialite_target_cpu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lspatialite  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char spatialite_target_cpu ();
+int
+main ()
+{
+return spatialite_target_cpu ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_spatialite_spatialite_target_cpu=yes
+else
+  ac_cv_lib_spatialite_spatialite_target_cpu=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_target_cpu" >&5
+$as_echo "$ac_cv_lib_spatialite_spatialite_target_cpu" >&6; }
+if test "x$ac_cv_lib_spatialite_spatialite_target_cpu" = xyes; then :
+  SPATIALITE_412_OR_LATER=yes
+else
+  SPATIALITE_412_OR_LATER=no
+fi
+
+    LIBS="${ax_save_LIBS}"
+fi
+
 HAVE_SPATIALITE=$HAVE_SPATIALITE
 
 SPATIALITE_INC=$SPATIALITE_INC
 
 SPATIALITE_AMALGAMATION=$SPATIALITE_AMALGAMATION
 
+SPATIALITE_412_OR_LATER=$SPATIALITE_412_OR_LATER
+
 
 
 if test "${HAVE_SPATIALITE}" = "no" ; then
@@ -26246,7 +26619,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GEOS_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -26315,7 +26688,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "
    "; then
        ac_prog_rejected=yes
@@ -26359,7 +26732,7 @@ fi
 
   if test x"$GEOS_CONFIG" != x"no" ; then
 
-    min_geos_version=2.2.0
+    min_geos_version=3.1.0
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GEOS version >= $min_geos_version" >&5
 $as_echo_n "checking for GEOS version >= $min_geos_version... " >&6; }
@@ -27133,6 +27506,133 @@ FREEXL_INCLUDE=$FREEXL_INCLUDE
 
 
 
+
+
+# Check whether --with-libjson-c was given.
+if test "${with_libjson_c+set}" = set; then :
+  withval=$with_libjson_c;
+fi
+
+
+if test "$with_libjson_c" = "external" -o "$with_libjson_c" = "" -o "$with_libjson_c" = "yes" ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_set_serializer in -ljson-c" >&5
+$as_echo_n "checking for json_object_set_serializer in -ljson-c... " >&6; }
+if ${ac_cv_lib_json_c_json_object_set_serializer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljson-c  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char json_object_set_serializer ();
+int
+main ()
+{
+return json_object_set_serializer ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_json_c_json_object_set_serializer=yes
+else
+  ac_cv_lib_json_c_json_object_set_serializer=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_c_json_object_set_serializer" >&5
+$as_echo "$ac_cv_lib_json_c_json_object_set_serializer" >&6; }
+if test "x$ac_cv_lib_json_c_json_object_set_serializer" = xyes; then :
+  LIBJSONC_SETTING=external
+else
+  LIBJSONC_SETTING=internal
+fi
+
+elif test "$with_libjson_c" = "internal" ; then
+  LIBJSONC_SETTING=internal
+elif test "$with_libjson_c" != "no"; then
+  LIBS="-L$with_libjson_c/lib $LIBS"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_set_serializer in -ljson-c" >&5
+$as_echo_n "checking for json_object_set_serializer in -ljson-c... " >&6; }
+if ${ac_cv_lib_json_c_json_object_set_serializer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljson-c -L$with_libjson_c/lib $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char json_object_set_serializer ();
+int
+main ()
+{
+return json_object_set_serializer ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_json_c_json_object_set_serializer=yes
+else
+  ac_cv_lib_json_c_json_object_set_serializer=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_c_json_object_set_serializer" >&5
+$as_echo "$ac_cv_lib_json_c_json_object_set_serializer" >&6; }
+if test "x$ac_cv_lib_json_c_json_object_set_serializer" = xyes; then :
+  LIBJSONC_SETTING=external
+else
+  LIBJSONC_SETTING=internal
+fi
+
+else
+  as_fn_error $? "libjson-c (internal or external) is required" "$LINENO" 5
+fi
+
+if test "$LIBJSONC_SETTING" = "external" ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: using pre-installed libjson-c" >&5
+$as_echo "using pre-installed libjson-c" >&6; }
+  LIBS="-ljson-c $LIBS"
+  if test "$with_libjson_c" != "" -a "$with_libjson_c" != "yes" -a "$with_libjson_c" != "external" ; then
+    JSON_INCLUDE="-I$with_libjson_c/include/json-c"
+  elif test -f "/usr/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/include/json-c"
+  elif test -f "/usr/local/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/local/include/json-c"
+  else
+    as_fn_error $? "could not find json-c/json.h" "$LINENO" 5
+  fi
+else
+    JSON_INCLUDE="-I\$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson/libjson"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libjson-c code" >&5
+$as_echo "using internal libjson-c code" >&6; }
+fi
+
+LIBJSONC_SETTING=$LIBJSONC_SETTING
+
+JSON_INCLUDE=$JSON_INCLUDE
+
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable PAM" >&5
 $as_echo_n "checking whether to enable PAM... " >&6; }
 
@@ -27189,8 +27689,18 @@ if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
     echo '#include <poppler/Page.h>' >> testpoppler.cpp
     echo '#include <poppler/splash/SplashBitmap.h>' >> testpoppler.cpp
     echo 'int main(int argc, char** argv) { return &(((Page*)0x8000)->pageObj) == 0; } ' >> testpoppler.cpp
+
     if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
         HAVE_POPPLER=yes
+    else
+        # poppler 0.23.0 needs to be linked against pthread
+        TEST_POPPLER_LIB="${TEST_POPPLER_LIB} -lpthread"
+        if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
+            HAVE_POPPLER=yes
+        fi
+    fi
+
+    if test "$HAVE_POPPLER" = "yes"; then
         LIBS="${TEST_POPPLER_LIB} ${LIBS}"
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -27934,7 +28444,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_PYTHON="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -28009,11 +28519,13 @@ $as_echo_n "checking whether we should include Java support... " >&6; }
 
 JAVA_HOME=""
 JAVA_INC=""
+mac_java_fw=""
 
 if test "x$with_java" = "xyes"; then
 
     JAVA_6_TEST_DIR=
     JAVA_7_TEST_DIR=
+    JAVA_MAC_TEST_DIR=
     case "$host_cpu" in
         i*86*)
             JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-i386
@@ -28026,6 +28538,11 @@ if test "x$with_java" = "xyes"; then
         *)
             ;;
     esac
+    case "${host_os}" in
+      darwin*)
+        JAVA_MAC_TEST_DIR=$(/usr/libexec/java_home)
+        ;;
+    esac
 
     if test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
         with_java="$JAVA_7_TEST_DIR"
@@ -28042,11 +28559,22 @@ if test "x$with_java" = "xyes"; then
 
     elif test -d /usr/java; then
         with_java="/usr/java"
+
+    elif test "x$JAVA_MAC_TEST_DIR" != "x"; then
+        if test -d "$JAVA_MAC_TEST_DIR/bundle"; then
+            # Mac default 1.6.0_x framework
+            # test for ./bundle first, since older installs also have ./include
+            with_java="$JAVA_MAC_TEST_DIR"
+            mac_java_fw="JavaVM"
+        elif test -d "$JAVA_MAC_TEST_DIR/include"; then
+            # Oracle Java install
+            with_java="$JAVA_MAC_TEST_DIR"
+        fi
     else
         as_fn_error $? "\"cannot find JDK root directory.\"" "$LINENO" 5
     fi
 
-    if test \! -d "$with_java/include" ; then
+    if test \! -d "$with_java/include" && test \! -d "$with_java/bundle"; then
         as_fn_error $? "\"$with_java is not a valid JDK.\"" "$LINENO" 5
     fi
 fi
@@ -28056,7 +28584,15 @@ if test "x$JAVA_INC" != "x"; then
 $as_echo "yes" >&6; }
 elif test "x$with_java" != "x" -a "x$with_java" != "xno"; then
 
-    if test -d "$with_java/include"; then
+    if test -d "$with_java/bundle" && test -d "/System/Library/Frameworks/JavaVM.framework/Headers"; then
+        # Mac default 1.6.0_x framework
+        # test for ./bundle first, since older installs also have ./include
+        JAVA_HOME="$with_java"
+        JAVA_INC="-I/System/Library/Frameworks/JavaVM.framework/Headers"
+        mac_java_fw="JavaVM"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    elif test -d "$with_java/include"; then
         if test -d "$with_java/include/linux"; then
             JAVA_HOME="$with_java"
             JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
@@ -28072,11 +28608,17 @@ $as_echo "yes" >&6; }
             JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/freebsd"
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+        elif test -d "$with_java/include/darwin"; then
+            # Oracle Java install, use instead of Mac default 1.6.0_x
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/darwin"
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
         else
-            as_fn_error $? "\"Cannot find $with_java/include/linux or solaris or freebsd directory.\"" "$LINENO" 5
+            as_fn_error $? "\"Cannot find $with_java/include/linux or solaris or freebsd or darwin directory.\"" "$LINENO" 5
         fi
     else
-        as_fn_error $? "\"Cannot find $with_java/include directory.\"" "$LINENO" 5
+        as_fn_error $? "\"Cannot find $with_java/include or <mac_java_framework>/Headers directory.\"" "$LINENO" 5
     fi
 
 else
@@ -28126,7 +28668,53 @@ fi
         if test -d "$with_jvm_lib"; then
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$with_jvm_lib"
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
+            if test "x$mac_java_fw" != "x"; then
+                as_ac_Lib=`$as_echo "ac_cv_lib_$mac_java_fw''_JNI_CreateJavaVM" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -framework $mac_java_fw" >&5
+$as_echo_n "checking for JNI_CreateJavaVM in -framework $mac_java_fw... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_fw_func_save_LIBS=$LIBS
+LIBS="-framework $mac_java_fw  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JNI_CreateJavaVM ();
+int
+main ()
+{
+return JNI_CreateJavaVM ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_fw_func_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  HAS_LIB_JVM=yes
+else
+  HAS_LIB_JVM=no
+fi
+
+            else
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
 $as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
 if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -28168,11 +28756,24 @@ else
   HAS_LIB_JVM=no
 fi
 
+            fi
             LDFLAGS="$saved_LDFLAGS"
             if test "$HAS_LIB_JVM" = "yes"; then
                 JVM_LIB="-L$with_jvm_lib -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
                 if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$with_jvm_lib -L$with_jvm_lib -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                          ;;
+                    esac
                 fi
             else
                 as_fn_error $? "\"--with-jvm-lib must point to a directory with a libjvm.\"" "$LINENO" 5
@@ -28182,11 +28783,65 @@ fi
         fi
     elif test "x$JAVA_HOME" != "x"; then
         TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
+        if test -d "$JAVA_HOME/jre/lib/server"; then
+            # Oracle Java install on Mac
+            TEST_DIR="$JAVA_HOME/jre/lib/server"
+        fi
+        if test "x$mac_java_fw" != "x"; then
+            # Mac default 1.6.0_x framework, TEST_DIR not used
+            TEST_DIR="$with_java"
+        fi
         if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
             unset ac_cv_lib_jvm_JNI_CreateJavaVM
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$TEST_DIR"
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
+            if test "x$mac_java_fw" != "x"; then
+                as_ac_Lib=`$as_echo "ac_cv_lib_$mac_java_fw''_JNI_CreateJavaVM" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -framework $mac_java_fw" >&5
+$as_echo_n "checking for JNI_CreateJavaVM in -framework $mac_java_fw... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_fw_func_save_LIBS=$LIBS
+LIBS="-framework $mac_java_fw  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JNI_CreateJavaVM ();
+int
+main ()
+{
+return JNI_CreateJavaVM ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_fw_func_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  HAS_LIB_JVM=yes
+else
+  HAS_LIB_JVM=no
+fi
+
+            else
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
 $as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
 if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -28228,11 +28883,24 @@ else
   HAS_LIB_JVM=no
 fi
 
+            fi
             LDFLAGS="$saved_LDFLAGS"
             if test "$HAS_LIB_JVM" = "yes"; then
                 JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
                 if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$TEST_DIR -L$TEST_DIR -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                          ;;
+                    esac
                 fi
             fi
         fi
@@ -28802,16 +29470,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -28871,28 +29539,16 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-	test -d "$1/.";
-      else
-	case $1 in #(
-	-*)set "./$1";;
-	esac;
-	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-	???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -28914,7 +29570,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # values after options handling.
 ac_log="
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -28980,10 +29636,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.68,
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -29072,7 +29728,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
@@ -31090,6 +31746,9 @@ echo "  Armadillo support:         ${HAVE_ARMADILLO}"
 echo "  FreeXL support:            ${HAVE_FREEXL}"
 
 
+echo "  SOSI support:              ${SOSI_ENABLED}"
+
+
 echo ""
 
 if test ! -z "`uname | grep Darwin`" ; then
diff --git a/configure.in b/configure.in
index 481e8ea..dfd94c4 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 25849 2013-04-03 22:15:46Z rouault $
+dnl $Id: configure.in 26958 2014-02-17 18:24:07Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -227,26 +227,26 @@ dnl ---------------------------------------------------------------------------
 AC_ARG_WITH(sse,
 [  --with-sse[=ARG]        Detect SSE availability for some optimized routines (ARG=yes(default), no)],,)
 
-AC_MSG_CHECKING([whether SSE is available])
+AC_MSG_CHECKING([whether SSE is available at compile time])
 
 if test "$with_sse" = "yes" -o "$with_sse" = ""; then
 
     rm -f detectsse.cpp
     echo '#ifdef __SSE__' > detectsse.cpp
     echo '#include <xmmintrin.h>' >> detectsse.cpp
-    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); } ' >> detectsse.cpp
+    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); }  int main() { return 0; }' >> detectsse.cpp
     echo '#else' >> detectsse.cpp
     echo 'some_error' >> detectsse.cpp
     echo '#endif' >> detectsse.cpp
-    if test -z "`${CXX} -c detectsse.cpp 2>&1`" ; then
+    if test -z "`${CXX} ${CXXFLAGS} -o detectsse detectsse.cpp 2>&1`" ; then
         AC_MSG_RESULT([yes])
-        CFLAGS="$CFLAGS -DHAVE_SSE_AT_COMPILE_TIME"
-        CXXFLAGS="$CXXFLAGS -DHAVE_SSE_AT_COMPILE_TIME"
+        SSEFLAGS="-DHAVE_SSE_AT_COMPILE_TIME"
+        HAVE_SSE_AT_COMPILE_TIME=yes
     else
-        if test -z "`${CXX} -msse -c detectsse.cpp 2>&1`" ; then
+        if test -z "`${CXX} ${CXXFLAGS} -msse -o detectsse detectsse.cpp 2>&1`" ; then
             AC_MSG_RESULT([yes])
-            CFLAGS="$CFLAGS -msse -DHAVE_SSE_AT_COMPILE_TIME"
-            CXXFLAGS="$CXXFLAGS -msse -DHAVE_SSE_AT_COMPILE_TIME"
+            SSEFLAGS="-msse -DHAVE_SSE_AT_COMPILE_TIME"
+            HAVE_SSE_AT_COMPILE_TIME=yes
         else
             AC_MSG_RESULT([no])
             if test "$with_sse" = "yes"; then
@@ -254,12 +254,109 @@ if test "$with_sse" = "yes" -o "$with_sse" = ""; then
             fi
         fi
     fi
-    rm -f detectsse.*
+
+    dnl On Solaris, the presence of SSE instructions is flagged in the binary
+    dnl and prevent it to run on non SSE hardware even if the instructions are
+    dnl not executed. So if the user did not explicitely requires SSE, test that
+    dnl we can run SSE binaries
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           AC_MSG_CHECKING([whether SSE is available and needed at runtime])
+           if ./detectsse; then
+             AC_MSG_RESULT([yes])
+           else
+             AC_MSG_RESULT([no])
+             if test "$with_sse" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling SSE as it is not explicitely required"
+               HAVE_SSE_AT_COMPILE_TIME=""
+               SSEFLAGS=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+      CFLAGS="$CFLAGS $SSEFLAGS"
+      CXXFLAGS="$CXXFLAGS $SSEFLAGS"
+    fi
+
+    rm -f detectsse*
 else
     AC_MSG_RESULT([no])
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl Check AVX availability
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(avx,
+[  --with-avx[=ARG]        Detect AVX availability for some optimized routines (ARG=yes(default), no)],,)
+
+AC_MSG_CHECKING([whether AVX is available at compile time])
+
+if test "$with_avx" = "yes" -o "$with_avx" = ""; then
+
+    rm -f detectavx.cpp
+    echo '#ifdef __AVX__' > detectavx.cpp
+    echo '#include <immintrin.h>' >> detectavx.cpp
+    echo 'void foo() { unsigned int nXCRLow, nXCRHigh; __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0)); float fEpsilon = 0.0000000000001f; __m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon); } int main() { return 0; }' >> detectavx.cpp
+    echo '#else' >> detectavx.cpp
+    echo 'some_error' >> detectavx.cpp
+    echo '#endif' >> detectavx.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectavx detectavx.cpp 2>&1`" ; then
+        AC_MSG_RESULT([yes])
+        AVXFLAGS=""
+        HAVE_AVX_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -mavx -o detectavx detectavx.cpp 2>&1`" ; then
+            AC_MSG_RESULT([yes])
+            AVXFLAGS="-mavx"
+            HAVE_AVX_AT_COMPILE_TIME=yes
+        else
+            AC_MSG_RESULT([no])
+            if test "$with_avx" = "yes"; then
+                AC_MSG_ERROR([--with-avx was requested, but AVX is not available])
+            fi
+        fi
+    fi
+
+    dnl On Solaris, the presence of AVX instructions is flagged in the binary
+    dnl and prevent it to run on non AVX hardware even if the instructions are
+    dnl not executed. So if the user did not explicitely requires AVX, test that
+    dnl we can run AVX binaries
+    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           AC_MSG_CHECKING([whether AVX is available and needed at runtime])
+           if ./detectavx; then
+             AC_MSG_RESULT([yes])
+           else
+             AC_MSG_RESULT([no])
+             if test "$with_avx" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling AVX as it is not explicitely required"
+               AVXFLAGS=""
+               HAVE_AVX_AT_COMPILE_TIME=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    rm -f detectavx*
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(AVXFLAGS,$AVXFLAGS)
+AC_SUBST(HAVE_AVX_AT_COMPILE_TIME,$HAVE_AVX_AT_COMPILE_TIME)
+
+dnl ---------------------------------------------------------------------------
 dnl Check if we need -lws2_32
 dnl ---------------------------------------------------------------------------
 
@@ -623,12 +720,21 @@ fi
 # TODO: separate libs for rasters and vectors
 if test "$with_grass" != "yes" -a "$with_grass" != "no" ; then
 
-  AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  AC_CHECK_LIB(grass_gis,G_is_initialized,GRASS_SETTING=grass70+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  if test "$GRASS_SETTING" = "no" ; then
+    AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  fi
    
-  if test "$GRASS_SETTING" = "grass57+" ; then   
-    G_RASTLIBS="-lgrass_I"
-    G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
-    LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+  if test "$GRASS_SETTING" != "no" ; then   
+    if test "$GRASS_SETTING" = "grass70+" ; then   
+      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
+      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    else
+      G_RASTLIBS="-lgrass_I"
+      G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    fi
     GRASS_INCLUDE="-I$with_grass/include"
     GRASS_GISBASE="$with_grass"
     HAVE_GRASS=yes
@@ -1355,6 +1461,64 @@ fi
 AC_SUBST(X_FME_HOME,$X_FME_HOME)
 
 dnl ---------------------------------------------------------------------------
+dnl Select a SOSI lib to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(sosi,[  --with-sosi[=ARG]        Include SOSI support (ARG=SOSI lib Path, yes or no)],,)
+
+if test -z "$with_sosi" -o "$with_sosi" = "no" ; then
+
+  SOSI_ENABLED=no
+
+  echo "SOSI support disabled."
+
+elif test "$with_sosi" = "yes" -o "$with_sosi" = "" ; then
+
+    AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib])
+    if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
+        AC_MSG_RESULT([found])
+        SOSI_ENABLED=yes
+        SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
+    else
+        AC_MSG_ERROR([not found.])
+    fi
+
+    AC_MSG_CHECKING([for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba])
+    if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
+        AC_MSG_RESULT([found])
+        SOSI_ENABLED=yes
+        SOSI_INC="-I/usr/local/include/fyba"
+    else
+        AC_MSG_ERROR([not found.])
+    fi
+
+else
+
+  AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib])
+  if test -r $with_sosi/lib/libfyba.a -a -r $with_sosi/lib/libfygm.a -a -r $with_sosi/lib/libfyut.a ; then
+    AC_MSG_RESULT([found.])
+    SOSI_LIB="$with_sosi/lib/libfyba.a $with_sosi/lib/libfygm.a $with_sosi/lib/libfyut.a"
+    SOSI_ENABLED=yes
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  AC_MSG_CHECKING([for fyba.h in $with_sosi/include/fyba])
+  if test -r $with_sosi/include/fyba/fyba.h -a -r $with_sosi/include/fyba/fygm.h -a -r $with_sosi/include/fyba/fyut.h ; then
+    AC_MSG_RESULT([found.])
+    SOSI_INC="-I$with_sosi/include/fyba"
+    SOSI_ENABLED=yes
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+AC_SUBST(SOSI_ENABLED, $SOSI_ENABLED)
+AC_SUBST(SOSI_LIB, $SOSI_LIB)
+AC_SUBST(SOSI_INC, $SOSI_INC)
+
+dnl ---------------------------------------------------------------------------
 dnl Select an HDF4 Library to use, or disable driver.
 dnl
 dnl We assume the user will have libjpeg and libz from other sources when
@@ -1817,10 +1981,10 @@ elif test "$with_fgdb" = "yes" -o "$with_fgdb" = "" ; then
     echo "#include <FileGDBAPI.h>" > testfgdb.cpp
     echo "using namespace FileGDBAPI;" >> testfgdb.cpp
     echo "int main() { Geodatabase oDB; std::wstring osStr; ::OpenGeodatabase(osStr, oDB); return 0; }" >> testfgdb.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -o testfgdb 2>&1`" ; then
+    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -lfgdbunixrtl -o testfgdb 2>&1`" ; then
         AC_MSG_RESULT([FileGDBAPI found])
         FGDB_ENABLED="yes"
-        FGDB_LIB="-lFileGDBAPI"
+        FGDB_LIB="-lFileGDBAPI -lfgdbunixrtl"
     else
         if test "$with_fgdb" = "yes"; then
             AC_MSG_ERROR([FileGDBAPI not found.])
@@ -1835,9 +1999,12 @@ else
 
   AC_MSG_CHECKING([for libFileGDBAPI.so in in $with_fgdb/lib])
   FGDB_ENABLED=yes
-  if test -r $with_fgdb/lib/libFileGDBAPI.so ; then
+  if test -r $with_fgdb/lib/libFileGDBAPI.so -a -r $with_fgdb/lib/libfgdbunixrtl.so ; then
     AC_MSG_RESULT([found.])
-    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI"
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
+  elif test -r $with_fgdb/lib/libFileGDBAPI.dylib -a -r $with_fgdb/lib/libfgdbunixrtl.dylib ; then
+    AC_MSG_RESULT([found.])
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
   else
     AC_MSG_ERROR([not found.])
   fi
@@ -1891,7 +2058,17 @@ elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
       ECW_LIBS="-lecwj2 $CARBON_FRAMEWORK"
     fi
   fi
-
+  # ECWJP2 SDK 5.1 style
+  if test "$ECW_SETTING" = "no" ; then
+        if test -r /Intergraph/ERDASEcwJpeg2000SDK5.1/lib/libEcwJp2SDK.a; then
+                ECW_LIBDIR=/Intergraph/ERDASEcwJpeg2000SDK5.1/lib
+                ECW_INCLUDE=-I/Intergraph/ERDASEcwJpeg2000SDK5.1/include
+                ECW_LIBS="-L$ECW_LIBDIR -lEcwJp2SDK -framework Cocoa"
+                ECW_SETTING=yes
+                ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
+                AC_MSG_RESULT([found Intergraph ERDAS EcwJpeg2000 SDK 5.1 in /Intergraph/ERDASEcwJpeg2000SDK5.1/.])
+        fi
+  fi
 else
 
   AC_MSG_CHECKING([for libNCSEcw.so or libecwj2])
@@ -1919,7 +2096,14 @@ else
     ECW_FLAGS="-DLINUX -DX86 -DPOSIX -DHAVE_COMPRESS -DECW_COMPRESS_RW_SDK_VERSION"
     ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw"
     AC_MSG_RESULT([found Intergraph 5.x+ SDK in ${ECW_LIBDIR}.])
-  else
+ # ECWJP2 SDK 5.1 style
+  elif test -r $with_ecw/lib/libEcwJp2SDK.a; then
+        ECW_LIBDIR=$with_ecw/lib
+        ECW_INCLUDE=-I$with_ecw/include
+        ECW_LIBS="-L$ECW_LIBDIR -lEcwJp2SDK -framework Cocoa"
+        ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
+        AC_MSG_RESULT([found Intergraph 5.1+ SDK in $ {with_ecw}.]) 
+ else
     AC_MSG_ERROR([not found in $with_ecw/lib or $with_ecw/bin.])
   fi
 
@@ -2049,7 +2233,16 @@ else
 
     AC_MSG_CHECKING([for MrSID JPEG2000 support])
     if test "x$with_jp2mrsid" = "xyes" -a "$HAVE_KAKADU" = "yes" ; then
-      AC_MSG_ERROR([MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu])
+      # SDK v8 or later don't seem to conflict with Kakadu
+      major_version=`cat $with_mrsid/include/lti_version.h | grep MAJOR | sed 's/#define LTI_SDK_MAJOR[ ]*\(.*\)/\1/'`
+      if test "x$major_version" != "x"; then
+        if test "$major_version" -ge 8; then
+            V8_OR_LATER=yes
+        fi
+      fi
+      if test "x$V8_OR_LATER" = "x"; then
+        AC_MSG_ERROR([MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu])
+      fi
     fi
 
     MRSID_KAKADU_LIB=""
@@ -2294,6 +2487,31 @@ else
       MYSQL_LIB="`$MYSQL_CONFIG --libs`"
       MYSQL_INC="`$MYSQL_CONFIG --include`"
       AC_MSG_RESULT([yes])
+
+      # Check if mysql headers declare load_defaults
+      AC_MSG_CHECKING([load_defaults() in MySQL])
+      rm -f testmysql.*
+      echo '#include "my_global.h"' > testmysql.cpp
+      echo '#include "my_sys.h"' >> testmysql.cpp
+      echo 'int main(int argc, char** argv) { load_defaults(0, 0, 0, 0); return 0; } ' >> testmysql.cpp
+      if test -z "`${CXX} ${CXXFLAGS} ${MYSQL_INC} -o testmysql testmysql.cpp ${MYSQL_LIB} 2>&1`" ; then
+        AC_MSG_RESULT([yes, found in my_sys.h])
+      else
+        echo 'extern "C" void load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv);' > testmysql.cpp
+        echo 'int main(int argc, char** argv) { load_defaults(0, 0, 0, 0); return 0; } ' >> testmysql.cpp
+        if test -z "`${CXX} ${CXXFLAGS} ${MYSQL_INC} -o testmysql testmysql.cpp ${MYSQL_LIB} 2>&1`" ; then
+            AC_MSG_RESULT([yes, found in library but not in header])
+            MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION=yes
+        else
+            HAVE_MYSQL=no
+            MYSQL_LIB=
+            MYSQL_INC=
+            AC_MSG_ERROR([Cannot find load_defaults()])
+        fi
+      fi
+      rm -f testmysql.*
+      rm -f testmysql
+
 	;;
   esac
 fi
@@ -2301,6 +2519,7 @@ fi
 AC_SUBST(HAVE_MYSQL,$HAVE_MYSQL)
 AC_SUBST(MYSQL_INC,$MYSQL_INC)
 AC_SUBST(MYSQL_LIB,$MYSQL_LIB)
+AC_SUBST(MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION,$MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION)
 
 dnl ---------------------------------------------------------------------------
 dnl INGRES support.
@@ -2322,8 +2541,6 @@ else
   HAVE_INGRES=yes
   II_SYSTEM=$with_ingres
   INGRES_LIB="-L$II_SYSTEM/ingres/lib \
-	$II_SYSTEM/ingres/lib/iiclsadt.o \
-	$II_SYSTEM/ingres/lib/iiuseradt.o \
 	-liiapi.1 -lcompat.1 -lq.1 -lframe.1" 
   INGRES_INC=-I$II_SYSTEM/ingres/files
 fi
@@ -2648,7 +2865,8 @@ elif test "$with_spatialite" = "yes"; then
             AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,)
             if test "$SPATIALITE_INIT_FOUND" = "yes"; then
                 HAVE_SPATIALITE=yes
-                LIBS="$LIBS -lspatialite"
+                SPATIALITE_LIBS="-lspatialite -lsqlite3"
+                LIBS="$LIBS $SPATIALITE_LIBS"
                 HAVE_SQLITE3=yes
             fi
         else
@@ -2670,7 +2888,8 @@ else
         # as there's a spatialite.h file in it, which we don't want to include.
         # We want to include include/spatialite.h instead !
         SQLITE3_CFLAGS="-I$with_spatialite/include"
-        LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+        LIBS="$LIBS $SPATIALITE_LIBS"
         HAVE_SQLITE3=yes
 
     elif test -f "$with_spatialite/include/spatialite.h" -a \
@@ -2680,7 +2899,8 @@ else
             AC_MSG_RESULT(enabled)
             SPATIALITE_INC="-I$with_spatialite/include"
             HAVE_SPATIALITE=yes
-            LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite -lsqlite3"
+            LIBS="$LIBS $SPATIALITE_LIBS"
             HAVE_SQLITE3=yes
         fi
     else
@@ -2688,9 +2908,17 @@ else
     fi
 fi
 
+if test "$HAVE_SPATIALITE" = "yes"; then
+    ax_save_LIBS="${LIBS}"
+    LIBS="$SPATIALITE_LIBS"
+    AC_CHECK_LIB(spatialite,spatialite_target_cpu,SPATIALITE_412_OR_LATER=yes,SPATIALITE_412_OR_LATER=no)
+    LIBS="${ax_save_LIBS}"
+fi
+
 AC_SUBST([HAVE_SPATIALITE], $HAVE_SPATIALITE)
 AC_SUBST([SPATIALITE_INC], $SPATIALITE_INC)
 AC_SUBST([SPATIALITE_AMALGAMATION], $SPATIALITE_AMALGAMATION)
+AC_SUBST([SPATIALITE_412_OR_LATER], $SPATIALITE_412_OR_LATER)
 
 dnl ---------------------------------------------------------------------------
 dnl Check for SQLite (only if SpatiaLite is not detected)
@@ -2974,7 +3202,7 @@ dnl ---------------------------------------------------------------------------
 dnl Check if geos library is available.
 dnl ---------------------------------------------------------------------------
 
-GEOS_INIT(2.2.0)
+GEOS_INIT(3.1.0)
 HAVE_GEOS_RESULT="no"
 if test "${HAVE_GEOS}" = "yes" ; then
 
@@ -3144,6 +3372,45 @@ fi
 AC_SUBST(HAVE_FREEXL,  $HAVE_FREEXL)
 AC_SUBST(FREEXL_INCLUDE,  $FREEXL_INCLUDE)
 
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libjson-c is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(libjson-c,[  --with-libjson-c[=ARG]       Include libjson-c support (ARG=internal or libjson-c directory)],,)
+
+if test "$with_libjson_c" = "external" -o "$with_libjson_c" = "" -o "$with_libjson_c" = "yes" ; then
+  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,)
+elif test "$with_libjson_c" = "internal" ; then
+  LIBJSONC_SETTING=internal
+elif test "$with_libjson_c" != "no"; then
+  LIBS="-L$with_libjson_c/lib $LIBS"
+  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,-L$with_libjson_c/lib)
+else
+  AC_MSG_ERROR([libjson-c (internal or external) is required])
+fi
+
+if test "$LIBJSONC_SETTING" = "external" ; then
+  AC_MSG_RESULT([using pre-installed libjson-c])
+  LIBS="-ljson-c $LIBS"
+  if test "$with_libjson_c" != "" -a "$with_libjson_c" != "yes" -a "$with_libjson_c" != "external" ; then
+    JSON_INCLUDE="-I$with_libjson_c/include/json-c"
+  elif test -f "/usr/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/include/json-c"
+  elif test -f "/usr/local/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/local/include/json-c"
+  else
+    AC_MSG_ERROR([could not find json-c/json.h])
+  fi
+else
+    JSON_INCLUDE="-I\$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson/libjson"
+    AC_MSG_RESULT([using internal libjson-c code])
+fi
+
+AC_SUBST(LIBJSONC_SETTING,$LIBJSONC_SETTING)
+AC_SUBST(JSON_INCLUDE,$JSON_INCLUDE)
+
+
 dnl ---------------------------------------------------------------------------
 dnl Check if we must enable PAM
 dnl ---------------------------------------------------------------------------
@@ -3192,8 +3459,18 @@ if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
     echo '#include <poppler/Page.h>' >> testpoppler.cpp
     echo '#include <poppler/splash/SplashBitmap.h>' >> testpoppler.cpp
     echo 'int main(int argc, char** argv) { return &(((Page*)0x8000)->pageObj) == 0; } ' >> testpoppler.cpp
+
     if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
         HAVE_POPPLER=yes
+    else
+        # poppler 0.23.0 needs to be linked against pthread
+        TEST_POPPLER_LIB="${TEST_POPPLER_LIB} -lpthread"
+        if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
+            HAVE_POPPLER=yes
+        fi
+    fi
+
+    if test "$HAVE_POPPLER" = "yes"; then
         LIBS="${TEST_POPPLER_LIB} ${LIBS}"
         AC_MSG_RESULT([yes])
         POPPLER_INC=$TEST_POPPLER_INC
@@ -3659,12 +3936,14 @@ AC_MSG_CHECKING([whether we should include Java support])
 
 JAVA_HOME=""
 JAVA_INC=""
+mac_java_fw=""
 
 if test "x$with_java" = "xyes"; then
 
 dnl Ubuntu
     JAVA_6_TEST_DIR=
     JAVA_7_TEST_DIR=
+    JAVA_MAC_TEST_DIR=
     case "$host_cpu" in
         i*86*)
             JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-i386
@@ -3677,6 +3956,11 @@ dnl Ubuntu
         *)
             ;;
     esac
+    case "${host_os}" in
+      darwin*)
+        JAVA_MAC_TEST_DIR=$(/usr/libexec/java_home)
+        ;;
+    esac
 
     if test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
         with_java="$JAVA_7_TEST_DIR"
@@ -3691,17 +3975,27 @@ dnl RHEL6
     elif test -d /usr/lib/jvm/java-openjdk; then
         with_java="/usr/lib/jvm/java-openjdk"
 
-dnl    elif test -d /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers; then
-dnl        JAVA_INC="-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers"
 
 dnl OpenSolaris
     elif test -d /usr/java; then
         with_java="/usr/java"
+
+dnl Mac OS X
+    elif test "x$JAVA_MAC_TEST_DIR" != "x"; then
+        if test -d "$JAVA_MAC_TEST_DIR/bundle"; then
+            # Mac default 1.6.0_x framework
+            # test for ./bundle first, since older installs also have ./include
+            with_java="$JAVA_MAC_TEST_DIR"
+            mac_java_fw="JavaVM"
+        elif test -d "$JAVA_MAC_TEST_DIR/include"; then
+            # Oracle Java install
+            with_java="$JAVA_MAC_TEST_DIR"
+        fi
     else
         AC_MSG_ERROR("cannot find JDK root directory.")
     fi
 
-    if test \! -d "$with_java/include" ; then
+    if test \! -d "$with_java/include" && test \! -d "$with_java/bundle"; then
         AC_MSG_ERROR("$with_java is not a valid JDK.")
     fi
 fi
@@ -3710,7 +4004,14 @@ if test "x$JAVA_INC" != "x"; then
     AC_MSG_RESULT([yes])
 elif test "x$with_java" != "x" -a "x$with_java" != "xno"; then
 
-    if test -d "$with_java/include"; then
+    if test -d "$with_java/bundle" && test -d "/System/Library/Frameworks/JavaVM.framework/Headers"; then
+        # Mac default 1.6.0_x framework
+        # test for ./bundle first, since older installs also have ./include
+        JAVA_HOME="$with_java"
+        JAVA_INC="-I/System/Library/Frameworks/JavaVM.framework/Headers"
+        mac_java_fw="JavaVM"
+        AC_MSG_RESULT([yes])
+    elif test -d "$with_java/include"; then
         if test -d "$with_java/include/linux"; then
             JAVA_HOME="$with_java"
             JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
@@ -3723,11 +4024,16 @@ elif test "x$with_java" != "x" -a "x$with_java" != "xno"; then
             JAVA_HOME="$with_java"
             JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/freebsd"
             AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/darwin"; then
+            # Oracle Java install, use instead of Mac default 1.6.0_x
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/darwin"
+            AC_MSG_RESULT([yes])
         else
-            AC_MSG_ERROR("Cannot find $with_java/include/linux or solaris or freebsd directory.")
+            AC_MSG_ERROR("Cannot find $with_java/include/linux or solaris or freebsd or darwin directory.")
         fi
     else
-        AC_MSG_ERROR("Cannot find $with_java/include directory.")
+        AC_MSG_ERROR("Cannot find $with_java/include or <mac_java_framework>/Headers directory.")
     fi
 
 else
@@ -3761,12 +4067,28 @@ if test "$with_mdb" = "yes" ; then
         if test -d "$with_jvm_lib"; then
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$with_jvm_lib"
-            AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            if test "x$mac_java_fw" != "x"; then
+                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            else
+                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            fi
             LDFLAGS="$saved_LDFLAGS"
             if test "$HAS_LIB_JVM" = "yes"; then
                 JVM_LIB="-L$with_jvm_lib -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
                 if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$with_jvm_lib -L$with_jvm_lib -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                          ;;
+                    esac
                 fi
             else
                 AC_MSG_ERROR("--with-jvm-lib must point to a directory with a libjvm.")
@@ -3776,16 +4098,40 @@ if test "$with_mdb" = "yes" ; then
         fi
     elif test "x$JAVA_HOME" != "x"; then
         TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
+        if test -d "$JAVA_HOME/jre/lib/server"; then
+            # Oracle Java install on Mac
+            TEST_DIR="$JAVA_HOME/jre/lib/server"
+        fi
+        if test "x$mac_java_fw" != "x"; then
+            # Mac default 1.6.0_x framework, TEST_DIR not used
+            TEST_DIR="$with_java"
+        fi
         if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
             unset ac_cv_lib_jvm_JNI_CreateJavaVM
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$TEST_DIR"
-            AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            if test "x$mac_java_fw" != "x"; then
+                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            else
+                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            fi
             LDFLAGS="$saved_LDFLAGS"
             if test "$HAS_LIB_JVM" = "yes"; then
                 JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
                 if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$TEST_DIR -L$TEST_DIR -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                          ;;
+                    esac
                 fi
             fi
         fi
@@ -3808,8 +4154,6 @@ if test "$with_mdb" = "yes" ; then
         if test "x$JVM_LIB" = "x"; then
             AC_MSG_ERROR("--with-jvm-lib must be specified.")
         fi
-dnl    elif test -f /System/Library/Frameworks/JavaVM.framework/Versions/Current/JavaVM; then
-dnl        JVM_LIB="-framework /System/Library/Frameworks/JavaVM.framework/Versions/Current/JavaVM"
     else
         AC_MSG_ERROR("--with-jvm-lib must be specified.")
     fi
@@ -4012,6 +4356,7 @@ LOC_MSG([  Podofo support:            ${HAVE_PODOFO}])
 LOC_MSG([  OpenCL support:            ${OPENCL_SETTING}])
 LOC_MSG([  Armadillo support:         ${HAVE_ARMADILLO}])
 LOC_MSG([  FreeXL support:            ${HAVE_FREEXL}])
+LOC_MSG([  SOSI support:              ${SOSI_ENABLED}])
 LOC_MSG()
 if test ! -z "`uname | grep Darwin`" ; then
   LOC_MSG([  Mac OS X Framework :       ${MACOSX_FRAMEWORK}])
diff --git a/data/compdcs.csv b/data/compdcs.csv
index 3a2c48f..7779ec9 100644
--- a/data/compdcs.csv
+++ b/data/compdcs.csv
@@ -36,6 +36,73 @@
 5855,"SWEREF99 20 15 + RH2000 height",3016,5613,1,0
 5856,"SWEREF99 21 45 + RH2000 height",3017,5613,1,0
 5857,"SWEREF99 23 15 + RH2000 height",3018,5613,1,0
+5942,"ETRS89 + NN2000 height",4258,5941,1,0
+5945,"ETRS89 / NTM zone 5 + NN2000 height",5105,5941,1,0
+5946,"ETRS89 / NTM zone 6 + NN2000 height",5106,5941,1,0
+5947,"ETRS89 / NTM zone 7 + NN2000 height",5107,5941,1,0
+5948,"ETRS89 / NTM zone 8 + NN2000 height",5108,5941,1,0
+5949,"ETRS89 / NTM zone 9 + NN2000 height",5109,5941,1,0
+5950,"ETRS89 / NTM zone 10 + NN2000 height",5110,5941,1,0
+5951,"ETRS89 / NTM zone 11 + NN2000 height",5111,5941,1,0
+5952,"ETRS89 / NTM zone 12 + NN2000 height",5112,5941,1,0
+5953,"ETRS89 / NTM zone 13 + NN2000 height",5113,5941,1,0
+5954,"ETRS89 / NTM zone 14 + NN2000 height",5114,5941,1,0
+5955,"ETRS89 / NTM zone 15 + NN2000 height",5115,5941,1,0
+5956,"ETRS89 / NTM zone 16 + NN2000 height",5116,5941,1,0
+5957,"ETRS89 / NTM zone 17 + NN2000 height",5117,5941,1,0
+5958,"ETRS89 / NTM zone 18 + NN2000 height",5118,5941,1,0
+5959,"ETRS89 / NTM zone 19 + NN2000 height",5119,5941,1,0
+5960,"ETRS89 / NTM zone 20 + NN2000 height",5120,5941,1,0
+5961,"ETRS89 / NTM zone 21 + NN2000 height",5121,5941,1,0
+5962,"ETRS89 / NTM zone 22 + NN2000 height",5122,5941,1,0
+5963,"ETRS89 / NTM zone 23 + NN2000 height",5123,5941,1,0
+5964,"ETRS89 / NTM zone 24 + NN2000 height",5124,5941,1,0
+5965,"ETRS89 / NTM zone 25 + NN2000 height",5125,5941,1,0
+5966,"ETRS89 / NTM zone 26 + NN2000 height",5126,5941,1,0
+5967,"ETRS89 / NTM zone 27 + NN2000 height",5127,5941,1,0
+5968,"ETRS89 / NTM zone 28 + NN2000 height",5128,5941,1,0
+5969,"ETRS89 / NTM zone 29 + NN2000 height",5129,5941,1,0
+5970,"ETRS89 / NTM zone 30 + NN2000 height",5130,5941,1,0
+5971,"ETRS89 / UTM zone 31 + NN2000 height",25831,5941,1,0
+5972,"ETRS89 / UTM zone 32 + NN2000 height",25832,5941,1,0
+5973,"ETRS89 / UTM zone 33 + NN2000 height",25833,5941,1,0
+5974,"ETRS89 / UTM zone 34 + NN2000 height",25834,5941,1,0
+5975,"ETRS89 / UTM zone 35 + NN2000 height",25835,5941,1,0
+5976,"ETRS89 / UTM zone 36 + NN2000 height",25836,5941,1,0
+6144,"ETRS89 + NN54 height",4258,5776,1,0
+6145,"ETRS89 / NTM zone 5 + NN54 height",5105,5776,1,0
+6146,"ETRS89 / NTM zone 6 + NN54 height",5106,5776,1,0
+6147,"ETRS89 / NTM zone 7 + NN54 height",5107,5776,1,0
+6148,"ETRS89 / NTM zone 8 + NN54 height",5108,5776,1,0
+6149,"ETRS89 / NTM zone 9 + NN54 height",5109,5776,1,0
+6150,"ETRS89 / NTM zone 10 + NN54 height",5110,5776,1,0
+6151,"ETRS89 / NTM zone 11 + NN54 height",5111,5776,1,0
+6152,"ETRS89 / NTM zone 12 + NN54 height",5112,5776,1,0
+6153,"ETRS89 / NTM zone 13 + NN54 height",5113,5776,1,0
+6154,"ETRS89 / NTM zone 14 + NN54 height",5114,5776,1,0
+6155,"ETRS89 / NTM zone 15 + NN54 height",5115,5776,1,0
+6156,"ETRS89 / NTM zone 16 + NN54 height",5116,5776,1,0
+6157,"ETRS89 / NTM zone 17 + NN54 height",5117,5776,1,0
+6158,"ETRS89 / NTM zone 18 + NN54 height",5118,5776,1,0
+6159,"ETRS89 / NTM zone 19 + NN54 height",5119,5776,1,0
+6160,"ETRS89 / NTM zone 20 + NN54 height",5120,5776,1,0
+6161,"ETRS89 / NTM zone 21 + NN54 height",5121,5776,1,0
+6162,"ETRS89 / NTM zone 22 + NN54 height",5122,5776,1,0
+6163,"ETRS89 / NTM zone 23 + NN54 height",5123,5776,1,0
+6164,"ETRS89 / NTM zone 24 + NN54 height",5124,5776,1,0
+6165,"ETRS89 / NTM zone 25 + NN54 height",5125,5776,1,0
+6166,"ETRS89 / NTM zone 26 + NN54 height",5126,5776,1,0
+6167,"ETRS89 / NTM zone 27 + NN54 height",5127,5776,1,0
+6168,"ETRS89 / NTM zone 28 + NN54 height",5128,5776,1,0
+6169,"ETRS89 / NTM zone 29 + NN54 height",5129,5776,1,0
+6170,"ETRS89 / NTM zone 30 + NN54 height",5130,5776,1,0
+6171,"ETRS89 / UTM zone 31 + NN54 height",25831,5776,1,0
+6172,"ETRS89 / UTM zone 32 + NN54 height",25832,5776,1,0
+6173,"ETRS89 / UTM zone 33 + NN54 height",25833,5776,1,0
+6174,"ETRS89 / UTM zone 34 + NN54 height",25834,5776,1,0
+6175,"ETRS89 / UTM zone 35 + NN54 height",25835,5776,1,0
+6176,"ETRS89 / UTM zone 36 + NN54 height",25836,5776,1,0
+6190,"Belge 1972 / Belgian Lambert 72 + Ostend height",31370,5710,1,0
 7400,"NTF (Paris) + NGF IGN69 height",4807,5720,1,0
 7401,"NTF (Paris) / France II + NGF Lallemand",27582,5719,1,1
 7402,"NTF (Paris) / France II + NGF IGN69",27582,5720,1,1
diff --git a/data/coordinate_axis.csv b/data/coordinate_axis.csv
index c72fa81..be6b073 100644
--- a/data/coordinate_axis.csv
+++ b/data/coordinate_axis.csv
@@ -21,6 +21,16 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 1033,9921,See associated operation,J,1024,2
 1034,9920,J-axis minus 90°,I,1024,1
 1034,9921,See associated operation,J,1024,2
+1035,9906,South along 180°E,X,9001,1
+1035,9907,South along 90°W,Y,9001,2
+1036,9906,South along 57°E,X,9001,1
+1036,9907,South along 147°E,Y,9001,2
+1037,9906,South along 108°E,X,9001,1
+1037,9907,South along 162°W,Y,9001,2
+1038,9906,South along 165°W,X,9001,1
+1038,9907,South along 75°W,Y,9001,2
+1039,9906,east,E,9002,1
+1039,9907,north,N,9002,2
 4400,9906,east,E,9001,1
 4400,9907,north,N,9001,2
 4401,9906,east,E,9062,1
diff --git a/data/datum_shift.csv b/data/datum_shift.csv
index 15f3cee..b903c34 100644
--- a/data/datum_shift.csv
+++ b/data/datum_shift.csv
@@ -11,10 +11,10 @@
 10,1965,4616,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,2779,29.98,30.2,-16.1,-15.79,1,0,9603,-289,-124,60,,,,,1
 11,1842,4617,4326,"For many purposes NAD83(CSRS) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS) is equivalent to WGS 84.",1061,40.04,86.45,-141,-47.74,1,0,9603,0,0,0,,,,,1
 12,1946,4617,4326,"Jointly derived by US NGS and Geodetic Survey of Canada - see also code 1901. Strictly between NAD83(CSRS) and ITRF96(1997.0).",Geodesy.,1061,40.04,86.45,-141,-47.74,1,0,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
-13,1864,4618,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1358,-45,12.51,-81.4,-29.03,1,0,9603,-57,1,-41,,,,,1
+13,1864,4618,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",4016,-45,12.51,-81.4,-34.74,1,0,9603,-57,1,-41,,,,,1
 14,1865,4618,4326,"Derived at 10 stations. Note: SAD69 not adopted in Argentina: see Campo Inchauspe (CRS code 4221).",For military purposes only. Accuracy 5m in each axis.,3215,-52.43,-21.78,-73.58,-53.65,1,0,9603,-62,-1,-37,,,,,0
 15,1866,4618,4326,"Derived at 4 stations. Note: SAD69 not adopted in Bolivia: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 15m in each axis.,1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,-61,2,-48,,,,,0
-16,1867,4618,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",3845,-35.71,7.04,-60.57,-29.03,1,0,9603,-60,-2,-41,,,,,0
+16,1867,4618,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",3887,-33.78,4.43,-60.57,-34.74,1,0,9603,-60,-2,-41,,,,,0
 17,1868,4618,4326,"Derived at 9 stations. Note: SAD69 not adopted in Chile.","For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",3227,-45,-17.51,-75.22,-67,1,0,9603,-75,-1,-44,,,,,0
 18,1869,4618,4326,"Derived at 7 stations. Note: SAD69 not adopted in Colombia: see Bogota 1975 (CRS code 4218).","For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",3229,-4.24,12.51,-79.1,-66.87,1,0,9603,-44,6,-36,,,,,0
 19,1870,4618,4326,"Derived at 11 stations. Note: SAD69 not adopted in Ecuador: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 3m in each axis.,3241,-5,1.45,-81.03,-75.22,1,0,9603,-48,3,-44,,,,,0
@@ -24,745 +24,753 @@
 23,1874,4618,4326,"Derived at 6 stations. Note: SAD69 not adopted in Peru: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 5m in each axis.,3292,-18.35,-0.04,-81.4,-68.67,1,0,9603,-58,0,-44,,,,,0
 24,1875,4618,4326,"Derived at 1 station. Note: SAD69 not adopted in Trinidad and Tobago.",For military purposes only. Accuracy 25m in each axis.,3143,9.99,10.89,-61.97,-60.86,1,0,9603,-45,12,-33,,,,,0
 25,1876,4618,4326,"Derived at 5 stations. Note: SAD69 not adopted in Venezuela: see PSAD56 (CRS code 4248).","For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",3327,0.65,12.25,-73.38,-59.8,1,0,9603,-45,8,-33,,,,,0
-26,1877,4618,4326,"Derived by Brazilian Institute of Geography and Statistics (IBGE) in 1989. Used by ANP. (Note: for historic reasons associated with one-time web url, tfm version uses initials IGBE, not IBGE). Replaced by SAD69 to WGS 84 (15) (tfm code 5528).",Medium and small scale mapping.,3845,-35.71,7.04,-60.57,-29.03,1,0,9603,-66.87,4.37,-38.52,,,,,0
-27,1879,4619,4326,"Parameter values taken from SWEREF to ETRS89 (1) (code 1878) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Geographic Information Systems.,1225,54.96,69.06,10.03,24.17,1,0,9603,0,0,0,,,,,1
-28,1880,4620,4326,Derived at one point in each of Burkina Faso and Niger.,For military purposes. Accuracy 25m in each axis.,2791,11.83,14.22,-4.64,4,1,0,9603,-106,-129,165,,,,,1
-29,1903,4621,4326,,"Accuracy +/- 10 metres.",2828,17.83,18.17,-63.2,-62.73,1,0,9603,137,248,-430,,,,,1
-30,1904,4622,4326,,"Accuracy +/- 10 metres.",2829,15.8,16.54,-61.85,-60.97,1,0,9603,-467,-16,-300,,,,,1
-31,1905,4622,4326,,"Accuracy +/- 0.1 metre.",2829,15.8,16.54,-61.85,-60.97,1,0,9606,-472.29,-5.63,-304.12,0.4362,-0.8374,0.2563,1.8984,0
-32,1906,4623,4326,,"Accuracy +/- 10 metres.",3105,3.43,5.81,-54.45,-51.62,1,0,9603,-186,230,110,,,,,1
-33,1907,4624,4326,,"Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,1,9603,2,2,-2,,,,,0
-34,4840,4624,4326,"Replaces RGFG95 to WGS 84 (1) (code 1907) which was not put into official use but issued in error.","Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,0,9603,0,0,0,,,,,1
-35,1909,4625,4326,,"Accuracy +/- 10 metres.",3276,14.35,14.93,-61.28,-60.77,1,0,9603,186,482,151,,,,,1
-36,1910,4625,4326,,"Accuracy +/- 0.1 metre.",3276,14.35,14.93,-61.28,-60.77,1,0,9606,126.93,547.94,130.41,-2.7867,5.1612,-0.8584,13.8227,0
-37,1911,4626,4326,Derived at 1 station.,"Accuracy +/- 30 metres.",1196,-25.92,-10.6,37.58,58.27,1,1,9603,94,-948,-1292,,,,,0
-38,15751,4626,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3337,-21.42,-20.81,55.17,55.9,1,0,9603,94,-948,-1262,,,,,1
-39,1912,4627,4326,,"Accuracy +/- 1 metre.",3902,-24.71,-18.29,51.84,58.24,1,0,9603,0,0,0,,,,,1
-40,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.92,-17.42,-149.99,-149.1,1,0,9603,162,117,154,,,,,1
-41,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.95,-16.18,-151.91,-150.9,1,0,9603,65,342,77,,,,,0
-42,15770,4629,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahaa 54 to RGPF (1) (tfm code 15758).","Accuracy +/- 1 metre.",2812,-16.95,-16.18,-151.91,-150.9,1,0,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746,1
-43,1914,4630,4326,,"Accuracy +/- 10 metres.",3129,-9.56,-8.73,-140.31,-139.45,1,0,9603,84,274,65,,,,,1
-44,15775,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (1) (tfm code 15763).","Accuracy +/- 1 metre.",2810,-9.01,-8.73,-140.31,-139.96,1,0,9607,165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204,0
-45,15776,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15764).","Accuracy +/- 2 metres.",3127,-8.99,-8.82,-139.65,-139.45,1,0,9607,1363.785,1362.687,398.811,-4.5322,-6.7579,-1.0574,268.361,0
-46,15777,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15765).","Accuracy +/- 1 metre.",3128,-9.56,-9.27,-140.2,-139.96,1,0,9607,259.551,297.612,197.833,1.4866,2.1224,0.4612,27.0249,0
-47,1915,4631,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,1,9603,145,-187,103,,,,,0
-48,1916,4632,4326,,"Accuracy +/- 10 metres.",3340,-13.04,-12.61,44.99,45.34,1,0,9603,-382,-59,-262,,,,,1
-49,1272,4121,4326,,For applications requiring 1m or better accuracy.,3254,34.88,41.75,19.58,28.3,1,0,9603,-199.87,74.79,246.62,,,,,1
-50,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-26.44,-14.83,156.26,174.28,1,1,9603,-13,-348,292,,,,,0
-51,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.04,163.93,167.08,1,1,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-52,1639,4123,4326,"Parameter values from KKJ to ETRS89 (1) (code 1638). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by KKJ to WGS 84 (2) (code 10099).",For applications to an accuracy of 1 to 2 metres.,3333,59.76,70.09,19.24,31.58,1,0,9606,-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37,0
-53,10099,4123,4326,"Parameter values from KKJ to ETRS89 (2) (code 10098). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces KKJ to WGS 84 (1) (code 1639).",For applications to an accuracy of 1 to 2 metres.,3333,59.76,70.09,19.24,31.58,1,0,9607,-96.062,-82.428,-121.753,-4.801,-0.345,1.376,1.496,1
-54,1680,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1437) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by RT90 to WGS 84 (2) (code 1896) from 2001.","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,0,9607,419.3836,99.3335,591.3451,-0.850389,-1.817277,7.862238,-0.99496,0
-55,1788,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1787) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Supersedes RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,1,9607,414.1,41.3,603.1,-0.855,2.141,-7.023,0,0
-56,1896,4124,4326,"Parameter values from RT90 to SWEREF99 (1) (code 1895) assuming that SWEREF99 is equivalent to WGS 84 within the accuracy of the transformation. Replaces RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,0,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0,1
-57,1282,4125,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.24,0,116.73,117.99,1,1,9603,-404.78,685.68,45.47,,,,,0
-58,1923,4638,4326,,"Accuracy +/- 10 metres.",3299,46.7,47.18,-56.47,-56.07,1,0,9603,30,430,368,,,,,1
-59,1683,4127,4326,"Parameter values taken from Tete to Moznet (1) (code 1297) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals as high as 30 metres.,3281,-26.86,-10.43,30.21,40.9,1,0,9607,-115.064,-87.39,-101.716,0.058,-4.001,2.062,9.366,0
-60,1684,4127,4326,"Parameter values taken from Tete to Moznet (2) (code 1298) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 1 metre.,2350,-26.86,-23.91,31.92,34.49,1,0,9607,-82.875,-57.097,-156.768,2.158,-1.524,0.982,-0.359,0
-61,1685,4127,4326,"Parameter values taken from Tete to Moznet (3) (code 1299) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 4 metres.,2351,-24.91,-19.74,31.3,35.65,1,0,9607,-138.527,-91.999,-114.591,0.14,-3.363,2.217,11.748,0
-62,1686,4127,4326,"Parameter values taken from Tete to Moznet (4) (code 1300) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 3 metres.,2352,-19.9,-14.01,30.21,39.18,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,1
-63,1687,4127,4326,"Parameter values taken from Tete to Moznet (5) (code 1301) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are 5-10 metres.,2353,-16.94,-10.43,34.37,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,0
-64,1934,4640,4326,RRAF 1991 was defined to be WGS84 at a single point in Martinique during the 1988 Tango mission.,"Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,1,9603,0,0,0,,,,,0
-65,1928,4641,4326,Withdrawn by information source and replaced by improved information - see tfm code 15901.,"Accuracy better than +/- 1 metre.",2819,-21.71,-21.33,167.76,168.18,1,0,9606,-408.809,366.856,-412.987,1.8842,-0.5308,2.1655,-121.0993,0
-66,15783,4641,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15901.,Accuracy 5 metres.,2819,-21.71,-21.33,167.76,168.18,1,0,9603,287,178,-136,,,,,0
-67,15901,4641,4326,"Parameter values taken from IGN53 Mare to RGNC91-93 (1) ( code 15884) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 2 metres.,2819,-21.71,-21.33,167.76,168.18,1,0,9603,287.58,177.78,-135.41,,,,,1
-68,1302,4130,4326,,For many purposes Moznet can be considered to be coincident with WGS 84. Accuracy better than 1 metre.,1167,-27.7,-10.09,30.21,43.02,1,0,9607,0,0,0,0,0,0,0,1
-69,1542,4131,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2359,14,18,105.62,109.32,1,0,9603,198,881,317,,,,,1
-70,1543,4131,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2360,8.59,8.82,106.5,106.79,1,0,9603,182,915,344,,,,,0
-71,1513,4132,4326,Derived in 1998 in Kangan district by Geoid for Total. Used for South Pars phases 2 and 3.,Oil exploration.,2362,27.3,28.2,51.8,53,1,0,9603,-241.54,-163.64,396.06,,,,,1
-72,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.22,26.86,52.5,53.43,1,0,9603,-239.1,-170.02,397.5,,,,,0
-73,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29.17,29.38,50.23,50.42,1,0,9603,-244.72,-162.773,400.75,,,,,0
-74,1333,4133,4326,,"?",3246,57.52,59.75,21.74,28.19,1,0,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014,1
-75,1439,4134,4326,"Replaced PSD93 to WGS 84 (2) (code 8581) in 1997.","Oil exploration. Residuals 0.5m at 67% probability level.",3288,16.6,26.57,52,59.9,1,0,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006,1
-76,1617,4134,4326,Accuracy better than 0.5m in block 4.,Oil exploration.,2404,19.58,21.17,56.5,59.02,1,0,9606,-191.808,-250.512,167.861,-0.792,-1.653,8.558,20.703,0
-77,15824,4135,4326,Derived at 15 satellite stations.,"Military mapping. Accuracy +/- 25m in X axis, +/- 20m in Y and Z axes.",1334,18.88,22.29,-160.3,-154.75,1,0,9603,61,-285,-181,,,,,1
-78,15825,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1546,18.88,20.33,-156.1,-154.75,1,0,9603,89,-279,-183,,,,,0
-79,15826,4135,4326,Derived at 3 satellite stations.,"Military mapping. Accuracy +/- 20m in each axis.",1549,21.82,22.29,-159.84,-159.24,1,0,9603,45,-290,-172,,,,,0
-80,15827,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1547,20.46,21.26,-157.35,-155.94,1,0,9603,65,-290,-190,,,,,0
-81,15828,4135,4326,Derived at 8 satellite stations.,"Military mapping only. Accuracy +/- 10m in X axis, +/- 6m in Y and Z axes.",1548,21.21,21.75,-158.32,-157.62,1,0,9603,58,-283,-182,,,,,0
-82,1893,4139,4326,Derived at 11 stations.,For military purposes only. Accuracy 3m in each axis.,1335,17.63,18.77,-67.96,-64.25,1,0,9603,11,72,-101,,,,,1
-83,1473,4140,4326,"For many purposes NAD83(CSRS98) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS98) is equivalent to WGS 84.",1336,44.61,62.56,-120,-57.1,1,1,9603,0,0,0,,,,,0
-84,1073,4141,4326,For more accurate transformation contact Survey of Israel.,"Accuracy: 2m",2603,29.45,33.27,34.18,35.68,1,0,9603,-48,55,52,,,,,1
-85,1469,4142,4326,,"?",2282,5.16,5.54,-4.22,-3.85,1,0,9603,-125,53,467,,,,,1
-86,1470,4143,4326,"Derived in Abidjan for use in the immediate area, but used by E&P industry more widely onshore and offshore. A similar transformation (dX=-123.1, dY=+53.2, dZ=+465.4, derivation unknown) was used by Western Geophysical for offshore surveys in the 1990s.",Accuracy is submetre in the area around Abidjan but unknown farther afield. There is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,1075,1.02,10.74,-8.61,-2.49,1,0,96 [...]
-87,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",3217,20.52,26.63,88.04,92.67,1,0,9603,282,726,254,,,,,0
-88,1533,4144,4326,,Oil exploration.,2361,9.49,17.87,93.94,99.66,1,0,9603,214,804,268,,,,,1
-89,1247,4145,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. No accuracy estimate available.",For military purposes.,3289,23.64,37.06,60.87,77.82,1,0,9603,283,682,231,,,,,1
-90,15494,4145,4326,Derived by Fugro-Geodetic in 2004 at 6 closely-spaced stations. Used by OMV in all blocks in Pakistan where operator.,Oil exploration.,3589,25.88,27.67,68.25,69.3,1,0,9603,274.164,677.282,226.704,,,,,0
-91,15701,4145,4326,Derived at Geodetic Survey office in Karachi in 1997.,Oil exploration.,2985,21.06,25.38,64,68.23,1,0,9603,275.57,676.78,229.6,,,,,0
-92,15702,4145,4326,"Derived at station S0001, an approximate offset to Survey of India primary station Kat Baman, in 1992 from 180 single point Transit passes observed in 1991 by Fugro-Geodetic for UTP.",Oil exploration.,2984,24,25.63,67.75,69.87,1,0,9603,278.9,684.39,226.05,,,,,0
-93,15703,4145,4326,Derived at Chitrawala triangulation station by Fugro-Geodetic for UTP.,Oil exploration.,2982,24.69,25.75,66.83,68,1,0,9603,271.905,669.593,231.495,,,,,0
-94,15704,4145,4326,Derived by Western Geophysical for UTP 1996 East Sind 2D survey.,Oil exploration.,2983,24.17,28.6,68.27,71.1,1,0,9606,230.25,632.76,161.03,-1.114,1.115,1.212,12.584,0
-95,1156,4146,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. Also source CRS may not apply to Nepal. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,8.02,35.51,68.09,97.38,1,0,9603,295,736,257,,,,,1
-96,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,9.03,11.02,105.5,107.59,1,0,9603,-17.51,-108.32,-62.39,,,,,1
-97,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.31,-22.14,13.33,42.85,1,0,9603,0,0,0,,,,,1
-98,1508,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT.","?",1286,45.83,47.81,5.97,10.49,1,1,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
-99,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.83,47.81,5.97,10.49,1,1,9603,674.374,15.056,405.346,,,,,0
-100,1753,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT. Used from 1987 to 1997. Not recommended for current usage - replaced by CH1903 to WGS 84 (2) (code 1766).","?",1286,45.83,47.81,5.97,10.49,1,0,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
-101,1766,4149,4326,"These parameters are derive from CH1903+ to ETRS89 (code 1647) and are used at lesser precision from CH1903 to WGS 84 as an approximation which is within the accuracy of the distortions in the CH1903 network. Replaces CH1903 to WGS 84 (1) (code 1753).",Accuracy 1.5 metres.,1286,45.83,47.81,5.97,10.49,1,0,9603,674.4,15.1,405.3,,,,,1
-102,1676,4150,4326,"Parameter values are from CH1903+ to CHTRF95 (1) (code 1509) assuming that CHTRF95 is equivalent to WGS 84. That transformation is also given as CH1903+ to ETRS89 (1) (code 1647). CHTRF95 is a realisation of ETRS89.","Approximation at the +/- 1m level.",1286,45.83,47.81,5.97,10.49,1,0,9603,674.374,15.056,405.346,,,,,1
-103,1511,4151,4326,,For many purposes CHTRF95 can be considered to be coincident with WGS 84.,1286,45.83,47.81,5.97,10.49,1,0,9603,0,0,0,,,,,1
-104,1580,4152,4326,"For many purposes NAD83(HARN) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(HARN) is equivalent to WGS 84.",1337,-14.58,49.38,144.58,-64.51,1,0,9603,0,0,0,,,,,1
-105,1900,4152,4326,"Strictly between NAD83(HARN) and ITRF94(1996.0). Replaced by NAD83(HARN) to WGS 84 (3) (code 1901).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.92,1,0,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-106,1901,4152,4326,"Jointly derived by US NGS and Geodetic Survey of Canada as transformation to target CRS of ITRF96(1997.0) - see also tfm code 1946. In USA only replaces NAD83 to WGS 84 (2) (code 1900).","Geodesy. Accuracy with respect to CORS at stations adjusted to HARN network is better than 0.05-0.07m. For locations outside a HARN network (i.e. NAD83), accuracy may be only 1m but will usually be better than 0.5m.",1323,24.41,49.38,-124.79,-66.92,1,0,9607,-0.991,1.9072,0.5129,-0.02 [...]
-107,15930,4152,4326,"Accuracy 0.1 to 0.2m in California, 0.05-0.11 in Oregon, elsewhere better than 0.05m.",For applications to an accuracy of 0.2 metre.,1323,24.41,49.38,-124.79,-66.92,1,1,9603,0,0,0,,,,,0
-108,1512,4153,4326,"Derived in 1998 at Assaluyeh (Taheri refinery) by Geoid for Total. Used for South Pars phases 2 and 3.",Oil industry engineering survey. Used only for terminal site.,1338,27.4,27.6,52.5,52.7,1,0,9603,-133.63,-157.5,-158.62,,,,,1
-109,1141,4154,4326,"Given by DMA as from ED50. OGP interpret that as ED50(ED77) in Iran. Derived at 27 stations.","For military purposes. Accuracy 9m, 12m and 11m in X, Y and Z axes.",1123,23.35,39.78,44.03,63.33,1,0,9603,-117,-132,-164,,,,,1
-110,1514,4154,4326,"Used for South Pars phases 6, 7 and 8.","Transformation for whole country: accuracy about 1m.",1123,23.35,39.78,44.03,63.33,1,0,9606,-110.33,-97.73,-119.85,0.3423,1.1634,0.2715,0.063,0
-111,1856,4154,4326,Derived in Kangan district by Geoid for Total in 1998. Used for South Pars phases 2 and 3.,Petroleum Exploration and Production.,2783,26.59,26.71,52.07,52.27,1,0,9603,-122.89,-159.08,-168.74,,,,,0
-112,1857,4154,4326,Derived in 1999 on Lavan island by Geoid for Elf.,Petroleum Exploration and Production.,2782,26.22,26.86,52.5,53.43,1,0,9603,-84.78,-107.55,-137.25,,,,,0
-113,1858,4154,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Petroleum Exploration and Production.,2781,29.17,29.38,50.23,50.42,1,0,9603,-123.92,-155.515,-157.721,,,,,0
-114,15745,4154,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11.,Petroleum Exploration and Production.,3140,26.46,26.63,52.23,52.41,1,0,9603,-123.02,-158.95,-168.47,,,,,0
-115,1518,4155,4326,,Accuracy 25m in each axis.,3257,7.19,12.68,-15.13,-7.65,1,0,9603,-83,37,124,,,,,1
-116,1623,4156,4326,"Parameter values from S-JTSK to ETRS89 (1) (code 1622). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by S-JTSK to WGS 84 (5) (code 5239).",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9606,570.8,85.7,462.8,4.998,1.587,5.261,3.56,0
-117,1625,4156,4326,"Parameter values from S-JTSK to ETRS89 (2) (code 1624). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,1,9606,559,68.7,451.5,7.92,4.073,4.251,5.71,0
-118,4828,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,1,9606,485,169.5,483.5,7.786,4.398,4.103,0,0
-119,4836,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,0,9606,485,169.5,483.8,7.786,4.398,4.103,0,0
-120,5239,4156,4326,"Parameter values from S-JTSK/05 to WGS 84 (1) (code 5227). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,0
-121,15965,4156,4326,Derived at 6 stations.,"For military purposes. Accuracy 4m, 2m and 3m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,0,9603,589,76,480,,,,,1
-122,1283,4669,4326,,LKS94 is a realisation of ETRS89 coincident to WGS 84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1145,53.89,56.45,19.02,26.81,1,0,9603,0,0,0,,,,,1
-123,1099,4670,4326,"Parameter values taken from IGM95 to ETRS89 (1) (code 1098) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation.",Approximation at the 1m level.,3343,34.77,47.09,5.94,18.99,1,0,9603,0,0,0,,,,,1
-124,1859,4159,4326,"Used by Repsol in Murzuq field, and PetroCanada and previous licence holders in NC177 and 72 (En Naga field). Reliability of connection to ELD79 questionned.",Oil Exploration,2785,27.33,27.66,18.37,18.72,1,0,9603,-69.06,-90.71,-142.56,,,,,0
-125,1860,4159,4326,Derived December 2001 by NAGECO. Connected to ITRF via Remsa 2000 data. Used by TotalFinaElf.,Oil Exploration. 3-dimensional SD at 11 points is 0.5m.,2785,27.33,27.66,18.37,18.72,1,0,9603,-113.997,-97.076,-152.312,,,,,0
-126,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.62,30.06,17.14,17.5,1,0,9603,-114.5,-96.1,-151.9,,,,,0
-127,1862,4159,4326,"Derived by Geoid in 2000 from ITRF connection by NAGECO for TotalFinaElf. For historic compatibility TFE use the 1994 tfm ELD79 to WGS 84 (3) (code 1861) rather than this transformation.",Oil Exploration,2786,29.62,30.06,17.14,17.5,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
-128,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.62,30.06,17.14,17.5,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
-129,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
-130,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.58,1,0,9603,-114.7,-98.5,-150.7,,,,,0
-131,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.5,33.22,9.31,25.21,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
-132,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.79,22.5,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
-133,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-44.64,-43.31,-177.24,-175.55,1,0,9603,175,-38,113,,,,,1
-134,1081,4673,4326,Derived at 4 stations using concatenation through WGS72. Parameter vales are also used to transform CI1979 to NZGD2000 - see tfm code 1082.,For applications requiring 2m accuracy.,2889,-44.64,-43.31,-177.24,-175.55,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
-135,15894,4674,4326,,Accuracy 1m.,3418,-59.86,32.72,-122.18,-26.01,1,0,9603,0,0,0,,,,,1
-136,1070,4675,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,3255,13.19,13.7,144.58,145,1,0,9603,-100,-248,259,,,,,1
-137,1682,4164,4326,"Parameter values taken from South Yemen to Yemen NGN96 (1) (code 1539) assuming that NGN96 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 5m level.",1340,12.55,19,43.37,53.13,1,0,9603,-76,-138,67,,,,,1
-138,1547,4165,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3258,10.88,12.68,-16.76,-13.64,1,0,9603,-173,253,27,,,,,1
-139,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.93,22.5,100.09,107.7,1,0,9603,44.585,-131.212,-39.544,,,,,1
-140,1565,4167,4326,,Assumes NZGD2000 is coincident to WGS 84 to the 1m accuracy level.,1175,-55.95,-25.89,160.61,-171.2,1,0,9603,0,0,0,,,,,1
-141,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.4,11.16,-3.79,2.1,1,0,9603,-199,32,322,,,,,1
-142,15495,4168,4326,Derived via WGS 72BE. Found in use within oil industry erroneously concatenated via WGS 72. See tfm code 8571.,Oil industry.,1505,1.4,6.06,-3.79,2.1,1,0,9606,-171.16,17.29,325.21,0,0,0.814,-0.38,0
-143,1577,4169,4326,Transformation based on observations at 2 stations in 1993.,For military purposes. One sigma uncertainty is 25m in each axis.,3109,-14.43,-14.12,-170.87,-169.39,1,0,9603,-115,118,426,,,,,1
-144,1581,4170,4326,,For military purposes. Accuracy 1m in each axis.,3448,-59.86,16.75,-113.2,-26.01,1,0,9603,0,0,0,,,,,1
-145,1671,4171,4326,"Parameter values from RGF93 to ETRS89 (1) (code 1591) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1096,41.15,51.56,-9.86,10.38,1,0,9603,0,0,0,,,,,1
-146,1598,4172,4326,,"?",1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,0,0,0,,,,,0
-147,1678,4173,4326,Assumes that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. IRENET95 is a regional realisation of ETRS89.,"Approximation at the +/- 1m level.",1305,51.4,55.43,-10.56,-5.35,1,0,9603,0,0,0,,,,,1
-148,15738,4686,4326,,MAGNA-SIRGAS is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1070,-4.24,15.5,-84.77,-66.87,1,0,9603,0,0,0,,,,,1
-149,1614,4175,4326,"Determined at 8 stations. Info. source has the source CRS as Sierra Leone 1960. Sierra Leone 1968 is a readjustment of the 1960 network: coordinates changed by less than 3 metres.","Accuracy +/- 15m in each axis.",3306,6.88,10,-13.34,-10.26,1,0,9603,-88,4,101,,,,,1
-150,1890,4176,4326,For many purposes Australian Antarctic can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that Australian Antarctic is equivalent to WGS 84.",1278,-90,-60,45,160,1,0,9603,0,0,0,,,,,1
-151,15773,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (1) (tfm code 15761).","Accuracy +/- 1 metre.",3131,-9.88,-9.65,-139.22,-138.76,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
-152,15774,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (2) (tfm code 15762).","Accuracy +/- 2 metres.",3132,-10.07,-9.87,-139.19,-138.98,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
-153,1675,4178,4326,"Parameter values from Pulkovo 1942(83) to ETRS89 (1) (code 1674) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Residuals under 2 m.,1343,50.2,54.73,9.92,15.03,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
-154,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.75,48.58,16.11,22.89,1,0,9603,28,-121,-77,,,,,0
-155,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
-156,1645,4179,4326,"Parameter values from Pulkovo 1942(58) to ETRS89 (1) (code 1644). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3293,49,54.89,14.15,24.14,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
-157,15496,4179,4326,,Oil exploration,1197,43.45,48.26,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
-158,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
-159,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.45,48.26,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
-160,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.15,24.14,1,0,9603,23,-124,-82,,,,,0
-161,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.66,19.22,21.05,1,0,9603,24,-130,-92,,,,,0
-162,1649,4180,4326,"Parameter values taken from EST97 to ETRS89 (1) (code 1648). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1090,57.52,59.99,20.37,28.19,1,0,9603,0,0,0,,,,,1
-163,1643,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (1) (code 1642). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1146,49.45,50.18,5.73,6.52,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,0
-164,5486,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (3) (code 5485) assuming ETRS89 and WGS 84 are coincident within the one metre level. Replaces tfm code 1643. For an equivalent transformation using the Molodensky-Badekas method see code 5484.",For applications to an accuracy of 1 metre.,1146,49.45,50.18,5.73,6.52,1,0,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598,1
-165,1210,4694,4326,,POSGAR 94 is a local realisation of WGS 84.,1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
-166,1886,4183,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-104,167,-38,,,,,1
-167,1885,4184,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1345,36.88,37.96,-25.91,-24.96,1,0,9603,-203,141,53,,,,,1
-168,15794,4708,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1069,-12.25,-12.08,96.77,96.92,1,0,9603,-491,-22,435,,,,,1
-169,15850,4698,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,0,9603,145,-187,103,,,,,1
-170,15784,4699,4326,Derived at 17 stations in 1994 by University of East London. Residuals less than 2m.,Accuracy 2m.,3209,-20.57,-19.94,57.25,57.85,1,0,9603,-770.1,158.4,-498.2,,,,,1
-171,1955,4188,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) OSNI 1952 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,2530,53.96,55.35,-8.17,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-172,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.65,16.75,-73.38,-58.95,1,0,9603,0,0,0,,,,,1
-173,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
-174,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,0,0,0,,,,,0
-175,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.17,4.98,8.45,10.39,1,0,9603,-206.1,-174.7,-87.7,,,,,1
-176,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.17,4.98,8.45,10.39,1,0,9603,-70.9,-151.8,-41.4,,,,,1
-177,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.28,-42.52,1,0,9603,164,138,-189,,,,,1
-178,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.28,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
-179,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.68,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
-180,1800,4196,4326,,Topographic mapping.,2571,65.52,65.9,-38.86,-36.82,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
-181,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.68,24.88,141.21,141.42,1,0,9603,145,75,-272,,,,,1
-182,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.07,-15.85,-5.84,-5.6,1,0,9603,-320,550,-494,,,,,1
-183,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.23,24.35,153.92,154.05,1,0,9603,124,-234,-25,,,,,1
-184,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
-185,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
-186,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.41,22.23,21.83,47.99,1,0,9603,-166,-15,204,,,,,1
-187,1101,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.4,15.08,-5.52,2.4,1,0,9603,-118,-14,218,,,,,0
-188,1102,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.08,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
-189,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.41,14.88,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
-190,1104,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25,-12.24,4.25,1,0,9603,-123,-20,220,,,,,0
-191,1105,4201,4326,"Derived at 2 stations connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.3,16.69,-17.58,-11.37,1,0,9603,-128,-18,224,,,,,0
-192,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.23,21.83,38.66,1,0,9603,-161,-14,205,,,,,0
-193,1108,4202,4326,Derived at 105 stations.,For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-133,-48,148,,,,,0
-194,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.92,-35.13,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
-195,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.16,140.96,153.68,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
-196,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.54,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
-197,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26,-10.86,129,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
-198,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.6,142.24,144.74,1,0,9603,-124,-60,154,,,,,0
-199,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-127.8,-52.3,152.9,,,,,0
-200,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.19,-8.88,109.23,163.19,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
-201,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-134,-48,149,,,,,1
-202,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.87,112.85,153.68,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
-203,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
-204,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-128.5,-53,153.4,,,,,0
-205,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-145.7,-249.1,1.5,,,,,0
-206,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
-207,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.08,46.55,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
-208,1058,4204,4326,,1 metre accuracy.,2957,28.54,29.44,46.55,48.47,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
-209,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.54,26.34,50.4,50.84,1,0,9603,-150,-250,-1,,,,,0
-210,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.62,32.15,34.52,55.67,1,0,9603,-143,-236,7,,,,,1
-211,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.46,1,0,9603,-43,-163,45,,,,,1
-212,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.85,-7.52,156.45,158.19,1,0,9603,230,-199,-752,,,,,1
-213,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.21,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
-214,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.96,42.15,-9.55,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
-215,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.96,42.15,-9.55,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
-216,1984,4207,4326,,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
-217,1988,4207,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
-218,1549,4208,4326,,Oil exploration.,2307,-28.4,-17.59,-48.79,-35.19,1,1,9603,-158,315,-148,,,,,0
-219,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.4,-39.03,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
-220,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.6,-9.8,-39.13,-38,1,0,9603,-141.15,293.44,-150.56,,,,,0
-221,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.26,-10.6,-39.07,-37.99,1,0,9603,-142.48,296.03,-149.74,,,,,0
-222,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.4,-22.67,-48.79,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
-223,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-170,305,-145,,,,,0
-224,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-162.904,312.531,-137.109,,,,,0
-225,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.12,-53.37,-44.71,1,0,9603,-158,309,-151,,,,,0
-226,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.37,-35.2,1,0,9603,-161,308,-142,,,,,0
-227,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.9,18.25,-16.1,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
-228,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.67,-53.37,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
-229,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
-230,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-161.11,310.25,-144.64,,,,,0
-231,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.02,-39.21,-34.61,1,0,9603,-160.4,302.29,-144.19,,,,,0
-232,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.19,-39.08,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
-233,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.26,-8.4,-39.13,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
-234,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.57,-8.73,-37.33,-32.02,1,0,9603,-156.8,298.41,-147.41,,,,,0
-235,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.16,-4.61,-35.09,-29.14,1,0,9603,-157.4,295.05,-150.19,,,,,0
-236,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.25,-44.79,-26.01,1,0,9603,-151.99,287.04,-147.45,,,,,1
-237,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-160,315,-142,,,,,0
-238,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.4,-22.67,-48.79,-40.2,1,0,9603,-158,309,-147,,,,,0
-239,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-161,310,-145,,,,,0
-240,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.4,-17.59,-48.79,-35.19,1,0,9603,-158,315,-148,,,,,0
-241,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.65,-8.19,20,35.92,1,0,9603,-143,-90,-294,,,,,1
-242,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,20,29.37,1,0,9603,-138,-105,-289,,,,,0
-243,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.85,1,1,9603,-153,-5,-292,,,,,0
-244,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.65,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
-245,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.38,32.68,35.92,1,0,9603,-161,-73,-317,,,,,0
-246,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.73,30.8,32.13,1,0,9603,-134,-105,-295,,,,,0
-247,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.38,11.8,31.3,1,1,9603,-169,-19,-278,,,,,0
-248,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.07,-8.19,22,33.7,1,0,9603,-147,-74,-283,,,,,0
-249,1121,4209,4326,Derived at 10 stations.,"For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.41,-15.62,25.24,33.07,1,0,9603,-142,-96,-293,,,,,0
-250,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.74,4.62,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
-251,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.62,33.91,41.91,1,0,9603,-157,-2,-299,,,,,0
-252,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.74,-1,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
-253,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.85,1,0,9603,-153,-5,-292,,,,,0
-254,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.98,5.96,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
-255,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.88,-4.08,105.78,110,1,0,9603,-378.873,676.002,-46.255,,,,,0
-256,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.81,117,1,0,9603,-377.7,675.1,-52.2,,,,,0
-257,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.38,1,0,9603,31.95,300.99,419.19,,,,,1
-258,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.78,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
-259,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.64,19.78,-80.13,-79.69,1,0,9603,42,124,147,,,,,1
-260,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.64,19.78,-80.13,-79.69,1,0,9603,44.4,109,151.7,,,,,0
-261,15800,4713,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.71,41.76,44.15,1,0,9603,-79,-129,145,,,,,1
-262,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.88,-64.62,1,0,9603,-73,213,296,,,,,1
-263,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.88,-64.62,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
-264,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.13,-25.01,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
-265,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.24,13.67,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
-266,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.67,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
-267,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.51,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.4142185637707,-2.99084175323096,-39.0346863906349,-20.81616,0
-268,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.4,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.22383004903209,2.42380329967319,-8.30827832824698,-13.56561,0
-269,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.4,1,0,9607,336.026,348.565,252.978,-17.2412894390071,-6.30649282215535,1.56204977191825,-5.771909,0
-270,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-72,1,0,9607,963.273,486.386,190.997,-16.4850360280866,-1.66882584284416,21.6928490465265,-13.89914,0
-271,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8,-77.91,-74.4,1,0,9607,-90.29,247.559,-21.989,-8.69688534851263,-4.18803362841004,-12.8082668496251,2.181658,0
-272,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5,-77.67,-74.4,1,0,9607,-0.562,244.299,-456.938,6.8668709851194,-8.25267346177889,-9.2967797230575,3.74656,0
-273,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.12,3,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.69049385992583,1.03196819622539,-19.7573941768278,6.325747,0
-274,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.24,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.80844591036278,-0.44850858891268,-2.81017234679107,-2.199943,0
-275,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.34,1,0,9603,-384,664,-48,,,,,1
-276,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.58,-7.75,12.58,13.39,1,0,9603,-42.01,-332.21,-229.75,,,,,0
-277,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7,-6.01,12.08,12.83,1,0,9603,-40,-354,-224,,,,,0
-278,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.25,-6.03,11.08,12.08,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
-279,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.25,-6.01,8.2,13.85,1,0,9603,-41.8,-342.2,-228.2,,,,,0
-280,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.33,-6.67,11.75,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
-281,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.08,-9.42,12.66,13.38,1,0,9603,-43,-337,-233,,,,,0
-282,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.08,-6.03,10.83,13.38,1,0,9603,-48,-345,-231,,,,,0
-283,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7,-6.01,12.08,12.83,1,0,9603,-48.6,-345.1,-230.8,,,,,0
-284,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.33,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
-285,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.58,-6.01,10.41,12.83,1,0,9603,-50.9,-347.6,-231,,,,,1
-286,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.92,-21.78,-73.58,-53.65,1,0,9603,-148,136,90,,,,,1
-287,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.15,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
-288,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.87,-22.14,16.45,32.94,1,0,9603,-136,-108,-292,,,,,1
-289,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.87,-22.14,16.45,32.94,1,0,9603,-134.73,-110.92,-292.66,,,,,0
-290,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.4,7.49,13.66,1,0,9603,-263,6,431,,,,,1
-291,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.4,7.82,13.66,1,0,9603,-260.1,5.5,432.2,,,,,0
-292,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.3,-62.56,-57.81,1,0,9603,-134,229,-29,,,,,1
-293,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.38,-48.09,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,0
-294,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.38,-48.09,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
-295,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,1
-296,1585,4227,4326,,"?",1227,32.31,37.29,34.97,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
-297,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.4,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
-298,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.8,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
-299,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.5,35.9,39.3,40.8,1,0,9603,-187.5,14.1,237.6,,,,,0
-300,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.29,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
-301,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.5,35.9,39.3,40.8,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
-302,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
-303,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
-304,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.9,33.81,24.71,37.91,1,0,9603,-130,110,-13,,,,,1
-305,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.2,30,32.34,34.26,1,1,9603,-146.21,112.63,4.05,,,,,0
-306,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.36,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
-307,1087,4230,4326,,Topographic mapping.,1130,29.19,33.38,34.88,39.3,1,0,9603,-112,-110.3,-140.2,,,,,0
-308,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.2,-9.55,31.58,1,0,9603,-87,-98,-121,,,,,1
-309,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
-310,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.62,37.38,34.18,55.67,1,0,9603,-103,-106,-141,,,,,0
-311,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.19,1,0,9603,-104,-101,-140,,,,,0
-312,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.67,24.71,30,1,0,9603,-130,-117,-151,,,,,0
-313,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.12,60.89,-10.56,1.83,1,0,9603,-86,-96,-120,,,,,0
-314,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.94,71.2,4.69,31.58,1,0,9603,-87,-95,-120,,,,,0
-315,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.58,28.3,1,0,9603,-84,-95,-130,,,,,0
-316,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.83,41.3,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
-317,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.6,38.35,12.37,15.7,1,0,9603,-97,-88,-135,,,,,0
-318,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.75,36.04,14.28,14.62,1,0,9603,-107,-88,-149,,,,,0
-319,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.81,-9.55,3.39,1,0,9603,-84,-107,-120,,,,,0
-320,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.4,7.49,13.66,1,0,9603,-112,-77,-145,,,,,0
-321,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
-322,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
-323,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.58,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
-324,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.16,-3.7,39.64,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
-325,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.09,62,1.37,11.13,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
-326,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
-327,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36.01,36.16,-5.41,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
-328,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.15,4.38,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
-329,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.53,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
-330,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.81,-9.36,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
-331,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.43,43.45,25.62,44.82,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
-332,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.67,24.71,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
-333,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.75,-12.5,-9.5,1,0,9603,-82.31,-95.23,-114.96,,,,,0
-334,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.43,55.77,2.54,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
-335,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
-336,1989,4230,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
-337,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.35,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
-338,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.43,55.77,2.54,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-339,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.43,55.77,2.54,6.4,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,0
-340,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.92,41.87,-13.86,-7.25,1,0,9603,-86.277,-108.879,-120.181,,,,,0
-341,1146,4231,4326,,"?",2330,51.04,62,-5.05,11.13,1,0,9606,-82.981,-99.719,-110.709,-0.104700015651026,0.0310016003789386,0.0804020214751182,-0.3143,0
-342,1960,4231,4326,,Scientific research.,1297,34.88,71.2,-10.56,31.58,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-343,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.2,-10.56,31.58,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,1
-344,1256,4232,4326,Derived at 7 stations.,"For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.6,26.41,52,59.9,1,0,9603,-346,-1,224,,,,,1
-345,1438,4232,4326,,Oil exploration.,4009,16.6,26.41,52,59.9,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,0
-346,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.09,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
-347,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.27,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
-348,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.27,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
-349,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.88,25.33,119.26,122.05,1,0,9603,-637,-549,-203,,,,,1
-350,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.75,48.58,16.11,22.89,1,0,9603,52.17,-71.82,-14.9,,,,,1
-351,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.75,48.58,16.11,22.89,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
-352,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.75,48.58,16.11,22.89,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
-353,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.75,48.58,16.11,22.89,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
-354,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.75,48.58,16.11,22.89,1,0,9603,57.01,-69.97,-9.29,,,,,0
-355,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.96,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
-356,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.96,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
-357,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.96,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
-358,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.45,97.35,105.64,1,0,9603,217,823,299,,,,,1
-359,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.45,97.35,105.64,1,0,9603,209,818,290,,,,,0
-360,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.45,97.35,105.64,1,0,9603,210,814,289,,,,,1
-361,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.75,8.15,102.16,103.04,1,0,9603,204.64,834.74,293.8,,,,,0
-362,1812,4240,4326,,Cadastral survey.,3317,5.63,20.45,97.35,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
-363,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
-364,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
-365,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
-366,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
+26,1877,4618,4326,"Derived by Brazilian Institute of Geography and Statistics (IBGE) in 1989 at Chua origin point. In use by Shell throughout Brazil. For use by Petrobras and ANP, replaced by tfm code 5882 from 1994.",Medium and small scale mapping. Valid for transforming GPS observations conducted in the period 1987 to 1993 inclusive.,1053,-35.71,7.04,-74,-25.28,1,0,9603,-66.87,4.37,-38.52,,,,,0
+27,5882,4618,4326,"Parameter values from SAD69 to SIRGAS 2000 (1) (tfm code 15485) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras throughout Brazil from 1994, relacing use of tfm code 1877.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).",1053,-35. [...]
+28,1879,4619,4326,"Parameter values taken from SWEREF to ETRS89 (1) (code 1878) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Geographic Information Systems.,1225,54.96,69.06,10.03,24.17,1,0,9603,0,0,0,,,,,1
+29,1880,4620,4326,Derived at one point in each of Burkina Faso and Niger.,For military purposes. Accuracy 25m in each axis.,2791,11.83,14.22,-4.64,4,1,0,9603,-106,-129,165,,,,,1
+30,1903,4621,4326,,"Accuracy +/- 10 metres.",2828,17.83,18.17,-63.2,-62.73,1,0,9603,137,248,-430,,,,,1
+31,1904,4622,4326,,"Accuracy +/- 10 metres.",2829,15.8,16.54,-61.85,-60.97,1,0,9603,-467,-16,-300,,,,,1
+32,1905,4622,4326,,"Accuracy +/- 0.1 metre.",2829,15.8,16.54,-61.85,-60.97,1,0,9606,-472.29,-5.63,-304.12,0.4362,-0.8374,0.2563,1.8984,0
+33,1906,4623,4326,,"Accuracy +/- 10 metres.",3105,3.43,5.81,-54.45,-51.62,1,0,9603,-186,230,110,,,,,1
+34,1907,4624,4326,,"Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,1,9603,2,2,-2,,,,,0
+35,4840,4624,4326,"Replaces RGFG95 to WGS 84 (1) (code 1907) which was not put into official use but issued in error.","Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,0,9603,0,0,0,,,,,1
+36,1909,4625,4326,,"Accuracy +/- 10 metres.",3276,14.35,14.93,-61.28,-60.77,1,0,9603,186,482,151,,,,,1
+37,1910,4625,4326,,"Accuracy +/- 0.1 metre.",3276,14.35,14.93,-61.28,-60.77,1,0,9606,126.93,547.94,130.41,-2.7867,5.1612,-0.8584,13.8227,0
+38,1911,4626,4326,Derived at 1 station.,"Accuracy +/- 30 metres.",1196,-25.92,-10.6,37.58,58.27,1,1,9603,94,-948,-1292,,,,,0
+39,15751,4626,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3337,-21.42,-20.81,55.17,55.9,1,0,9603,94,-948,-1262,,,,,1
+40,1912,4627,4326,,"Accuracy +/- 1 metre.",3902,-24.71,-18.29,51.84,58.24,1,0,9603,0,0,0,,,,,1
+41,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.92,-17.42,-149.99,-149.1,1,0,9603,162,117,154,,,,,1
+42,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.95,-16.18,-151.91,-150.9,1,0,9603,65,342,77,,,,,0
+43,15770,4629,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahaa 54 to RGPF (1) (tfm code 15758).","Accuracy +/- 1 metre.",2812,-16.95,-16.18,-151.91,-150.9,1,0,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746,1
+44,1914,4630,4326,,"Accuracy +/- 10 metres.",3129,-9.56,-8.73,-140.31,-139.45,1,0,9603,84,274,65,,,,,1
+45,15775,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (1) (tfm code 15763).","Accuracy +/- 1 metre.",2810,-9.01,-8.73,-140.31,-139.96,1,0,9607,165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204,0
+46,15776,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15764).","Accuracy +/- 2 metres.",3127,-8.99,-8.82,-139.65,-139.45,1,0,9607,1363.785,1362.687,398.811,-4.5322,-6.7579,-1.0574,268.361,0
+47,15777,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15765).","Accuracy +/- 1 metre.",3128,-9.56,-9.27,-140.2,-139.96,1,0,9607,259.551,297.612,197.833,1.4866,2.1224,0.4612,27.0249,0
+48,1915,4631,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,1,9603,145,-187,103,,,,,0
+49,1916,4632,4326,,"Accuracy +/- 10 metres.",3340,-13.04,-12.61,44.99,45.34,1,0,9603,-382,-59,-262,,,,,1
+50,1272,4121,4326,,For applications requiring 1m or better accuracy.,3254,34.88,41.75,19.58,28.3,1,0,9603,-199.87,74.79,246.62,,,,,1
+51,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-26.44,-14.83,156.26,174.28,1,1,9603,-13,-348,292,,,,,0
+52,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.04,163.93,167.08,1,1,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+53,1639,4123,4326,"Parameter values from KKJ to ETRS89 (1) (code 1638). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by KKJ to WGS 84 (2) (code 10099).",For applications to an accuracy of 1 to 2 metres.,3333,59.76,70.09,19.24,31.58,1,0,9606,-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37,0
+54,10099,4123,4326,"Parameter values from KKJ to ETRS89 (2) (code 10098). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces KKJ to WGS 84 (1) (code 1639).",For applications to an accuracy of 1 to 2 metres.,3333,59.76,70.09,19.24,31.58,1,0,9607,-96.062,-82.428,-121.753,-4.801,-0.345,1.376,1.496,1
+55,1680,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1437) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by RT90 to WGS 84 (2) (code 1896) from 2001.","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,0,9607,419.3836,99.3335,591.3451,-0.850389,-1.817277,7.862238,-0.99496,0
+56,1788,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1787) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Supersedes RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,1,9607,414.1,41.3,603.1,-0.855,2.141,-7.023,0,0
+57,1896,4124,4326,"Parameter values from RT90 to SWEREF99 (1) (code 1895) assuming that SWEREF99 is equivalent to WGS 84 within the accuracy of the transformation. Replaces RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.06,10.03,24.17,1,0,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0,1
+58,1282,4125,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.24,0,116.73,117.99,1,1,9603,-404.78,685.68,45.47,,,,,0
+59,1923,4638,4326,,"Accuracy +/- 10 metres.",3299,46.7,47.18,-56.47,-56.07,1,0,9603,30,430,368,,,,,1
+60,1683,4127,4326,"Parameter values taken from Tete to Moznet (1) (code 1297) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals as high as 30 metres.,3281,-26.86,-10.43,30.21,40.9,1,0,9607,-115.064,-87.39,-101.716,0.058,-4.001,2.062,9.366,0
+61,1684,4127,4326,"Parameter values taken from Tete to Moznet (2) (code 1298) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 1 metre.,2350,-26.86,-23.91,31.92,34.49,1,0,9607,-82.875,-57.097,-156.768,2.158,-1.524,0.982,-0.359,0
+62,1685,4127,4326,"Parameter values taken from Tete to Moznet (3) (code 1299) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 4 metres.,2351,-24.91,-19.74,31.3,35.65,1,0,9607,-138.527,-91.999,-114.591,0.14,-3.363,2.217,11.748,0
+63,1686,4127,4326,"Parameter values taken from Tete to Moznet (4) (code 1300) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 3 metres.,2352,-19.9,-14.01,30.21,39.18,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,1
+64,1687,4127,4326,"Parameter values taken from Tete to Moznet (5) (code 1301) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are 5-10 metres.,2353,-16.94,-10.43,34.37,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,0
+65,1934,4640,4326,RRAF 1991 was defined to be WGS84 at a single point in Martinique during the 1988 Tango mission.,"Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,1,9603,0,0,0,,,,,0
+66,1928,4641,4326,Withdrawn by information source and replaced by improved information - see tfm code 15901.,"Accuracy better than +/- 1 metre.",2819,-21.71,-21.33,167.76,168.18,1,0,9606,-408.809,366.856,-412.987,1.8842,-0.5308,2.1655,-121.0993,0
+67,15783,4641,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15901.,Accuracy 5 metres.,2819,-21.71,-21.33,167.76,168.18,1,0,9603,287,178,-136,,,,,0
+68,15901,4641,4326,"Parameter values taken from IGN53 Mare to RGNC91-93 (1) ( code 15884) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 2 metres.,2819,-21.71,-21.33,167.76,168.18,1,0,9603,287.58,177.78,-135.41,,,,,1
+69,1302,4130,4326,,For many purposes Moznet can be considered to be coincident with WGS 84. Accuracy better than 1 metre.,1167,-27.7,-10.09,30.21,43.02,1,0,9607,0,0,0,0,0,0,0,1
+70,1542,4131,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2359,14,18,105.62,109.32,1,0,9603,198,881,317,,,,,1
+71,1543,4131,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2360,8.59,8.82,106.5,106.79,1,0,9603,182,915,344,,,,,0
+72,1513,4132,4326,Derived in 1998 in Kangan district by Geoid for Total. Used for South Pars phases 2 and 3.,Oil exploration.,2362,27.3,28.2,51.8,53,1,0,9603,-241.54,-163.64,396.06,,,,,1
+73,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.22,26.86,52.5,53.43,1,0,9603,-239.1,-170.02,397.5,,,,,0
+74,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29.17,29.38,50.23,50.42,1,0,9603,-244.72,-162.773,400.75,,,,,0
+75,1333,4133,4326,,"?",3246,57.52,59.75,21.74,28.19,1,0,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014,1
+76,1439,4134,4326,"Replaced PSD93 to WGS 84 (2) (code 8581) in 1997.","Oil exploration. Residuals 0.5m at 67% probability level.",3288,16.6,26.57,52,59.9,1,0,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006,1
+77,1617,4134,4326,Accuracy better than 0.5m in block 4.,Oil exploration.,2404,19.58,21.17,56.5,59.02,1,0,9606,-191.808,-250.512,167.861,-0.792,-1.653,8.558,20.703,0
+78,15824,4135,4326,Derived at 15 satellite stations.,"Military mapping. Accuracy +/- 25m in X axis, +/- 20m in Y and Z axes.",1334,18.88,22.29,-160.3,-154.75,1,0,9603,61,-285,-181,,,,,1
+79,15825,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1546,18.88,20.33,-156.1,-154.75,1,0,9603,89,-279,-183,,,,,0
+80,15826,4135,4326,Derived at 3 satellite stations.,"Military mapping. Accuracy +/- 20m in each axis.",1549,21.82,22.29,-159.84,-159.24,1,0,9603,45,-290,-172,,,,,0
+81,15827,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1547,20.46,21.26,-157.35,-155.94,1,0,9603,65,-290,-190,,,,,0
+82,15828,4135,4326,Derived at 8 satellite stations.,"Military mapping only. Accuracy +/- 10m in X axis, +/- 6m in Y and Z axes.",1548,21.21,21.75,-158.32,-157.62,1,0,9603,58,-283,-182,,,,,0
+83,1893,4139,4326,Derived at 11 stations.,For military purposes only. Accuracy 3m in each axis.,1335,17.63,18.77,-67.96,-64.25,1,0,9603,11,72,-101,,,,,1
+84,1473,4140,4326,"For many purposes NAD83(CSRS98) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS98) is equivalent to WGS 84.",1336,44.61,62.56,-120,-57.1,1,1,9603,0,0,0,,,,,0
+85,1073,4141,4326,For more accurate transformation contact Survey of Israel.,"Accuracy: 2m",2603,29.45,33.27,34.18,35.68,1,0,9603,-48,55,52,,,,,1
+86,1469,4142,4326,,"?",2282,5.16,5.54,-4.22,-3.85,1,0,9603,-125,53,467,,,,,1
+87,1470,4143,4326,"Derived in Abidjan for use in the immediate area, but used by E&P industry more widely onshore and offshore. A similar transformation (dX=-123.1, dY=+53.2, dZ=+465.4, derivation unknown) was used by Western Geophysical for offshore surveys in the 1990s.",Accuracy is submetre in the area around Abidjan but unknown farther afield. There is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,1075,1.02,10.74,-8.61,-2.49,1,0,96 [...]
+88,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",3217,20.52,26.63,88.04,92.67,1,0,9603,282,726,254,,,,,0
+89,1533,4144,4326,,Oil exploration.,2361,9.49,17.87,93.94,99.66,1,0,9603,214,804,268,,,,,1
+90,1247,4145,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. No accuracy estimate available.",For military purposes.,3289,23.64,37.06,60.87,77.82,1,0,9603,283,682,231,,,,,1
+91,15494,4145,4326,Derived by Fugro-Geodetic in 2004 at 6 closely-spaced stations. Used by OMV in all blocks in Pakistan where operator.,Oil exploration.,3589,25.88,27.67,68.25,69.3,1,0,9603,274.164,677.282,226.704,,,,,0
+92,15701,4145,4326,Derived at Geodetic Survey office in Karachi in 1997.,Oil exploration.,2985,21.06,25.38,64,68.23,1,0,9603,275.57,676.78,229.6,,,,,0
+93,15702,4145,4326,"Derived at station S0001, an approximate offset to Survey of India primary station Kat Baman, in 1992 from 180 single point Transit passes observed in 1991 by Fugro-Geodetic for UTP.",Oil exploration.,2984,24,25.63,67.75,69.87,1,0,9603,278.9,684.39,226.05,,,,,0
+94,15703,4145,4326,Derived at Chitrawala triangulation station by Fugro-Geodetic for UTP.,Oil exploration.,2982,24.69,25.75,66.83,68,1,0,9603,271.905,669.593,231.495,,,,,0
+95,15704,4145,4326,Derived by Western Geophysical for UTP 1996 East Sind 2D survey.,Oil exploration.,2983,24.17,28.6,68.27,71.1,1,0,9606,230.25,632.76,161.03,-1.114,1.115,1.212,12.584,0
+96,1156,4146,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. Also source CRS may not apply to Nepal. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,8.02,35.51,68.09,97.38,1,0,9603,295,736,257,,,,,1
+97,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,9.03,11.02,105.5,107.59,1,0,9603,-17.51,-108.32,-62.39,,,,,1
+98,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.31,-22.14,13.33,42.85,1,0,9603,0,0,0,,,,,1
+99,1508,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT.","?",1286,45.83,47.81,5.97,10.49,1,1,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
+100,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.83,47.81,5.97,10.49,1,1,9603,674.374,15.056,405.346,,,,,0
+101,1753,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT. Used from 1987 to 1997. Not recommended for current usage - replaced by CH1903 to WGS 84 (2) (code 1766).","?",1286,45.83,47.81,5.97,10.49,1,0,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
+102,1766,4149,4326,"These parameters are derive from CH1903+ to ETRS89 (code 1647) and are used at lesser precision from CH1903 to WGS 84 as an approximation which is within the accuracy of the distortions in the CH1903 network. Replaces CH1903 to WGS 84 (1) (code 1753).",Accuracy 1.5 metres.,1286,45.83,47.81,5.97,10.49,1,0,9603,674.4,15.1,405.3,,,,,1
+103,1676,4150,4326,"Parameter values are from CH1903+ to CHTRF95 (1) (code 1509) assuming that CHTRF95 is equivalent to WGS 84. That transformation is also given as CH1903+ to ETRS89 (1) (code 1647). CHTRF95 is a realisation of ETRS89.","Approximation at the +/- 1m level.",1286,45.83,47.81,5.97,10.49,1,0,9603,674.374,15.056,405.346,,,,,1
+104,1511,4151,4326,,For many purposes CHTRF95 can be considered to be coincident with WGS 84.,1286,45.83,47.81,5.97,10.49,1,0,9603,0,0,0,,,,,1
+105,1580,4152,4326,"For many purposes NAD83(HARN) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(HARN) is equivalent to WGS 84.",1337,-14.58,49.38,144.58,-64.51,1,0,9603,0,0,0,,,,,1
+106,1900,4152,4326,"Strictly between NAD83(HARN) and ITRF94(1996.0). Replaced by NAD83(HARN) to WGS 84 (3) (code 1901).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.92,1,0,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
+107,1901,4152,4326,"Jointly derived by US NGS and Geodetic Survey of Canada as transformation to target CRS of ITRF96(1997.0) - see also tfm code 1946. In USA only replaces NAD83 to WGS 84 (2) (code 1900).","Geodesy. Accuracy with respect to CORS at stations adjusted to HARN network is better than 0.05-0.07m. For locations outside a HARN network (i.e. NAD83), accuracy may be only 1m but will usually be better than 0.5m.",1323,24.41,49.38,-124.79,-66.92,1,0,9607,-0.991,1.9072,0.5129,-0.02 [...]
+108,15930,4152,4326,"Accuracy 0.1 to 0.2m in California, 0.05-0.11 in Oregon, elsewhere better than 0.05m.",For applications to an accuracy of 0.2 metre.,1323,24.41,49.38,-124.79,-66.92,1,1,9603,0,0,0,,,,,0
+109,1512,4153,4326,"Derived in 1998 at Assaluyeh (Taheri refinery) by Geoid for Total. Used for South Pars phases 2 and 3.",Oil industry engineering survey. Used only for terminal site.,1338,27.4,27.6,52.5,52.7,1,0,9603,-133.63,-157.5,-158.62,,,,,1
+110,1141,4154,4326,"Given by DMA as from ED50. OGP interpret that as ED50(ED77) in Iran. Derived at 27 stations.","For military purposes. Accuracy 9m, 12m and 11m in X, Y and Z axes.",1123,23.35,39.78,44.03,63.33,1,0,9603,-117,-132,-164,,,,,1
+111,1514,4154,4326,"Used for South Pars phases 6, 7 and 8.","Transformation for whole country: accuracy about 1m.",1123,23.35,39.78,44.03,63.33,1,0,9606,-110.33,-97.73,-119.85,0.3423,1.1634,0.2715,0.063,0
+112,1856,4154,4326,Derived in Kangan district by Geoid for Total in 1998. Used for South Pars phases 2 and 3.,Petroleum Exploration and Production.,2783,26.59,26.71,52.07,52.27,1,0,9603,-122.89,-159.08,-168.74,,,,,0
+113,1857,4154,4326,Derived in 1999 on Lavan island by Geoid for Elf.,Petroleum Exploration and Production.,2782,26.22,26.86,52.5,53.43,1,0,9603,-84.78,-107.55,-137.25,,,,,0
+114,1858,4154,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Petroleum Exploration and Production.,2781,29.17,29.38,50.23,50.42,1,0,9603,-123.92,-155.515,-157.721,,,,,0
+115,15745,4154,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11.,Petroleum Exploration and Production.,3140,26.46,26.63,52.23,52.41,1,0,9603,-123.02,-158.95,-168.47,,,,,0
+116,1518,4155,4326,,Accuracy 25m in each axis.,3257,7.19,12.68,-15.13,-7.65,1,0,9603,-83,37,124,,,,,1
+117,1623,4156,4326,"Parameter values from S-JTSK to ETRS89 (1) (code 1622). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by S-JTSK to WGS 84 (5) (code 5239).",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9606,570.8,85.7,462.8,4.998,1.587,5.261,3.56,0
+118,1625,4156,4326,"Parameter values from S-JTSK to ETRS89 (2) (code 1624). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,1,9606,559,68.7,451.5,7.92,4.073,4.251,5.71,0
+119,4828,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,1,9606,485,169.5,483.5,7.786,4.398,4.103,0,0
+120,4836,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.74,49.6,16.84,22.56,1,0,9606,485,169.5,483.8,7.786,4.398,4.103,0,0
+121,5239,4156,4326,"Parameter values from S-JTSK/05 to WGS 84 (1) (code 5227). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,0
+122,15965,4156,4326,Derived at 6 stations.,"For military purposes. Accuracy 4m, 2m and 3m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,0,9603,589,76,480,,,,,1
+123,1283,4669,4326,,LKS94 is a realisation of ETRS89 coincident to WGS 84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1145,53.89,56.45,19.02,26.81,1,0,9603,0,0,0,,,,,1
+124,1099,4670,4326,"Parameter values taken from IGM95 to ETRS89 (1) (code 1098) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation.",Approximation at the 1m level.,3343,34.77,47.09,5.94,18.99,1,0,9603,0,0,0,,,,,1
+125,1859,4159,4326,"Used by Repsol in Murzuq field, and PetroCanada and previous licence holders in NC177 and 72 (En Naga field). Reliability of connection to ELD79 questionned.",Oil Exploration,2785,27.33,27.66,18.37,18.72,1,0,9603,-69.06,-90.71,-142.56,,,,,0
+126,1860,4159,4326,Derived December 2001 by NAGECO. Connected to ITRF via Remsa 2000 data. Used by TotalFinaElf.,Oil Exploration. 3-dimensional SD at 11 points is 0.5m.,2785,27.33,27.66,18.37,18.72,1,0,9603,-113.997,-97.076,-152.312,,,,,0
+127,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.62,30.06,17.14,17.5,1,0,9603,-114.5,-96.1,-151.9,,,,,0
+128,1862,4159,4326,"Derived by Geoid in 2000 from ITRF connection by NAGECO for TotalFinaElf. For historic compatibility TFE use the 1994 tfm ELD79 to WGS 84 (3) (code 1861) rather than this transformation.",Oil Exploration,2786,29.62,30.06,17.14,17.5,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
+129,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.62,30.06,17.14,17.5,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
+130,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
+131,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.58,1,0,9603,-114.7,-98.5,-150.7,,,,,0
+132,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.5,33.22,9.31,25.21,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
+133,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.79,22.5,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
+134,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-44.64,-43.31,-177.24,-175.55,1,0,9603,175,-38,113,,,,,1
+135,1081,4673,4326,Derived at 4 stations using concatenation through WGS72. Parameter vales are also used to transform CI1979 to NZGD2000 - see tfm code 1082.,For applications requiring 2m accuracy.,2889,-44.64,-43.31,-177.24,-175.55,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
+136,15894,4674,4326,,Accuracy 1m.,3418,-59.86,32.72,-122.18,-25.28,1,0,9603,0,0,0,,,,,1
+137,1070,4675,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,3255,13.19,13.7,144.58,145,1,0,9603,-100,-248,259,,,,,1
+138,1682,4164,4326,"Parameter values taken from South Yemen to Yemen NGN96 (1) (code 1539) assuming that NGN96 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 5m level.",1340,12.55,19,43.37,53.13,1,0,9603,-76,-138,67,,,,,1
+139,1547,4165,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3258,10.88,12.68,-16.76,-13.64,1,0,9603,-173,253,27,,,,,1
+140,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.93,22.5,100.09,107.7,1,0,9603,44.585,-131.212,-39.544,,,,,1
+141,1565,4167,4326,,Assumes NZGD2000 is coincident to WGS 84 to the 1m accuracy level.,1175,-55.95,-25.89,160.61,-171.2,1,0,9603,0,0,0,,,,,1
+142,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.4,11.16,-3.79,2.1,1,0,9603,-199,32,322,,,,,1
+143,15495,4168,4326,Derived via WGS 72BE. Found in use within oil industry erroneously concatenated via WGS 72. See tfm code 8571.,Oil industry.,1505,1.4,6.06,-3.79,2.1,1,0,9606,-171.16,17.29,325.21,0,0,0.814,-0.38,0
+144,1577,4169,4326,Transformation based on observations at 2 stations in 1993.,For military purposes. One sigma uncertainty is 25m in each axis.,3109,-14.43,-14.12,-170.87,-169.39,1,0,9603,-115,118,426,,,,,1
+145,1581,4170,4326,,For military purposes. Accuracy 1m in each axis.,3448,-59.86,16.75,-113.2,-26.01,1,0,9603,0,0,0,,,,,1
+146,1671,4171,4326,"Parameter values from RGF93 to ETRS89 (1) (code 1591) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1096,41.15,51.56,-9.86,10.38,1,0,9603,0,0,0,,,,,1
+147,1598,4172,4326,,"?",1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,0,0,0,,,,,0
+148,1678,4173,4326,Assumes that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. IRENET95 is a regional realisation of ETRS89.,"Approximation at the +/- 1m level.",1305,51.4,55.43,-10.56,-5.35,1,0,9603,0,0,0,,,,,1
+149,15738,4686,4326,,MAGNA-SIRGAS is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1070,-4.24,15.5,-84.77,-66.87,1,0,9603,0,0,0,,,,,1
+150,1614,4175,4326,"Determined at 8 stations. Info. source has the source CRS as Sierra Leone 1960. Sierra Leone 1968 is a readjustment of the 1960 network: coordinates changed by less than 3 metres.","Accuracy +/- 15m in each axis.",3306,6.88,10,-13.34,-10.26,1,0,9603,-88,4,101,,,,,1
+151,1890,4176,4326,For many purposes Australian Antarctic can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that Australian Antarctic is equivalent to WGS 84.",1278,-90,-60,45,160,1,0,9603,0,0,0,,,,,1
+152,15773,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (1) (tfm code 15761).","Accuracy +/- 1 metre.",3131,-9.88,-9.65,-139.22,-138.76,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
+153,15774,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (2) (tfm code 15762).","Accuracy +/- 2 metres.",3132,-10.07,-9.87,-139.19,-138.98,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
+154,1675,4178,4326,"Parameter values from Pulkovo 1942(83) to ETRS89 (1) (code 1674) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Residuals under 2 m.,1343,50.2,54.73,9.92,15.03,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
+155,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.75,48.58,16.11,22.89,1,0,9603,28,-121,-77,,,,,0
+156,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
+157,1645,4179,4326,"Parameter values from Pulkovo 1942(58) to ETRS89 (1) (code 1644). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3293,49,54.89,14.15,24.14,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
+158,15496,4179,4326,,Oil exploration,1197,43.45,48.26,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
+159,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
+160,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.45,48.26,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
+161,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.15,24.14,1,0,9603,23,-124,-82,,,,,0
+162,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.66,19.22,21.05,1,0,9603,24,-130,-92,,,,,0
+163,1649,4180,4326,"Parameter values taken from EST97 to ETRS89 (1) (code 1648). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1090,57.52,59.99,20.37,28.19,1,0,9603,0,0,0,,,,,1
+164,1643,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (1) (code 1642). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1146,49.45,50.18,5.73,6.52,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,0
+165,5486,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (3) (code 5485) assuming ETRS89 and WGS 84 are coincident within the one metre level. Replaces tfm code 1643. For an equivalent transformation using the Molodensky-Badekas method see code 5484.",For applications to an accuracy of 1 metre.,1146,49.45,50.18,5.73,6.52,1,0,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598,1
+166,1210,4694,4326,,POSGAR 94 is a local realisation of WGS 84.,1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
+167,1886,4183,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-104,167,-38,,,,,1
+168,1885,4184,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1345,36.88,37.96,-25.91,-24.62,1,0,9603,-203,141,53,,,,,1
+169,15794,4708,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1069,-12.25,-12.08,96.77,96.92,1,0,9603,-491,-22,435,,,,,1
+170,15850,4698,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,0,9603,145,-187,103,,,,,1
+171,15784,4699,4326,Derived at 17 stations in 1994 by University of East London. Residuals less than 2m.,Accuracy 2m.,3209,-20.57,-19.94,57.25,57.85,1,0,9603,-770.1,158.4,-498.2,,,,,1
+172,1955,4188,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) OSNI 1952 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,2530,53.96,55.35,-8.17,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+173,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.65,16.75,-73.38,-58.95,1,0,9603,0,0,0,,,,,1
+174,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
+175,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,0,0,0,,,,,0
+176,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.17,4.98,8.45,10.39,1,0,9603,-206.1,-174.7,-87.7,,,,,1
+177,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.17,4.98,8.45,10.39,1,0,9603,-70.9,-151.8,-41.4,,,,,1
+178,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.28,-42.52,1,0,9603,164,138,-189,,,,,1
+179,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.28,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
+180,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.68,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
+181,1800,4196,4326,,Topographic mapping.,2571,65.52,65.9,-38.86,-36.82,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
+182,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.68,24.88,141.21,141.42,1,0,9603,145,75,-272,,,,,1
+183,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.07,-15.85,-5.84,-5.6,1,0,9603,-320,550,-494,,,,,1
+184,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.23,24.35,153.92,154.05,1,0,9603,124,-234,-25,,,,,1
+185,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
+186,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
+187,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.41,22.23,21.83,47.99,1,0,9603,-166,-15,204,,,,,1
+188,1101,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.4,15.08,-5.52,2.4,1,0,9603,-118,-14,218,,,,,0
+189,1102,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.08,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
+190,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.41,14.88,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
+191,1104,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25,-12.24,4.25,1,0,9603,-123,-20,220,,,,,0
+192,1105,4201,4326,"Derived at 2 stations connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.3,16.69,-17.58,-11.37,1,0,9603,-128,-18,224,,,,,0
+193,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.23,21.83,38.66,1,0,9603,-161,-14,205,,,,,0
+194,1108,4202,4326,Derived at 105 stations.,For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-133,-48,148,,,,,0
+195,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.92,-35.13,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
+196,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.16,140.96,153.68,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
+197,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.54,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
+198,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26,-10.86,129,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
+199,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.6,142.24,144.74,1,0,9603,-124,-60,154,,,,,0
+200,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-127.8,-52.3,152.9,,,,,0
+201,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.19,-8.88,109.23,163.19,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
+202,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-134,-48,149,,,,,1
+203,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.87,112.85,153.68,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
+204,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
+205,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,-128.5,-53,153.4,,,,,0
+206,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-145.7,-249.1,1.5,,,,,0
+207,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
+208,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.08,46.55,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
+209,1058,4204,4326,,1 metre accuracy.,2957,28.54,29.44,46.55,48.47,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
+210,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.54,26.34,50.4,50.84,1,0,9603,-150,-250,-1,,,,,0
+211,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.62,32.15,34.52,55.67,1,0,9603,-143,-236,7,,,,,1
+212,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.46,1,0,9603,-43,-163,45,,,,,1
+213,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.85,-7.52,156.45,158.19,1,0,9603,230,-199,-752,,,,,1
+214,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.21,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
+215,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.96,42.15,-9.55,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
+216,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.96,42.15,-9.55,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
+217,1984,4207,4326,,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
+218,1988,4207,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
+219,1549,4208,4326,,Oil exploration.,2307,-28.4,-17.59,-48.79,-35.19,1,1,9603,-158,315,-148,,,,,0
+220,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.4,-39.03,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
+221,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.6,-9.8,-39.13,-38,1,0,9603,-141.15,293.44,-150.56,,,,,0
+222,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.26,-10.6,-39.07,-37.99,1,0,9603,-142.48,296.03,-149.74,,,,,0
+223,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.4,-22.67,-48.79,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
+224,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-170,305,-145,,,,,0
+225,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-162.904,312.531,-137.109,,,,,0
+226,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.12,-53.37,-44.71,1,0,9603,-158,309,-151,,,,,0
+227,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.37,-35.2,1,0,9603,-161,308,-142,,,,,0
+228,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.9,18.25,-16.1,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
+229,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.67,-53.37,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
+230,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
+231,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-161.11,310.25,-144.64,,,,,0
+232,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.02,-39.21,-34.61,1,0,9603,-160.4,302.29,-144.19,,,,,0
+233,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.19,-39.08,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
+234,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.26,-8.4,-39.13,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
+235,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.57,-8.73,-37.33,-32.02,1,0,9603,-156.8,298.41,-147.41,,,,,0
+236,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.16,-4.61,-35.09,-29.14,1,0,9603,-157.4,295.05,-150.19,,,,,0
+237,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.25,-44.79,-26.01,1,0,9603,-151.99,287.04,-147.45,,,,,1
+238,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.03,-37.11,1,0,9603,-160,315,-142,,,,,0
+239,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.4,-22.67,-48.79,-40.2,1,0,9603,-158,309,-147,,,,,0
+240,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.19,1,0,9603,-161,310,-145,,,,,0
+241,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.4,-17.59,-48.79,-35.19,1,0,9603,-158,315,-148,,,,,0
+242,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.65,-8.19,20,35.92,1,0,9603,-143,-90,-294,,,,,1
+243,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,20,29.37,1,0,9603,-138,-105,-289,,,,,0
+244,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.85,1,1,9603,-153,-5,-292,,,,,0
+245,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.65,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
+246,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.38,32.68,35.92,1,0,9603,-161,-73,-317,,,,,0
+247,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.73,30.8,32.13,1,0,9603,-134,-105,-295,,,,,0
+248,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.38,11.8,31.3,1,1,9603,-169,-19,-278,,,,,0
+249,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.07,-8.19,22,33.7,1,0,9603,-147,-74,-283,,,,,0
+250,1121,4209,4326,Derived at 10 stations.,"For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.41,-15.62,25.24,33.07,1,0,9603,-142,-96,-293,,,,,0
+251,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.74,4.62,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
+252,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.62,33.91,41.91,1,0,9603,-157,-2,-299,,,,,0
+253,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.74,-1,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
+254,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.85,1,0,9603,-153,-5,-292,,,,,0
+255,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.98,5.96,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
+256,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.88,-4.08,105.78,110,1,0,9603,-378.873,676.002,-46.255,,,,,0
+257,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.81,117,1,0,9603,-377.7,675.1,-52.2,,,,,0
+258,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.38,1,0,9603,31.95,300.99,419.19,,,,,1
+259,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.78,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
+260,6143,4726,4326,"Parameter values are taken from SIGD59 to CIGD11 (1) (code 6137) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3186,19.64,19.78,-80.13,-79.69,1,0,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081,1
+261,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.64,19.78,-80.13,-79.69,1,0,9603,42,124,147,,,,,0
+262,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.64,19.78,-80.13,-79.69,1,0,9603,44.4,109,151.7,,,,,0
+263,15800,4713,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.71,41.76,44.15,1,0,9603,-79,-129,145,,,,,1
+264,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.88,-64.62,1,0,9603,-73,213,296,,,,,1
+265,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.88,-64.62,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
+266,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.13,-25.01,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
+267,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.24,13.67,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
+268,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.67,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
+269,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.51,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.4142185637707,-2.99084175323096,-39.0346863906349,-20.81616,0
+270,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.4,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.22383004903209,2.42380329967319,-8.30827832824698,-13.56561,0
+271,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.4,1,0,9607,336.026,348.565,252.978,-17.2412894390071,-6.30649282215535,1.56204977191825,-5.771909,0
+272,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-72,1,0,9607,963.273,486.386,190.997,-16.4850360280866,-1.66882584284416,21.6928490465265,-13.89914,0
+273,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8,-77.91,-74.4,1,0,9607,-90.29,247.559,-21.989,-8.69688534851263,-4.18803362841004,-12.8082668496251,2.181658,0
+274,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5,-77.67,-74.4,1,0,9607,-0.562,244.299,-456.938,6.8668709851194,-8.25267346177889,-9.2967797230575,3.74656,0
+275,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.12,3,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.69049385992583,1.03196819622539,-19.7573941768278,6.325747,0
+276,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.24,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.80844591036278,-0.44850858891268,-2.81017234679107,-2.199943,0
+277,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.34,1,0,9603,-384,664,-48,,,,,1
+278,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.58,-7.75,12.58,13.39,1,0,9603,-42.01,-332.21,-229.75,,,,,0
+279,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7,-6.01,12.08,12.83,1,0,9603,-40,-354,-224,,,,,0
+280,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.25,-6.03,11.08,12.08,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
+281,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.25,-6.01,8.2,13.85,1,0,9603,-41.8,-342.2,-228.2,,,,,0
+282,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.33,-6.67,11.75,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
+283,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.08,-9.42,12.66,13.38,1,0,9603,-43,-337,-233,,,,,0
+284,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.08,-6.03,10.83,13.38,1,0,9603,-48,-345,-231,,,,,0
+285,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7,-6.01,12.08,12.83,1,0,9603,-48.6,-345.1,-230.8,,,,,0
+286,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.33,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
+287,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.58,-6.01,10.41,12.83,1,0,9603,-50.9,-347.6,-231,,,,,1
+288,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.92,-21.78,-73.58,-53.65,1,0,9603,-148,136,90,,,,,1
+289,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.15,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
+290,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.87,-22.14,16.45,32.94,1,0,9603,-136,-108,-292,,,,,1
+291,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.87,-22.14,16.45,32.94,1,0,9603,-134.73,-110.92,-292.66,,,,,0
+292,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.4,7.49,13.66,1,0,9603,-263,6,431,,,,,1
+293,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.4,7.82,13.66,1,0,9603,-260.1,5.5,432.2,,,,,0
+294,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.3,-62.56,-57.81,1,0,9603,-134,229,-29,,,,,1
+295,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.38,-48.09,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,0
+296,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.38,-48.09,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
+297,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,1
+298,6192,4225,4326,"Formed by concatenation of tfms codes 6191 and 1877. Used by Petrobras and ANP until February 2005 when replaced by Corrego Alegre 1970-72 to WGS 84 (4) (tfm code 6194).",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-205.57,168.77,-4.12,,,,,0
+299,6194,4225,4326,"Parameter values from Corrego Alegre to SIRGAS 2000 (2) (tfm code 6193) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras from February 2005, replacing use of tfm code 6192.",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206.05,168.28,-3.82,,,,,0
+300,1585,4227,4326,,"?",1227,32.31,37.29,34.97,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
+301,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.4,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
+302,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.8,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
+303,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.5,35.9,39.3,40.8,1,0,9603,-187.5,14.1,237.6,,,,,0
+304,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.29,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
+305,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.5,35.9,39.3,40.8,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
+306,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.88,85.19,18.93,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
+307,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
+308,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.9,33.81,24.71,37.91,1,0,9603,-130,110,-13,,,,,1
+309,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.2,30,32.34,34.26,1,1,9603,-146.21,112.63,4.05,,,,,0
+310,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.36,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
+311,1087,4230,4326,,Topographic mapping.,1130,29.19,33.38,34.88,39.3,1,0,9603,-112,-110.3,-140.2,,,,,0
+312,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.2,-9.55,31.58,1,0,9603,-87,-98,-121,,,,,1
+313,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
+314,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.62,37.38,34.18,55.67,1,0,9603,-103,-106,-141,,,,,0
+315,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.19,1,0,9603,-104,-101,-140,,,,,0
+316,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.67,24.71,30,1,0,9603,-130,-117,-151,,,,,0
+317,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.12,60.89,-10.56,1.83,1,0,9603,-86,-96,-120,,,,,0
+318,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.94,71.2,4.69,31.58,1,0,9603,-87,-95,-120,,,,,0
+319,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.58,28.3,1,0,9603,-84,-95,-130,,,,,0
+320,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.83,41.3,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
+321,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.6,38.35,12.37,15.7,1,0,9603,-97,-88,-135,,,,,0
+322,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.75,36.04,14.28,14.62,1,0,9603,-107,-88,-149,,,,,0
+323,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.81,-9.55,3.39,1,0,9603,-84,-107,-120,,,,,0
+324,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.4,7.49,13.66,1,0,9603,-112,-77,-145,,,,,0
+325,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
+326,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
+327,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.58,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
+328,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.16,-3.7,39.64,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
+329,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.09,62,1.37,11.13,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
+330,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
+331,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36.01,36.16,-5.41,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
+332,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.15,4.38,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
+333,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.53,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
+334,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.81,-9.36,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
+335,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.43,43.45,25.62,44.82,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
+336,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.67,24.71,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
+337,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.75,-12.5,-9.5,1,0,9603,-82.31,-95.23,-114.96,,,,,0
+338,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.43,55.77,2.54,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
+339,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
+340,1989,4230,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
+341,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.35,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
+342,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.43,55.77,2.54,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+343,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.43,55.77,2.54,6.4,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,0
+344,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.92,41.87,-13.86,-7.25,1,0,9603,-86.277,-108.879,-120.181,,,,,0
+345,1146,4231,4326,,"?",2330,51.04,62,-5.05,11.13,1,0,9606,-82.981,-99.719,-110.709,-0.104700015651026,0.0310016003789386,0.0804020214751182,-0.3143,0
+346,1960,4231,4326,,Scientific research.,1297,34.88,71.2,-10.56,31.58,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+347,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.2,-10.56,31.58,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,1
+348,1256,4232,4326,Derived at 7 stations.,"For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.6,26.41,52,59.9,1,0,9603,-346,-1,224,,,,,1
+349,1438,4232,4326,,Oil exploration.,4009,16.6,26.41,52,59.9,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,0
+350,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.09,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
+351,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.27,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
+352,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.27,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
+353,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.88,25.33,119.26,122.05,1,0,9603,-637,-549,-203,,,,,1
+354,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.75,48.58,16.11,22.89,1,0,9603,52.17,-71.82,-14.9,,,,,1
+355,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.75,48.58,16.11,22.89,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
+356,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.75,48.58,16.11,22.89,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
+357,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.75,48.58,16.11,22.89,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
+358,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.75,48.58,16.11,22.89,1,0,9603,57.01,-69.97,-9.29,,,,,0
+359,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.96,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
+360,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.96,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
+361,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.96,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
+362,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.45,97.35,105.64,1,0,9603,217,823,299,,,,,1
+363,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.45,97.35,105.64,1,0,9603,209,818,290,,,,,0
+364,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.45,97.35,105.64,1,0,9603,210,814,289,,,,,1
+365,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.75,8.15,102.16,103.04,1,0,9603,204.64,834.74,293.8,,,,,0
+366,1812,4240,4326,,Cadastral survey.,3317,5.63,20.45,97.35,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
+367,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
+368,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
+369,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
+370,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
 Note: Info source paper contains an error in sign of dS, subsequently confirmed by primary author and NLA of Jamaica, and corrected in this record.",For applications requiring 1m accuracy.,3342,17.65,18.57,-78.43,-76.17,1,0,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,8.95,0
-367,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.72,-22.49,167.37,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
-368,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.72,-22.49,167.37,167.61,1,0,9603,-13,-348,292,,,,,1
-369,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.87,9.88,79.65,81.94,1,0,9603,-97,787,86,,,,,1
-370,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",1309,1.13,6.71,99.59,104.6,1,0,9603,-11,851,5,,,,,1
-371,1059,4246,4326,,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-294.7,-200.1,525.5,,,,,1
-372,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
-373,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.51,-81.4,-56.47,1,0,9603,-288,175,-376,,,,,1
-374,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
-375,1203,4248,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2402,-21.5,-17.51,-70.48,-68.19,1,0,9603,-270,183,-390,,,,,0
-376,1204,4248,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2403,-45,-39,-75.22,-71.11,1,0,9603,-305,243,-442,,,,,0
-377,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.24,12.51,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
-378,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5,1.45,-81.03,-75.22,1,0,9603,-278,171,-367,,,,,0
-379,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.19,10.69,-61.39,-55.78,1,0,9603,-298,159,-369,,,,,0
-380,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.04,-84.67,-68.67,1,0,9603,-279,175,-379,,,,,0
-381,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.65,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
-382,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.57,-68.95,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
-383,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.7,-21.09,-63.43,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
-384,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.59,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
-385,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5,1.45,-81.03,-75.22,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
-386,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13.01,19.43,1,0,9603,0,0,0,,,,,1
-387,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
-388,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.51,-11.51,-7.37,1,0,9603,-90,40,88,,,,,1
-389,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.76,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
-390,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.76,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
-391,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.76,19.44,116.9,125.87,1,0,9603,-133,-77,-51,,,,,1
-392,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,5,10.52,119.77,126.65,1,0,9603,-133,-79,-72,,,,,0
-393,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.1,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
-394,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.95,-52.4,-74.82,-66.34,1,0,9603,16,196,93,,,,,1
-395,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.41,38.47,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
-396,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.84,-4.51,55.33,55.59,1,0,9603,41,-220,-134,,,,,1
-397,1837,4257,4326,,Oil exploration.,1316,-6.53,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
-398,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.16,-16.1,39.64,1,0,9603,0,0,0,,,,,1
-399,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.54,7.21,1,1,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-400,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
-401,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
-402,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
-403,1316,4260,4326,,"?",1060,1.65,13.08,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
-404,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.23,-1.01,1,0,9603,31,146,47,,,,,1
-405,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.09,36.44,43.3,1,0,9603,639,405,60,,,,,1
-406,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.25,5.54,4.42,6.28,1,0,9603,-92.1,-89.9,114.9,,,,,0
-407,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.08,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
-408,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.89,2.67,14.65,1,0,9603,-92,-93,122,,,,,1
-409,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.36,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-410,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.36,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-411,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.67,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
-412,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.36,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-413,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.02,6.95,1,0,9603,-93.2,-93.31,121.156,,,,,0
-414,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.5,7.17,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
-415,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.3,3.84,5.16,1,0,9603,-92.726,-90.304,115.735,,,,,0
-416,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.25,3.85,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
-417,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.12,1,0,9603,-93,-94,124,,,,,0
-418,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,4,5,6,8,1,0,9603,-94.031,-83.317,116.708,,,,,0
-419,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.22,5.03,7.3,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
-420,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.67,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
-421,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.35,6.54,6.83,1,0,9603,-90.2,-87.32,114.17,,,,,0
-422,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.03,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
-423,1088,4265,4326,,Oil exploration and production,2882,43.63,45.73,12.23,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
-424,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.13,1,0,9603,-225.4,-67.7,7.85,,,,,0
-425,1090,4265,4326,,Oil exploration and production,2884,40.73,42.28,15.96,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
-426,1091,4265,4326,,Marine navigation,2885,39.78,41.02,17.96,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
-427,1092,4265,4326,,Marine navigation,2886,37.68,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
-428,1093,4265,4326,,Marine navigation,2887,35.23,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
-429,1094,4265,4326,,Marine navigation,2888,35.29,38.44,10.69,13,1,0,9603,-230.47,-56.08,22.43,,,,,0
-430,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.83,41.3,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
-431,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.87,47.09,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
-432,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.83,41.3,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
-433,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.6,38.35,12.37,15.7,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
-434,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
-435,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
-436,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.24,-85.01,-59.38,1,0,9603,-3,142,183,,,,,0
-437,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
-438,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.45,-141,-47.74,1,0,9603,-10,158,187,,,,,1
-439,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.92,1,0,9603,-8,160,176,,,,,0
-440,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.92,1,0,9603,-9,161,179,,,,,0
-441,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.84,49.05,-124.79,-89.65,1,0,9603,-8,159,175,,,,,0
-442,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.35,71.4,-168.25,-129.99,1,0,9603,-5,135,172,,,,,0
-443,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.87,27.29,-79.03,-72.69,1,0,9603,-4,154,178,,,,,0
-444,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.91,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
-445,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
-446,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.68,60,-102,-74.36,1,0,9603,-9,157,184,,,,,0
-447,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.42,62.61,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
-448,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.16,-136.45,-60.73,1,0,9603,4,159,188,,,,,0
-449,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,60,69.7,-141,-123.91,1,0,9603,-7,139,181,,,,,0
-450,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.44,-80.06,-79.47,1,0,9603,0,125,201,,,,,0
-451,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.24,-85.01,-74.08,1,0,9603,-9,152,178,,,,,0
-452,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.19,-73.28,-60.99,1,0,9603,11,114,195,,,,,0
-453,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.52,32.72,-118.46,-86.69,1,0,9603,-12,130,190,,,,,0
-454,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
-455,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.06,172.43,179.85,1,0,9603,2,204,105,,,,,0
-456,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.5,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
-457,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.76,1,0,9603,-2,124.7,196,,,,,0
-458,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
-459,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.62,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
-460,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.98,28.96,-97.21,-95,1,0,9603,-7,151,178,,,,,0
-461,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
-462,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.21,-81.17,1,0,9603,-7,158,172,,,,,0
-463,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.88,23,-94.32,-88.68,1,0,9603,0,125,196,,,,,0
-464,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.5,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
-465,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.82,86.45,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
-466,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.43,-164.84,1,0,9603,-2,0,4,,,,,0
-467,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.28,1,0,9603,1,1,-1,,,,,0
-468,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.92,1,1,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-469,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.92,1,1,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
-470,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59,1,0,9603,-247,-148,369,,,,,0
-471,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.96,50.8,1,0,9603,-243,-192,477,,,,,0
-472,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.26,51.51,57.13,1,0,9603,-249,-156,381,,,,,0
-473,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.53,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
-474,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.04,50.56,53.03,1,0,9603,-250.2,-153.09,391.7,,,,,0
-475,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.38,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
-476,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.51,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
-477,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.51,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
-478,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.95,25.79,54.07,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
-479,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.33,54.85,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
-480,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.89,-60.47,1,0,9603,-10,375,165,,,,,1
-481,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.89,-60.47,1,0,9603,-2,374,172,,,,,0
-482,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.64,-33.9,165.87,179.26,1,0,9603,84,-22,209,,,,,0
-483,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.64,-33.9,165.87,179.26,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
-484,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.64,-33.9,165.87,179.26,1,0,9603,54.4,-20.1,183.1,,,,,0
-485,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.94,71.2,4.69,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
-486,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.96,42.15,-9.55,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
-487,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.96,42.15,-9.55,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
-488,1983,4274,4326,,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
-489,1987,4274,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
-490,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
-491,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.81,60.89,-8.73,1.83,1,0,9603,375,-111,431,,,,,0
-492,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.49,1.83,1,0,9603,371,-112,434,,,,,0
-493,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.49,1.83,1,0,9603,371,-111,434,,,,,0
-494,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.58,60.89,-8.73,-0.66,1,0,9603,384,-111,425,,,,,0
-495,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.47,-5.34,-2.66,1,0,9603,370,-108,434,,,,,0
-496,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.81,60.89,-8.73,1.83,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
-497,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.54,50.8,-2.19,-1.69,1,0,9603,370.396,-108.938,435.682,,,,,0
-498,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,0,9603,0,0,0,,,,,1
-499,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.27,34.18,35.68,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
-500,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.71,8.85,18.64,1,0,9603,-148,51,-291,,,,,1
-501,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.85,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
-502,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.85,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
-503,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,0,0,0,,,,,1
-504,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.88,85.19,18.93,-168.97,1,0,9603,28,-130,-95,,,,,0
-505,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.88,85.19,18.93,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
-506,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.75,48.58,16.11,22.89,1,1,9603,28,-121,-77,,,,,0
-507,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.92,14.15,24.14,1,1,9603,23,-124,-82,,,,,0
-508,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
-509,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.08,19.07,28.24,1,0,9603,24,-124,-82,,,,,0
-510,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.44,46.5,87.35,1,0,9603,15,-130,-84,,,,,0
-511,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.64,42.66,18.46,21.05,1,1,9603,24,-130,-92,,,,,0
-512,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-513,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.16,46.96,48.91,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
-514,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.19,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
-515,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.81,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
-516,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
+371,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.72,-22.49,167.37,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
+372,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.72,-22.49,167.37,167.61,1,0,9603,-13,-348,292,,,,,1
+373,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.87,9.88,79.65,81.94,1,0,9603,-97,787,86,,,,,1
+374,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",1309,1.13,6.71,99.59,104.6,1,0,9603,-11,851,5,,,,,1
+375,1059,4246,4326,,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-294.7,-200.1,525.5,,,,,1
+376,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
+377,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.51,-81.4,-56.47,1,0,9603,-288,175,-376,,,,,1
+378,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
+379,1203,4248,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2402,-21.5,-17.51,-70.48,-68.19,1,0,9603,-270,183,-390,,,,,0
+380,1204,4248,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2403,-45,-39,-75.22,-71.11,1,0,9603,-305,243,-442,,,,,0
+381,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.24,12.51,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
+382,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5,1.45,-81.03,-75.22,1,0,9603,-278,171,-367,,,,,0
+383,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.19,10.69,-61.39,-55.78,1,0,9603,-298,159,-369,,,,,0
+384,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.04,-84.67,-68.67,1,0,9603,-279,175,-379,,,,,0
+385,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.65,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
+386,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.57,-68.95,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
+387,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.7,-21.09,-63.43,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
+388,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.59,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
+389,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5,1.45,-81.03,-75.22,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
+390,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13.01,19.43,1,0,9603,0,0,0,,,,,1
+391,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
+392,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.51,-11.51,-7.37,1,0,9603,-90,40,88,,,,,1
+393,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.76,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
+394,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.76,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
+395,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.76,19.44,116.9,125.87,1,0,9603,-133,-77,-51,,,,,1
+396,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,5,10.52,119.77,126.65,1,0,9603,-133,-79,-72,,,,,0
+397,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.1,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
+398,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.95,-52.4,-74.82,-66.34,1,0,9603,16,196,93,,,,,1
+399,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.41,38.47,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
+400,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.84,-4.51,55.33,55.59,1,0,9603,41,-220,-134,,,,,1
+401,1837,4257,4326,,Oil exploration.,1316,-6.53,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
+402,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.16,-16.1,39.64,1,0,9603,0,0,0,,,,,1
+403,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.54,7.21,1,1,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
+404,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
+405,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
+406,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.03,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
+407,1316,4260,4326,,"?",1060,1.65,13.08,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
+408,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.23,-1.01,1,0,9603,31,146,47,,,,,1
+409,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.09,36.44,43.3,1,0,9603,639,405,60,,,,,1
+410,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.25,5.54,4.42,6.28,1,0,9603,-92.1,-89.9,114.9,,,,,0
+411,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.08,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
+412,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.89,2.67,14.65,1,0,9603,-92,-93,122,,,,,1
+413,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.36,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+414,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.36,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+415,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.67,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
+416,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.36,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+417,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.02,6.95,1,0,9603,-93.2,-93.31,121.156,,,,,0
+418,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.5,7.17,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
+419,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.3,3.84,5.16,1,0,9603,-92.726,-90.304,115.735,,,,,0
+420,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.25,3.85,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
+421,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.12,1,0,9603,-93,-94,124,,,,,0
+422,6196,4263,4326,Used by Addax for OPL 118 and OML 124. Derived in 1999 at 4 stations during  extension into OPL 118 of control in Chevron block OML 53.,Oil industry exploration and production.,4127,5.5,5.8,6.7,7,1,0,9603,-93.179,-87.124,114.338,,,,,0
+423,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,4,5,6,8,1,0,9603,-94.031,-83.317,116.708,,,,,0
+424,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.22,5.03,7.3,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
+425,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.67,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
+426,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.35,6.54,6.83,1,0,9603,-90.2,-87.32,114.17,,,,,0
+427,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.03,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
+428,1088,4265,4326,,Oil exploration and production,2882,43.63,45.73,12.23,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
+429,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.13,1,0,9603,-225.4,-67.7,7.85,,,,,0
+430,1090,4265,4326,,Oil exploration and production,2884,40.73,42.28,15.96,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
+431,1091,4265,4326,,Marine navigation,2885,39.78,41.02,17.96,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
+432,1092,4265,4326,,Marine navigation,2886,37.68,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
+433,1093,4265,4326,,Marine navigation,2887,35.23,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
+434,1094,4265,4326,,Marine navigation,2888,35.29,38.44,10.69,13,1,0,9603,-230.47,-56.08,22.43,,,,,0
+435,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.83,41.3,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
+436,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.87,47.09,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
+437,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.83,41.3,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
+438,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.6,38.35,12.37,15.7,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
+439,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
+440,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
+441,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.24,-85.01,-59.38,1,0,9603,-3,142,183,,,,,0
+442,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
+443,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.45,-141,-47.74,1,0,9603,-10,158,187,,,,,1
+444,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.92,1,0,9603,-8,160,176,,,,,0
+445,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.92,1,0,9603,-9,161,179,,,,,0
+446,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.84,49.05,-124.79,-89.65,1,0,9603,-8,159,175,,,,,0
+447,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.35,71.4,-168.25,-129.99,1,0,9603,-5,135,172,,,,,0
+448,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.87,27.29,-79.03,-72.69,1,0,9603,-4,154,178,,,,,0
+449,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.91,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
+450,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
+451,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.68,60,-102,-74.36,1,0,9603,-9,157,184,,,,,0
+452,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.42,62.61,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
+453,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.16,-136.45,-60.73,1,0,9603,4,159,188,,,,,0
+454,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,60,69.7,-141,-123.91,1,0,9603,-7,139,181,,,,,0
+455,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.44,-80.06,-79.47,1,0,9603,0,125,201,,,,,0
+456,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.24,-85.01,-74.08,1,0,9603,-9,152,178,,,,,0
+457,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.19,-73.28,-60.99,1,0,9603,11,114,195,,,,,0
+458,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.52,32.72,-118.46,-86.69,1,0,9603,-12,130,190,,,,,0
+459,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
+460,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.06,172.43,179.85,1,0,9603,2,204,105,,,,,0
+461,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.5,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
+462,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.76,1,0,9603,-2,124.7,196,,,,,0
+463,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
+464,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.62,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
+465,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.98,28.96,-97.21,-95,1,0,9603,-7,151,178,,,,,0
+466,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
+467,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.21,-81.17,1,0,9603,-7,158,172,,,,,0
+468,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.88,23,-94.32,-88.68,1,0,9603,0,125,196,,,,,0
+469,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.5,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
+470,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.82,86.45,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
+471,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.43,-164.84,1,0,9603,-2,0,4,,,,,0
+472,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.28,1,0,9603,1,1,-1,,,,,0
+473,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.92,1,1,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
+474,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.92,1,1,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
+475,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59,1,0,9603,-247,-148,369,,,,,0
+476,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.96,50.8,1,0,9603,-243,-192,477,,,,,0
+477,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.26,51.51,57.13,1,0,9603,-249,-156,381,,,,,0
+478,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.53,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
+479,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.04,50.56,53.03,1,0,9603,-250.2,-153.09,391.7,,,,,0
+480,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.38,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
+481,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.51,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
+482,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.51,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
+483,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.95,25.79,54.07,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
+484,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.33,54.85,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
+485,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.89,-60.47,1,0,9603,-10,375,165,,,,,1
+486,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.89,-60.47,1,0,9603,-2,374,172,,,,,0
+487,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.64,-33.9,165.87,179.26,1,0,9603,84,-22,209,,,,,0
+488,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.64,-33.9,165.87,179.26,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
+489,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.64,-33.9,165.87,179.26,1,0,9603,54.4,-20.1,183.1,,,,,0
+490,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.94,71.2,4.69,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
+491,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.96,42.15,-9.55,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
+492,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.96,42.15,-9.55,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
+493,1983,4274,4326,,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
+494,1987,4274,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
+495,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
+496,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.81,60.89,-8.73,1.83,1,0,9603,375,-111,431,,,,,0
+497,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.49,1.83,1,0,9603,371,-112,434,,,,,0
+498,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.49,1.83,1,0,9603,371,-111,434,,,,,0
+499,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.58,60.89,-8.73,-0.66,1,0,9603,384,-111,425,,,,,0
+500,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.47,-5.34,-2.66,1,0,9603,370,-108,434,,,,,0
+501,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.81,60.89,-8.73,1.83,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
+502,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.54,50.8,-2.19,-1.69,1,0,9603,370.396,-108.938,435.682,,,,,0
+503,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,0,9603,0,0,0,,,,,1
+504,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.27,34.18,35.68,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
+505,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.71,8.85,18.64,1,0,9603,-148,51,-291,,,,,1
+506,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.85,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
+507,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.85,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
+508,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.87,112.85,153.68,1,0,9603,0,0,0,,,,,1
+509,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.88,85.19,18.93,-168.97,1,0,9603,28,-130,-95,,,,,0
+510,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.88,85.19,18.93,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
+511,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.75,48.58,16.11,22.89,1,1,9603,28,-121,-77,,,,,0
+512,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.92,14.15,24.14,1,1,9603,23,-124,-82,,,,,0
+513,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.74,51.05,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
+514,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.08,19.07,28.24,1,0,9603,24,-124,-82,,,,,0
+515,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.44,46.5,87.35,1,0,9603,15,-130,-84,,,,,0
+516,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.64,42.66,18.46,21.05,1,1,9603,24,-130,-92,,,,,0
+517,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+518,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.16,46.96,48.91,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
+519,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.19,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
+520,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.81,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
+521,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
 Do not confuse with AIOC95 vertical datum as used in southern Caspian Sea and at Sangachal terminal by AIOC.",Oil industry operations by AIOC prior to 1997.,1038,37.9,42.58,44.78,51.73,1,0,9606,27,-135,-84.5,0,0,0.554,0.2263,0
-517,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.9,43.58,40,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
-518,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.39,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
-519,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.88,85.19,18.93,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
-520,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.15,81.9,19.58,-168.98,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
-521,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.56,26.2,50.7,51.67,1,0,9603,-128,-283,22,,,,,0
-522,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.04,50.56,53.03,1,0,9603,-128.16,-282.42,21.93,,,,,1
-523,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.56,26.2,50.7,51.67,1,0,9603,-128.033,-283.697,21.052,,,,,0
-524,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
-525,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.69,3.21,7.21,1,0,9606,593.16,26.15,478.54,-1.30439800822601,-0.103297414968546,-1.14450153042326,4.0775,0
-526,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-527,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725,1
-528,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.2369,50.0087,465.658,0.406857330322398,-0.350732676542563,1.8703473836068,4.0812,0
-529,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
-530,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,-62,-1,-37,,,,,0
-531,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.9,-9.68,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
-532,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74,-25.28,1,1,9603,-60,-2,-41,,,,,0
-533,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.86,-17.51,-113.2,-65.73,1,1,9603,-75,-1,-44,,,,,0
-534,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.24,15.5,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
-535,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5,5,-95.35,-75.22,1,1,9603,-48,3,-44,,,,,0
-536,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.17,-91.71,-89.2,1,1,9603,-47,26,-42,,,,,0
-537,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.19,10.69,-61.39,-55.78,1,1,9603,-53,3,-47,,,,,0
-538,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.58,-19.3,-62.64,-54.24,1,1,9603,-61,2,-33,,,,,0
-539,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.04,-84.67,-68.67,1,1,9603,-58,0,-44,,,,,0
-540,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.33,-62.08,-57.29,1,1,9603,-45,12,-33,,,,,0
-541,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.65,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
-542,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
-543,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.39,-51.24,-59.8,-57.65,1,0,9603,-355,21,72,,,,,1
-544,1226,4293,4326,"Derived at 3 stations. 
+522,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.9,43.58,40,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
+523,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.39,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
+524,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.88,85.19,18.93,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
+525,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.15,81.9,19.58,-168.98,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
+526,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.56,26.2,50.7,51.67,1,0,9603,-128,-283,22,,,,,0
+527,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.04,50.56,53.03,1,0,9603,-128.16,-282.42,21.93,,,,,1
+528,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.56,26.2,50.7,51.67,1,0,9603,-128.033,-283.697,21.052,,,,,0
+529,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
+530,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.69,3.21,7.21,1,0,9606,593.16,26.15,478.54,-1.30439800822601,-0.103297414968546,-1.14450153042326,4.0775,0
+531,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
+532,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725,1
+533,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.69,3.21,7.21,1,0,9607,565.2369,50.0087,465.658,0.406857330322398,-0.350732676542563,1.8703473836068,4.0812,0
+534,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
+535,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.4,-21.78,-73.58,-52.63,1,1,9603,-62,-1,-37,,,,,0
+536,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.9,-9.68,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
+537,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74,-25.28,1,1,9603,-60,-2,-41,,,,,0
+538,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.86,-17.51,-113.2,-65.73,1,1,9603,-75,-1,-44,,,,,0
+539,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.24,15.5,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
+540,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5,5,-95.35,-75.22,1,1,9603,-48,3,-44,,,,,0
+541,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.17,-91.71,-89.2,1,1,9603,-47,26,-42,,,,,0
+542,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.19,10.69,-61.39,-55.78,1,1,9603,-53,3,-47,,,,,0
+543,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.58,-19.3,-62.64,-54.24,1,1,9603,-61,2,-33,,,,,0
+544,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.04,-84.67,-68.67,1,1,9603,-58,0,-44,,,,,0
+545,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.33,-62.08,-57.29,1,1,9603,-45,12,-33,,,,,0
+546,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.65,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
+547,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
+548,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.39,-51.24,-59.8,-57.65,1,0,9603,-355,21,72,,,,,1
+549,1226,4293,4326,"Derived at 3 stations. 
 Beware!  Source CRS uses German legal metres, transformation parameter values are in (International) metres. See tfm code 1271 for example.",For military purposes only. Accuracy 20m in each axis.,1169,-30.64,-16.95,8.24,25.26,1,0,9603,616,97,-251,,,,,1
-545,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.26,1,0,9603,615.64,102.08,-255.81,,,,,0
-546,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.23,4.37,108.8,119.06,1,1,9603,-403,684,41,,,,,0
-547,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.23,4.37,108.8,119.06,1,1,9603,-403,684,41,,,,,0
-548,1835,4294,4326,,Oil exploration.,1360,-4.23,4.29,114.56,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
-549,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.97,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
-550,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
-551,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.66,109.32,119.61,1,0,9603,-679,669,-48,,,,,1
-552,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.02,6.3,112.37,115.36,1,0,9603,-678,670,-48,,,,,0
-553,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.02,5.1,114.1,115.36,1,0,9603,-726.282,703.611,-48.999,,,,,0
-554,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.57,7.66,109.32,117.3,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
-555,5248,4298,4326,,Oil exploration.,1055,4.02,6.3,112.37,115.36,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-556,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5248) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.02,6.3,112.37,115.36,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-557,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.4,55.43,-10.56,-5.35,1,1,9603,506,-122,611,,,,,0
-558,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.4,55.43,-10.56,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-559,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.4,55.43,-10.56,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-560,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.4,55.43,-10.56,-5.35,1,0,9603,506,-122,611,,,,,0
-561,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.84,145.87,1,0,9603,-148,507,685,,,,,0
-562,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.19,45.54,128.32,145.87,1,0,9603,-148,507,685,,,,,0
-563,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.54,131,1,0,9603,-146,507,687,,,,,0
-564,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.99,26.9,122.84,131.38,1,0,9603,-158,507,676,,,,,0
-565,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.54,131,1,0,9603,-147,506,687,,,,,0
-566,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.84,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
-567,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.5,-62.08,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
-568,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.5,-62.08,-60,1,0,9603,-61,285.2,471.6,,,,,0
-569,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.36,-22.2,166.35,166.53,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
-570,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.36,-22.2,166.35,166.53,1,0,9603,-10.18,-350.43,291.37,,,,,1
-571,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,32,37.14,-2.94,9.08,1,0,9603,-73,-247,227,,,,,1
-572,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.59,29.29,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
-573,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.98,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
-574,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,32,37.14,-2.94,9.08,1,0,9603,-123,-206,219,,,,,0
-575,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
-576,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.91,1,0,9603,-95.7,10.2,158.9,,,,,0
-577,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.17,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
-578,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.07,27.5,1.25,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
-579,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.98,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
-580,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
-581,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-34.99,-30.1,-58.49,-53.1,1,0,9603,-155,171,37,,,,,1
-582,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-34.99,-30.1,-58.49,-53.1,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
-583,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.41,-37.01,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
-584,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.84,9.35,-58.07,-52.66,1,0,9603,-265,120,-358,,,,,1
-585,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.65,47.83,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
-586,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.86,46.88,13.38,23.03,1,1,9603,682,-203,480,,,,,0
-587,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.41,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.1365988,-1.4742,-5.2970436,-2.4232,0
-588,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.41,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
-589,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13.01,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-590,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-591,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.8,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
-592,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-593,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.51,51.5,2.51,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
-594,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.51,51.5,2.51,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
-595,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.51,51.87,2.24,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
-596,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.51,51.5,2.51,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
-597,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.83,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
-598,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.83,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
-599,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.73,9.92,15.03,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
-600,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
-601,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.45,48.26,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
-602,1995,4316,4326,,Oil exploration,3295,43.62,48.26,20.26,29.73,1,0,9603,103.25,-100.4,-307.19,,,,,1
-603,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-604,1996,4317,4326,,Oil exploration,1197,43.45,48.26,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
-605,1060,4318,4326,,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-3.2,-5.7,2.8,,,,,1
-606,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.44,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
-607,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.44,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
-608,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-609,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
-610,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.2,178.74,1,1,9603,51,391,-36,,,,,0
-611,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
-612,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.98,-11.32,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
-613,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.67,19.37,162.27,167.81,1,0,9603,102,52,-38,,,,,1
-614,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.58,-30.86,-5.56,1,0,9603,0,0,0,,,,,1
-615,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.75,48.58,16.11,22.89,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
-616,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.44,-14.83,156.26,174.28,1,1,9603,0,0,0,,,,,0
-617,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.23,19.37,166.56,166.71,1,0,9603,276,-57,149,,,,,1
-618,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.37,26.95,114.32,123.61,1,0,9603,0,0,0,,,,,1
-619,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.44,-81.43,1,0,9603,0,0,0,,,,,1
-620,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.48,-7.19,72.31,72.54,1,0,9603,208,-435,-229,,,,,1
-621,5377,5371,4326,,Accuracy 1m.,1186,5,12.5,-84.32,-77.05,1,0,9603,0,0,0,,,,,1
-622,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.04,-84.67,-68.67,1,0,9603,0,0,0,,,,,1
-623,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.83,-60.88,-60.35,1,0,9603,260,12,-147,,,,,1
-624,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
-625,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.1,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
-626,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.27,1,0,9603,0,0,0,,,,,1
-627,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
-628,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.56,-16.35,-152.38,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
-629,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
-630,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.43,-91.42,-87.65,1,0,9603,0,0,0,,,,,1
-631,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.14,22.57,113.77,114.5,1,0,9603,-156,-271,-189,,,,,1
-632,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.43,43.45,25.62,44.82,1,0,9603,0,0,0,,,,,1
-633,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.4,-13.16,-176.24,-176.07,1,1,9603,252,-132,-125,,,,,0
-634,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.4,-13.16,-176.24,-176.07,1,0,9603,253,-132,-127,,,,,1
-635,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.3,-17.37,168.1,169.95,1,0,9603,-127,-769,472,,,,,1
-636,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.18,165.74,167.43,1,0,9603,-104,-129,239,,,,,1
-637,1994,4657,4326,,Low accuracy applications.,3262,63.35,66.58,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
-638,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
-639,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.38,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
-640,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.88,31.08,46.47,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
-641,1951,4658,4326,Derived at 6 stations.,"Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.35,66.58,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,1
-642,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.38,38.79,48.75,1,0,9603,0,0,0,,,,,1
-643,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.58,-30.86,-5.56,1,0,9603,0,0,0,,,,,1
-644,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.23,-9.17,-7.88,1,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805,1
-645,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.08,19.07,28.24,1,0,9603,0,0,0,,,,,1
-646,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.69,7.82,14.9,1,0,9603,-106,-87,188,,,,,1
-647,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.69,-174.6,-170.67,1,0,9603,298,-304,-375,,,,,1
-648,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-649,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-650,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.86,46.88,13.38,23.03,1,0,9603,682,-203,480,,,,,1
-651,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.35,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-652,3965,3906,4326,,Oil industry,3536,41.8,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
-653,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.02,-75,8.12,1,0,9603,0,0,0,,,,,1
-654,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.04,163.93,167.08,1,0,9603,-13,-348,292,,,,,0
-655,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.04,163.93,167.08,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-656,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.04,163.93,167.08,1,0,9603,-11.64,-348.6,291.98,,,,,1
-657,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.06,-16.1,178.43,-179.77,1,0,9603,51,391,-36,,,,,1
-658,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.59,33.14,-17.3,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
-659,1967,4663,4326,,For medium resolution applications.,2870,32.59,33.14,-17.3,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
-660,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.44,-14.83,156.26,174.28,1,0,9603,0,0,0,,,,,1
-661,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.66,37.96,-25.91,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
-662,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.66,37.96,-25.91,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
-663,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.88,37.96,-25.91,-24.96,1,0,9603,-204.619,140.176,55.226,,,,,1
-664,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.88,37.96,-25.91,-24.96,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
-665,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.45,166.7,1,0,9603,-56.263,16.136,-22.856,,,,,1
-666,1972,4665,4326,,For low resolution applications.,2872,38.58,38.85,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
-667,1973,4665,4326,,For medium resolution applications.,2872,38.58,38.85,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
-668,1974,4665,4326,,For low resolution applications.,2873,38.46,38.69,-28.9,-28.55,1,0,9603,-106.248,166.244,-37.845,,,,,0
-669,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.69,-28.9,-28.55,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
-670,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.99,1,0,9603,-106.044,166.655,-37.876,,,,,0
-671,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.99,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
-672,1978,4665,4326,,For low resolution applications.,2875,38.49,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
-673,1979,4665,4326,,For medium resolution applications.,2875,38.49,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
-674,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
-675,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
-676,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
-677,1990,4666,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
-678,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.87,30.83,-82.33,-72.69,1,0,9603,-2,151,181,,,,,1
-679,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.32,88.75,92.11,1,0,9603,0,0,0,,,,,1
-680,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.94,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
-681,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.31,46.36,48.61,1,0,9603,0,0,0,,,,,1
-682,15897,4752,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.2,178.74,1,0,9603,51,391,-36,,,,,1
-683,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.2,-10.56,31.58,1,0,9603,-86,-98,-119,,,,,1
-684,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.42,162.86,163.09,1,0,9603,647,1777,-1124,,,,,1
-685,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
-686,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.42,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
-687,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,0,9603,0,0,0,,,,,1
-688,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.25,7.78,92.02,141.46,1,0,9603,0,0,0,,,,,1
-689,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.89,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
-690,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.89,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
-691,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.34,43.68,46.69,1,0,9603,0,0,0,,,,,1
-692,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.35,11.02,104.25,107.1,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,1
-693,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.84,-19.51,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
-694,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.04,-12.61,44.99,45.34,1,0,9603,-381.788,-57.501,-256.673,,,,,1
-695,5374,5354,4326,,Accuracy 1m.,1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
-696,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
-697,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.18,-84.64,1,0,9603,0,0,0,,,,,1
-698,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.23,-20.63,166.99,167.52,1,0,9603,336,223,-231,,,,,0
-699,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.23,-20.63,166.99,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
-700,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.23,-20.63,166.99,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
-701,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.59,-74.51,1,0,9603,0,0,0,,,,,1
-702,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.2,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
-703,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.93,74.71,167.65,-63.89,1,0,9603,0,0,0,,,,,1
-704,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.96,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
-705,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.25,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
-706,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.02,-109.5,-109.16,1,0,9603,211,147,111,,,,,1
-707,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.73,27.29,-20.04,-4.81,1,0,9603,0,0,0,,,,,1
-708,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.72,-68.83,-60.71,1,0,9603,0,0,0,,,,,1
-709,5375,5360,4326,,Accuracy 1m.,1066,-59.86,-17.51,-113.2,-65.73,1,0,9603,0,0,0,,,,,1
-710,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.13,-25.01,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
-711,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.54,131,1,0,9603,0,0,0,,,,,1
-712,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.75,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
-713,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-60,145,-150,1,0,9603,0,0,0,,,,,1
-714,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.57,139.2,162.8,1,0,9603,0,0,0,,,,,1
-715,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.89,1,0,9603,-80.01,253.26,291.19,,,,,1
-716,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.43,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
-717,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.58,166.47,168.71,1,0,9603,170,42,84,,,,,1
-718,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.9,18.25,-16.1,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
-719,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.45,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
-720,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by Ukraine 2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.19,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
-721,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.19,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
-722,5840,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Ukraine 2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.19,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
-723,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.57,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
-724,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.57,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
-725,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.45,166.7,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
-726,5470,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,1
-727,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.21,-85.96,-82.53,1,0,9607,213.116,9.358,-74.946,2.3514187912169,-0.0614669122616347,6.39420899365999,-5.22,0
-728,5474,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,205.435,-29.099,292.202,,,,,0
-729,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
-730,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.22,19.4,-81.45,-81.04,1,0,9603,67.8,106.1,138.8,,,,,1
-731,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.42,11.8,29.81,1,0,9603,0,0,0,,,,,1
-732,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.2,30,32.34,34.26,1,0,9603,-146.21,112.63,4.05,,,,,1
-733,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
-734,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.39,119.24,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
-735,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.32,22.89,110.14,116.75,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
-736,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.46,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
-737,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.82,21.68,107.16,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
-738,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
-739,15875,4721,4326,Derived at 20 stations.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.21,-16.1,176.82,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
-740,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.8,-12.43,176.82,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-741,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.21,-16.1,176.82,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
-742,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.67,12,1,0,9603,0,0,0,,,,,1
-743,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.53,-158.13,-131.98,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
-744,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.53,-158.13,-131.98,1,0,9603,0,0,0,,,,,0
-745,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.11,139.45,141.5,1,0,9603,365,194,166,,,,,1
-746,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
-747,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.87,9.88,79.65,81.94,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
-748,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.86,46.18,18.82,23.01,1,0,9603,0,0,0,,,,,1
-749,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.92,-17.44,-149.69,-149.1,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
-750,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.62,136,142,1,0,9603,325,154,172,,,,,1
-751,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.84,-14.46,-14.25,1,0,9603,-205,107,53,,,,,1
-752,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.62,-17.42,-149.99,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
-753,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.94,-53.94,-38.07,-35.74,1,0,9603,-794,119,-298,,,,,1
-754,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12,-11.14,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
-755,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.8,52.1,52.25,1,0,9603,0,-0.15,0.68,,,,,1
-756,1441,4601,4326,,"?",1273,16.94,17.21,-61.94,-61.62,1,0,9603,-255,-15,71,,,,,1
-757,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.21,-61.94,-61.62,1,0,9603,-270,13,62,,,,,0
-758,1442,4602,4326,,"?",3239,15.15,15.68,-61.54,-61.2,1,0,9603,725,685,536,,,,,1
-759,1443,4603,4326,,"?",3118,11.95,12.29,-61.83,-61.55,1,0,9603,72,213.7,93,,,,,1
-760,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.86,-62.29,-62.09,1,0,9603,174,359,365,,,,,1
-761,1445,4605,4326,,"?",3297,17.07,17.46,-62.91,-62.5,1,0,9603,9,183,236,,,,,1
-762,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.07,17.46,-62.91,-62.5,1,0,9603,-7,215,225,,,,,0
-763,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.83,1,0,9603,-149,128,296,,,,,1
-764,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.55,13.43,-61.51,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
+550,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.26,1,0,9603,615.64,102.08,-255.81,,,,,0
+551,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.23,4.37,108.8,119.06,1,1,9603,-403,684,41,,,,,0
+552,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.23,4.37,108.8,119.06,1,1,9603,-403,684,41,,,,,0
+553,1835,4294,4326,,Oil exploration.,1360,-4.23,4.29,114.56,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
+554,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.97,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
+555,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
+556,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.66,109.32,119.61,1,0,9603,-679,669,-48,,,,,1
+557,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.02,6.3,112.37,115.36,1,0,9603,-678,670,-48,,,,,0
+558,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.02,5.1,114.1,115.36,1,0,9603,-726.282,703.611,-48.999,,,,,0
+559,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.57,7.66,109.32,117.3,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
+560,5248,4298,4326,,Oil exploration.,1055,4.02,6.3,112.37,115.36,1,1,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+561,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5878) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.02,6.3,112.37,115.36,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+562,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.4,55.43,-10.56,-5.35,1,1,9603,506,-122,611,,,,,0
+563,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.4,55.43,-10.56,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+564,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.4,55.43,-10.56,-5.35,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+565,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.4,55.43,-10.56,-5.35,1,0,9603,506,-122,611,,,,,0
+566,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.84,145.87,1,0,9603,-148,507,685,,,,,0
+567,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.19,45.54,128.32,145.87,1,0,9603,-148,507,685,,,,,0
+568,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.54,131,1,0,9603,-146,507,687,,,,,0
+569,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.99,26.9,122.84,131.38,1,0,9603,-158,507,676,,,,,0
+570,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.54,131,1,0,9603,-147,506,687,,,,,0
+571,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.84,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
+572,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.5,-62.08,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
+573,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.5,-62.08,-60,1,0,9603,-61,285.2,471.6,,,,,0
+574,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.36,-22.2,166.35,166.53,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
+575,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.36,-22.2,166.35,166.53,1,0,9603,-10.18,-350.43,291.37,,,,,1
+576,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,32,37.14,-2.94,9.08,1,0,9603,-73,-247,227,,,,,1
+577,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.59,29.29,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
+578,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.98,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
+579,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,32,37.14,-2.94,9.08,1,0,9603,-123,-206,219,,,,,0
+580,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
+581,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.91,1,0,9603,-95.7,10.2,158.9,,,,,0
+582,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.17,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
+583,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.07,27.5,1.25,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
+584,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.98,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
+585,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
+586,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-34.99,-30.1,-58.49,-53.1,1,0,9603,-155,171,37,,,,,1
+587,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-34.99,-30.1,-58.49,-53.1,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
+588,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.41,-37.01,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
+589,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.84,9.35,-58.07,-52.66,1,0,9603,-265,120,-358,,,,,1
+590,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.65,47.83,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
+591,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.86,46.88,13.38,23.03,1,1,9603,682,-203,480,,,,,0
+592,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.41,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.1365988,-1.4742,-5.2970436,-2.4232,0
+593,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.41,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
+594,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13.01,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+595,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+596,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.8,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
+597,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+598,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.51,51.5,2.51,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
+599,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.51,51.5,2.51,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
+600,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.51,51.87,2.24,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
+601,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.51,51.5,2.51,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
+602,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.83,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
+603,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.83,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
+604,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.73,9.92,15.03,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
+605,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
+606,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.45,48.26,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
+607,1995,4316,4326,,Oil exploration,3295,43.62,48.26,20.26,29.73,1,0,9603,103.25,-100.4,-307.19,,,,,1
+608,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.45,48.26,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+609,1996,4317,4326,,Oil exploration,1197,43.45,48.26,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
+610,1060,4318,4326,,1 metre accuracy.,3267,28.54,30.08,46.55,48.47,1,0,9603,-3.2,-5.7,2.8,,,,,1
+611,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.44,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
+612,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.44,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
+613,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+614,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
+615,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.2,178.74,1,1,9603,51,391,-36,,,,,0
+616,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
+617,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.98,-11.32,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
+618,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.67,19.37,162.27,167.81,1,0,9603,102,52,-38,,,,,1
+619,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.58,-30.86,-5.56,1,0,9603,0,0,0,,,,,1
+620,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.75,48.58,16.11,22.89,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
+621,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.44,-14.83,156.26,174.28,1,1,9603,0,0,0,,,,,0
+622,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.23,19.37,166.56,166.71,1,0,9603,276,-57,149,,,,,1
+623,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.37,26.95,114.32,123.61,1,0,9603,0,0,0,,,,,1
+624,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.44,-81.43,1,0,9603,0,0,0,,,,,1
+625,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.48,-7.19,72.31,72.54,1,0,9603,208,-435,-229,,,,,1
+626,5377,5371,4326,,Accuracy 1m.,1186,5,12.5,-84.32,-77.05,1,0,9603,0,0,0,,,,,1
+627,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.04,-84.67,-68.67,1,0,9603,0,0,0,,,,,1
+628,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.83,-60.88,-60.35,1,0,9603,260,12,-147,,,,,1
+629,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
+630,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.1,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
+631,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.94,-53.94,-38.07,-35.74,1,0,9603,-794,119,-298,,,,,1
+632,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.05,12.09,18.85,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
+633,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.56,-16.35,-152.38,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
+634,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
+635,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.43,-91.42,-87.65,1,0,9603,0,0,0,,,,,1
+636,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.14,22.57,113.77,114.5,1,0,9603,-156,-271,-189,,,,,1
+637,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.43,43.45,25.62,44.82,1,0,9603,0,0,0,,,,,1
+638,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.4,-13.16,-176.24,-176.07,1,1,9603,252,-132,-125,,,,,0
+639,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.4,-13.16,-176.24,-176.07,1,0,9603,253,-132,-127,,,,,1
+640,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.3,-17.37,168.1,169.95,1,0,9603,-127,-769,472,,,,,1
+641,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.18,165.74,167.43,1,0,9603,-104,-129,239,,,,,1
+642,1994,4657,4326,,Low accuracy applications.,3262,63.35,66.58,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
+643,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.4,-21.78,-73.58,-52.63,1,0,9603,0,0,0,,,,,1
+644,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.38,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
+645,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.88,31.08,46.47,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
+646,1951,4658,4326,Derived at 6 stations.,"Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.35,66.58,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,1
+647,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.38,38.79,48.75,1,0,9603,0,0,0,,,,,1
+648,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.58,-30.86,-5.56,1,0,9603,0,0,0,,,,,1
+649,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.23,-9.17,-7.88,1,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805,1
+650,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.08,19.07,28.24,1,0,9603,0,0,0,,,,,1
+651,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.69,7.82,14.9,1,0,9603,-106,-87,188,,,,,1
+652,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.69,-174.6,-170.67,1,0,9603,298,-304,-375,,,,,1
+653,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+654,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.43,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+655,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.86,46.88,13.38,23.03,1,0,9603,682,-203,480,,,,,1
+656,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.35,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+657,3965,3906,4326,,Oil industry,3536,41.8,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
+658,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.02,-75,8.12,1,0,9603,0,0,0,,,,,1
+659,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.04,163.93,167.08,1,0,9603,-13,-348,292,,,,,0
+660,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.04,163.93,167.08,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+661,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.04,163.93,167.08,1,0,9603,-11.64,-348.6,291.98,,,,,1
+662,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.06,-16.1,178.43,-179.77,1,0,9603,51,391,-36,,,,,1
+663,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.59,33.14,-17.3,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
+664,1967,4663,4326,,For medium resolution applications.,2870,32.59,33.14,-17.3,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
+665,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.44,-14.83,156.26,174.28,1,0,9603,0,0,0,,,,,1
+666,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.66,37.96,-25.91,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
+667,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.66,37.96,-25.91,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
+668,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.88,37.96,-25.91,-24.62,1,0,9603,-204.619,140.176,55.226,,,,,1
+669,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.88,37.96,-25.91,-24.62,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
+670,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.45,166.7,1,0,9603,-56.263,16.136,-22.856,,,,,1
+671,1972,4665,4326,,For low resolution applications.,2872,38.58,38.85,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
+672,1973,4665,4326,,For medium resolution applications.,2872,38.58,38.85,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
+673,1974,4665,4326,,For low resolution applications.,2873,38.46,38.69,-28.9,-28.55,1,0,9603,-106.248,166.244,-37.845,,,,,0
+674,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.69,-28.9,-28.55,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
+675,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.99,1,0,9603,-106.044,166.655,-37.876,,,,,0
+676,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.99,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
+677,1978,4665,4326,,For low resolution applications.,2875,38.49,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
+678,1979,4665,4326,,For medium resolution applications.,2875,38.49,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
+679,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
+680,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
+681,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
+682,1990,4666,4326,,For medium resolution applications.,1294,36.96,42.15,-9.55,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
+683,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.87,30.83,-82.33,-72.69,1,0,9603,-2,151,181,,,,,1
+684,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.32,88.75,92.11,1,0,9603,0,0,0,,,,,1
+685,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.94,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
+686,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.31,46.36,48.61,1,0,9603,0,0,0,,,,,1
+687,15897,4752,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.2,178.74,1,0,9603,51,391,-36,,,,,1
+688,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.2,-10.56,31.58,1,0,9603,-86,-98,-119,,,,,1
+689,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.42,162.86,163.09,1,0,9603,647,1777,-1124,,,,,1
+690,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
+691,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.42,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
+692,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.53,-63.66,-57.53,1,0,9603,0,0,0,,,,,1
+693,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.25,7.78,92.02,141.46,1,0,9603,0,0,0,,,,,1
+694,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.89,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
+695,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.89,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
+696,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.34,43.68,46.69,1,0,9603,0,0,0,,,,,1
+697,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.35,11.02,104.25,107.1,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,1
+698,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.84,-19.51,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
+699,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.04,-12.61,44.99,45.34,1,0,9603,-381.788,-57.501,-256.673,,,,,1
+700,5374,5354,4326,,Accuracy 1m.,1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
+701,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
+702,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.18,-84.64,1,0,9603,0,0,0,,,,,1
+703,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.23,-20.63,166.99,167.52,1,0,9603,336,223,-231,,,,,0
+704,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.23,-20.63,166.99,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
+705,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.23,-20.63,166.99,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
+706,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.59,-74.51,1,0,9603,0,0,0,,,,,1
+707,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.2,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
+708,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.93,74.71,167.65,-63.89,1,0,9603,0,0,0,,,,,1
+709,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.96,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
+710,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.25,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
+711,6195,5527,4326,"Parameter values from SAD69(96) to SIRGAS 2000 (2)) (tfm code 5881) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation, based on SAD69 to SIRGAS 2000 (1)) (tfm code 15485). Used by Petrobras and ANP from 1994.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).", [...]
+712,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.02,-109.5,-109.16,1,0,9603,211,147,111,,,,,1
+713,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.73,27.29,-20.04,-4.81,1,0,9603,0,0,0,,,,,1
+714,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.72,-68.83,-60.71,1,0,9603,0,0,0,,,,,1
+715,5375,5360,4326,,Accuracy 1m.,1066,-59.86,-17.51,-113.2,-65.73,1,0,9603,0,0,0,,,,,1
+716,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.13,-25.01,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
+717,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.54,131,1,0,9603,0,0,0,,,,,1
+718,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.75,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
+719,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-60,145,-150,1,0,9603,0,0,0,,,,,1
+720,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.57,139.2,162.8,1,0,9603,0,0,0,,,,,1
+721,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.89,1,0,9603,-80.01,253.26,291.19,,,,,1
+722,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.43,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
+723,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.58,166.47,168.71,1,0,9603,170,42,84,,,,,1
+724,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.9,18.25,-16.1,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
+725,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.45,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
+726,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.27,1,0,9603,0,0,0,,,,,1
+727,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by UCS-2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.19,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
+728,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.19,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
+729,5840,5561,4326,"Parameter values taken from UCS-2000 to ITRF2005 (1) (code 5822) assuming that WGS 84 is equivalent to ITRS2005 within the accuracy of the transformation. Replaces UCS-2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that WGS 84 is equivalent to ITRS2005.",1242,43.19,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
+730,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.57,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
+731,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.57,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
+732,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.45,166.7,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
+733,5470,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,1
+734,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.21,-85.96,-82.53,1,0,9607,213.116,9.358,-74.946,2.3514187912169,-0.0614669122616347,6.39420899365999,-5.22,0
+735,5474,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,205.435,-29.099,292.202,,,,,0
+736,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
+737,6177,6135,4326,"Approximation at the +/- 1m level assuming that CIGD11 is equivalent to WGS 84.","Accuracy +/- 1m.",1063,17.58,20.67,-83.6,-78.72,1,0,9603,0,0,0,,,,,1
+738,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.42,11.8,29.81,1,0,9603,0,0,0,,,,,1
+739,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.2,30,32.34,34.26,1,0,9603,-146.21,112.63,4.05,,,,,1
+740,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
+741,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.39,119.24,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
+742,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.32,22.89,110.14,116.75,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
+743,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.46,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
+744,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.82,21.68,107.16,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
+745,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
+746,15875,4721,4326,Derived at 20 stations.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.21,-16.1,176.82,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
+747,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.8,-12.43,176.82,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+748,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.21,-16.1,176.82,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
+749,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.67,12,1,0,9603,0,0,0,,,,,1
+750,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.53,-158.13,-131.98,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
+751,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.53,-158.13,-131.98,1,0,9603,0,0,0,,,,,0
+752,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.11,139.45,141.5,1,0,9603,365,194,166,,,,,1
+753,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
+754,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.87,9.88,79.65,81.94,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
+755,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.86,46.18,18.82,23.01,1,0,9603,0,0,0,,,,,1
+756,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.92,-17.44,-149.69,-149.1,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
+757,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.62,136,142,1,0,9603,325,154,172,,,,,1
+758,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.84,-14.46,-14.25,1,0,9603,-205,107,53,,,,,1
+759,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.62,-17.42,-149.99,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
+760,6142,4723,4326,"Parameter values are taken from GCGD59 to CIGD11 (1) (code 6136) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3185,19.22,19.4,-81.45,-81.04,1,0,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925,1
+761,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.22,19.4,-81.45,-81.04,1,0,9603,67.8,106.1,138.8,,,,,0
+762,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12,-11.14,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
+763,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.8,52.1,52.25,1,0,9603,0,-0.15,0.68,,,,,1
+764,1441,4601,4326,,"?",1273,16.94,17.21,-61.94,-61.62,1,0,9603,-255,-15,71,,,,,1
+765,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.21,-61.94,-61.62,1,0,9603,-270,13,62,,,,,0
+766,1442,4602,4326,,"?",3239,15.15,15.68,-61.54,-61.2,1,0,9603,725,685,536,,,,,1
+767,1443,4603,4326,,"?",3118,11.95,12.29,-61.83,-61.55,1,0,9603,72,213.7,93,,,,,1
+768,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.86,-62.29,-62.09,1,0,9603,174,359,365,,,,,1
+769,1445,4605,4326,,"?",3297,17.07,17.46,-62.91,-62.5,1,0,9603,9,183,236,,,,,1
+770,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.07,17.46,-62.91,-62.5,1,0,9603,-7,215,225,,,,,0
+771,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.83,1,0,9603,-149,128,296,,,,,1
+772,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.55,13.43,-61.51,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
diff --git a/data/ellipsoid.csv b/data/ellipsoid.csv
index b3c9c9b..d58aa6c 100644
--- a/data/ellipsoid.csv
+++ b/data/ellipsoid.csv
@@ -6,8 +6,8 @@ ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor
 7004,Bessel 1841,6377397.155,9001,299.1528128,,1,"Original Bessel definition is a=3272077.14 and b=3261139.33 toise. This used a weighted mean of values from several authors but did not account for differences in the length of the various toise: the ""Bessel toise"" is therefore of uncertain length.","US Army Map Service Technical Manual; 1943.",OGP,1999/04/22,1998.321 1998.340,0
 7005,Bessel Modified,6377492.018,9001,299.1528128,,1,Used in Norway and also in Sweden with a 1mm increase in semi-major axis.,,OGP,1999/04/22,1998.321,0
 7006,Bessel Namibia,6377483.865,9001,299.1528128,,1,a = 6377397.155 German legal metres. This is the same value as the Bessel 1841 figure (code 7004) but in different units.  Used in Namibia.,"Chief Directorate: Surveys and Mapping, Mowbray, South Africa.",OGP,1999/04/22,1997.160,1
-7007,Clarke 1858,20926348,9005,,20855233,1,"Clarke's 1858/II solution. Derived parameters: a = 6378293.645m using his 1865 ratio of 0.3047972654 feet per metre; 1/f = 294.26068
  In Australia and Amoco Trinidad 1/f taken to two decimal places (294.26 exactly); elsewhere a and b used to derive 1/f.","""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" by Georg Strasser.",OGP,2005/08/14,1999.700 2005.370,0
-7008,Clarke 1866,6378206.4,9001,,6356583.8,1,Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the United States using 39.37 exactly giving a=20925832.16 ft US).,"US Army Map Service Technical Manual No. 7; 1943.",OGP,1995/06/02,1998.340,0
+7007,Clarke 1858,20926348,9005,,20855233,1,"Clarke's 1858/II solution. Derived parameters: a = 6378293.645m using his 1865 ratio of 0.3047972654 feet per metre; 1/f = 294.26068Â…  In Australia and Amoco Trinidad 1/f taken to two decimal places (294.26 exactly); elsewhere a and b used to derive 1/f.","""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" by Georg Strasser.",OGP,2005/08/14,1999.700 2005.370,0
+7008,Clarke 1866,6378206.4,9001,,6356583.8,1,Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the US and international feet for use in Cayman Islands).,"US Army Map Service Technical Manual No. 7; 1943.",OGP,2013/01/17,1998.340 2012.095,0
 7009,Clarke 1866 Michigan,20926631.531,9003,,20855688.674,1,"Used for Michigan NAD27 State Plane zones.  Radius = ellipsoid radius + 800 feet; this approximates the average elevation of the state.   Derived parameter: 1/f = 294.97870",USGS Professional Paper #1395.,OGP,1995/06/02,1998.220,0
 7010,Clarke 1880 (Benoit),6378300.789,9001,,6356566.435,1,Adopts Clarke's values for a and b.  Uses Benoit's 1895 ratio of 0.9143992 metres per yard to convert to metres.,,OGP,1995/06/02,,0
 7011,Clarke 1880 (IGN),6378249.2,9001,,6356515,1,Adopts Clarke's values for a and b using his 1865 ratio of 39.370432 inches per metre to convert axes to metres.,,OGP,1998/04/16,1998.120,0
@@ -47,7 +47,7 @@ ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor
 7052,Clarke 1866 Authalic Sphere,6370997,9001,,6370997,0,Authalic sphere derived from Clarke 1866 ellipsoid (code 7008).,OGP,OGP,2004/04/27,,0
 7053,Hough 1960,6378270,9001,297,,1,,DMA / NIMA / NGA TR8350.2,OGP,2006/01/26,,0
 7054,PZ-90,6378136,9001,298.257839303,,1,,"Geodeziya i Katografiya, 1993.",OGP,2006/02/03,,0
-7055,Clarke 1880 (international foot),20926202,9002,,20854895,1,Clark'es 1880 definition in feet assumed for the purposes of metric conversion to be international foot. a = 6378306.370
metres. 1/f derived from a and b = 293.4663077
 Used in Fiji.,"Department of Lands and Survey, Fiji.",OGP,2006/07/14,,0
+7055,Clarke 1880 (international foot),20926202,9002,,20854895,1,Clark'es 1880 definition in feet assumed for the purposes of metric conversion to be international foot. a = 6378306.370Â…metres. 1/f derived from a and b = 293.4663077Â… Used in Fiji.,"Department of Lands and Survey, Fiji.",OGP,2006/07/14,,0
 7056,Everest 1830 (RSO 1969),6377295.664,9001,300.8017,,1,Adopted for 1969 metrication of peninsula Malaysia RSO grid.  Uses Sears 1922 yard-metre ratio truncated to 6 significant figures applied to Everest 1830 original definition of a and 1/f but with a taken to be in British rather than Indian feet.,Defence Geographic Centre,OGP,2006/07/24,,0
 7057,International 1924 Authalic Sphere,6371228,9001,,6371228,0,Authalic sphere derived from International 1924 ellipsoid (code 7022).,OGP,OGP,2006/09/22,,0
 7058,Hughes 1980,6378273,9001,,6356889.449,1,Used in US DMSP SSM/I microwave sensor processing software. Semi-minor axis derived from eccentricity=0.081816153. Semi-major axis (a) sometimes given as 3443.992nm which OGP suspects is a derived approximation. OGP conversion assumes 1nm=1852m exactly.,US National Snow and Ice Data Center,OGP,2006/09/22,,0
diff --git a/data/gcs.csv b/data/gcs.csv
index 1a8e301..a9a254d 100644
--- a/data/gcs.csv
+++ b/data/gcs.csv
@@ -152,7 +152,7 @@
 4222,Cape,6222,Cape,6222,9122,7013,8901,1,0,6422,1128,1,9603,-136,-108,-292,,,,
 4223,Carthage,6223,Carthage,6223,9122,7011,8901,1,0,6422,1130,1,9603,-263,6,431,,,,
 4224,Chua,6224,Chua,6224,9122,7022,8901,1,0,6422,1131,1,9603,-134,229,-29,,,,
-4225,Corrego Alegre 1970-72,6225,Corrego Alegre 1970-72,6225,9122,7022,8901,1,0,6422,1132,0,9603,-206,172,-6,,,,
+4225,Corrego Alegre 1970-72,6225,Corrego Alegre 1970-72,6225,9122,7022,8901,1,0,6422,1132,1,9603,-206,172,-6,,,,
 4226,"Cote d'Ivoire",6226,"Cote d'Ivoire",6226,9108,7011,8901,1,1,6402,,0,,,,,,,,
 4227,Deir ez Zor,6227,Deir ez Zor,6227,9122,7011,8901,1,0,6422,15742,1,9603,-190.421,8.532,238.69,,,,
 4228,Douala,6228,Douala,6228,9108,7011,8901,1,1,6402,,0,,,,,,,,
@@ -368,10 +368,10 @@
 4720,Fiji 1986,6720,Fiji Geodetic Datum 1986,6720,9122,7043,8901,1,0,6422,15876,1,9606,0,0,4.5,0,0,0.554,0.2263
 4721,Fiji 1956,6721,Fiji 1956,6721,9122,7022,8901,1,0,6422,15875,0,9603,265.025,384.929,-194.046,,,,
 4722,South Georgia 1968,6722,South Georgia 1968,6722,9122,7022,8901,1,0,6422,15813,0,9603,-794,119,-298,,,,
-4723,Grand Cayman 1959,6723,Grand Cayman 1959,6723,9122,7008,8901,1,0,6422,15830,0,9603,67.8,106.1,138.8,,,,
+4723,GCGD59,6723,Grand Cayman Geodetic Datum 1959,6723,9122,7008,8901,1,0,6422,6142,1,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925
 4724,Diego Garcia 1969,6724,Diego Garcia 1969,6724,9122,7022,8901,1,0,6422,15808,0,9603,208,-435,-229,,,,
 4725,Johnston Island 1961,6725,Johnston Island 1961,6725,9122,7022,8901,1,0,6422,15809,0,9603,189,-79,-202,,,,
-4726,Little Cayman 1961,6726,Little Cayman 1961,6726,9122,7008,8901,1,0,6422,15814,1,9603,42,124,147,,,,
+4726,SIGD61,6726,Sister Islands Geodetic Datum 1961,6726,9122,7008,8901,1,0,6422,6143,1,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081
 4727,Midway 1961,6727,Midway 1961,6727,9122,7022,8901,1,0,6422,15818,1,9603,403,-81,277,,,,
 4728,Pico de las Nieves 1984,6728,Pico de las Nieves 1984,6728,9122,7022,8901,1,0,6422,15815,0,9603,-307,-92,127,,,,
 4729,Pitcairn 1967,6729,Pitcairn 1967,6729,9122,7022,8901,1,0,6422,15819,0,9603,185,165,42,,,,
@@ -459,8 +459,10 @@
 5467,Panama-Colon 1911,1072,Panama-Colon 1911,1072,9122,7008,8901,1,0,6422,,0,,,,,,,,
 5489,RGAF09,1073,Reseau Geodesique des Antilles Francaises 2009,1073,9122,7019,8901,1,0,6422,5501,0,9603,0,0,0,,,,
 5524,Corrego Alegre 1961,1074,Corrego Alegre 1961,1074,9122,7022,8901,1,0,6422,,0,,,,,,,,
-5527,"SAD69(96)",1075,"South American Datum 1969(96)",1075,9122,7050,8901,1,0,6422,,0,,,,,,,,
+5527,"SAD69(96)",1075,"South American Datum 1969(96)",1075,9122,7050,8901,1,0,6422,6195,0,9603,-67.35,3.88,-38.22,,,,
 5546,PNG94,1076,Papua New Guinea Geodetic Datum 1994,1076,9122,7019,8901,1,0,6422,5553,0,9603,0,0,0,,,,
-5561,Ukraine 2000,1077,Ukraine 2000,1077,9122,7024,8901,1,0,6422,5590,1,9607,25,-141,-78.5,0,-0.35,-0.736,0
+5561,UCS-2000,1077,Ukraine 2000,1077,9122,7024,8901,1,0,6422,5590,1,9607,25,-141,-78.5,0,-0.35,-0.736,0
 5593,FEH2010,1078,Fehmarnbelt Datum 2010,1078,9122,7019,8901,1,0,6422,5599,0,9603,0,0,0,,,,
 5681,"DB_REF",1081,Deutsche Bahn Reference System,1081,9122,7004,8901,1,0,6422,,0,,,,,,,,
+5886,TGD2005,1095,Tonga Geodetic Datum 2005,1095,9122,7019,8901,1,0,6422,,0,,,,,,,,
+6135,CIGD11,1100,Cayman Islands Geodetic Datum 2011,1100,9122,7019,8901,1,0,6422,6177,0,9603,0,0,0,,,,
diff --git a/data/gdal_datum.csv b/data/gdal_datum.csv
index c3c66bb..6ac5c10 100644
--- a/data/gdal_datum.csv
+++ b/data/gdal_datum.csv
@@ -51,9 +51,9 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1072,Panama-Colon 1911,geodetic,"Fundamental point: Balboa Hill. Latitude: 09°04'57.637""N, longtitude: 79°43'50.313""W.",1911,7008,8901,3290,Topographic mapping and engineering survey.,"Reports of the existence of an Ancon datum are probably erroneous, considering that the origin of the Panamá-Colón Datum of 1911 is at Balboa Hill and the access road up the hill is from the town of Ancon, Canal Zone.","Clifford Mugnier's PE&RS July 1999 Grids and Datums article on The Republic of Panama [...]
 1073,Reseau Geodesique des Antilles Francaises 2009,geodetic,ITRF2005 at epoch 2009.0,2009,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Replaces RRAF91 in Martinique and Guadeloupe.,IGN Paris.,OGP,"2011/03/23",2011.030,0,
 1074,Corrego Alegre 1961,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1961,7022,8901,3874,"Topographic mapping, geodetic survey.","Replaced by Corrego Alegre 1970-72 (datum code 6225). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W.",IBGE,OGP,"2011/07/10",2011.053,0,
-1075,"South American Datum 1969(96)",geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1996,7050,8901,3845,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. Replaces original 1969 adjustment (datum code 6618) in Brazil.",IBGE.,OGP,"2011/07/10",2011.053,0,
+1075,"South American Datum 1969(96)",geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1996,7050,8901,1053,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. Replaces original 1969 adjustment (datum code 6618) in Brazil.",IBGE.,OGP,"2012/11/26",2011.053 2012.070,0,
 1076,Papua New Guinea Geodetic Datum 1994,geodetic,ITRF92 at epoch 1994.0.,1994,7019,8901,1187,"Topographic mapping, geodetic, engineering and cadastral survey.",Adopted 1996. Coincident with WGS 84 in 1994 but rapidly divergent due to significant tectonic motion in PNG.,"Quickclose Geomatics and http://www.aspng.org/techinfopng94.htm",OGP,"2011/07/15",2011.059,0,
-1077,Ukraine 2000,geodetic,Orientation and scale constrained to be same as ITRF2000 at epoch 2005.0. Position is minimised deviation between reference ellipsoid and quasigeoid in territory of Ukraine.,2000,7024,8901,1242,Geodesy.,,"Berlin 2008 GNSS Symposium paper 4-7 (""Creation of ZAKPOS active Network Reference Stations for Transcarpathian Region of Ukraine"") by Savchuk et al.",OGP,"2011/08/15",2011.044,0,
+1077,Ukraine 2000,geodetic,Orientation and scale constrained to be same as ITRF2000 at epoch 2005.0. Position is minimised deviation between reference ellipsoid and quasigeoid in territory of Ukraine.,2005,7024,8901,1242,Geodesy.,,"Berlin 2008 GNSS Symposium paper 4-7 (""Creation of ZAKPOS active Network Reference Stations for Transcarpathian Region of Ukraine"") by Savchuk et al.",OGP,"2012/12/17",2011.044 2012.087,0,
 1078,Fehmarnbelt Datum 2010,geodetic,ITRF2005 at epoch 2010.14.,2010,7019,8901,3889,Engineering survey and construction of Fehmarnbelt tunnel.,Defined through coordinates of four permanant GNSS stations.,"Femern A/S.",OGP,"2011/09/23",2011.083,0,
 1079,Fehmarnbelt Vertical Reference 2010,vertical,"Realised by precise levelling between tide gauges at Marienleuchte (Germany), Rodbyhavn (Denmark) and four Fehmarnbelt project GNSS stations.",2010,,,3890,Engineering survey and construction of Fehmarnbelt tunnel.,,"Femern A/S",OGP,"2011/09/24",2011.083,0,
 1080,Lowest Astronomic Tide,vertical,The lowest tide level which can be predicted to occur under average meterological conditions and under any combination of astronomical conditions.,,,,1262,Hydrography and Nautical Charting.,"Users are advised to not use this generic vertical datum but to define explicit realisations of LAT by specifying location and epoch, for instance ""LAT at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5th Edition, 2936.",OGP,"2012/08/10",2011.047,0,
@@ -71,6 +71,22 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1092,Mean High Water,vertical,The average height of the high waters at a place over a 19-year period.,,,,1262,Hydrography and Nautical Charting.,"Users are advised to not use this generic vertical datum but to define explicit realisations of MHW by specifying location and epoch, for instance ""MHW at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5th Edition, 3141.",OGP,"2012/08/10",2011.047,0,
 1093,Low Water,vertical,"The lowest level reached by the water surface in one tidal cycle. When used in inland (non-tidal) waters it is generally defined as a level which the daily mean water level would fall below less than 5% of the time.",,,,1262,"Hydrography and Nautical Charting, mostly in harbour and river engineering.","On a river it is a sloping surface. Users are advised to not use this generic vertical datum but to define explicit realisations of low water by specifying locatio [...]
 1094,High Water,vertical,"The highest level reached at a place by the water surface in one tidal cycle. When used on inland (non-tidal) waters it is generally defined as a level which the daily mean water level exceeds less than 5% of the time.",,,,1262,"Hydrography and Nautical Charting, mostly in harbour and river engineering.","Users are advised to not use this generic vertical datum but to define explicit realisations of high water by specifying location and epoch, for instance ""Hig [...]
+1095,Tonga Geodetic Datum 2005,geodetic,Based on ITRF2000 at epoch 2005.0,2000,7019,8901,1234,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"World Bank Cyclone Emergency Recovery and Management Project, Report 7, Report of the Development of a Geodetic Datum and Map Grid for the Kingdom of Tonga, prepared for the Ministry of Lands, Survey and Natural Resources, 1st November 2004.",OGP,"2012/10/22",2012.085,0,
+1096,Norway Normal Null 2000,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 2000.0 using values computed from the NKG2005LU uplift model.",2000,,,1352,"Topographic mapping, geodetic survey.",Replaces NN54. Uses Normal heights.,Norwegian Mapping Authority.,OGP,"2012/12/17",2012.094,0,
+1097,Grand Cayman Vertical Datum 1954,vertical,,1954,,,3185,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1098,Little Cayman Vertical Datum 1961,vertical,,1961,,,4121,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1099,Cayman Brac Vertical Datum 1961,vertical,,1961,,,3207,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1100,Cayman Islands Geodetic Datum 2011,geodetic,ITRF2005 at epoch 2011.0,2011,7019,8901,1063,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces GCGD59 (datum code 6723) and SIGD61 (datum code 6726).","Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1101,Cais da Pontinha - Funchal,vertical,"Mean Sea Level during 1913 at Cais da Pontinha, Funchal.",1913,,,4125,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1102,Cais da Vila - Porto Santo,vertical,"Mean Sea Level during 1936 at Cais da Vila, Porto Santo.",1936,,,3680,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1103,Cais das Velas,vertical,Mean Sea Level during 1937 at Cais das Velas.,1937,,,2875,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1104,Horta,vertical,Mean Sea Level during 1935 at Horta.,1935,,,2873,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1105,Cais da Madalena,vertical,Mean Sea Level during 1937 at Cais da Madalena.,1937,,,2874,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1106,Santa Cruz da Graciosa,vertical,Mean Sea Level during 1938 at Santa Cruz da Graciosa.,1938,,,3681,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1107,"Cais da Figueirinha - Angra do Heroísmo",vertical,"Mean Sea Level during 1951 at Cais da Figueirinha - Angra do Heroísmo.",1951,,,2872,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1108,Santa Cruz das Flores,vertical,Mean Sea Level during 1965 at Santa Cruz das Flores.,1965,,,1344,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1109,Cais da Vila do Porto,vertical,"Mean Sea Level during 1965 at Cais da Vila, Porto.",1965,,,4126,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1110,Ponta Delgada,vertical,Mean Sea Level during 1991 at Ponta Delgada.,1991,,,2871,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 5100,Mean Sea Level,vertical,"The average height of the surface of the sea at a tide station for all stages of the tide over a 19-year period, usually determined from hourly height readings measured from a fixed predetermined reference level.",,,,1262,Hydrography.,"Approximates geoid. Users are advised to not use this generic vertical datum but to define explicit realisations of MSL by specifying location and epoch, for instance ""MSL at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5t [...]
 5101,Ordnance Datum Newlyn,vertical,Mean Sea Level at Newlyn between 1915 and 1921.,,,,2792,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2004/06/16",2004.100,0,"D_Ordnance_Datum_Newlyn"
 5102,National Geodetic Vertical Datum 1929,vertical,26 tide gauges in the US and Canada.,1929,,,1323,"Topographic mapping, geodetic survey.",Normal orthometric heights.,,OGP,"1996/09/12",,0,
@@ -80,7 +96,7 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 5106,Caspian Sea,vertical,Defined as -28.0m Baltic datum,,,,1291,Hydrography.,,,OGP,"1996/09/12",,0,
 5107,Nivellement general de la France,vertical,Mean sea level at Marseille,,,,1326,"Topographic mapping, geodetic survey.",The CNIG states that NGF is a general term applying to all vertical network readjustments of France and recommends more specific terminology. See codes 5118-5120.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"1996/09/12",,1,
 5109,Normaal Amsterdams Peil,vertical,Mean high tide at Amsterdams Peil in 1684.,,,,1275,"Topographic mapping, geodetic survey, hydrography.",Orthometric heights.,"Nederlandse Commissie voor Geodesie publication 30; 1993",OGP,"2006/01/16",2004.100 2005.880,0,
-5110,Oostende,vertical,Mean low water during 1958,1958,,,1347,"Topographic mapping, geodetic survey.",,"Nederlandse Commissie voor Geodesie publication 30; 1993",OGP,"2006/01/16",2005.880,0,
+5110,Ostend,vertical,Mean low water at Ostend 1855-78 transferred to benchmark GIKMN at Uccle.,1981,,,1347,"Topographic mapping, geodetic survey.","Realised through the second general levelling (DNG or TAW) 1981-1999.","EuroGeographics, http://www.crs-geo.eu",OGP,"2013/04/25",2005.880 2013.012,0,
 5111,Australian Height Datum,vertical,MSL 1966-68 at 30 gauges around coast.,1968,,,1281,"Topographic mapping, geodetic survey.",,Australian Land Information Group  www.auslig.gov.au,OGP,"2005/09/06",2005.460,0,
 5112,"Australian Height Datum (Tasmania)",vertical,MSL 1972 at Hobart and Burnie.,1972,,,2947,"Topographic mapping, geodetic survey.",,,OGP,"2012/01/21",2012.007,0,
 5113,Instantaneous Water Level,vertical,Instantaneous water level uncorrected for tide.,,,,1262,Hydrography.,Not specific to any location or epoch.,OGP,OGP,"2012/08/10",2011.047,0,
@@ -145,7 +161,7 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5171,EGM96 geoid,vertical,WGS 84 ellipsoid.,1996,,,1262,Geodesy.,,"NASA http://cddis.gsfc.nasa.gov/926/egm96/egm96.html",OGP,"2004/04/27",,0,
 5172,Nivellement General du Luxembourg,vertical,"Reference point Wemperhardt defined as 528.030m above Normaal Amsterdams Peil (NAP). Datum at NAP is mean high tide in 1684. Network adjusted in 1995.",1995,,,1146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Administration du Cadastre et de la Topographie. http://www.etat.lu/ACT",OGP,"2004/03/09",,0,
 5173,Antalya,vertical,Mean sea Level at Antalya 1936-71.,,,,3322,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/11/26",2004.722,0,
-5174,Norway Normal Nul 1954,vertical,MSL defined by regression at 7 gauges with between 17 and 67 years observations.,1974,,,1352,"Geodetic survey, topographic mapping, engineering survey.",Includes initial NN1954 system and NNN1957 system. Former name retained. Normal-orthometric heights.,Statoil,OGP,"2004/03/09",,0,
+5174,Norway Normal Null 1954,vertical,MSL defined by regression at 7 gauges with between 17 and 67 years observations.,1974,,,1352,"Geodetic survey, topographic mapping, engineering survey.",Includes initial NN1954 system and NNN1957 system. Former name retained. Normal-orthometric heights. Replaced by NN2000.,Statoil,OGP,"2012/12/17",2012.094,0,
 5175,Durres,vertical,Mean Sea Level at Durres.,,,,3212,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5176,Gebrauchshohen ADRIA,vertical,Reference point Hutbiegl defined relative to mean sea level at Trieste in 1875.,,,,1037,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5177,National Vertical Network 1999,vertical,Reference point Ruse defined relative to mean sea level at Trieste in 1875.,1999,,,3307,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
@@ -456,7 +472,7 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2006/08/25",2002.151 2
 6622,Guadeloupe 1948,geodetic,,1948,7022,8901,2829,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2009.073,0,"D_Sainte_Anne"
 6623,Centre Spatial Guyanais 1967,geodetic,"Fundamental point: Kourou-Diane. Latitude: 5°15'53.699""N, longitude: 52°48'09.149""W (of Greenwich).",1967,7022,8901,3105,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGFG95 (code 6624).",IGN Paris.,OGP,"2008/06/24",2004.562 2008.045,0,"D_CSG_1967"
 6624,Reseau Geodesique Francais Guyane 1995,geodetic,ITRF93 at epoch 1995.0,1995,7019,8901,1097,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces CSG67 (datum code 6623).",IGN Paris.,OGP,"2002/11/29",,0,"D_RGFG_1995"
-6625,Martinique 1938,geodetic,"Fundamental point: Fort Desaix. Latitude: 14°36'54.090""N, longitude: 61°04'04.030""W (of Greenwich).",1938,7022,8901,3276,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2008.045 2009.073,0,"D_Fort_Desaix"
+6625,Martinique 1938,geodetic,"Fundamental point: Fort Desaix. Latitude: 14°36'54.090""N, longitude: 61°04'04.030""W (of Greenwich).",1938,7022,8901,3276,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2008.045 2009.073,0,"D_Fort_Desaix"
 6626,Reunion 1947,geodetic,"Fundamental point: Piton des Neiges (Borne). Latitude: 21°05'13.119""S, longitude: 55°29'09.193""E (of Greenwich).",1947,7022,8901,3337,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGR92 (datum code 6627).",IGN Paris.,OGP,"2008/06/24",2004.561 2008.045,0,"D_Reunion_1947"
 6627,Reseau Geodesique de la Reunion 1992,geodetic,ITRF91 at epoch 1993.0,1992,7019,8901,3902,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Piton des Neiges (code 6626).",IGN Paris.,OGP,"2012/01/05",2006.770 2011.109,0,"D_RGR_1992"
 6628,Tahiti 52,geodetic,"Fundamental point: Tahiti North Base. Latitude: 17°38'10.0""S, longitude: 149°36'57.8""W (of Greenwich).",1952,7022,8901,2811,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by Tahiti 79 (datum code 6690) in Tahiti and Moorea 87 (code 6691) in Moorea.","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_Tahiti_1952"
@@ -553,10 +569,10 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6720,Fiji Geodetic Datum 1986,geodetic,NWL 9D coordinates of 6 stations on Vitu Levu and Vanua Levu.,1986,7043,8901,1094,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Viti Levu 1912, Vanua Levu 1915 and Fiji 1956.","Survey Review 30,231 (January 1989).",OGP,"2006/07/19",2006.500,0,"D_Fiji_1986"
 6721,Fiji 1956,geodetic,"Latitude origin was obtained astronomically at station Rasusuva = 17°49'03.13""S,  longitude origin was obtained astronomically at station Suva = 178°25'35.835""E (of Greenwich).",1956,7022,8901,3398,Military and topographic mapping,For topographic mapping replaces Viti Levu 1912 and Vanua Levu 1915. Replaced by Fiji Geodetic Datum 1986.,"SOPAC, www.sopac.org, and Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org." [...]
 6722,South Georgia 1968,geodetic,"Fundamental point: ISTS 061.",1968,7022,8901,3529,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2012/02/13",2012.023,0,
-6723,Grand Cayman 1959,geodetic,"Fundamental point: GC1. Latitude: 19°17'54.43""N, longitude: 81°22'37.17""W (of Greenwich).",1959,7008,8901,3185,Topographic mapping,,"Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1998. http://www.asprs.org/",OGP,"2008/06/24",2008.045,0,"D_Grand_Cayman_1959"
+6723,Grand Cayman Geodetic Datum 1959,geodetic,"Fundamental point: GC1. Latitude: 19°17'54.43""N, longitude: 81°22'37.17""W (of Greenwich).",1959,7008,8901,3185,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Grand_Cayman_1959"
 6724,Diego Garcia 1969,geodetic,"Fundamental point: ISTS 073.",1969,7022,8901,3189,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,
 6725,Johnston Island 1961,geodetic,,1961,7022,8901,3201,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Johnston_Island_1961"
-6726,Little Cayman 1961,geodetic,"Fundamental point: LC5. Latitude: 19°39'46.324""N, longitude: 81°03'47.910""W (of Greenwich).",1961,7008,8901,3186,Military and topographic mapping.,,"Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1998. http://www.asprs.org/",OGP,"2008/06/24",2008.045,0,"D_Little_Cayman_1961"
+6726,Sister Islands Geodetic Datum 1961,geodetic,"Fundamental point: LC5. Latitude: 19°39'46.324""N, longitude: 80°03'47.910""W (of Greenwich).",1961,7008,8901,3186,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Little_Cayman_1961"
 6727,Midway 1961,geodetic,,1961,7022,8901,3202,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Midway_1961"
 6728,Pico de las Nieves 1984,geodetic,,,7022,8901,3873,Military and topographic mapping,"Replaces Pico de las Nieves 1968 (PN68). Replaced by REGCAN95.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2011/05/09",2009.033 2011.035,0,"D_Pico_de_Las_Nieves"
 6729,Pitcairn 1967,geodetic,"Fundamental point: Pitcairn Astro. Latitude: 25°04'06.87""S, longitude: 130°06'47.83""W (of Greenwich).",1967,7022,8901,3208,Military and topographic mapping,Replaced by Pitcairn 2006.,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2008/06/24",2008.004 2008.045,0,"D_Pitcairn_1967"
diff --git a/data/gdalicon.png b/data/gdalicon.png
index cadfc2f..8e7731d 100644
Binary files a/data/gdalicon.png and b/data/gdalicon.png differ
diff --git a/data/geoccs.csv b/data/geoccs.csv
index 9e18919..e8168da 100644
--- a/data/geoccs.csv
+++ b/data/geoccs.csv
@@ -125,6 +125,8 @@
 5391,"SIRGAS_ES2007.8",1069,"SIRGAS_ES2007.8",1069,9001,7019,8901,1,0,6500
 5487,RGAF09,1073,Reseau Geodesique des Antilles Francaises 2009,1073,9001,7019,8901,1,0,6500
 5544,PNG94,1076,Papua New Guinea Geodetic Datum 1994,1076,9001,7019,8901,1,0,6500
-5558,Ukraine 2000,1077,Ukraine 2000,1077,9001,7024,8901,1,0,6500
+5558,UCS-2000,1077,Ukraine 2000,1077,9001,7024,8901,1,0,6500
 5591,FEH2010,1078,Fehmarnbelt Datum 2010,1078,9001,7019,8901,1,0,6500
 5828,"DB_REF",1081,Deutsche Bahn Reference System,1081,9001,7004,8901,1,0,6500
+5884,TGD2005,1095,Tonga Geodetic Datum 2005,1095,9001,7019,8901,1,0,6500
+6133,CIGD11,1100,Cayman Islands Geodetic Datum 2011,1100,9001,7019,8901,1,0,6500
diff --git a/data/gml_registry.xml b/data/gml_registry.xml
new file mode 100644
index 0000000..bfaa4c3
--- /dev/null
+++ b/data/gml_registry.xml
@@ -0,0 +1,40 @@
+<gml_registry>
+    <!-- Finnish National Land Survey cadastral data -->
+    <namespace prefix="ktjkiiwfs" uri="http://xml.nls.fi/ktjkiiwfs/2010/02" useGlobalSRSName="true">
+        <featureType elementName="KiinteistorajanSijaintitiedot"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/KiinteistorajanSijaintitiedot.xsd"/>
+        <featureType elementName="PalstanTunnuspisteenSijaintitiedot"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/palstanTunnuspisteenSijaintitiedot.xsd"/>
+        <featureType elementName="RekisteriyksikonTietoja"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/RekisteriyksikonTietoja.xsd"/>
+        <featureType elementName="PalstanTietoja"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/PalstanTietoja.xsd"/>
+    </namespace>
+
+    <!-- Inspire CadastralParcels schema -->
+    <namespace prefix="cp" uri="urn:x-inspire:specification:gmlas:CadastralParcels:3.0" useGlobalSRSName="true">
+        <featureType elementName="BasicPropertyUnit"
+                     gfsSchemaLocation="inspire_cp_BasicPropertyUnit.gfs"/>
+        <featureType elementName="CadastralBoundary"
+                     gfsSchemaLocation="inspire_cp_CadastralBoundary.gfs"/>
+        <featureType elementName="CadastralParcel"
+                     gfsSchemaLocation="inspire_cp_CadastralParcel.gfs"/>
+        <featureType elementName="CadastralZoning"
+                     gfsSchemaLocation="inspire_cp_CadastralZoning.gfs"/>
+    </namespace>
+
+    <!-- Czech RUIAN (VFR) schema -->
+    <namespace prefix="vf"
+               uri="urn:cz:isvs:ruian:schemas:VymennyFormatTypy:v1 ../ruian/xsd/vymenny_format/VymennyFormatTypy.xsd"
+               useGlobalSRSName="true">
+        <featureType elementName="TypSouboru"
+                     elementValue="OB"
+                     gfsSchemaLocation="ruian_vf_ob_v1.gfs" />
+        <featureType elementName="TypSouboru"
+                     elementValue="ST_Z"
+                     gfsSchemaLocation="ruian_vf_ob_v1.gfs" />
+        <featureType elementName="TypSouboru"
+                     elementValue="ST"
+                     gfsSchemaLocation="ruian_vf_st_v1.gfs" />
+    </namespace>
+</gml_registry>
diff --git a/data/inspire_cp_BasicPropertyUnit.gfs b/data/inspire_cp_BasicPropertyUnit.gfs
new file mode 100644
index 0000000..43e0f47
--- /dev/null
+++ b/data/inspire_cp_BasicPropertyUnit.gfs
@@ -0,0 +1,57 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>BasicPropertyUnit</Name>
+    <ElementPath>BasicPropertyUnit</ElementPath>
+    <GeometryType>None</GeometryType>
+    <PropertyDefn>
+      <Name>inspireId_localId</Name>
+      <ElementPath>inspireId|Identifier|localId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>inspireId_namespace</Name>
+      <ElementPath>inspireId|Identifier|namespace</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>nationalCadastralReference</Name>
+      <ElementPath>nationalCadastralReference</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>areaValue</Name>
+      <ElementPath>areaValue</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>areaValue_uom</Name>
+      <ElementPath>areaValue at uom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validFrom</Name>
+      <ElementPath>validFrom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validTo</Name>
+      <ElementPath>validTo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>beginLifespanVersion</Name>
+      <ElementPath>beginLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>endLifespanVersion</Name>
+      <ElementPath>endLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>administrativeUnit_href</Name>
+      <ElementPath>administrativeUnit at href</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/inspire_cp_CadastralBoundary.gfs b/data/inspire_cp_CadastralBoundary.gfs
new file mode 100644
index 0000000..6b27130
--- /dev/null
+++ b/data/inspire_cp_CadastralBoundary.gfs
@@ -0,0 +1,60 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>CadastralBoundary</Name>
+    <ElementPath>CadastralBoundary</ElementPath>
+
+    <GeometryElementPath>geometry</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+
+    <PropertyDefn>
+      <Name>beginLifespanVersion</Name>
+      <ElementPath>beginLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>endLifespanVersion</Name>
+      <ElementPath>endLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+
+    <PropertyDefn>
+      <Name>estimatedAccuracy</Name>
+      <ElementPath>estimatedAccuracy</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>estimatedAccuracy_uom</Name>
+      <ElementPath>estimatedAccuracy at uom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>inspireId_localId</Name>
+      <ElementPath>inspireId|Identifier|localId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>inspireId_namespace</Name>
+      <ElementPath>inspireId|Identifier|namespace</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>validFrom</Name>
+      <ElementPath>validFrom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validTo</Name>
+      <ElementPath>validTo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>parcel_href</Name>
+      <ElementPath>parcel at href</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/inspire_cp_CadastralParcel.gfs b/data/inspire_cp_CadastralParcel.gfs
new file mode 100644
index 0000000..129b0e2
--- /dev/null
+++ b/data/inspire_cp_CadastralParcel.gfs
@@ -0,0 +1,81 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>CadastralParcel</Name>
+    <ElementPath>CadastralParcel</ElementPath>
+    <GeomPropertyDefn>
+        <Name>geometry</Name>
+        <ElementPath>geometry</ElementPath>
+        <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <GeomPropertyDefn>
+        <Name>referencePoint</Name>
+        <ElementPath>referencePoint</ElementPath>
+        <Type>Point</Type>
+    </GeomPropertyDefn>
+    <PropertyDefn>
+      <Name>areaValue</Name>
+      <ElementPath>areaValue</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>areaValue_uom</Name>
+      <ElementPath>areaValue at uom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>beginLifespanVersion</Name>
+      <ElementPath>beginLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>endLifespanVersion</Name>
+      <ElementPath>endLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>inspireId_localId</Name>
+      <ElementPath>inspireId|Identifier|localId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>inspireId_namespace</Name>
+      <ElementPath>inspireId|Identifier|namespace</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>label</Name>
+      <ElementPath>label</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>nationalCadastralReference</Name>
+      <ElementPath>nationalCadastralReference</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validFrom</Name>
+      <ElementPath>validFrom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validTo</Name>
+      <ElementPath>validTo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>basicPropertyUnit_href</Name>
+      <ElementPath>basicPropertyUnit at href</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>administrativeUnit_href</Name>
+      <ElementPath>administrativeUnit at href</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>zoning_href</Name>
+      <ElementPath>zoning at href</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/inspire_cp_CadastralZoning.gfs b/data/inspire_cp_CadastralZoning.gfs
new file mode 100644
index 0000000..e564dff
--- /dev/null
+++ b/data/inspire_cp_CadastralZoning.gfs
@@ -0,0 +1,161 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>CadastralZoning</Name>
+    <ElementPath>CadastralZoning</ElementPath>
+
+    <GeomPropertyDefn>
+        <Name>geometry</Name>
+        <ElementPath>geometry</ElementPath>
+        <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <GeomPropertyDefn>
+        <Name>referencePoint</Name>
+        <ElementPath>referencePoint</ElementPath>
+        <Type>Point</Type>
+    </GeomPropertyDefn>
+
+    <PropertyDefn>
+      <Name>beginLifespanVersion</Name>
+      <ElementPath>beginLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>endLifespanVersion</Name>
+      <ElementPath>endLifespanVersion</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>estimatedAccuracy</Name>
+      <ElementPath>estimatedAccuracy</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>estimatedAccuracy_uom</Name>
+      <ElementPath>estimatedAccuracy at uom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>inspireId_localId</Name>
+      <ElementPath>inspireId|Identifier|localId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>inspireId_namespace</Name>
+      <ElementPath>inspireId|Identifier|namespace</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>label</Name>
+      <ElementPath>label</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>level</Name>
+      <ElementPath>level</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>levelName</Name>
+      <ElementPath>levelName|LocalisedCharacterString</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>levelName_locale</Name>
+      <ElementPath>levelName|LocalisedCharacterString at locale</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+
+<!--
+    <PropertyDefn>
+      <Name>levelName_en</Name>
+      <ElementPath>levelName|LocalisedCharacterString</ElementPath>
+      <Condition>@locale='en'</Condition>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>levelName_fr</Name>
+      <ElementPath>levelName|LocalisedCharacterString</ElementPath>
+      <Condition>@locale='fr'</Condition>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>levelName_others_locale</Name>
+      <ElementPath>levelName|LocalisedCharacterString at locale</ElementPath>
+      <Condition>@locale!='en' and @locale!='fr'</Condition>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>levelName_others</Name>
+      <ElementPath>levelName|LocalisedCharacterString</ElementPath>
+      <Condition>@locale!='en' and @locale!='fr'</Condition>
+      <Type>StringList</Type>
+    </PropertyDefn>
+-->
+
+    <PropertyDefn>
+      <Name>name_language</Name>
+      <ElementPath>name|GeographicalName|language</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_nativeness</Name>
+      <ElementPath>name|GeographicalName|nativeness</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_nameStatus</Name>
+      <ElementPath>name|GeographicalName|nameStatus</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_pronunciation</Name>
+      <ElementPath>name|GeographicalName|pronunciation</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_spelling_text</Name>
+      <ElementPath>name|GeographicalName|spelling|SpellingOfName|text</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_spelling_script</Name>
+      <ElementPath>name|GeographicalName|spelling|SpellingOfName|script</ElementPath>
+      <Type>StringList</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>nationalCadastalZoningReference</Name>
+      <ElementPath>nationalCadastalZoningReference</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>originalMapScaleDenominator</Name>
+      <ElementPath>originalMapScaleDenominator</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>validFrom</Name>
+      <ElementPath>validFrom</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>validTo</Name>
+      <ElementPath>validTo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+    <PropertyDefn>
+      <Name>upperLevelUnit_href</Name>
+      <ElementPath>upperLevelUnit at href</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/ogrvrt.xsd b/data/ogrvrt.xsd
new file mode 100644
index 0000000..7e9aae4
--- /dev/null
+++ b/data/ogrvrt.xsd
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/******************************************************************************
+ * $Id: ogrvrt.xsd 27000 2014-03-01 14:41:36Z rouault $
+ *
+ * Project:  GDAL/OGR
+ * Purpose:  XML Schema for OGR VRT files.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2012, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.0">
+    <xs:element name="OGRVRTDataSource">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:choice minOccurs="0" maxOccurs="unbounded">
+                    <xs:element name="OGRVRTLayer" type="OGRVRTLayerType"/>
+                    <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType"/>
+                    <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType"/>
+                </xs:choice>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:complexType name="OGRVRTLayerType">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="SrcDataSource" type="SrcDataSourceType">
+                    <xs:annotation>
+                        <xs:documentation>Required element</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="SrcLayer" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>SrcLayer or(eclusive) SrcSQL are required elements</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="SrcSQL">
+                    <xs:complexType>
+                        <xs:simpleContent>
+                            <xs:extension base="nonEmptyStringType">
+                                <xs:attribute name="dialect" type="nonEmptyStringType"/>
+                            </xs:extension>
+                        </xs:simpleContent>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="FID" type="nonEmptyStringType"/>
+                <xs:element name="Style" type="nonEmptyStringType"/>
+                <xs:element name="GeometryType" type="GeometryTypeType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.GeometryType for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="LayerSRS" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.SRS for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="Field" type="FieldType">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="GeometryField" type="GeometryFieldType">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="SrcRegion" type="SrcRegionType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.SrcRegion for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="attrFilterPassThrough" type="OGRBooleanType">
+                    <xs:annotation>
+                        <xs:documentation>Default to FALSE.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="FeatureCount" type="xs:integer"/>
+                <xs:group ref="ExtentType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.ExtentXMin, etc... for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:group>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
+    </xs:complexType>
+
+    <xs:group name="ExtentType">
+        <xs:sequence>
+            <xs:element name="ExtentXMin" type="xs:double" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="ExtentYMin" type="xs:double" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="ExtentXMax" type="xs:double" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="ExtentYMax" type="xs:double" minOccurs="1" maxOccurs="1"/>
+        </xs:sequence>
+    </xs:group>
+
+    <xs:complexType name="SrcDataSourceType">
+        <xs:simpleContent>
+            <xs:extension base="nonEmptyStringType">
+                <xs:attribute name="relativeToVRT" type="OGRBooleanType" default="FALSE">
+                    <xs:annotation>
+                        <xs:documentation>Default to FALSE.</xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <!-- alternate case -->
+                <xs:attribute name="relativetoVRT" type="OGRBooleanType" default="FALSE">
+                    <xs:annotation>
+                        <xs:documentation>Default to FALSE.</xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="shared" type="OGRBooleanType"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="nonEmptyStringType">
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="GeometryTypeType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="wkbNone"/>
+            <xs:enumeration value="wkbUnknown"/>
+            <xs:enumeration value="wkbPoint"/>
+            <xs:enumeration value="wkbLineString"/>
+            <xs:enumeration value="wkbPolygon"/>
+            <xs:enumeration value="wkbMultiPoint"/>
+            <xs:enumeration value="wkbMultiLineString"/>
+            <xs:enumeration value="wkbMultiPolygon"/>
+            <xs:enumeration value="wkbGeometryCollection"/>
+            <xs:enumeration value="wkbPoint25D"/>
+            <xs:enumeration value="wkbLineString25D"/>
+            <xs:enumeration value="wkbPolygon25D"/>
+            <xs:enumeration value="wkbMultiPoint25D"/>
+            <xs:enumeration value="wkbMultiLineString25D"/>
+            <xs:enumeration value="wkbMultiPolygon25D"/>
+            <xs:enumeration value="wkbGeometryCollection25D"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="FieldTypeWithoutSrc">
+        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
+        <xs:attribute name="type" type="OGRFieldTypeType" default="String"/>
+        <xs:attribute name="width" type="xs:nonNegativeInteger"/>
+        <xs:attribute name="precision" type="xs:nonNegativeInteger"/>
+    </xs:complexType>
+
+    <xs:complexType name="FieldType">
+        <xs:complexContent>
+            <xs:extension base="FieldTypeWithoutSrc">
+                <xs:attribute name="src" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>Defaults to the value of "name" if not specified.</xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:simpleType name="OGRFieldTypeType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="Integer"/>
+            <xs:enumeration value="integer"/>
+            <xs:enumeration value="Real"/>
+            <xs:enumeration value="real"/>
+            <xs:enumeration value="String"/>
+            <xs:enumeration value="string"/>
+            <xs:enumeration value="IntegerList"/>
+            <xs:enumeration value="integerlist"/>
+            <xs:enumeration value="RealList"/>
+            <xs:enumeration value="reallist"/>
+            <xs:enumeration value="StringList"/>
+            <xs:enumeration value="stringlist"/>
+            <xs:enumeration value="Binary"/>
+            <xs:enumeration value="binary"/>
+            <xs:enumeration value="Date"/>
+            <xs:enumeration value="date"/>
+            <xs:enumeration value="Time"/>
+            <xs:enumeration value="time"/>
+            <xs:enumeration value="DateTime"/>
+            <xs:enumeration value="datetime"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="EncodingType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="Direct"/>
+            <xs:enumeration value="None"/>
+            <xs:enumeration value="WKT"/>
+            <xs:enumeration value="WKB"/>
+            <xs:enumeration value="Shape"/>
+            <xs:enumeration value="shape"/>
+            <xs:enumeration value="PointFromColumns"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:attributeGroup name="GeometryFieldTypeAttrGroupWithoutSrc">
+        <xs:attribute name="encoding" type="EncodingType">
+            <xs:annotation>
+                <xs:documentation>Defaults to Direct.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="name" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Name of the geometry field</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="x" type="nonEmptyStringType">
+            <xs:annotation>
+                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="y" type="nonEmptyStringType">
+            <xs:annotation>
+                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="z" type="nonEmptyStringType">
+            <xs:annotation>
+                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="useSpatialSubquery" type="OGRBooleanType">
+            <xs:annotation>
+                <xs:documentation>Only used if encoding = "PointFromColumns". Defaults to TRUE.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="reportSrcColumn" type="OGRBooleanType">
+            <xs:annotation>
+                <xs:documentation>Only used if no Field element is found at the OGRVRTLayer level</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:complexType name="GeometryFieldTypeWithoutSrc">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="GeometryType" type="GeometryTypeType"/>
+                <xs:element name="SrcRegion" type="SrcRegionType"/>
+                <xs:element name="SRS" type="nonEmptyStringType"/>
+                <xs:group ref="ExtentType"/>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attributeGroup ref="GeometryFieldTypeAttrGroupWithoutSrc"/>
+    </xs:complexType>
+
+    <xs:complexType name="GeometryFieldType">
+        <xs:complexContent>
+            <xs:extension base="GeometryFieldTypeWithoutSrc">
+                <xs:attribute name="field" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>Used if encoding = "WKT", "WKB" or "Shape" to find
+                        the attribute field of the source layer.
+                        Used also in multiple geometry fields scenario to retrieve the
+                        source geometry field matching the target VRT geometry field.</xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="SrcRegionType">
+        <xs:simpleContent>
+            <xs:extension base="PolygonWKTType">
+                <xs:attribute name="clip" type="OGRBooleanType">
+                    <xs:annotation>
+                        <xs:documentation>Defaults to FALSE.</xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="PolygonWKTType">
+        <xs:annotation>
+            <xs:documentation>A valid WKT for a POLYGON</xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="POLYGON.*"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="OGRBooleanType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="1"/>
+            <xs:enumeration value="0"/>
+            <xs:enumeration value="ON"/>
+            <xs:enumeration value="OFF"/>
+            <xs:enumeration value="on"/>
+            <xs:enumeration value="off"/>
+            <xs:enumeration value="YES"/>
+            <xs:enumeration value="NO"/>
+            <xs:enumeration value="yes"/>
+            <xs:enumeration value="no"/>
+            <xs:enumeration value="TRUE"/>
+            <xs:enumeration value="FALSE"/>
+            <xs:enumeration value="true"/>
+            <xs:enumeration value="false"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="OGRVRTWarpedLayerType">
+        <xs:sequence>
+            <xs:choice minOccurs="1" maxOccurs="1">
+                <xs:element name="OGRVRTLayer" type="OGRVRTLayerType"/>
+                <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType"/>
+                <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType"/>
+            </xs:choice>
+            <xs:element name="WarpedGeomFieldName" type="nonEmptyStringType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="SrcSRS" type="nonEmptyStringType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="TargetSRS" type="nonEmptyStringType" minOccurs="1" maxOccurs="1"/>
+            <xs:group ref="ExtentType" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="OGRVRTUnionLayerType">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="OGRVRTLayer" type="OGRVRTLayerType">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+
+                <xs:element name="GeometryType" type="GeometryTypeType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.GeometryType for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="LayerSRS" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.SRS for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="FieldStrategy" type="FieldStrategyType">
+                    <xs:annotation>
+                        <xs:documentation>Defaults to Union if no Field or GeometryField element is speicified.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="Field" type="FieldTypeWithoutSrc">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="GeometryField" type="GeometryFieldTypeWithoutSrc">
+                    <xs:annotation>
+                        <xs:documentation>May be repeated</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="PreserveSrcFID" type="OGRBooleanType">
+                    <xs:annotation>
+                        <xs:documentation>Defaults to FALSE.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="SourceLayerFieldName" type="nonEmptyStringType">
+                    <xs:annotation>
+                        <xs:documentation>Name of fields in which to place the name of the source layer of each feature.</xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+                <xs:element name="FeatureCount" type="xs:integer"/>
+                <xs:group ref="ExtentType">
+                    <xs:annotation>
+                        <xs:documentation>Use GeometryField.ExtentXMin, etc. for multi-geometry field support.</xs:documentation>
+                    </xs:annotation>
+                </xs:group>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
+    </xs:complexType>
+
+    <xs:simpleType name="FieldStrategyType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="FirstLayer"/>
+            <xs:enumeration value="Union"/>
+            <xs:enumeration value="Intersection"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+</xs:schema>
diff --git a/data/osmconf.ini b/data/osmconf.ini
index bea4479..81e0df7 100644
--- a/data/osmconf.ini
+++ b/data/osmconf.ini
@@ -27,11 +27,13 @@ osm_changeset=no
 # keys to report as OGR fields
 attributes=name,barrier,highway,ref,address,is_in,place,man_made
 # keys that, alone, are not significant enough to report a node as a OGR point
-unsignificant=created_by,converted_by,source,time,ele
+unsignificant=created_by,converted_by,source,time,ele,attribution
 # keys that should NOT be reported in the "other_tags" field
 ignore=created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
 # uncomment to avoid creation of "other_tags" field
 #other_tags=no
+# uncomment to create "all_tags" field. "all_tags" and "other_tags" are exclusive
+#all_tags=yes
 
 [lines]
 # common attributes
@@ -48,6 +50,8 @@ attributes=name,highway,waterway,aerialway,barrier,man_made
 ignore=created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
 # uncomment to avoid creation of "other_tags" field
 #other_tags=no
+# uncomment to create "all_tags" field. "all_tags" and "other_tags" are exclusive
+#all_tags=yes
 
 [multipolygons]
 # common attributes
@@ -66,6 +70,8 @@ attributes=name,type,aeroway,amenity,admin_level,barrier,boundary,building,craft
 ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
 # uncomment to avoid creation of "other_tags" field
 #other_tags=no
+# uncomment to create "all_tags" field. "all_tags" and "other_tags" are exclusive
+#all_tags=yes
 
 [multilinestrings]
 # common attributes
@@ -82,6 +88,8 @@ attributes=name,type
 ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
 # uncomment to avoid creation of "other_tags" field
 #other_tags=no
+# uncomment to create "all_tags" field. "all_tags" and "other_tags" are exclusive
+#all_tags=yes
 
 [other_relations]
 # common attributes
@@ -98,3 +106,5 @@ attributes=name,type
 ignore=area,created_by,converted_by,source,time,ele,note,openGeoDB:,fixme,FIXME
 # uncomment to avoid creation of "other_tags" field
 #other_tags=no
+# uncomment to create "all_tags" field. "all_tags" and "other_tags" are exclusive
+#all_tags=yes
diff --git a/data/pcs.csv b/data/pcs.csv
index f1c0856..4ed4af0 100644
--- a/data/pcs.csv
+++ b/data/pcs.csv
@@ -1346,8 +1346,8 @@
 3353,"Mhast (onshore) / UTM zone 32S",9001,4704,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 3354,"Mhast (offshore) / UTM zone 32S",9001,4705,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 3355,"Egypt Gulf of Suez S-650 TL / Red Belt",9001,4706,18072,9807,1,0,4400,8801,30,9102,8802,31,9102,8805,1,9201,8806,615000,9001,8807,810000,9001,,,,,,
-3356,"Grand Cayman 1959 / UTM zone 17N",9001,4723,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3357,"Little Cayman 1961 / UTM zone 17N",9001,4726,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3356,"Grand Cayman 1959 / UTM zone 17N",9001,4723,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3357,"Little Cayman 1961 / UTM zone 17N",9001,4726,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3358,"NAD83(HARN) / North Carolina",9001,4152,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,
 3359,"NAD83(HARN) / North Carolina (ftUS)",9002,4152,15346,9802,1,1,4495,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
 3360,"NAD83(HARN) / South Carolina",9001,4152,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,
@@ -1566,7 +1566,7 @@
 3573,"WGS 84 / North Pole LAEA Canada",9001,4326,17297,9820,1,0,4466,8801,90,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 3574,"WGS 84 / North Pole LAEA Atlantic",9001,4326,17298,9820,1,0,4465,8801,90,9102,8802,-40,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 3575,"WGS 84 / North Pole LAEA Europe",9001,4326,17299,9820,1,0,4463,8801,90,9102,8802,10,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3576,"WGS 84 / North Pole LAEA Russia",9001,4326,17300,9820,1,0,4462,8801,90,9102,8802,90,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+3576,"WGS 84 / North Pole LAEA Russia",9001,4326,17300,9820,1,0,1035,8801,90,9102,8802,90,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 3577,"GDA94 / Australian Albers",9001,4283,17365,9822,1,0,4400,8821,0,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
 3578,"NAD83 / Yukon Albers",9001,4269,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,
 3579,"NAD83(CSRS) / Yukon Albers",9001,4617,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,
@@ -1947,7 +1947,7 @@
 4462,"WGS 84 / Australian Centre for Remote Sensing Lambert",9001,4326,4460,9802,1,0,4400,8821,-27,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
 4467,"RGSPM06 / UTM zone 21N",9001,4463,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 4471,"RGM04 / UTM zone 38S",9001,4470,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4474,"Cadastre 1997 / UTM zone 38S",9001,4632,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+4474,"Cadastre 1997 / UTM zone 38S",9001,4632,16138,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 4484,"Mexican Datum of 1993 / UTM zone 11N",9001,4483,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 4485,"Mexican Datum of 1993 / UTM zone 12N",9001,4483,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 4486,"Mexican Datum of 1993 / UTM zone 13N",9001,4483,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -2280,28 +2280,28 @@
 5551,"PNG94 / PNGMG94 zone 55",9001,5546,5548,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 5552,"PNG94 / PNGMG94 zone 56",9001,5546,5549,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 5559,"Ocotepeque 1935 / Guatemala Norte",9001,5451,18211,9801,1,0,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
-5562,"Ukraine 2000 / Gauss-Kruger zone 4",9001,5561,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5563,"Ukraine 2000 / Gauss-Kruger zone 5",9001,5561,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5564,"Ukraine 2000 / Gauss-Kruger zone 6",9001,5561,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-5565,"Ukraine 2000 / Gauss-Kruger zone 7",9001,5561,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-5566,"Ukraine 2000 / Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5567,"Ukraine 2000 / Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5568,"Ukraine 2000 / Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5569,"Ukraine 2000 / Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5570,"Ukraine 2000 / 3-degree Gauss-Kruger zone 7",9001,5561,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-5571,"Ukraine 2000 / 3-degree Gauss-Kruger zone 8",9001,5561,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-5572,"Ukraine 2000 / 3-degree Gauss-Kruger zone 9",9001,5561,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-5573,"Ukraine 2000 / 3-degree Gauss-Kruger zone 10",9001,5561,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-5574,"Ukraine 2000 / 3-degree Gauss-Kruger zone 11",9001,5561,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-5575,"Ukraine 2000 / 3-degree Gauss-Kruger zone 12",9001,5561,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-5576,"Ukraine 2000 / 3-degree Gauss-Kruger zone 13",9001,5561,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-5577,"Ukraine 2000 / 3-degree Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5578,"Ukraine 2000 / 3-degree Gauss-Kruger CM 24E",9001,5561,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5579,"Ukraine 2000 / 3-degree Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5580,"Ukraine 2000 / 3-degree Gauss-Kruger CM 30E",9001,5561,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5581,"Ukraine 2000 / 3-degree Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5582,"Ukraine 2000 / 3-degree Gauss-Kruger CM 36E",9001,5561,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5583,"Ukraine 2000 / 3-degree Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5562,"UCS-2000 / Gauss-Kruger zone 4",9001,5561,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
+5563,"UCS-2000 / Gauss-Kruger zone 5",9001,5561,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
+5564,"UCS-2000 / Gauss-Kruger zone 6",9001,5561,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
+5565,"UCS-2000 / Gauss-Kruger zone 7",9001,5561,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
+5566,"UCS-2000 / Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5567,"UCS-2000 / Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5568,"UCS-2000 / Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5569,"UCS-2000 / Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5570,"UCS-2000 / 3-degree Gauss-Kruger zone 7",9001,5561,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
+5571,"UCS-2000 / 3-degree Gauss-Kruger zone 8",9001,5561,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
+5572,"UCS-2000 / 3-degree Gauss-Kruger zone 9",9001,5561,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
+5573,"UCS-2000 / 3-degree Gauss-Kruger zone 10",9001,5561,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
+5574,"UCS-2000 / 3-degree Gauss-Kruger zone 11",9001,5561,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
+5575,"UCS-2000 / 3-degree Gauss-Kruger zone 12",9001,5561,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
+5576,"UCS-2000 / 3-degree Gauss-Kruger zone 13",9001,5561,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
+5577,"UCS-2000 / 3-degree Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5578,"UCS-2000 / 3-degree Gauss-Kruger CM 24E",9001,5561,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5579,"UCS-2000 / 3-degree Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5580,"UCS-2000 / 3-degree Gauss-Kruger CM 30E",9001,5561,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5581,"UCS-2000 / 3-degree Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5582,"UCS-2000 / 3-degree Gauss-Kruger CM 36E",9001,5561,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5583,"UCS-2000 / 3-degree Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 5588,"NAD27 / New Brunswick Stereographic (NAD27)",9002,4267,5587,9809,1,0,1029,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,1000000,9002,8807,1000000,9002,,,,,,
 5589,"Sibun Gorge 1922 / Colony Grid",9005,5464,5465,9807,1,0,4403,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,
 5596,"FEH2010 / Fehmarnbelt TM",9001,5593,5595,9807,1,0,4400,8801,0,9110,8802,11.2,9110,8805,1,9201,8806,1000000,9001,8807,0,9001,,,,,,
@@ -2364,6 +2364,112 @@
 5842,"WGS 84 / TM 12 SE",9001,4326,16612,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 5844,"RGRDC 2005 / Congo TM zone 30",9001,4046,17430,9807,1,0,4499,8801,0,9102,8802,30,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 5858,"SAD69(96) / UTM zone 22S",9001,5527,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5875,"SAD69(96) / UTM zone 18S",9001,5527,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5876,"SAD69(96) / UTM zone 19S",9001,5527,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5877,"SAD69(96) / UTM zone 20S",9001,5527,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5879,"Cadastre 1997 / UTM zone 38S",9001,4475,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5880,"SIRGAS 2000 / Brazil Polyconic",9001,4674,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
+5887,"TGD2005 / Tonga Map Grid",9001,5886,5883,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1500000,9001,8807,5000000,9001,,,,,,
+5890,JAXA Snow Depth Polar Stereographic North,9001,4054,5889,9829,1,0,1035,8806,0,9001,8807,0,9001,8832,70,9102,8833,90,9102,,,,,,,,,
+5921,"WGS 84 / EPSG Arctic Regional zone A1",9001,4326,5906,9802,1,0,4400,8821,81.19020136,9110,8822,-111,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5922,"WGS 84 / EPSG Arctic Regional zone A2",9001,4326,5907,9802,1,0,4400,8821,81.19020136,9110,8822,-39,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5923,"WGS 84 / EPSG Arctic Regional zone A3",9001,4326,5908,9802,1,0,4400,8821,81.19020136,9110,8822,33,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5924,"WGS 84 / EPSG Arctic Regional zone A4",9001,4326,5909,9802,1,0,4400,8821,81.19020136,9110,8822,105,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5925,"WGS 84 / EPSG Arctic Regional zone A5",9001,4326,5910,9802,1,0,4400,8821,81.19020136,9110,8822,177,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5926,"WGS 84 / EPSG Arctic Regional zone B1",9001,4326,5911,9802,1,0,4400,8821,73.09206671,9110,8822,-111,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5927,"WGS 84 / EPSG Arctic Regional zone B2",9001,4326,5912,9802,1,0,4400,8821,73.09206671,9110,8822,-39,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5928,"WGS 84 / EPSG Arctic Regional zone B3",9001,4326,5913,9802,1,0,4400,8821,73.09206671,9110,8822,33,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5929,"WGS 84 / EPSG Arctic Regional zone B4",9001,4326,5914,9802,1,0,4400,8821,73.09206671,9110,8822,105,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5930,"WGS 84 / EPSG Arctic Regional zone B5",9001,4326,5915,9802,1,0,4400,8821,73.09206671,9110,8822,177,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5931,"WGS 84 / EPSG Arctic Regional zone C1",9001,4326,5916,9802,1,0,4400,8821,65.06045752,9110,8822,-111,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5932,"WGS 84 / EPSG Arctic Regional zone C2",9001,4326,5917,9802,1,0,4400,8821,65.06045752,9110,8822,-39,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5933,"WGS 84 / EPSG Arctic Regional zone C3",9001,4326,5918,9802,1,0,4400,8821,65.06045752,9110,8822,33,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5934,"WGS 84 / EPSG Arctic Regional zone C4",9001,4326,5919,9802,1,0,4400,8821,65.06045752,9110,8822,105,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5935,"WGS 84 / EPSG Arctic Regional zone C5",9001,4326,5920,9802,1,0,4400,8821,65.06045752,9110,8822,177,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5936,"WGS 84 / EPSG Alaska Polar Stereographic",9001,4326,5901,9810,1,0,4467,8801,90,9102,8802,-150,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5937,"WGS 84 / EPSG Canada Polar Stereographic",9001,4326,5902,9810,1,0,4466,8801,90,9102,8802,-100,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5938,"WGS 84 / EPSG Greenland Polar Stereographic",9001,4326,5903,9810,1,0,1036,8801,90,9102,8802,-33,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5939,"WGS 84 / EPSG Norway Polar Stereographic",9001,4326,5904,9810,1,0,1037,8801,90,9102,8802,18,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5940,"WGS 84 / EPSG Russia Polar Stereographic",9001,4326,5905,9810,1,0,1038,8801,90,9102,8802,105,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+6050,"GR96 / EPSG Arctic zone 1-25",9001,4747,5979,9802,1,0,4400,8821,85.2613626,9110,8822,-30,9110,8823,87,9110,8824,83.4,9110,8826,25500000,9001,8827,1500000,9001,,,
+6051,"GR96 / EPSG Arctic zone 2-18",9001,4747,5987,9802,1,0,4400,8821,82.03303296,9110,8822,-52,9110,8823,83.4,9110,8824,80.2,9110,8826,18500000,9001,8827,2500000,9001,,,
+6052,"GR96 / EPSG Arctic zone 2-20",9001,4747,5988,9802,1,0,4400,8821,82.03303296,9110,8822,-12,9110,8823,83.4,9110,8824,80.2,9110,8826,20500000,9001,8827,2500000,9001,,,
+6053,"GR96 / EPSG Arctic zone 3-29",9001,4747,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,
+6054,"GR96 / EPSG Arctic zone 3-31",9001,4747,6003,9802,1,0,4400,8821,78.42264151,9110,8822,-39,9110,8823,80.2,9110,8824,77,9110,8826,31500000,9001,8827,3500000,9001,,,
+6055,"GR96 / EPSG Arctic zone 3-33",9001,4747,6004,9802,1,0,4400,8821,78.42264151,9110,8822,-10,9110,8823,80.2,9110,8824,77,9110,8826,33500000,9001,8827,3500000,9001,,,
+6056,"GR96 / EPSG Arctic zone 4-20",9001,4747,6009,9802,1,0,4400,8821,75.21518519,9110,8822,-64,9110,8823,77,9110,8824,73.4,9110,8826,20500000,9001,8827,4500000,9001,,,
+6057,"GR96 / EPSG Arctic zone 4-22",9001,4747,6010,9802,1,0,4400,8821,75.21518519,9110,8822,-39,9110,8823,77,9110,8824,73.4,9110,8826,22500000,9001,8827,4500000,9001,,,
+6058,"GR96 / EPSG Arctic zone 4-24",9001,4747,6011,9802,1,0,4400,8821,75.21518519,9110,8822,-14,9110,8823,77,9110,8824,73.4,9110,8826,24500000,9001,8827,4500000,9001,,,
+6059,"GR96 / EPSG Arctic zone 5-41",9001,4747,6035,9802,1,0,4400,8821,72.01300331,9110,8822,-62,9110,8823,73.4,9110,8824,70.2,9110,8826,41500000,9001,8827,5500000,9001,,,
+6060,"GR96 / EPSG Arctic zone 5-43",9001,4747,6036,9802,1,0,4400,8821,72.01300331,9110,8822,-42,9110,8823,73.4,9110,8824,70.2,9110,8826,43500000,9001,8827,5500000,9001,,,
+6061,"GR96 / EPSG Arctic zone 5-45",9001,4747,6037,9802,1,0,4400,8821,72.01300331,9110,8822,-22,9110,8823,73.4,9110,8824,70.2,9110,8826,45500000,9001,8827,5500000,9001,,,
+6062,"GR96 / EPSG Arctic zone 6-26",9001,4747,6045,9802,1,0,4400,8821,68.4114912,9110,8822,-56,9110,8823,70.2,9110,8824,67,9110,8826,26500000,9001,8827,6500000,9001,,,
+6063,"GR96 / EPSG Arctic zone 6-28",9001,4747,6046,9802,1,0,4400,8821,68.4114912,9110,8822,-38,9110,8823,70.2,9110,8824,67,9110,8826,28500000,9001,8827,6500000,9001,,,
+6064,"GR96 / EPSG Arctic zone 6-30",9001,4747,6047,9802,1,0,4400,8821,68.4114912,9110,8822,-20,9110,8823,70.2,9110,8824,67,9110,8826,30500000,9001,8827,6500000,9001,,,
+6065,"GR96 / EPSG Arctic zone 7-11",9001,4747,6048,9802,1,0,4400,8821,65.21037415,9110,8822,-51,9110,8823,67,9110,8824,63.4,9110,8826,11500000,9001,8827,7500000,9001,,,
+6066,"GR96 / EPSG Arctic zone 7-13",9001,4747,6049,9802,1,0,4400,8821,65.21037415,9110,8822,-34,9110,8823,67,9110,8824,63.4,9110,8826,13500000,9001,8827,7500000,9001,,,
+6067,"GR96 / EPSG Arctic zone 8-20",9001,4747,5943,9802,1,0,4400,8821,62.00551048,9110,8822,-52,9110,8823,63.4,9110,8824,60.2,9110,8826,20500000,9001,8827,8500000,9001,,,
+6068,"GR96 / EPSG Arctic zone 8-22",9001,4747,5944,9802,1,0,4400,8821,62.00551048,9110,8822,-37,9110,8823,63.4,9110,8824,60.2,9110,8826,22500000,9001,8827,8500000,9001,,,
+6069,"ETRS89 / EPSG Arctic zone 2-22",9001,4258,5989,9802,1,0,4400,8821,82.03303296,9110,8822,16,9110,8823,83.4,9110,8824,80.2,9110,8826,22500000,9001,8827,2500000,9001,,,
+6070,"ETRS89 / EPSG Arctic zone 3-11",9001,4258,5993,9802,1,0,4400,8821,78.42264151,9110,8822,21,9110,8823,80.2,9110,8824,77,9110,8826,11500000,9001,8827,3500000,9001,,,
+6071,"ETRS89 / EPSG Arctic zone 4-26",9001,4258,6012,9802,1,0,4400,8821,75.21518519,9110,8822,10,9110,8823,77,9110,8824,73.4,9110,8826,26500000,9001,8827,4500000,9001,,,
+6072,"ETRS89 / EPSG Arctic zone 4-28",9001,4258,6013,9802,1,0,4400,8821,75.21518519,9110,8822,34,9110,8823,77,9110,8824,73.4,9110,8826,28500000,9001,8827,4500000,9001,,,
+6073,"ETRS89 / EPSG Arctic zone 5-11",9001,4258,6020,9802,1,0,4400,8821,72.01300331,9110,8822,14,9110,8823,73.4,9110,8824,70.2,9110,8826,11500000,9001,8827,5500000,9001,,,
+6074,"ETRS89 / EPSG Arctic zone 5-13",9001,4258,6021,9802,1,0,4400,8821,72.01300331,9110,8822,34,9110,8823,73.4,9110,8824,70.2,9110,8826,13500000,9001,8827,5500000,9001,,,
+6075,"WGS 84 / EPSG Arctic zone 2-24",9001,4326,5990,9802,1,0,4400,8821,82.03303296,9110,8822,53,9110,8823,83.4,9110,8824,80.2,9110,8826,24500000,9001,8827,2500000,9001,,,
+6076,"WGS 84 / EPSG Arctic zone 2-26",9001,4326,5991,9802,1,0,4400,8821,82.03303296,9110,8822,93,9110,8823,83.4,9110,8824,80.2,9110,8826,26500000,9001,8827,2500000,9001,,,
+6077,"WGS 84 / EPSG Arctic zone 3-13",9001,4326,5994,9802,1,0,4400,8821,78.42264151,9110,8822,52,9110,8823,80.2,9110,8824,77,9110,8826,13500000,9001,8827,3500000,9001,,,
+6078,"WGS 84 / EPSG Arctic zone 3-15",9001,4326,5995,9802,1,0,4400,8821,78.42264151,9110,8822,83,9110,8823,80.2,9110,8824,77,9110,8826,15500000,9001,8827,3500000,9001,,,
+6079,"WGS 84 / EPSG Arctic zone 3-17",9001,4326,5996,9802,1,0,4400,8821,78.42264151,9110,8822,114,9110,8823,80.2,9110,8824,77,9110,8826,17500000,9001,8827,3500000,9001,,,
+6080,"WGS 84 / EPSG Arctic zone 3-19",9001,4326,5997,9802,1,0,4400,8821,78.42264151,9110,8822,145,9110,8823,80.2,9110,8824,77,9110,8826,19500000,9001,8827,3500000,9001,,,
+6081,"WGS 84 / EPSG Arctic zone 4-30",9001,4326,6014,9802,1,0,4400,8821,75.21518519,9110,8822,58,9110,8823,77,9110,8824,73.4,9110,8826,30500000,9001,8827,4500000,9001,,,
+6082,"WGS 84 / EPSG Arctic zone 4-32",9001,4326,6015,9802,1,0,4400,8821,75.21518519,9110,8822,82,9110,8823,77,9110,8824,73.4,9110,8826,32500000,9001,8827,4500000,9001,,,
+6083,"WGS 84 / EPSG Arctic zone 4-34",9001,4326,6016,9802,1,0,4400,8821,75.21518519,9110,8822,106,9110,8823,77,9110,8824,73.4,9110,8826,34500000,9001,8827,4500000,9001,,,
+6084,"WGS 84 / EPSG Arctic zone 4-36",9001,4326,6017,9802,1,0,4400,8821,75.21518519,9110,8822,130,9110,8823,77,9110,8824,73.4,9110,8826,36500000,9001,8827,4500000,9001,,,
+6085,"WGS 84 / EPSG Arctic zone 4-38",9001,4326,6018,9802,1,0,4400,8821,75.21518519,9110,8822,154,9110,8823,77,9110,8824,73.4,9110,8826,38500000,9001,8827,4500000,9001,,,
+6086,"WGS 84 / EPSG Arctic zone 4-40",9001,4326,6019,9802,1,0,4400,8821,75.21518519,9110,8822,179,9110,8823,77,9110,8824,73.4,9110,8826,40500000,9001,8827,4500000,9001,,,
+6087,"WGS 84 / EPSG Arctic zone 5-15",9001,4326,6022,9802,1,0,4400,8821,72.01300331,9110,8822,54,9110,8823,73.4,9110,8824,70.2,9110,8826,15500000,9001,8827,5500000,9001,,,
+6088,"WGS 84 / EPSG Arctic zone 5-17",9001,4326,6023,9802,1,0,4400,8821,72.01300331,9110,8822,74,9110,8823,73.4,9110,8824,70.2,9110,8826,17500000,9001,8827,5500000,9001,,,
+6089,"WGS 84 / EPSG Arctic zone 5-19",9001,4326,6024,9802,1,0,4400,8821,72.01300331,9110,8822,95,9110,8823,73.4,9110,8824,70.2,9110,8826,19500000,9001,8827,5500000,9001,,,
+6090,"WGS 84 / EPSG Arctic zone 5-21",9001,4326,6025,9802,1,0,4400,8821,72.01300331,9110,8822,116,9110,8823,73.4,9110,8824,70.2,9110,8826,21500000,9001,8827,5500000,9001,,,
+6091,"WGS 84 / EPSG Arctic zone 5-23",9001,4326,6026,9802,1,0,4400,8821,72.01300331,9110,8822,137,9110,8823,73.4,9110,8824,70.2,9110,8826,23500000,9001,8827,5500000,9001,,,
+6092,"WGS 84 / EPSG Arctic zone 5-25",9001,4326,6027,9802,1,0,4400,8821,72.01300331,9110,8822,158,9110,8823,73.4,9110,8824,70.2,9110,8826,25500000,9001,8827,5500000,9001,,,
+6093,"WGS 84 / EPSG Arctic zone 5-27",9001,4326,6028,9802,1,0,4400,8821,72.01300331,9110,8822,179,9110,8823,73.4,9110,8824,70.2,9110,8826,27500000,9001,8827,5500000,9001,,,
+6094,"NAD83(NSRS2007) / EPSG Arctic zone 5-29",9001,4759,6029,9802,1,0,4400,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,
+6095,"NAD83(NSRS2007) / EPSG Arctic zone 5-31",9001,4759,6030,9802,1,0,4400,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,
+6096,"NAD83(NSRS2007) / EPSG Arctic zone 6-14",9001,4759,6039,9802,1,0,4400,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,
+6097,"NAD83(NSRS2007) / EPSG Arctic zone 6-16",9001,4759,6040,9802,1,0,4400,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,
+6098,"NAD83(CSRS) / EPSG Arctic zone 1-23",9001,4617,5978,9802,1,0,4400,8821,85.2613626,9110,8822,-90,9110,8823,87,9110,8824,83.4,9110,8826,23500000,9001,8827,1500000,9001,,,
+6099,"NAD83(CSRS) / EPSG Arctic zone 2-14",9001,4617,5985,9802,1,0,4400,8821,82.03303296,9110,8822,-115,9110,8823,83.4,9110,8824,80.2,9110,8826,14500000,9001,8827,2500000,9001,,,
+6100,"NAD83(CSRS) / EPSG Arctic zone 2-16",9001,4617,5986,9802,1,0,4400,8821,82.03303296,9110,8822,-75,9110,8823,83.4,9110,8824,80.2,9110,8826,16500000,9001,8827,2500000,9001,,,
+6101,"NAD83(CSRS) / EPSG Arctic zone 3-25",9001,4617,6000,9802,1,0,4400,8821,78.42264151,9110,8822,-129,9110,8823,80.2,9110,8824,77,9110,8826,25500000,9001,8827,3500000,9001,,,
+6102,"NAD83(CSRS) / EPSG Arctic zone 3-27",9001,4617,6001,9802,1,0,4400,8821,78.42264151,9110,8822,-99,9110,8823,80.2,9110,8824,77,9110,8826,27500000,9001,8827,3500000,9001,,,
+6103,"NAD83(CSRS) / EPSG Arctic zone 3-29",9001,4617,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,
+6104,"NAD83(CSRS) / EPSG Arctic zone 4-14",9001,4617,6006,9802,1,0,4400,8821,75.21518519,9110,8822,-129,9110,8823,77,9110,8824,73.4,9110,8826,14500000,9001,8827,4500000,9001,,,
+6105,"NAD83(CSRS) / EPSG Arctic zone 4-16",9001,4617,6007,9802,1,0,4400,8821,75.21518519,9110,8822,-104,9110,8823,77,9110,8824,73.4,9110,8826,16500000,9001,8827,4500000,9001,,,
+6106,"NAD83(CSRS) / EPSG Arctic zone 4-18",9001,4617,6008,9802,1,0,4400,8821,75.21518519,9110,8822,-79,9110,8823,77,9110,8824,73.4,9110,8826,18500000,9001,8827,4500000,9001,,,
+6107,"NAD83(CSRS) / EPSG Arctic zone 5-33",9001,4617,6031,9802,1,0,4400,8821,72.01300331,9110,8822,-131,9110,8823,73.4,9110,8824,70.2,9110,8826,33500000,9001,8827,5500000,9001,,,
+6108,"NAD83(CSRS) / EPSG Arctic zone 5-35",9001,4617,6032,9802,1,0,4400,8821,72.01300331,9110,8822,-111,9110,8823,73.4,9110,8824,70.2,9110,8826,35500000,9001,8827,5500000,9001,,,
+6109,"NAD83(CSRS) / EPSG Arctic zone 5-37",9001,4617,6033,9802,1,0,4400,8821,72.01300331,9110,8822,-91,9110,8823,73.4,9110,8824,70.2,9110,8826,37500000,9001,8827,5500000,9001,,,
+6110,"NAD83(CSRS) / EPSG Arctic zone 5-39",9001,4617,6034,9802,1,0,4400,8821,72.01300331,9110,8822,-71,9110,8823,73.4,9110,8824,70.2,9110,8826,39500000,9001,8827,5500000,9001,,,
+6111,"NAD83(CSRS) / EPSG Arctic zone 6-18",9001,4617,6041,9802,1,0,4400,8821,68.4114912,9110,8822,-132,9110,8823,70.2,9110,8824,67,9110,8826,18500000,9001,8827,6500000,9001,,,
+6112,"NAD83(CSRS) / EPSG Arctic zone 6-20",9001,4617,6042,9802,1,0,4400,8821,68.4114912,9110,8822,-113,9110,8823,70.2,9110,8824,67,9110,8826,20500000,9001,8827,6500000,9001,,,
+6113,"NAD83(CSRS) / EPSG Arctic zone 6-22",9001,4617,6043,9802,1,0,4400,8821,68.4114912,9110,8822,-94,9110,8823,70.2,9110,8824,67,9110,8826,22500000,9001,8827,6500000,9001,,,
+6114,"NAD83(CSRS) / EPSG Arctic zone 6-24",9001,4617,6044,9802,1,0,4400,8821,68.4114912,9110,8822,-75,9110,8823,70.2,9110,8824,67,9110,8826,24500000,9001,8827,6500000,9001,,,
+6115,"WGS 84 / EPSG Arctic zone 1-27",9001,4326,5980,9802,1,0,4400,8821,85.2613626,9110,8822,30,9110,8823,87,9110,8824,83.4,9110,8826,27500000,9001,8827,1500000,9001,,,
+6116,"WGS 84 / EPSG Arctic zone 1-29",9001,4326,5981,9802,1,0,4400,8821,85.2613626,9110,8822,90,9110,8823,87,9110,8824,83.4,9110,8826,29500000,9001,8827,1500000,9001,,,
+6117,"WGS 84 / EPSG Arctic zone 1-31",9001,4326,5982,9802,1,0,4400,8821,85.2613626,9110,8822,150,9110,8823,87,9110,8824,83.4,9110,8826,31500000,9001,8827,1500000,9001,,,
+6118,"WGS 84 / EPSG Arctic zone 1-21",9001,4326,5977,9802,1,0,4400,8821,85.2613626,9110,8822,-150,9110,8823,87,9110,8824,83.4,9110,8826,21500000,9001,8827,1500000,9001,,,
+6119,"WGS 84 / EPSG Arctic zone 2-28",9001,4326,5992,9802,1,0,4400,8821,82.03303296,9110,8822,133,9110,8823,83.4,9110,8824,80.2,9110,8826,28500000,9001,8827,2500000,9001,,,
+6120,"WGS 84 / EPSG Arctic zone 2-10",9001,4326,5983,9802,1,0,4400,8821,82.03303296,9110,8822,166,9110,8823,83.4,9110,8824,80.2,9110,8826,10500000,9001,8827,2500000,9001,,,
+6121,"WGS 84 / EPSG Arctic zone 2-12",9001,4326,5984,9802,1,0,4400,8821,82.03303296,9110,8822,-154,9110,8823,83.4,9110,8824,80.2,9110,8826,12500000,9001,8827,2500000,9001,,,
+6122,"WGS 84 / EPSG Arctic zone 3-21",9001,4326,5998,9802,1,0,4400,8821,78.42264151,9110,8822,176,9110,8823,80.2,9110,8824,77,9110,8826,21500000,9001,8827,3500000,9001,,,
+6123,"WGS 84 / EPSG Arctic zone 3-23",9001,4326,5999,9802,1,0,4400,8821,78.42264151,9110,8822,-153,9110,8823,80.2,9110,8824,77,9110,8826,23500000,9001,8827,3500000,9001,,,
+6124,"WGS 84 / EPSG Arctic zone 4-12",9001,4326,6005,9802,1,0,4400,8821,75.21518519,9110,8822,-155,9110,8823,77,9110,8824,73.4,9110,8826,12500000,9001,8827,4500000,9001,,,
+6125,"ETRS89 / EPSG Arctic zone 5-47",9001,4258,6038,9802,1,0,4400,8821,72.01300331,9110,8822,-5,9110,8823,73.4,9110,8824,70.2,9110,8826,47500000,9001,8827,5500000,9001,,,
+6128,Grand Cayman National Grid 1959,9002,4723,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
+6129,Sister Islands National Grid 1961,9002,4726,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
+6141,Cayman Islands National Grid 2011,9002,6135,6126,9802,1,0,1039,8821,19.2,9110,8822,80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,
 20004,"Pulkovo 1995 / Gauss-Kruger zone 4",9001,4200,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
 20005,"Pulkovo 1995 / Gauss-Kruger zone 5",9001,4200,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
 20006,"Pulkovo 1995 / Gauss-Kruger zone 6",9001,4200,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
diff --git a/data/projop_wparm.csv b/data/projop_wparm.csv
index c64d763..4d2cbe5 100644
--- a/data/projop_wparm.csv
+++ b/data/projop_wparm.csv
@@ -200,6 +200,105 @@
 5648,UTM zone 33N with prefix,9807,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,33500000,9001,8807,0,9001,,,,,,
 5658,TM Emilia-Romagna,9807,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500053,9001,8807,-3999820,9001,,,,,,
 5824,ACT Standard Grid,9807,8801,-35.19038506,9110,8802,149.003346139,9110,8805,1.000086,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5883,Tonga Map Grid,9807,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1500000,9001,8807,5000000,9001,,,,,,
+5889,JAXA Snow Depth Polar Stereographic North,9829,8806,0,9001,8807,0,9001,8832,70,9102,8833,90,9102,,,,,,,,,
+5901,EPSG Alaska Polar Stereographic,9810,8801,90,9102,8802,-150,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5902,EPSG Canada Polar Stereographic,9810,8801,90,9102,8802,-100,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5903,EPSG Greenland Polar Stereographic,9810,8801,90,9102,8802,-33,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5904,EPSG Norway Polar Stereographic,9810,8801,90,9102,8802,18,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5905,EPSG Russia Polar Stereographic,9810,8801,90,9102,8802,105,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5906,EPSG Arctic Regional LCC zone A1,9802,8821,81.19020136,9110,8822,-111,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5907,EPSG Arctic Regional LCC zone A2,9802,8821,81.19020136,9110,8822,-39,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5908,EPSG Arctic Regional LCC zone A3,9802,8821,81.19020136,9110,8822,33,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5909,EPSG Arctic Regional LCC zone A4,9802,8821,81.19020136,9110,8822,105,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5910,EPSG Arctic Regional LCC zone A5,9802,8821,81.19020136,9110,8822,177,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
+5911,EPSG Arctic Regional LCC zone B1,9802,8821,73.09206671,9110,8822,-111,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5912,EPSG Arctic Regional LCC zone B2,9802,8821,73.09206671,9110,8822,-39,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5913,EPSG Arctic Regional LCC zone B3,9802,8821,73.09206671,9110,8822,33,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5914,EPSG Arctic Regional LCC zone B4,9802,8821,73.09206671,9110,8822,105,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5915,EPSG Arctic Regional LCC zone B5,9802,8821,73.09206671,9110,8822,177,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
+5916,EPSG Arctic Regional LCC zone C1,9802,8821,65.06045752,9110,8822,-111,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5917,EPSG Arctic Regional LCC zone C2,9802,8821,65.06045752,9110,8822,-39,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5918,EPSG Arctic Regional LCC zone C3,9802,8821,65.06045752,9110,8822,33,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5919,EPSG Arctic Regional LCC zone C4,9802,8821,65.06045752,9110,8822,105,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5920,EPSG Arctic Regional LCC zone C5,9802,8821,65.06045752,9110,8822,177,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
+5943,EPSG Arctic LCC zone 8-20,9802,8821,62.00551048,9110,8822,-52,9110,8823,63.4,9110,8824,60.2,9110,8826,20500000,9001,8827,8500000,9001,,,
+5944,EPSG Arctic LCC zone 8-22,9802,8821,62.00551048,9110,8822,-37,9110,8823,63.4,9110,8824,60.2,9110,8826,22500000,9001,8827,8500000,9001,,,
+5977,EPSG Arctic LCC zone 1-21,9802,8821,85.2613626,9110,8822,-150,9110,8823,87,9110,8824,83.4,9110,8826,21500000,9001,8827,1500000,9001,,,
+5978,EPSG Arctic LCC zone 1-23,9802,8821,85.2613626,9110,8822,-90,9110,8823,87,9110,8824,83.4,9110,8826,23500000,9001,8827,1500000,9001,,,
+5979,EPSG Arctic LCC zone 1-25,9802,8821,85.2613626,9110,8822,-30,9110,8823,87,9110,8824,83.4,9110,8826,25500000,9001,8827,1500000,9001,,,
+5980,EPSG Arctic LCC zone 1-27,9802,8821,85.2613626,9110,8822,30,9110,8823,87,9110,8824,83.4,9110,8826,27500000,9001,8827,1500000,9001,,,
+5981,EPSG Arctic LCC zone 1-29,9802,8821,85.2613626,9110,8822,90,9110,8823,87,9110,8824,83.4,9110,8826,29500000,9001,8827,1500000,9001,,,
+5982,EPSG Arctic LCC zone 1-31,9802,8821,85.2613626,9110,8822,150,9110,8823,87,9110,8824,83.4,9110,8826,31500000,9001,8827,1500000,9001,,,
+5983,EPSG Arctic LCC zone 2-10,9802,8821,82.03303296,9110,8822,166,9110,8823,83.4,9110,8824,80.2,9110,8826,10500000,9001,8827,2500000,9001,,,
+5984,EPSG Arctic LCC zone 2-12,9802,8821,82.03303296,9110,8822,-154,9110,8823,83.4,9110,8824,80.2,9110,8826,12500000,9001,8827,2500000,9001,,,
+5985,EPSG Arctic LCC zone 2-14,9802,8821,82.03303296,9110,8822,-115,9110,8823,83.4,9110,8824,80.2,9110,8826,14500000,9001,8827,2500000,9001,,,
+5986,EPSG Arctic LCC zone 2-16,9802,8821,82.03303296,9110,8822,-75,9110,8823,83.4,9110,8824,80.2,9110,8826,16500000,9001,8827,2500000,9001,,,
+5987,EPSG Arctic LCC zone 2-18,9802,8821,82.03303296,9110,8822,-52,9110,8823,83.4,9110,8824,80.2,9110,8826,18500000,9001,8827,2500000,9001,,,
+5988,EPSG Arctic LCC zone 2-20,9802,8821,82.03303296,9110,8822,-12,9110,8823,83.4,9110,8824,80.2,9110,8826,20500000,9001,8827,2500000,9001,,,
+5989,EPSG Arctic LCC zone 2-22,9802,8821,82.03303296,9110,8822,16,9110,8823,83.4,9110,8824,80.2,9110,8826,22500000,9001,8827,2500000,9001,,,
+5990,EPSG Arctic LCC zone 2-24,9802,8821,82.03303296,9110,8822,53,9110,8823,83.4,9110,8824,80.2,9110,8826,24500000,9001,8827,2500000,9001,,,
+5991,EPSG Arctic LCC zone 2-26,9802,8821,82.03303296,9110,8822,93,9110,8823,83.4,9110,8824,80.2,9110,8826,26500000,9001,8827,2500000,9001,,,
+5992,EPSG Arctic LCC zone 2-28,9802,8821,82.03303296,9110,8822,133,9110,8823,83.4,9110,8824,80.2,9110,8826,28500000,9001,8827,2500000,9001,,,
+5993,EPSG Arctic LCC zone 3-11,9802,8821,78.42264151,9110,8822,21,9110,8823,80.2,9110,8824,77,9110,8826,11500000,9001,8827,3500000,9001,,,
+5994,EPSG Arctic LCC zone 3-13,9802,8821,78.42264151,9110,8822,52,9110,8823,80.2,9110,8824,77,9110,8826,13500000,9001,8827,3500000,9001,,,
+5995,EPSG Arctic LCC zone 3-15,9802,8821,78.42264151,9110,8822,83,9110,8823,80.2,9110,8824,77,9110,8826,15500000,9001,8827,3500000,9001,,,
+5996,EPSG Arctic LCC zone 3-17,9802,8821,78.42264151,9110,8822,114,9110,8823,80.2,9110,8824,77,9110,8826,17500000,9001,8827,3500000,9001,,,
+5997,EPSG Arctic LCC zone 3-19,9802,8821,78.42264151,9110,8822,145,9110,8823,80.2,9110,8824,77,9110,8826,19500000,9001,8827,3500000,9001,,,
+5998,EPSG Arctic LCC zone 3-21,9802,8821,78.42264151,9110,8822,176,9110,8823,80.2,9110,8824,77,9110,8826,21500000,9001,8827,3500000,9001,,,
+5999,EPSG Arctic LCC zone 3-23,9802,8821,78.42264151,9110,8822,-153,9110,8823,80.2,9110,8824,77,9110,8826,23500000,9001,8827,3500000,9001,,,
+6000,EPSG Arctic LCC zone 3-25,9802,8821,78.42264151,9110,8822,-129,9110,8823,80.2,9110,8824,77,9110,8826,25500000,9001,8827,3500000,9001,,,
+6001,EPSG Arctic LCC zone 3-27,9802,8821,78.42264151,9110,8822,-99,9110,8823,80.2,9110,8824,77,9110,8826,27500000,9001,8827,3500000,9001,,,
+6002,EPSG Arctic LCC zone 3-29,9802,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,
+6003,EPSG Arctic LCC zone 3-31,9802,8821,78.42264151,9110,8822,-39,9110,8823,80.2,9110,8824,77,9110,8826,31500000,9001,8827,3500000,9001,,,
+6004,EPSG Arctic LCC zone 3-33,9802,8821,78.42264151,9110,8822,-10,9110,8823,80.2,9110,8824,77,9110,8826,33500000,9001,8827,3500000,9001,,,
+6005,EPSG Arctic LCC zone 4-12,9802,8821,75.21518519,9110,8822,-155,9110,8823,77,9110,8824,73.4,9110,8826,12500000,9001,8827,4500000,9001,,,
+6006,EPSG Arctic LCC zone 4-14,9802,8821,75.21518519,9110,8822,-129,9110,8823,77,9110,8824,73.4,9110,8826,14500000,9001,8827,4500000,9001,,,
+6007,EPSG Arctic LCC zone 4-16,9802,8821,75.21518519,9110,8822,-104,9110,8823,77,9110,8824,73.4,9110,8826,16500000,9001,8827,4500000,9001,,,
+6008,EPSG Arctic LCC zone 4-18,9802,8821,75.21518519,9110,8822,-79,9110,8823,77,9110,8824,73.4,9110,8826,18500000,9001,8827,4500000,9001,,,
+6009,EPSG Arctic LCC zone 4-20,9802,8821,75.21518519,9110,8822,-64,9110,8823,77,9110,8824,73.4,9110,8826,20500000,9001,8827,4500000,9001,,,
+6010,EPSG Arctic LCC zone 4-22,9802,8821,75.21518519,9110,8822,-39,9110,8823,77,9110,8824,73.4,9110,8826,22500000,9001,8827,4500000,9001,,,
+6011,EPSG Arctic LCC zone 4-24,9802,8821,75.21518519,9110,8822,-14,9110,8823,77,9110,8824,73.4,9110,8826,24500000,9001,8827,4500000,9001,,,
+6012,EPSG Arctic LCC zone 4-26,9802,8821,75.21518519,9110,8822,10,9110,8823,77,9110,8824,73.4,9110,8826,26500000,9001,8827,4500000,9001,,,
+6013,EPSG Arctic LCC zone 4-28,9802,8821,75.21518519,9110,8822,34,9110,8823,77,9110,8824,73.4,9110,8826,28500000,9001,8827,4500000,9001,,,
+6014,EPSG Arctic LCC zone 4-30,9802,8821,75.21518519,9110,8822,58,9110,8823,77,9110,8824,73.4,9110,8826,30500000,9001,8827,4500000,9001,,,
+6015,EPSG Arctic LCC zone 4-32,9802,8821,75.21518519,9110,8822,82,9110,8823,77,9110,8824,73.4,9110,8826,32500000,9001,8827,4500000,9001,,,
+6016,EPSG Arctic LCC zone 4-34,9802,8821,75.21518519,9110,8822,106,9110,8823,77,9110,8824,73.4,9110,8826,34500000,9001,8827,4500000,9001,,,
+6017,EPSG Arctic LCC zone 4-36,9802,8821,75.21518519,9110,8822,130,9110,8823,77,9110,8824,73.4,9110,8826,36500000,9001,8827,4500000,9001,,,
+6018,EPSG Arctic LCC zone 4-38,9802,8821,75.21518519,9110,8822,154,9110,8823,77,9110,8824,73.4,9110,8826,38500000,9001,8827,4500000,9001,,,
+6019,EPSG Arctic LCC zone 4-40,9802,8821,75.21518519,9110,8822,179,9110,8823,77,9110,8824,73.4,9110,8826,40500000,9001,8827,4500000,9001,,,
+6020,EPSG Arctic LCC zone 5-11,9802,8821,72.01300331,9110,8822,14,9110,8823,73.4,9110,8824,70.2,9110,8826,11500000,9001,8827,5500000,9001,,,
+6021,EPSG Arctic LCC zone 5-13,9802,8821,72.01300331,9110,8822,34,9110,8823,73.4,9110,8824,70.2,9110,8826,13500000,9001,8827,5500000,9001,,,
+6022,EPSG Arctic LCC zone 5-15,9802,8821,72.01300331,9110,8822,54,9110,8823,73.4,9110,8824,70.2,9110,8826,15500000,9001,8827,5500000,9001,,,
+6023,EPSG Arctic LCC zone 5-17,9802,8821,72.01300331,9110,8822,74,9110,8823,73.4,9110,8824,70.2,9110,8826,17500000,9001,8827,5500000,9001,,,
+6024,EPSG Arctic LCC zone 5-19,9802,8821,72.01300331,9110,8822,95,9110,8823,73.4,9110,8824,70.2,9110,8826,19500000,9001,8827,5500000,9001,,,
+6025,EPSG Arctic LCC zone 5-21,9802,8821,72.01300331,9110,8822,116,9110,8823,73.4,9110,8824,70.2,9110,8826,21500000,9001,8827,5500000,9001,,,
+6026,EPSG Arctic LCC zone 5-23,9802,8821,72.01300331,9110,8822,137,9110,8823,73.4,9110,8824,70.2,9110,8826,23500000,9001,8827,5500000,9001,,,
+6027,EPSG Arctic LCC zone 5-25,9802,8821,72.01300331,9110,8822,158,9110,8823,73.4,9110,8824,70.2,9110,8826,25500000,9001,8827,5500000,9001,,,
+6028,EPSG Arctic LCC zone 5-27,9802,8821,72.01300331,9110,8822,179,9110,8823,73.4,9110,8824,70.2,9110,8826,27500000,9001,8827,5500000,9001,,,
+6029,EPSG Arctic LCC zone 5-29,9802,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,
+6030,EPSG Arctic LCC zone 5-31,9802,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,
+6031,EPSG Arctic LCC zone 5-33,9802,8821,72.01300331,9110,8822,-131,9110,8823,73.4,9110,8824,70.2,9110,8826,33500000,9001,8827,5500000,9001,,,
+6032,EPSG Arctic LCC zone 5-35,9802,8821,72.01300331,9110,8822,-111,9110,8823,73.4,9110,8824,70.2,9110,8826,35500000,9001,8827,5500000,9001,,,
+6033,EPSG Arctic LCC zone 5-37,9802,8821,72.01300331,9110,8822,-91,9110,8823,73.4,9110,8824,70.2,9110,8826,37500000,9001,8827,5500000,9001,,,
+6034,EPSG Arctic LCC zone 5-39,9802,8821,72.01300331,9110,8822,-71,9110,8823,73.4,9110,8824,70.2,9110,8826,39500000,9001,8827,5500000,9001,,,
+6035,EPSG Arctic LCC zone 5-41,9802,8821,72.01300331,9110,8822,-62,9110,8823,73.4,9110,8824,70.2,9110,8826,41500000,9001,8827,5500000,9001,,,
+6036,EPSG Arctic LCC zone 5-43,9802,8821,72.01300331,9110,8822,-42,9110,8823,73.4,9110,8824,70.2,9110,8826,43500000,9001,8827,5500000,9001,,,
+6037,EPSG Arctic LCC zone 5-45,9802,8821,72.01300331,9110,8822,-22,9110,8823,73.4,9110,8824,70.2,9110,8826,45500000,9001,8827,5500000,9001,,,
+6038,EPSG Arctic LCC zone 5-47,9802,8821,72.01300331,9110,8822,-5,9110,8823,73.4,9110,8824,70.2,9110,8826,47500000,9001,8827,5500000,9001,,,
+6039,EPSG Arctic LCC zone 6-14,9802,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,
+6040,EPSG Arctic LCC zone 6-16,9802,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,
+6041,EPSG Arctic LCC zone 6-18,9802,8821,68.4114912,9110,8822,-132,9110,8823,70.2,9110,8824,67,9110,8826,18500000,9001,8827,6500000,9001,,,
+6042,EPSG Arctic LCC zone 6-20,9802,8821,68.4114912,9110,8822,-113,9110,8823,70.2,9110,8824,67,9110,8826,20500000,9001,8827,6500000,9001,,,
+6043,EPSG Arctic LCC zone 6-22,9802,8821,68.4114912,9110,8822,-94,9110,8823,70.2,9110,8824,67,9110,8826,22500000,9001,8827,6500000,9001,,,
+6044,EPSG Arctic LCC zone 6-24,9802,8821,68.4114912,9110,8822,-75,9110,8823,70.2,9110,8824,67,9110,8826,24500000,9001,8827,6500000,9001,,,
+6045,EPSG Arctic LCC zone 6-26,9802,8821,68.4114912,9110,8822,-56,9110,8823,70.2,9110,8824,67,9110,8826,26500000,9001,8827,6500000,9001,,,
+6046,EPSG Arctic LCC zone 6-28,9802,8821,68.4114912,9110,8822,-38,9110,8823,70.2,9110,8824,67,9110,8826,28500000,9001,8827,6500000,9001,,,
+6047,EPSG Arctic LCC zone 6-30,9802,8821,68.4114912,9110,8822,-20,9110,8823,70.2,9110,8824,67,9110,8826,30500000,9001,8827,6500000,9001,,,
+6048,EPSG Arctic LCC zone 7-11,9802,8821,65.21037415,9110,8822,-51,9110,8823,67,9110,8824,63.4,9110,8826,11500000,9001,8827,7500000,9001,,,
+6049,EPSG Arctic LCC zone 7-13,9802,8821,65.21037415,9110,8822,-34,9110,8823,67,9110,8824,63.4,9110,8826,13500000,9001,8827,7500000,9001,,,
+6126,"Cayman Islands LCC (ft)",9802,8821,19.2,9110,8822,80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,
+6127,"Cayman Islands TM (ft)",9807,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
 10101,Alabama CS27 East zone,9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,
 10102,Alabama CS27 West zone,9807,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
 10131,"SPCS83 Alabama East zone (meters)",9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
diff --git a/data/ruian_vf_ob_v1.gfs b/data/ruian_vf_ob_v1.gfs
new file mode 100644
index 0000000..6747123
--- /dev/null
+++ b/data/ruian_vf_ob_v1.gfs
@@ -0,0 +1,1041 @@
+<GMLFeatureClassList>
+  <!-- Obce -->
+  <GMLFeatureClass>
+    <Name>Obce</Name>
+    <ElementPath>Data|Obce|Obec</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu obce -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice obce -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice obce (stupeň generalizace 3) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice3</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód obce -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název obce -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Status obce -->
+    <PropertyDefn>
+      <Name>StatusKod</Name>
+      <ElementPath>StatusKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený okres -->
+    <PropertyDefn>
+      <Name>OkresKod</Name>
+      <ElementPath>Okres|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený POU -->
+    <PropertyDefn>
+      <Name>PouKod</Name>
+      <ElementPath>Pou|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Text popisující vlajku obce -->
+    <PropertyDefn>
+      <Name>VlajkaText</Name>
+      <ElementPath>VlajkaText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek vlajky obce -->
+    <PropertyDefn>
+      <Name>VlajkaObrazek</Name>
+      <ElementPath>VlajkaObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+    <!-- Text popisující znak obce -->
+    <PropertyDefn>
+      <Name>ZnakText</Name>
+      <ElementPath>ZnakText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek znaku obce -->
+    <PropertyDefn>
+      <Name>ZnakObrazek</Name>
+      <ElementPath>ZnakObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+    <!-- Rozsah členění statutárního města na MOMC -->
+    <PropertyDefn>
+      <Name>CleneniSMRozsahKod</Name>
+      <ElementPath>CleneniSMRozsahKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Typ MOMC, na něž je statutární město rozčleněno -->
+    <PropertyDefn>
+      <Name>CleneniSMTypKod</Name>
+      <ElementPath>CleneniSMTypKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>12</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- CastiObci -->
+  <GMLFeatureClass>
+    <Name>CastiObci</Name>
+    <ElementPath>Data|CastiObci|CastObce</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu části obce -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Kód části obce -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název části obce -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Katastralní území -->
+  <GMLFeatureClass>
+    <Name>KatastralniUzemi</Name>
+    <ElementPath>Data|KatastralniUzemi|KatastralniUzemi</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu katastrálního území -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice katastrálního území -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice katastrálního území (stupeň generalizace 2) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice2</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód katastrálního území -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název katastrálního území -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Příznak existence digitální mapy -->
+    <PropertyDefn>
+      <Name>ExistujeDigitalniMapa</Name>
+      <ElementPath>ExistujeDigitalniMapa</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>RizeniId</Name>
+      <ElementPath>RizeniId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- ZSJ -->
+  <GMLFeatureClass>
+    <Name>Zsj</Name>
+    <ElementPath>Data|Zsj|Zsj</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu ZSJ -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice ZSJ -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód ZSJ -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název ZSJ -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazené katastrální území -->
+    <PropertyDefn>
+      <Name>KatastralniUzemiKod</Name>
+      <ElementPath>KatastralniUzemi|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Výměra ZSJ v metrech čtverečních -->
+    <PropertyDefn>
+      <Name>Vymera</Name>
+      <ElementPath>Vymera</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Převažující charakter využití ZSJ -->
+    <PropertyDefn>
+      <Name>CharakterZsjKod</Name>
+      <ElementPath>CharakterZsjKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Ulice -->
+  <GMLFeatureClass>
+    <Name>Ulice</Name>
+    <ElementPath>Data|Ulice|Ulice</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definiční čáry ulice -->
+    <GeomPropertyDefn>
+      <Name>DefinicniCara</Name> 
+      <ElementPath>Geometrie|DefinicniCara</ElementPath> 
+      <Type>MultiLineString</Type>
+    </GeomPropertyDefn>
+    <!-- Kód ulice -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název ulice -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Parcely -->
+  <GMLFeatureClass>
+    <Name>Parcely</Name>
+    <ElementPath>Data|Parcely|Parcela</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu parcely -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice parcely ? -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>Polygon</Type>
+    </GeomPropertyDefn>
+    <!-- Jednoznační identifikátor parcely -->
+    <PropertyDefn>
+      <Name>Id</Name>
+      <ElementPath>Id</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Kmenové parcelní číslo -->
+    <PropertyDefn>
+      <Name>KmenoveCislo</Name>
+      <ElementPath>KmenoveCislo</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Poddělení čísla parcely -->
+    <PropertyDefn>
+      <Name>PododdeleniCisla</Name>
+      <ElementPath>PododdeleniCisla</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Výměra parcely -->
+    <PropertyDefn>
+      <Name>VymeraParcely</Name>
+      <ElementPath>VymeraParcely</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Způsob využití pozemku -->
+    <PropertyDefn>
+      <Name>ZpusobyVyuzitiPozemku</Name>
+      <ElementPath>ZpusobyVyuzitiPozemku</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Rozlišení druhu číslování parcely -->
+    <PropertyDefn>
+      <Name>DruhCislovaniKod</Name>
+      <ElementPath>DruhCislovaniKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Kód druhu pozemku -->
+    <PropertyDefn>
+      <Name>DruhPozemkuKod</Name>
+      <ElementPath>DruhPozemkuKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazené katastrální území -->
+    <PropertyDefn>
+      <Name>KatastralniUzemiKod</Name>
+      <ElementPath>KatastralniUzemi|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>RizeniId</Name>
+      <ElementPath>RizeniId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Bonitované díly parcely - výměra v metrech čtverečných -->
+    <PropertyDefn>
+      <Name>BonitovanyDilVymera</Name>
+      <ElementPath>BonitovaneDily|BonitovanyDil|Vymera</ElementPath>
+      <Type>IntegerList</Type>
+    </PropertyDefn>
+    <!-- Kód bonitovaných půdně ekologických jednotek -->
+    <PropertyDefn>
+      <Name>BonitovanyDilBonitovanaJednotkaKod</Name>
+      <ElementPath>BonitovaneDily|BonitovanyDil|BonitovanaJednotkaKod</ElementPath>
+      <Type>IntegerList</Type>
+    </PropertyDefn>
+    <!-- Bonitované díly parcely - ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>BonitovanyDilIdTranskace</Name>
+      <ElementPath>BonitovaneDily|BonitovanyDil|IdTranskace</ElementPath>
+      <Type>IntegerList</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Bonitované díly parcely - ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>BonitovaneDilRizeniId</Name>
+      <ElementPath>BonitovaneDily|BonitovanyDil|RizeniId</ElementPath>
+      <Type>IntegerList</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Způsob ochrany pozemku - kód ochrany -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyKod</Name>
+      <ElementPath>ZpusobyOchranyPozemku|ZpusobOchrany|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany pozemku - typ ochrany -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyTypOchranyKod</Name>
+      <ElementPath>ZpusobyOchranyPozemku|ZpusobOchrany|TypOchranyKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+        <!-- Způsob ochrany pozemku - ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyIdTransakce</Name>
+      <ElementPath>ZpusobyOchranyPozemku|ZpusobOchrany|IdTransakce</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany pozemku - ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyRizeniId</Name>
+      <ElementPath>ZpusobyOchranyPozemku|ZpusobOchrany|RizeniId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Stavební objekty -->
+  <GMLFeatureClass>
+    <Name>StavebniObjekty</Name>
+    <ElementPath>Data|StavebniObjekty|StavebniObjekt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu stavebního objektu -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice stavebního objektu ? -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód stavebního objektu -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Seznam čísel domovních stavebního objektu -->
+    <PropertyDefn>
+      <Name>CisloDomovni</Name>
+      <ElementPath>CislaDomovni|CisloDomovni</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Jedna z parcel, na nichž je stavební objekt postaven, zvolená
+         pro identifikaci objektu (tzv. definiční parcela) -->
+    <PropertyDefn>
+      <Name>IdentifikacniParcelaId</Name>
+      <ElementPath>IdentifikacniParcela|Id</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Typ stavebního objektu -->
+    <PropertyDefn>
+      <Name>TypStavebnihoObjektuKod</Name>
+      <ElementPath>TypStavebnihoObjektuKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob využití -->
+    <PropertyDefn>
+      <Name>ZpusobVyuzitiKod</Name>
+      <ElementPath>ZpusobVyuzitiKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazená část obce -->
+    <PropertyDefn>
+      <Name>CastObceKod</Name>
+      <ElementPath>CastObce|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený MOMC -->
+    <PropertyDefn>
+      <Name>MomcKod</Name>
+      <ElementPath>Momc|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID budovy v ISKN -->
+    <PropertyDefn>
+      <Name>IsknBudovaId</Name>
+      <ElementPath>IsknBudovaId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Datum dokončení stavebního objektu -->
+    <PropertyDefn>
+      <Name>Dokonceni</Name>
+      <ElementPath>Dokonceni</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Druh svislé nosné konstrukce -->
+    <PropertyDefn>
+      <Name>DruhKonstrukceKod</Name>
+      <ElementPath>DruhKonstrukceKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Obestavěný prostor v m3 -->
+    <PropertyDefn>
+      <Name>ObestavenyProstor</Name>
+      <ElementPath>ObestavenyProstor</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Počet bytů u stavebního objektu s byty -->
+    <PropertyDefn>
+      <Name>PocetBytu</Name>
+      <ElementPath>PocetBytu</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Počet nadzemních a podzemních podlaží -->
+    <PropertyDefn>
+      <Name>PocetPodlazi</Name>
+      <ElementPath>PocetPodlazi</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Podlahová plocha v m2 -->
+    <PropertyDefn>
+      <Name>PodlahovaPlocha</Name>
+      <ElementPath>PodlahovaPlocha</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Připojení na kanalizační síť -->
+    <PropertyDefn>
+      <Name>PripojeniKanalizaceKod</Name>
+      <ElementPath>PripojeniKanalizaceKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Připojení na rozvod plynu -->
+    <PropertyDefn>
+      <Name>PripojeniPlynKod</Name>
+      <ElementPath>PripojeniPlynKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Připojení na vodovod -->
+    <PropertyDefn>
+      <Name>PripojeniVodovodKod</Name>
+      <ElementPath>PripojeniVodovodKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Vybavení výtahem -->
+    <PropertyDefn>
+      <Name>VybaveniVytahemKod</Name>
+      <ElementPath>VybaveniVytahemKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Zastavěná plocha v m2 -->
+    <PropertyDefn>
+      <Name>ZastavenaPlocha</Name>
+      <ElementPath>ZastavenaPlocha</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob vytápění -->
+    <PropertyDefn>
+      <Name>ZpusobVytapeniKod</Name>
+      <ElementPath>ZpusobVytapeniKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany stavebního objektu - kód ochrany -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyKod</Name>
+      <ElementPath>ZpusobyOchranyPozemku|ZpusobOchrany|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany stavebního objektu - typ ochrany -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyTypOchranyKod</Name>
+      <ElementPath>ZpusobyOchrany|TypOchranyKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany stavebního objektu - ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyIdTransakce</Name>
+      <ElementPath>ZpusobyOchrany|IdTransakce</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Způsob ochrany stavebního objektu - ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>ZpusobOchranyRizeniId</Name>
+      <ElementPath>ZpusobyOchrany|RizeniId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Detailní tecnicko-ekonomické atributy (TEA) (?) -->
+    <PropertyDefn>
+      <Name>DetailniTEAKod</Name>
+      <ElementPath>DetailniTEA|Kod</ElementPath>
+      <Type>IntegerList</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Adresní místa -->
+  <GMLFeatureClass>
+    <Name>AdresniMista</Name>
+    <ElementPath>Data|AdresniMista|AdresniMisto</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Definiční bod typu Adresní bod -->
+    <GeomPropertyDefn>
+      <Name>AdresniBod</Name>
+      <ElementPath>Geometrie|DefinicniBod|AdresniBod</ElementPath>
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Definiční bod typu Přístup pro záchrannou službu -->
+    <GeomPropertyDefn>
+      <Name>Zachranka</Name>
+      <ElementPath>Geometrie|DefinicniBod|Zachranka</ElementPath>
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Definiční bod typu Přístup pro hasiče -->
+    <GeomPropertyDefn>
+      <Name>Hasici</Name>
+      <ElementPath>Geometrie|DefinicniBod|Hasici</ElementPath>
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Kód adresního místa -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Číslo domovní -->
+    <PropertyDefn>
+      <Name>CisloDomovni</Name>
+      <ElementPath>CisloDomovni</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Číselná část čísla orientačního -->
+    <PropertyDefn>
+      <Name>CisloOrientacni</Name>
+      <ElementPath>CisloOrientacni</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Koncové písmeno čísla orientačního -->
+    <PropertyDefn>
+      <Name>CisloOrientacniPismeno</Name>
+      <ElementPath>CisloOrientacniPismeno</ElementPath>
+      <Type>String</Type>
+      <Width>1</Width>
+    </PropertyDefn>
+    <!-- PSČ adresní pošty -->
+    <PropertyDefn>
+      <Name>Psc</Name>
+      <ElementPath>Psc</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený stavební objekt -->
+    <PropertyDefn>
+      <Name>StavebniObjektKod</Name>
+      <ElementPath>StavebniObjekt|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazená ulice -->
+    <PropertyDefn>
+      <Name>UliceKod</Name>
+      <ElementPath>Ulice|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID budovy v ISKN -->
+    <PropertyDefn>
+      <Name>IsknBudovaId</Name>
+      <ElementPath>IsknBudovaId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/ruian_vf_st_v1.gfs b/data/ruian_vf_st_v1.gfs
new file mode 100644
index 0000000..648ccb2
--- /dev/null
+++ b/data/ruian_vf_st_v1.gfs
@@ -0,0 +1,1391 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <!-- Seznam států -->
+    <Name>Staty</Name>
+    <ElementPath>Data|Staty|Stat</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu státu -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice státu -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice státu (stupeň generalizace 5) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice5</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód státu -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název státu -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změny v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>2</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Regiony soudržnosti -->
+  <GMLFeatureClass>
+    <Name>RegionySoudrznosti</Name>
+    <ElementPath>Data|RegionySoudrznosti|RegionSoudrznosti</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu regionu soudržnosti -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice regionu soudržnosti -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice státu (stupeň generalizace 5) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice5</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód regionu soudržnosti -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název regionu soudržnosti -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazený stát -->
+    <PropertyDefn>
+      <Name>StatKod</Name>
+      <ElementPath>Stat|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>4</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Kraje -->
+  <GMLFeatureClass>
+    <Name>Kraje</Name>
+    <ElementPath>Data|Kraje|Kraj</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu kraje -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice kraje -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice kraje (stupeň generalizace 5) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice5</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód kraje -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název kraje -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazený stát -->
+    <PropertyDefn>
+      <Name>StatKod</Name>
+      <ElementPath>Stat|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>4</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- VÚSC -->
+  <GMLFeatureClass>
+    <Name>Vusc</Name>
+    <ElementPath>Data|Vusc|Vusc</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu VÚSC -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice VÚSC -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice VÚSC (stupeň generalizace 5) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice5</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód VÚSC -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+      <Width>6</Width>
+    </PropertyDefn>
+    <!-- Název VÚSC -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazený region soudržnosti -->
+    <PropertyDefn>
+      <Name>RegionSoudrznostiKod</Name>
+      <ElementPath>RegionSoudrznosti|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!--  ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Okresy -->
+  <GMLFeatureClass>
+    <Name>Okresy</Name>
+    <ElementPath>Data|Okresy|Okres</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu okresu -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice okresu -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice okresu (stupeň generalizace 4) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice4</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód okresu -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název okresu -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazený kraj -->
+    <PropertyDefn>
+      <Name>KrajKod</Name>
+      <ElementPath>Kraj|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený VÚSC -->
+    <PropertyDefn>
+      <Name>VuscKod</Name>
+      <ElementPath>Vusc|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>6</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- ORP -->
+  <GMLFeatureClass>
+    <Name>Orp</Name>
+    <ElementPath>Data|Orp|Orp</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu ORP -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice ORP-->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice ORP (stupeň generalizace 4) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice4</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód ORP -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název ORP -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Kód správni obce -->
+    <PropertyDefn>
+      <Name>SpravniObecKod</Name>
+      <ElementPath>SpravniObecKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený VÚSC -->
+    <PropertyDefn>
+      <Name>VuscKod</Name>
+      <ElementPath>Vusc|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- POU -->
+  <GMLFeatureClass>
+    <Name>Pou</Name>
+    <ElementPath>Data|Pou|Pou</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu POU -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice POU -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice POU (stupeň generalizace 4) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice4</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód POU -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název POU -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Kód správni obce -->
+    <PropertyDefn>
+      <Name>SpravniObecKod</Name>
+      <ElementPath>SpravniObecKod</ElementPath>
+      <Type>Integer</Type>
+      <Width>6</Width>
+    </PropertyDefn>
+    <!-- Nadřazený ORP -->
+    <PropertyDefn>
+      <Name>OrpKod</Name>
+      <ElementPath>Orp|Kod</ElementPath>
+      <Type>Integer</Type>
+      <Width>6</Width>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Obce -->
+  <GMLFeatureClass>
+    <Name>Obce</Name>
+    <ElementPath>Data|Obce|Obec</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu obce -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice obce -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice obce (stupeň generalizace 3) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice3</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód obce -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název obce -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Status obce -->
+    <PropertyDefn>
+      <Name>StatusKod</Name>
+      <ElementPath>StatusKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený okres -->
+    <PropertyDefn>
+      <Name>OkresKod</Name>
+      <ElementPath>Okres|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený POU -->
+    <PropertyDefn>
+      <Name>PouKod</Name>
+      <ElementPath>Pou|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Text popisující vlajku obce -->
+    <PropertyDefn>
+      <Name>VlajkaText</Name>
+      <ElementPath>VlajkaText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek vlajky obce -->
+    <PropertyDefn>
+      <Name>VlajkaObrazek</Name>
+      <ElementPath>VlajkaObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+    <!-- Text popisující znak obce -->
+    <PropertyDefn>
+      <Name>ZnakText</Name>
+      <ElementPath>ZnakText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek znaku obce -->
+    <PropertyDefn>
+      <Name>ZnakObrazek</Name>
+      <ElementPath>ZnakObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+    <!-- Rozsah členění statutárního města na MOMC -->
+    <PropertyDefn>
+      <Name>CleneniSMRozsahKod</Name>
+      <ElementPath>CleneniSMRozsahKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Typ MOMC, na něž je statutární město rozčleněno -->
+    <PropertyDefn>
+      <Name>CleneniSMTypKod</Name>
+      <ElementPath>CleneniSMTypKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Kód územního celku v NUTS / LAU -->
+    <PropertyDefn>
+      <Name>NutsLau</Name>
+      <ElementPath>NutsLau</ElementPath>
+      <Type>String</Type>
+      <Width>12</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Spravní obvody -->
+  <GMLFeatureClass>
+    <Name>SpravniObvody</Name>
+    <ElementPath>Data|SpravniObvody|SpravniObvod</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu správního obvodu-->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice správního obvodu -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód správního obvodu -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název správního obvodu -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Kód správniho MOMC -->
+    <PropertyDefn>
+      <Name>SpravniMomcKod</Name>
+      <ElementPath>SpravniMomcKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- MOP -->
+  <GMLFeatureClass>
+    <Name>Mop</Name>
+    <ElementPath>Data|Mop|Mop</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu MOP -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice MOP -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód MOP -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název MOP -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>32</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- MOMC -->
+  <GMLFeatureClass>
+    <Name>Momc</Name>
+    <ElementPath>Data|Momc|Momc</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu MOMC -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice MOMC -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód MOMC -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název MOMC -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená MOP -->
+    <PropertyDefn>
+      <Name>MopKod</Name>
+      <ElementPath>Mop|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Nadřazený správní obvod -->
+    <PropertyDefn>
+      <Name>SpravniObvodKod</Name>
+      <ElementPath>SpravniObvod|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Text popisující vlajku MOMC -->
+    <PropertyDefn>
+      <Name>VlajkaText</Name>
+      <ElementPath>VlajkaText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek vlajky MOMC -->
+    <PropertyDefn>
+      <Name>VlajkaObrazek</Name>
+      <ElementPath>VlajkaObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Text popisující znak MOMC -->
+    <PropertyDefn>
+      <Name>ZnakText</Name>
+      <ElementPath>ZnakText</ElementPath>
+      <Type>String</Type>
+      <Width>4000</Width>
+    </PropertyDefn>
+    <!-- Obrázek znaku MOMC -->
+    <PropertyDefn>
+      <Name>ZnakObrazek</Name>
+      <ElementPath>ZnakObrazek</ElementPath>
+      <Type>Complex</Type> <!-- ??? -->
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- CastiObci -->
+  <GMLFeatureClass>
+    <Name>CastiObci</Name>
+    <ElementPath>Data|CastiObci|CastObce</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu části obce -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>Point</Type>
+    </GeomPropertyDefn>
+    <!-- Kód části obce -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název části obce -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- Katastralní území -->
+  <GMLFeatureClass>
+    <Name>KatastralniUzemi</Name>
+    <ElementPath>Data|KatastralniUzemi|KatastralniUzemi</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu katastrálního území -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice katastrálního území -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Generalizovaná geometrie hranice katastrálního území (stupeň generalizace 2) -->
+    <GeomPropertyDefn>
+      <Name>GeneralizovaneHranice</Name> 
+      <ElementPath>Geometrie|GeneralizovaneHranice2</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód katastrálního území -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název katastrálního území -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Příznak existence digitální mapy -->
+    <PropertyDefn>
+      <Name>ExistujeDigitalniMapa</Name>
+      <ElementPath>ExistujeDigitalniMapa</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazená obec -->
+    <PropertyDefn>
+      <Name>ObecKod</Name>
+      <ElementPath>Obec|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID řízení v ISKN -->
+    <PropertyDefn>
+      <Name>RizeniId</Name>
+      <ElementPath>RizeniId</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+  </GMLFeatureClass>
+  <!-- ZSJ -->
+  <GMLFeatureClass>
+    <Name>Zsj</Name>
+    <ElementPath>Data|Zsj|Zsj</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::5514</SRSName>
+    <!-- Geometrie definičního bodu ZSJ -->
+    <GeomPropertyDefn>
+      <Name>DefinicniBod</Name> 
+      <ElementPath>Geometrie|DefinicniBod</ElementPath> 
+      <Type>MultiPoint</Type>
+    </GeomPropertyDefn>
+    <!-- Originální geometrie hranice ZSJ -->
+    <GeomPropertyDefn>
+      <Name>OriginalniHranice</Name> 
+      <ElementPath>Geometrie|OriginalniHranice</ElementPath> 
+      <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <!-- Kód ZSJ -->
+    <PropertyDefn>
+      <Name>Kod</Name>
+      <ElementPath>Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Název ZSJ -->
+    <PropertyDefn>
+      <Name>Nazev</Name>
+      <ElementPath>Nazev</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Identifikátor nesprávnosti na prvku (?) -->
+    <PropertyDefn>
+      <Name>Nespravny</Name>
+      <ElementPath>Nespravny</ElementPath>
+      <Type>String</Type>
+      <Width>5</Width>
+    </PropertyDefn>
+    <!-- Nadřazené katastrální území -->
+    <PropertyDefn>
+      <Name>KatastralniUzemiKod</Name>
+      <ElementPath>KatastralniUzemi|Kod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+    <!-- Začátek platnosti -->
+    <PropertyDefn>
+      <Name>PlatiOd</Name>
+      <ElementPath>PlatiOd</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- Konec platnosti -->
+    <PropertyDefn>
+      <Name>PlatiDo</Name>
+      <ElementPath>PlatiDo</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
+    <!-- ID transakce v RUIAN -->
+    <PropertyDefn>
+      <Name>IdTransakce</Name>
+      <ElementPath>IdTransakce</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- ID návrhu změn v ISUI -->
+    <PropertyDefn>
+      <Name>GlobalniIdNavrhuZmeny</Name>
+      <ElementPath>GlobalniIdNavrhuZmeny</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Mluvnické charakteristiky 2 až 7 pád -->
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad2</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad2</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad3</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad3</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad4</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad4</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad6</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad6</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>MluvnickeCharakteristikyPad7</Name>
+      <ElementPath>MluvnickeCharakteristiky|Pad7</ElementPath>
+      <Type>String</Type>
+      <Width>48</Width>
+    </PropertyDefn>
+    <!-- Výměra ZSJ v metrech čtverečních -->
+    <PropertyDefn>
+      <Name>Vymera</Name>
+      <ElementPath>Vymera</ElementPath>
+      <Type>Integer</Type>
+      <Width>18</Width>
+    </PropertyDefn>
+    <!-- Převažující charakter využití ZSJ -->
+    <PropertyDefn>
+      <Name>CharakterZsjKod</Name>
+      <ElementPath>CharakterZsjKod</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/unit_of_measure.csv b/data/unit_of_measure.csv
index 4e60455..1f55224 100644
--- a/data/unit_of_measure.csv
+++ b/data/unit_of_measure.csv
@@ -37,7 +37,7 @@ uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,r
 9087,Indian yard (1975),length,9001,0.9143985,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures as 1 Ind ft=0.3047995m.  Used in India since metrication.,"G. Bomford; ""Geodesy""; 3rd edition 1975",OGP,2007/01/25,1997.231 1999.990 2007.011,0
 9093,Statute mile,length,9001,1609.344,1,=5280 feet,OGP,OGP,2000/03/07,,0
 9094,Gold Coast foot,length,9001,6378300,20926201,"Used in Ghana and some adjacent parts of British west Africa prior to metrication, except for the metrication of projection defining parameters when British foot (Sears 1922) used.",Ordnance Survey International,OGP,2001/01/21,2000.861,0
-9095,British foot (1936),length,9001,0.3048007491,1,For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through the logarithmic relationship (10^0.48401603 exactly). 1 ft = 0.3048007491
m. Also used for metric conversions in Ireland.,"1. ""The Retriangulation of Great Britain"", Ordnance Survey of Great Britain.
+9095,British foot (1936),length,9001,0.3048007491,1,For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through the logarithmic relationship (10^0.48401603 exactly). 1 ft = 0.3048007491Â…m. Also used for metric conversions in Ireland.,"1. ""The Retriangulation of Great Britain"", Ordnance Survey of Great Britain.
 2. ""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",OGP,2006/11/27,2002.621 2006.932,0
 9096,yard,length,9001,0.9144,1,=3 international feet.,OGP,OGP,2006/07/14,,0
 9097,chain,length,9001,20.1168,1,=22 international yards or 66 international feet.,OGP,OGP,2006/07/14,,0
diff --git a/data/vertcs.csv b/data/vertcs.csv
index ccfb9ff..f9e3080 100644
--- a/data/vertcs.csv
+++ b/data/vertcs.csv
@@ -40,7 +40,7 @@
 5705,Baltic height,5105,Baltic Sea,9001,1,0,6499,,
 5706,Caspian depth,5106,Caspian Sea,9001,1,0,6498,,
 5709,NAP height,5109,Normaal Amsterdams Peil,9001,1,0,6499,,
-5710,Oostende height,5110,Oostende,9001,1,0,6499,,
+5710,Ostend height,5110,Ostend,9001,1,0,6499,,
 5711,AHD height,5111,Australian Height Datum,9001,1,0,6499,,
 5712,"AHD (Tasmania) height",5112,"Australian Height Datum (Tasmania)",9001,1,0,6499,,
 5713,CGVD28 height,5114,Canadian Geodetic Vertical Datum of 1928,9001,1,0,6499,,
@@ -106,7 +106,7 @@
 5773,EGM96 geoid height,5171,EGM96 geoid,9001,1,0,6499,9665,"egm96_15.gtx"
 5774,NG-L height,5172,Nivellement General du Luxembourg,9001,1,0,6499,,
 5775,Antalya height,5173,Antalya,9001,1,0,6499,,
-5776,NN54 height,5174,Norway Normal Nul 1954,9001,1,0,6499,,
+5776,NN54 height,5174,Norway Normal Null 1954,9001,1,0,6499,,
 5777,Durres height,5175,Durres,9001,1,0,6499,,
 5778,GHA height,5176,Gebrauchshohen ADRIA,9001,1,0,6499,,
 5779,NVN99 height,5177,National Vertical Network 1999,9001,1,0,6499,,
@@ -146,3 +146,17 @@
 5872,HAT height,1082,Highest Astronomic Tide,9001,1,0,6499,,
 5873,Low Water depth,1093,Low Water,9001,1,0,6498,,
 5874,High Water height,1094,High Water,9001,1,0,6499,,
+5941,NN2000 height,1096,Norway Normal Null 2000,9001,1,0,6499,,
+6130,GCVD54 height,1097,Grand Cayman Vertical Datum 1954,9002,1,0,1030,,
+6131,LCVD61 height,1098,Little Cayman Vertical Datum 1961,9002,1,0,1030,,
+6132,CBVD61 height,1099,Cayman Brac Vertical Datum 1961,9002,1,0,1030,,
+6178,Cais da Pontinha - Funchal height,1101,Cais da Pontinha - Funchal,9001,1,0,6499,,
+6179,Cais da Vila - Porto Santo height,1102,Cais da Vila - Porto Santo,9001,1,0,6499,,
+6180,Cais das Velas height,1103,Cais das Velas,9001,1,0,6499,,
+6181,Horta height,1104,Horta,9001,1,0,6499,,
+6182,Cais da Madalena height,1105,Cais da Madalena,9001,1,0,6499,,
+6183,Santa Cruz da Graciosa height,1106,Santa Cruz da Graciosa,9001,1,0,6499,,
+6184,"Cais da Figueirinha - Angra do Heroísmo height",1107,"Cais da Figueirinha - Angra do Heroísmo",9001,1,0,6499,,
+6185,Santa Cruz das Flores height,1108,Santa Cruz das Flores,9001,1,0,6499,,
+6186,Cais da Vila do Porto height,1109,Cais da Vila do Porto,9001,1,0,6499,,
+6187,Ponta Delgada height,1110,Ponta Delgada,9001,1,0,6499,,
diff --git a/doc/br/index_br.dox b/doc/br/index_br.dox
index 3dc7aa2..d93ff7b 100644
--- a/doc/br/index_br.dox
+++ b/doc/br/index_br.dox
@@ -27,7 +27,7 @@ A bilioteca GDAL também conta com uma variadade de programas
 para a tradução de formatos bem como uma série de outras funções. 
 A página 
 <a href="http://trac.osgeo.org/gdal/wiki/Release/1.9.0-News">novidades</a> descreve o 
-lançamento em Dezembro de 2011 da release 1.9.0 da biblioteca GDAL/OGR.
+lançamento em Abril de 2013 da release 1.10.0 da biblioteca GDAL/OGR.
 
 A bilioteca <a href="ogr">OGR</a> (cujo código fonte esta incluído na GDAL) possue
 funcionalidades semelhantes às da GDAL para datos vetorias (Simple Features).
diff --git a/doc/gdal_tutorial.dox b/doc/gdal_tutorial.dox
index 32c5346..17c7ac4 100644
--- a/doc/gdal_tutorial.dox
+++ b/doc/gdal_tutorial.dox
@@ -1,4 +1,4 @@
-/* $Id: gdal_tutorial.dox 20418 2010-08-23 19:01:36Z rouault $ */
+/* $Id: gdal_tutorial.dox 26639 2013-11-20 12:34:03Z rouault $ */
 
 /*!
 \page gdal_tutorial GDAL API Tutorial
@@ -83,15 +83,20 @@ area, and having the same resolution.  It also has metadata, a coordinate
 system, a georeferencing transform, size of raster and various other 
 information.  
 
+In the particular, but common, case of a "north up" image without any rotation
+or shearing, the georeferencing transform takes the following form :
+
 \code
     adfGeoTransform[0] /* top left x */
     adfGeoTransform[1] /* w-e pixel resolution */
-    adfGeoTransform[2] /* rotation, 0 if image is "north up" */
+    adfGeoTransform[2] /* 0 */
     adfGeoTransform[3] /* top left y */
-    adfGeoTransform[4] /* rotation, 0 if image is "north up" */
-    adfGeoTransform[5] /* n-s pixel resolution */
+    adfGeoTransform[4] /* 0 */
+    adfGeoTransform[5] /* n-s pixel resolution (negative value) */
 \endcode
 
+In the general case, this is an affine transform.
+
 If we wanted to print some general information about the 
 dataset we might do the following:
 
@@ -646,7 +651,7 @@ In Python:
 
 \htmlonly
 <p>
-$Id: gdal_tutorial.dox 20418 2010-08-23 19:01:36Z rouault $
+$Id: gdal_tutorial.dox 26639 2013-11-20 12:34:03Z rouault $
 </p>
 \endhtmlonly
 
diff --git a/doc/images/foss4g09.png b/doc/images/foss4g09.png
deleted file mode 100644
index df913fb..0000000
Binary files a/doc/images/foss4g09.png and /dev/null differ
diff --git a/doc/images/foss4g2013.png b/doc/images/foss4g2013.png
new file mode 100644
index 0000000..62968da
Binary files /dev/null and b/doc/images/foss4g2013.png differ
diff --git a/doc/index.dox b/doc/index.dox
index 46ca210..0b04f84 100644
--- a/doc/index.dox
+++ b/doc/index.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP                                                            
-/* $Id: index.dox 25344 2012-12-23 23:56:10Z rouault $ */               
+/* $Id: index.dox 26546 2013-10-22 22:22:36Z warmerdam $ */               
 #endif /* DOXYGEN_SKIP */                                                       
 
 /*! \mainpage GDAL - Geospatial Data Abstraction Library
@@ -16,8 +16,8 @@ Geospatial Foundation</a>.  As a library, it presents a
 to the calling application for all supported formats.  It also comes with a variety
 of useful \link gdal_utilities.html commandline utilities\endlink
 for data translation and processing.  The 
-<a href="http://trac.osgeo.org/gdal/wiki/Release/1.9.2-News">NEWS</a>
-page describes the October 2012 GDAL/OGR 1.9.2 release.
+<a href="http://trac.osgeo.org/gdal/wiki/Release/1.10.1-News">NEWS</a>
+page describes the August 2013 GDAL/OGR 1.10.1 release.
 
 The related <a href="ogr/index.html">OGR</a> library (which lives within the GDAL source tree) 
 provides a similar capability for simple features vector data.
@@ -59,6 +59,24 @@ Download:
 <li> <a href="wince.html">GDAL for Windows CE</a>
 </ul>
 
+\section foss4g Conference 
+ 
+\htmlonly 
+<table border="0" cellspacing="4" cellpadding="4"> 
+
+<tr><td><a href="http://2013.foss4g.org/"> 
+<img src="foss4g2013.png" alt="FOSS4G 2013" border="0" width="200" height="117"> 
+</a></td> 
+ 
+<td><a href="http://2013.foss4g.org">FOSS4G 2013</a> is the leading annual  
+conference for free and open source geospatial software.  It will include  
+presentations related to GDAL/OGR, and some of the GDAL/OGR  
+development community will be attending.  It is <i>the</i> event for those  
+interested in GDAL/OGR, other FOSS geospatial technologies and the community  
+around them.</td> 
+</table> 
+\endhtmlonly
+
 \section index_maillist Mailing List
 
 A gdal-announce mailing list <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce/">subscription</a> is a low volume way of keeping track of major
@@ -92,10 +110,10 @@ The following bindings of GDAL in other languages are available:
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPerl">Perl</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
 <li> <a href="vb6_tutorial.html">VB6 Bindings</a> (not using SWIG)
-<li> <a href="https://r-forge.r-project.org/projects/rgdal/">GDAL Bindings into R</a> by Timothy H. Keitt.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInRuby">Ruby</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInJava">Java</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharp">C# / .Net</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInRuby">Ruby</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInR">R</a>
 
 </ul>
 
diff --git a/frmts/aaigrid/aaigriddataset.cpp b/frmts/aaigrid/aaigriddataset.cpp
index 38ebe75..faf5309 100644
--- a/frmts/aaigrid/aaigriddataset.cpp
+++ b/frmts/aaigrid/aaigriddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $
+ * $Id: aaigriddataset.cpp 27050 2014-03-18 00:09:03Z kyle $
  *
  * Project:  GDAL
  * Purpose:  Implements Arc/Info ASCII Grid Format.
@@ -7,6 +7,8 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam (warmerdam at pobox.com)
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2014, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +35,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $");
+CPL_CVSID("$Id: aaigriddataset.cpp 27050 2014-03-18 00:09:03Z kyle $");
 
 CPL_C_START
 void    GDALRegister_AAIGrid(void);
@@ -1034,47 +1036,70 @@ GDALDataset * AAIGDataset::CreateCopy(
     }
 
 /* -------------------------------------------------------------------- */
+/*     Builds the format string used for printing float values.         */
+/* -------------------------------------------------------------------- */
+    char szFormatFloat[32];
+    strcpy(szFormatFloat, " %.20g");
+    const char *pszDecimalPrecision = 
+        CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
+    const char *pszSignificantDigits =
+        CSLFetchNameValue( papszOptions, "SIGNIFICANT_DIGITS" );
+    int bIgnoreSigDigits = FALSE;
+    if( pszDecimalPrecision && pszSignificantDigits )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Conflicting precision arguments, using DECIMAL_PRECISION" );
+        bIgnoreSigDigits = TRUE;
+    }
+    int nPrecision;
+    if ( pszSignificantDigits && !bIgnoreSigDigits )
+    {
+        nPrecision = atoi( pszSignificantDigits );
+        if (nPrecision >= 0)
+            sprintf( szFormatFloat, " %%.%dg", nPrecision );
+        CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
+    }
+    else if( pszDecimalPrecision )
+    {
+        nPrecision = atoi( pszDecimalPrecision );
+        if ( nPrecision >= 0 )
+            sprintf( szFormatFloat, " %%.%dlf", nPrecision );
+        CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Handle nodata (optionally).                                     */
 /* -------------------------------------------------------------------- */
     GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
     double dfNoData;
     int bSuccess;
+    int bReadAsInt;
+    bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte
+                || poBand->GetRasterDataType() == GDT_Int16
+                || poBand->GetRasterDataType() == GDT_UInt16
+                || poBand->GetRasterDataType() == GDT_Int32 );
 
     // Write `nodata' value to header if it is exists in source dataset
     dfNoData = poBand->GetNoDataValue( &bSuccess );
     if ( bSuccess )
-        sprintf( szHeader+strlen(szHeader), "NODATA_value %6.20g\n", 
-                 dfNoData );
-    
-    VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
-
-/* -------------------------------------------------------------------- */
-/*     Builds the format string used for printing float values.         */
-/* -------------------------------------------------------------------- */
-    char szFormatFloat[32];
-    strcpy(szFormatFloat, " %.20g");
-    const char *pszDecimalPrecision = 
-        CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
-    if (pszDecimalPrecision)
     {
-        int nDecimal = atoi(pszDecimalPrecision);
-        if (nDecimal >= 0)
-            sprintf(szFormatFloat, " %%.%dg", nDecimal);
+        sprintf( szHeader+strlen( szHeader ), "NODATA_value " );
+        if( bReadAsInt )
+            sprintf( szHeader+strlen( szHeader ), "%d", (int)dfNoData );
+        else
+            sprintf( szHeader+strlen( szHeader ), szFormatFloat, dfNoData );
+        sprintf( szHeader+strlen( szHeader ), "\n" );
     }
 
+    VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
+
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
     int         *panScanline = NULL;
     double      *padfScanline = NULL;
-    int         bReadAsInt;
     int         iLine, iPixel;
     CPLErr      eErr = CE_None;
-    
-    bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte 
-                || poBand->GetRasterDataType() == GDT_Int16
-                || poBand->GetRasterDataType() == GDT_UInt16
-                || poBand->GetRasterDataType() == GDT_Int32 );
 
     // Write scanlines to output file
     if (bReadAsInt)
@@ -1275,7 +1300,8 @@ void GDALRegister_AAIGrid()
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
 "<CreationOptionList>\n"
 "   <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
-"   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers.'/>\n"
+"   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers(%f).'/>\n"
+"   <Option name='SIGNIFICANT_DIGITS' type='int' description='Number of significant digits when writing floating-point numbers(%g).'/>\n"
 "</CreationOptionList>\n" );
 
         poDriver->pfnOpen = AAIGDataset::Open;
diff --git a/frmts/adrg/adrgdataset.cpp b/frmts/adrg/adrgdataset.cpp
index 2c61a20..8c6382c 100644
--- a/frmts/adrg/adrgdataset.cpp
+++ b/frmts/adrg/adrgdataset.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: adrgdataset.cpp 25843 2013-04-02 22:35:21Z rouault $
+ * $Id: adrgdataset.cpp 27095 2014-03-26 15:07:10Z rouault $
  *
  * Purpose:  ADRG reader
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "iso8211.h"
 
-CPL_CVSID("$Id: adrgdataset.cpp 25843 2013-04-02 22:35:21Z rouault $");
+CPL_CVSID("$Id: adrgdataset.cpp 27095 2014-03-26 15:07:10Z rouault $");
 
 #define N_ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))
 
@@ -79,6 +79,7 @@ class ADRGDataset : public GDALPamDataset
     virtual CPLErr GetGeoTransform( double * padfGeoTransform );
     virtual CPLErr SetGeoTransform( double * padfGeoTransform );
 
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
     
     virtual char      **GetFileList();
@@ -686,6 +687,17 @@ void ADRGDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGF
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **ADRGDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -1068,6 +1080,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     if (fdIMG == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
+        delete[] TILEINDEX;
         return NULL;
     }
     
@@ -1075,6 +1088,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
         VSIFCloseL(fdIMG);
+        delete[] TILEINDEX;
         return NULL;
     }
     
@@ -1085,6 +1099,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
     {
         VSIFCloseL(fdIMG);
+        delete[] TILEINDEX;
         return NULL;
     }
     while (!VSIFEofL(fdIMG))
@@ -1094,20 +1109,18 @@ ADRGDataset* ADRGDataset::OpenDataset(
             if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
             {
                 VSIFCloseL(fdIMG);
+                delete[] TILEINDEX;
                 return NULL;
             }
             offsetInIMG += 3;
             if (strncmp(recordName,"IMG",3) == 0)
             {
                 offsetInIMG += 4;
-                if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
-                {
-                    VSIFCloseL(fdIMG);
-                    return NULL;
-                }
-                if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
+                if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0 ||
+                    VSIFReadL(&c, 1, 1, fdIMG) != 1)
                 {
                     VSIFCloseL(fdIMG);
+                    delete[] TILEINDEX;
                     return NULL;
                 }
                 while(c ==' ')
@@ -1116,6 +1129,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
                     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
                     {
                         VSIFCloseL(fdIMG);
+                        delete[] TILEINDEX;
                         return NULL;
                     }
                 }
@@ -1128,6 +1142,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
         {
             VSIFCloseL(fdIMG);
+            delete[] TILEINDEX;
             return NULL;
         }
     }
@@ -1135,6 +1150,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     if (VSIFEofL(fdIMG))
     {
         VSIFCloseL(fdIMG);
+        delete[] TILEINDEX;
         return NULL;
     }
     
diff --git a/frmts/adrg/srpdataset.cpp b/frmts/adrg/srpdataset.cpp
index f1f9450..47119f2 100644
--- a/frmts/adrg/srpdataset.cpp
+++ b/frmts/adrg/srpdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: srpdataset.cpp 25844 2013-04-02 22:40:27Z rouault $
+ * $Id: srpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  * Purpose:  ASRP/USRP Reader
  * Author:   Frank Warmerdam (warmerdam at pobox.com)
  *
  * Derived from ADRG driver by Even Rouault, even.rouault at mines-paris.org.
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2009, Frank Warmerdam
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -33,7 +33,10 @@
 #include "cpl_string.h"
 #include "iso8211.h"
 
-CPL_CVSID("$Id: srpdataset.cpp 25844 2013-04-02 22:40:27Z rouault $");
+// Uncomment to recognize also .gen files in addition to .img files
+// #define OPEN_GEN
+
+CPL_CVSID("$Id: srpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 class SRPDataset : public GDALPamDataset
 {
@@ -46,8 +49,9 @@ class SRPDataset : public GDALPamDataset
     int          offsetInIMG;
     CPLString    osProduct;
     CPLString    osSRS;
-    CPLString    osGENFilename;
-    CPLString    osQALFilename;
+    CPLString    osGENFileName;
+    CPLString    osQALFileName;
+    CPLString    osIMGFileName;
     int          NFC;
     int          NFL;
     int          ZNA;
@@ -60,19 +64,33 @@ class SRPDataset : public GDALPamDataset
     int          PCB;
     int          PVB;
 
+
+    char**       papszSubDatasets;
+
     GDALColorTable oCT;
 
-  public:
-                 SRPDataset();
+
+    static char** GetGENListFromTHF(const char* pszFileName);
+    static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
+    static SRPDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
+    static DDFRecord*  FindRecordInGENForIMG(DDFModule& module,
+        const char* pszGENFileName, const char* pszIMGFileName);
+
+public:
+    SRPDataset();
     virtual     ~SRPDataset();
     
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * padfGeoTransform );
 
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+
     virtual char **GetFileList();
 
     int                 GetFromRecord( const char* pszFileName, 
                                        DDFRecord * record);
+    void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
+    void  AddMetadatafromFromTHF(const char* pszFileName);
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -314,6 +332,7 @@ SRPDataset::SRPDataset()
     fdIMG = NULL;
     TILEINDEX = NULL;
     offsetInIMG = 0;
+    papszSubDatasets = NULL;
 }
 
 /************************************************************************/
@@ -322,6 +341,9 @@ SRPDataset::SRPDataset()
 
 SRPDataset::~SRPDataset()
 {
+
+    CSLDestroy(papszSubDatasets);
+
     if (fdIMG)
     {
         VSIFCloseL(fdIMG);
@@ -620,48 +642,100 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 /*      Try to collect a color map from the .QAL file.                  */
 /* -------------------------------------------------------------------- */
     CPLString osBasename = CPLGetBasename(pszFileName);
-    osQALFilename = CPLFormCIFilename(osDirname, osBasename, "QAL");
+    osQALFileName = CPLFormCIFilename(osDirname, osBasename, "QAL");
 
     DDFModule oQALModule;
 
-    if( oQALModule.Open( osQALFilename, TRUE ) )
+    if( oQALModule.Open( osQALFileName, TRUE ) )
     {
-        while( (record = oQALModule.ReadRecord()) != NULL
-               && record->FindField( "COL" ) == NULL ) {}
-
-        if( record != NULL )
+        while( (record = oQALModule.ReadRecord()) != NULL)
         {
-            int            iColor;
-            int            nColorCount = 
-                record->FindField("COL")->GetRepeatCount();
+            if( record->FindField( "COL" ) != NULL ) 
+            {
+                int            iColor;
+                int            nColorCount = 
+                    record->FindField("COL")->GetRepeatCount();
 
-            for( iColor = 0; iColor < nColorCount; iColor++ )
+                for( iColor = 0; iColor < nColorCount; iColor++ )
+                {
+                    int bSuccess;
+                    int nCCD, nNSR, nNSG, nNSB;
+                    GDALColorEntry sEntry;
+
+                    nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
+                        &bSuccess );
+                    if( !bSuccess )
+                        break;
+
+                    nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
+                    nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
+                    nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
+
+                    sEntry.c1 = (short) nNSR;
+                    sEntry.c2 = (short) nNSG;
+                    sEntry.c3 = (short) nNSB;
+                    sEntry.c4 = 255;
+
+                    oCT.SetColorEntry( nCCD, &sEntry );
+                }
+            }
+
+            if (record->FindField( "QUV" ) != NULL )
             {
-                int bSuccess;
-                int nCCD, nNSR, nNSG, nNSB;
-                GDALColorEntry sEntry;
+                //Date de production du produit : QAL.QUV.DAT1
+                //Num�ro d'�dition  du produit : QAL.QUV.EDN
 
-                nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
-                                               &bSuccess );
-                if( !bSuccess )
-                    break;
+                int EDN = record->GetIntSubfield( "QUV", 0, "EDN", 0, &bSuccess );
+                if (bSuccess)
+                {
+                    CPLDebug("SRP", "EDN=%d", EDN);
+                    char pszValue[5];
+                    sprintf(pszValue, "%d", EDN);
+                    SetMetadataItem( "SRP_EDN", pszValue );
+                }
 
-                nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
-                nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
-                nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
 
-                sEntry.c1 = (short) nNSR;
-                sEntry.c2 = (short) nNSG;
-                sEntry.c3 = (short) nNSB;
-                sEntry.c4 = 255;
+                const char* pszCDV07 = record->GetStringSubfield( "QUV", 0, "CDV07", 0 );
+                if (pszCDV07!=NULL)
+                    SetMetadataItem( "SRP_CREATIONDATE", pszCDV07 );
+                else
+                { /*USRP1.2*/
+                    const char* pszDAT = record->GetStringSubfield("QUV", 0, "DAT1", 0);
+                    if( pszDAT != NULL )
+                    {
+                        char dat[9];
+                        strncpy(dat,pszDAT+4,8);
+                        dat[8]='\0';
+                        CPLDebug("SRP", "Record DAT %s",dat);
+                        SetMetadataItem( "SRP_CREATIONDATE", dat );
+                    }
+                }
 
-                oCT.SetColorEntry( nCCD, &sEntry );
+                const char* pszCDV24 = record->GetStringSubfield( "QUV", 0, "CDV24", 0 );
+                if (pszCDV24!=NULL)
+                    SetMetadataItem( "SRP_REVISIONDATE", pszCDV24 );
+                else
+                { /*USRP1.2*/
+                    const char* pszDAT = record->GetStringSubfield("QUV", 0, "DAT2", 0);
+                    if( pszDAT != NULL )
+                    {
+                        char dat[9];
+                        strncpy(dat,pszDAT+4,8);
+                        dat[8]='\0';
+                        CPLDebug("SRP", "Record DAT %s",dat);
+                        SetMetadataItem( "SRP_REVISIONDATE", dat );
+                    }
+                }
+
+                const char* pszQSS = record->GetStringSubfield( "QSR", 0, "QSS", 0 );
+                if (pszQSS!=NULL)
+                    SetMetadataItem( "SRP_CLASSIFICATION", pszQSS );
             }
         }
     }
     else
     {
-        osQALFilename = "";
+        osQALFileName = "";
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Unable to find .QAL file, no color table applied." );
     }
@@ -707,6 +781,9 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         CPLFree( pszWKT );
     }
 
+    sprintf(pszValue, "%d", ZNA);
+    SetMetadataItem( "SRP_ZNA", pszValue );
+
     return TRUE;
 }
 
@@ -717,155 +794,808 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 char **SRPDataset::GetFileList()
 
 {
-     char **papszFileList = GDALPamDataset::GetFileList();
+    char **papszFileList = GDALPamDataset::GetFileList();
+    if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
+    {
+        CPLString osMainFilename = GetDescription();
+        int bMainFileReal;
+        VSIStatBufL  sStat;
+
+        bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
+        if (bMainFileReal)
+        {
+            CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
+            CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
+            if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
+                papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
+        }
+        else
+            papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
 
-     papszFileList = CSLAddString( papszFileList, osGENFilename );
+        papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
 
-     if( strlen(osQALFilename) > 0 )
-         papszFileList = CSLAddString( papszFileList, osQALFilename );
 
-     return papszFileList;
+        if( strlen(osQALFileName) > 0 )
+            papszFileList = CSLAddString( papszFileList, osQALFileName );
+    }
+    return papszFileList;
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                           AddSubDataset()                            */
 /************************************************************************/
 
-GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
+void SRPDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName )
 {
-    DDFModule module;
-    DDFRecord * record;
-    CPLString osFileName(poOpenInfo->pszFilename);
-    CPLString osNAM;
+    char	szName[80];
+    int		nCount = CSLCount(papszSubDatasets ) / 2;
+
+    CPLString osSubDatasetName;
+    osSubDatasetName = "SRP:";
+    osSubDatasetName += pszGENFileName;
+    osSubDatasetName += ",";
+    osSubDatasetName += pszIMGFileName;
+
+    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets = 
+        CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
+
+    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets = 
+        CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
+}
 
-/* -------------------------------------------------------------------- */
-/*      Verify that this appears to be a valid ISO8211 .IMG file.       */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 500 )
-        return NULL;
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **SRPDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        return papszSubDatasets;
+
+    return GDALPamDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
+/*                      FindRecordInGENForIMG()                         */
+/************************************************************************/
 
-    if (!EQUAL(CPLGetExtension(osFileName), "img"))
+DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
+                                            const char* pszGENFileName,
+                                            const char* pszIMGFileName)
+{
+    /* Finds the GEN file corresponding to the IMG file */
+    if (!module.Open(pszGENFileName, TRUE))
         return NULL;
 
-    static const size_t nLeaderSize = 24;
-    int         i;
 
-    for( i = 0; i < (int)nLeaderSize; i++ )
+    CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
+
+    DDFField* field;
+    DDFFieldDefn *fieldDefn;
+
+    /* Now finds the record */
+    while (TRUE)
     {
-        if( poOpenInfo->pabyHeader[i] < 32 
-            || poOpenInfo->pabyHeader[i] > 126 )
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        DDFRecord* record = module.ReadRecord();
+        CPLPopErrorHandler();
+        CPLErrorReset();
+        if (record == NULL)
             return NULL;
+
+        if (record->GetFieldCount() >= 5)
+        {
+            field = record->GetField(0);
+            fieldDefn = field->GetFieldDefn();
+            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                fieldDefn->GetSubfieldCount() == 2))
+            {
+                continue;
+            }
+
+            const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
+            if( RTY == NULL )
+                continue;
+            /* Ignore overviews */
+            if ( strcmp(RTY, "OVV") == 0 )
+                continue;
+
+            if ( strcmp(RTY, "GIN") != 0 )
+                continue;
+
+            field = record->GetField(3);
+            fieldDefn = field->GetFieldDefn();
+
+            if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
+                fieldDefn->GetSubfieldCount() == 15))
+            {
+                continue;
+            }
+
+            const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
+            if( pszBAD == NULL || strlen(pszBAD) != 12 )
+                continue;
+            CPLString osBAD = pszBAD;
+            {
+                char* c = (char*) strchr(osBAD.c_str(), ' ');
+                if (c)
+                    *c = 0;
+            }
+
+            if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
+            {
+                return record;
+            }
+        }
     }
+}
+/************************************************************************/
+/*                           OpenDataset()                              */
+/************************************************************************/
 
-    if( poOpenInfo->pabyHeader[5] != '1' 
-        && poOpenInfo->pabyHeader[5] != '2' 
-        && poOpenInfo->pabyHeader[5] != '3' )
+SRPDataset* SRPDataset::OpenDataset(
+    const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
+{
+    DDFModule module;    
+    DDFField* field;
+    DDFFieldDefn *fieldDefn;
+
+    if (record == NULL)
+    {
+        record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
+        if (record == NULL)
+            return NULL;
+    }
+
+    field = record->GetField(1);
+    if( field == NULL )
         return NULL;
+    fieldDefn = field->GetFieldDefn();
 
-    if( poOpenInfo->pabyHeader[6] != 'L' )
+    if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
+        fieldDefn->GetSubfieldCount() == 2))
+    {
         return NULL;
-    if( poOpenInfo->pabyHeader[8] != '1' && poOpenInfo->pabyHeader[8] != ' ' )
+    }
+
+    const char* pszPRT = record->GetStringSubfield("DSI", 0, "PRT", 0);
+    if( pszPRT == NULL) 
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Find and open the .GEN file.                                    */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
+    CPLString osPRT = pszPRT;
+    osPRT.resize(4);
+    CPLDebug("SRP", "osPRT=%s", osPRT.c_str());
+    if( !EQUAL(osPRT,"ASRP") && !EQUAL(osPRT,"USRP") )
+        return NULL;
+
+    const char* pszNAM = record->GetStringSubfield("DSI", 0, "NAM", 0);
+    if( pszNAM == NULL  )
+        return NULL;
+
+
+    CPLString osNAM = pszNAM;
+    CPLDebug("SRP", "osNAM=%s", osNAM.c_str());
+    if ( strlen(pszNAM) != 8 )
+    {
+        CPLDebug("SRP", "Name Size=%d", (int)strlen(pszNAM) );
+    }
+
+    SRPDataset* poDS = new SRPDataset();
+
+    poDS->osProduct = osPRT;
+    poDS->osGENFileName = pszGENFileName;
+    poDS->osIMGFileName = pszIMGFileName;
+
+
+    
+    poDS->SetMetadataItem( "SRP_NAM", osNAM );
+    poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
+
 
-    CPLString basename = CPLGetBasename( osFileName );
-    if( basename.size() != 8 )
+    if (!poDS->GetFromRecord( pszGENFileName, record ) )
     {
-        CPLDebug("SRP", "Invalid basename file");
+        delete poDS;
         return NULL;
     }
 
-    int zoneNumber = CPLScanLong( basename + 6, 2 );
+    return poDS;
+
+}
+
+
+
+/************************************************************************/
+/*                          GetGENListFromTHF()                         */
+/************************************************************************/
+
+char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
+{
+    DDFModule module;
+    DDFRecord * record;
+    DDFField* field;
+    DDFFieldDefn *fieldDefn;
+    int i;
+    int nFilenames = 0;
+
+    char** papszFileNames = NULL;
+    if (!module.Open(pszFileName, TRUE))
+        return papszFileNames;
 
-    CPLString path = CPLGetDirname( osFileName );
-    CPLString basename01 = ResetTo01( basename );
-    osFileName = CPLFormFilename( path, basename01, ".IMG" );
+    CPLString osDirName(CPLGetDirname(pszFileName));
 
-    osFileName = CPLResetExtension( osFileName, "GEN" );
-    if( VSIStatL( osFileName, &sStatBuf ) != 0 )
+    while (TRUE)
     {
-        osFileName = CPLResetExtension( osFileName, "gen" );
-        if( VSIStatL( osFileName, &sStatBuf ) != 0 )
-            return NULL;
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        record = module.ReadRecord();
+        CPLPopErrorHandler();
+        CPLErrorReset();
+        if (record == NULL)
+            break;
+        if (record->GetFieldCount() > 2)
+        {
+            field = record->GetField(0);
+            fieldDefn = field->GetFieldDefn();
+            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                fieldDefn->GetSubfieldCount() == 2))
+            {
+                continue;
+            }
+
+            const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
+            if ( RTY == NULL )
+            {
+                continue;
+            }
+
+            if ( strcmp(RTY, "THF") == 0 )
+            {
+                field = record->GetField(1);
+                fieldDefn = field->GetFieldDefn();
+                if (!(strcmp(fieldDefn->GetName(), "VDR") == 0 &&
+                    fieldDefn->GetSubfieldCount() == 8))
+                {
+                    continue;
+                }
+
+                int iFDRFieldInstance = 0;
+                for (i = 2; i < record->GetFieldCount() ; i++)
+                {
+                    field = record->GetField(i);
+                    fieldDefn = field->GetFieldDefn();
+
+                    if (!(strcmp(fieldDefn->GetName(), "FDR") == 0 &&
+                        fieldDefn->GetSubfieldCount() == 7))
+                    {
+                        CPLDebug("SRP", "Record FDR  %d",fieldDefn->GetSubfieldCount());
+                        continue;
+                    }
+
+                    const char* pszNAM = record->GetStringSubfield("FDR", iFDRFieldInstance++, "NAM", 0);
+                    if( pszNAM == NULL)
+                        continue;
+
+
+                    CPLString osName = CPLString(pszNAM);
+
+                    /* Define a subdirectory from Dataset but with only 6 caracatere */
+                    CPLString osDirDataset = pszNAM;
+                    osDirDataset.resize(6); 
+                    CPLString osDatasetDir = CPLFormFilename(osDirName.c_str(), osDirDataset.c_str(), NULL);
+
+                    CPLString osGENFileName="";
+
+
+                    int bFound=0;
+                    if (bFound ==0)
+                    {
+                        char** papszDirContent = VSIReadDir(osDatasetDir.c_str());
+                        char** ptrDir = papszDirContent;
+                        if (ptrDir)
+                        {
+                            while(*ptrDir)
+                            {
+                                if ( EQUAL(CPLGetExtension(*ptrDir), "GEN") )
+                                {
+                                    bFound = 1;
+                                    osGENFileName = CPLFormFilename(osDatasetDir.c_str(), *ptrDir, NULL);
+                                    CPLDebug("SRP", "Building GEN full file name : %s", osGENFileName.c_str());
+                                    break;
+                                }
+                                ptrDir ++;
+                            }
+                            CSLDestroy(papszDirContent);
+                        }
+
+                    }
+                    /* If not found in sub directory then search in the same directory of the THF file */
+                    if (bFound ==0)
+                    {
+                        char** papszDirContent = VSIReadDir(osDirName.c_str());
+                        char** ptrDir = papszDirContent;
+                        if (ptrDir)
+                        {
+                            while(*ptrDir)
+                            {
+                                if ( EQUAL(CPLGetExtension(*ptrDir), "GEN") &&  EQUALN(CPLGetBasename(*ptrDir), osName,6))
+                                {
+                                    bFound = 1;
+                                    osGENFileName = CPLFormFilename(osDirName.c_str(), *ptrDir, NULL);
+                                    CPLDebug("SRP", "Building GEN full file name : %s", osGENFileName.c_str());
+                                    break;
+                                }
+                                ptrDir ++;
+                            }
+                            CSLDestroy(papszDirContent);
+                        }
+
+                    }
+
+
+                    if (bFound ==1)
+                    {
+                        papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
+                        papszFileNames[nFilenames] = CPLStrdup(osGENFileName.c_str());
+                        papszFileNames[nFilenames + 1] = NULL;
+                        nFilenames ++;
+                    }
+
+                }
+            }
+
+        }
     }
+    return papszFileNames;
+}
 
-    if (!module.Open(osFileName, TRUE))
-        return NULL;
 
-    if( poOpenInfo->eAccess == GA_Update )
+/************************************************************************/
+/*                          AddMetadatafromFromTHF()                         */
+/************************************************************************/
+
+void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
+{
+    DDFModule module;
+    DDFRecord * record;
+    DDFField* field;
+    DDFFieldDefn *fieldDefn;
+
+    int bSuccess=0;
+    if (!module.Open(pszFileName, TRUE))
+        return ;
+
+    CPLString osDirName(CPLGetDirname(pszFileName));
+
+    while (TRUE)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The SRP driver does not support update access to existing"
-                  " datasets.\n" );
-        return NULL;
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        record = module.ReadRecord();
+        CPLPopErrorHandler();
+        CPLErrorReset();
+        if (record == NULL || record->GetFieldCount() <= 2)
+            break;
+
+        field = record->GetField(0);
+        fieldDefn = field->GetFieldDefn();
+        if (!(strcmp(fieldDefn->GetName(), "001") == 0) ||
+            fieldDefn->GetSubfieldCount() != 2)
+            break;
+
+        const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
+        if ( RTY != NULL &&  strcmp(RTY, "THF") == 0 )
+        {
+            field = record->GetField(1);
+            fieldDefn = field->GetFieldDefn();
+            if ((strcmp(fieldDefn->GetName(), "VDR") == 0 &&
+                fieldDefn->GetSubfieldCount() == 8))
+            {
+
+                const char* pszVOO = record->GetStringSubfield("VDR", 0, "VOO", 0);
+                if( pszVOO != NULL )
+                {
+                    CPLDebug("SRP", "Record VOO %s",pszVOO);
+                    SetMetadataItem( "SRP_VOO", pszVOO );
+                }
+
+
+                int EDN = record->GetIntSubfield( "VDR", 0, "EDN", 0, &bSuccess );
+                if (bSuccess)
+                {
+                    CPLDebug("SRP", "Record EDN %d",EDN);
+                    char pszValue[5];
+                    sprintf(pszValue, "%d", EDN);
+                    SetMetadataItem( "SRP_EDN", pszValue );
+                }
+
+
+                const char* pszCDV07 = record->GetStringSubfield("VDR", 0, "CDV07", 0);
+                if( pszCDV07 != NULL )
+                {
+                    CPLDebug("SRP", "Record pszCDV07 %s",pszCDV07);
+                    SetMetadataItem( "SRP_CREATIONDATE", pszCDV07 );
+                }
+                else
+                {  /*USRP1.2*/
+                    const char* pszDAT = record->GetStringSubfield("VDR", 0, "DAT", 0);
+                    if( pszDAT != NULL )
+                    {
+                        char dat[9];
+                        strncpy(dat,pszDAT+4,8);
+                        dat[8]='\0';
+                        CPLDebug("SRP", "Record DAT %s",dat);
+                        SetMetadataItem( "SRP_CREATIONDATE", dat );
+                    }
+                }
+
+            }
+        } /* End of THF part */
+
+        if ( RTY != NULL && strcmp(RTY, "LCF") == 0 )
+        {
+            field = record->GetField(1);
+            fieldDefn = field->GetFieldDefn();
+            if ((strcmp(fieldDefn->GetName(), "QSR") == 0 &&
+                fieldDefn->GetSubfieldCount() == 4))
+            {
+
+                const char* pszQSS = record->GetStringSubfield("QSR", 0, "QSS", 0);
+                if( pszQSS != NULL )
+                {
+                    CPLDebug("SRP", "Record Classification %s",pszQSS);
+                    SetMetadataItem( "SRP_CLASSIFICATION", pszQSS );
+                }
+            }
+
+            field = record->GetField(2);
+            fieldDefn = field->GetFieldDefn();
+            if ((strcmp(fieldDefn->GetName(), "QUV") == 0 &&
+                fieldDefn->GetSubfieldCount() == 6))
+            {
+                const char* pszSRC2 = record->GetStringSubfield("QUV", 0, "SRC1", 0);
+                if( pszSRC2 != NULL )
+                {
+                    SetMetadataItem( "SRP_PRODUCTVERSION", pszSRC2 );
+                }
+                else
+                {
+                    const char* pszSRC = record->GetStringSubfield("QUV", 0, "SRC", 0);
+                    if( pszSRC != NULL )
+                    {
+                        SetMetadataItem( "SRP_PRODUCTVERSION", pszSRC );
+                    }
+                }
+            }
+        }  /* End of LCF part */
+
     }
+}
+
+/************************************************************************/
+/*                          GetIMGListFromGEN()                         */
+/************************************************************************/
+
+char** SRPDataset::GetIMGListFromGEN(const char* pszFileName,
+                                    int *pnRecordIndex)
+{
+    DDFRecord * record;
+    DDFField* field;
+    DDFFieldDefn *fieldDefn;
+    int nFilenames = 0;
+    char** papszFileNames = NULL;
+    int nRecordIndex = -1;
+
+    if (pnRecordIndex)
+        *pnRecordIndex = -1;
+
+    DDFModule module;
+    if (!module.Open(pszFileName, TRUE))
+        return NULL;    
 
-/* -------------------------------------------------------------------- */
-/*      Loop processing records - we are basically looking for the      */
-/*      GIN record which is normally first in the .GEN file.            */
-/* -------------------------------------------------------------------- */
-    int recordIndex = 0;
     while (TRUE)
     {
+        nRecordIndex ++;
+
         CPLPushErrorHandler( CPLQuietErrorHandler );
         record = module.ReadRecord();
         CPLPopErrorHandler();
         CPLErrorReset();
         if (record == NULL)
-          break;
-        if ( ++recordIndex < zoneNumber )
-          continue;
-
-        const char* RTY = record->GetStringSubfield( "001", 0, "RTY", 0 );
-        if( RTY == NULL || !EQUAL(RTY,"GIN") )
-            continue;
-
-        const char *PRT = record->GetStringSubfield( "DSI", 0, "PRT", 0 );
-        if( PRT == NULL )
-            continue;
-
-        CPLString osPRT = PRT;
-        osPRT.resize(4);
-        if( !EQUAL(osPRT,"ASRP") && !EQUAL(osPRT,"USRP") )
-            continue;
-
-        const char* pszNAM = record->GetStringSubfield( "DSI", 0, "NAM", 0 );
-        if( pszNAM == NULL )
-            pszNAM = "";
-        osNAM = pszNAM;
-        CPLDebug("SRP", "NAM=%s", osNAM.c_str());
-
-        SRPDataset *poDS = new SRPDataset();
-        
-        poDS->osProduct = osPRT;
-        poDS->osGENFilename = osFileName;
-        poDS->SetMetadataItem( "SRP_NAM", osNAM );
-        poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
+            break;
+
+        if (record->GetFieldCount() >= 5)
+        {
+            field = record->GetField(0);
+            fieldDefn = field->GetFieldDefn();
+            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                fieldDefn->GetSubfieldCount() == 2))
+            {
+                continue;
+            }
+
+            const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
+            if( RTY == NULL )
+                continue;
+            /* Ignore overviews */
+            if ( strcmp(RTY, "OVV") == 0 )
+                continue;
+
+            if ( strcmp(RTY, "GIN") != 0 )
+                continue;
+
+            field = record->GetField(3);
+            if( field == NULL )
+                continue;
+            fieldDefn = field->GetFieldDefn();
+
+            if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
+                fieldDefn->GetSubfieldCount() == 15))
+            {
+                continue;
+            }
+
+            const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
+            if( pszBAD == NULL || strlen(pszBAD) != 12 )
+                continue;
+            CPLString osBAD = pszBAD;
+            {
+                char* c = (char*) strchr(osBAD.c_str(), ' ');
+                if (c)
+                    *c = 0;
+            }
+            CPLDebug("SRP", "BAD=%s", osBAD.c_str());
+
+            /* Build full IMG file name from BAD value */
+            CPLString osGENDir(CPLGetDirname(pszFileName));
+
+            CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
+            VSIStatBufL sStatBuf;
+            if( VSIStatL( osFileName, &sStatBuf ) == 0 )
+            {
+                osBAD = osFileName;
+                CPLDebug("SRP", "Building IMG full file name : %s", osBAD.c_str());
+            }
+            else
+            {
+                char** papszDirContent;
+                if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
+                {
+                    CPLString osTmp = osGENDir + "/";
+                    papszDirContent = VSIReadDir(osTmp);
+                }
+                else
+                    papszDirContent = VSIReadDir(osGENDir);
+                char** ptrDir = papszDirContent;
+                while(ptrDir && *ptrDir)
+                {
+                    if (EQUAL(*ptrDir, osBAD.c_str()))
+                    {
+                        osBAD = CPLFormFilename(osGENDir.c_str(), *ptrDir, NULL);
+                        CPLDebug("SRP", "Building IMG full file name : %s", osBAD.c_str());
+                        break;
+                    }
+                    ptrDir ++;
+                }
+                CSLDestroy(papszDirContent);
+            }
+
+            if (nFilenames == 0 && pnRecordIndex)
+                *pnRecordIndex = nRecordIndex;
+
+            papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
+            papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
+            papszFileNames[nFilenames + 1] = NULL;
+            nFilenames ++;
+        }
+    }
+
+    return papszFileNames;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    int nRecordIndex = -1;
+    CPLString osGENFileName;
+    CPLString osIMGFileName;
+    int bFromSubdataset = FALSE;
+    int bTHFWithSingleGEN = FALSE;
+
+    if( EQUALN(poOpenInfo->pszFilename, "SRP:", 4) )
+    {
+        char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 4, ",", 0);
+        if (CSLCount(papszTokens) == 2)
+        {
+            osGENFileName = papszTokens[0];
+            osIMGFileName = papszTokens[1];
+            bFromSubdataset = TRUE;
+        }
+        CSLDestroy(papszTokens);
+    }
+    else
+    {
+        if( poOpenInfo->nHeaderBytes < 500 )
+            return NULL;
+        CPLString osFileName(poOpenInfo->pszFilename);
 
-        if (!poDS->GetFromRecord( osFileName, record ) )
+        if (EQUAL(CPLGetExtension(osFileName.c_str()), "THF"))
         {
-            delete poDS;
-            continue;
+
+            CPLDebug("SRP", "Read THF");
+
+            char** papszFileNames = GetGENListFromTHF(osFileName.c_str());
+            if (papszFileNames == NULL)
+                return NULL;
+            if (papszFileNames[1] == NULL &&
+                CSLTestBoolean(CPLGetConfigOption("SRP_SINGLE_GEN_IN_THF_AS_DATASET", "TRUE")))
+            {
+                osFileName = papszFileNames[0];
+                CSLDestroy(papszFileNames);
+                bTHFWithSingleGEN = TRUE;
+            }
+            else
+            {
+                char** ptr = papszFileNames;
+                SRPDataset* poDS = new SRPDataset();
+                poDS->AddMetadatafromFromTHF(osFileName.c_str());
+                while(*ptr)
+                {
+                    char** papszIMGFileNames = GetIMGListFromGEN(*ptr);
+                    char** papszIMGIter = papszIMGFileNames;
+                    while(papszIMGIter && *papszIMGIter)
+                    {
+                        poDS->AddSubDataset(*ptr, *papszIMGIter);
+                        papszIMGIter ++;
+                    }
+                    CSLDestroy(papszIMGFileNames);
+
+                    ptr ++;
+                }
+                CSLDestroy(papszFileNames);
+                return poDS;
+            }
         }
-        
-        /* ---------------------------------------------------------- */
-        /*      Initialize any PAM information.                       */
-        /* ---------------------------------------------------------- */
-        poDS->SetDescription( poOpenInfo->pszFilename );
-        poDS->TryLoadXML();
 
-        /* ---------------------------------------------------------- */
-        /*      Check for external overviews.                         */
-        /* ---------------------------------------------------------- */
-        poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+        if ( bTHFWithSingleGEN
+#ifdef OPEN_GEN
+                || EQUAL(CPLGetExtension(osFileName.c_str()), "GEN")
+#endif
+            )
+        {
+            osGENFileName = osFileName;
+
+            char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
+            if (papszFileNames == NULL)
+                return NULL;
+            if (papszFileNames[1] == NULL)
+            {
+                osIMGFileName = papszFileNames[0];
+                CSLDestroy(papszFileNames);
+            }
+            else
+            {
+                char** ptr = papszFileNames;
+                SRPDataset* poDS = new SRPDataset();
+                while(*ptr)
+                {
+                    poDS->AddSubDataset(osFileName.c_str(), *ptr);
+                    ptr ++;
+                }
+                CSLDestroy(papszFileNames);
+                return poDS;
+            }
+        }
+
+        if (EQUAL(CPLGetExtension(osFileName.c_str()), "IMG"))
+        {
+
+            osIMGFileName = osFileName;
+
+            static const size_t nLeaderSize = 24;
+            int         i;
+
+            for( i = 0; i < (int)nLeaderSize; i++ )
+            {
+                if( poOpenInfo->pabyHeader[i] < 32 
+                    || poOpenInfo->pabyHeader[i] > 126 )
+                    return NULL;
+            }
+
+            if( poOpenInfo->pabyHeader[5] != '1' 
+                && poOpenInfo->pabyHeader[5] != '2' 
+                && poOpenInfo->pabyHeader[5] != '3' )
+                return NULL;
+
+            if( poOpenInfo->pabyHeader[6] != 'L' )
+                return NULL;
+            if( poOpenInfo->pabyHeader[8] != '1' && poOpenInfo->pabyHeader[8] != ' ' )
+                return NULL;
+
+            // --------------------------------------------------------------------
+            //      Find and open the .GEN file.                                   
+            // -------------------------------------------------------------------- 
+            VSIStatBufL sStatBuf;
+
+            CPLString basename = CPLGetBasename( osFileName );
+            if( basename.size() != 8 )
+            {
+                CPLDebug("SRP", "Invalid basename file");
+                return NULL;
+            }
+
+            nRecordIndex = CPLScanLong( basename + 6, 2 );
+
+            CPLString path = CPLGetDirname( osFileName );
+            CPLString basename01 = ResetTo01( basename );
+            osFileName = CPLFormFilename( path, basename01, ".IMG" );
+
+            osFileName = CPLResetExtension( osFileName, "GEN" );
+            if( VSIStatL( osFileName, &sStatBuf ) != 0 )
+            {
+                osFileName = CPLResetExtension( osFileName, "gen" );
+                if( VSIStatL( osFileName, &sStatBuf ) != 0 )
+                    return NULL;
+            }
 
-        return poDS;
+            osGENFileName = osFileName;
+        }
     }
-    
+
+    if (osGENFileName.size() > 0 &&
+        osIMGFileName.size() > 0)
+    {
+
+
+        if( poOpenInfo->eAccess == GA_Update )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported, 
+                "The SRP driver does not support update access to existing"
+                " datasets.\n" );
+            return NULL;
+        }
+
+        DDFModule module;
+        DDFRecord* record = NULL;
+        if (nRecordIndex >= 0 &&
+            module.Open(osGENFileName.c_str(), TRUE))
+        {
+            int i;
+            for(i=0;i<nRecordIndex;i++)
+            {
+                CPLPushErrorHandler( CPLQuietErrorHandler );
+                record = module.ReadRecord();
+                CPLPopErrorHandler();
+                CPLErrorReset();
+                if (record == NULL)
+                    break;
+            }
+        }
+        SRPDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
+
+        if (poDS)
+        {
+            /* ---------------------------------------------------------- */
+            /*      Initialize any PAM information.                       */
+            /* ---------------------------------------------------------- */
+            poDS->SetDescription( poOpenInfo->pszFilename );
+            poDS->TryLoadXML();
+
+            /* ---------------------------------------------------------- */
+            /*      Check for external overviews.                         */
+            /* ---------------------------------------------------------- */
+            if( bFromSubdataset )
+                poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
+            else
+                poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+            return poDS;
+        }
+    }
+
     return NULL;
 }
 
@@ -888,6 +1618,7 @@ void GDALRegister_SRP()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#SRP" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
+        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = SRPDataset::Open;
diff --git a/frmts/aigrid/aigccitt.c b/frmts/aigrid/aigccitt.c
index 37f770c..132da78 100644
--- a/frmts/aigrid/aigccitt.c
+++ b/frmts/aigrid/aigccitt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigccitt.c 22640 2011-07-03 15:52:40Z rouault $
+ * $Id: aigccitt.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Code for decoding CCITT RLE (G1) compressed data.
@@ -11,6 +11,7 @@
  * Copyright (c) 2002 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 1990-1997 Sam Leffler
  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and 
  * its documentation for any purpose is hereby granted without fee, provided
@@ -1487,7 +1488,7 @@ typedef struct {
 
 #define	is2DEncoding(sp) \
 	(sp->b.groupoptions & GROUP3OPT_2DENCODING)
-#define	isAligned(p,t)	((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
+#define	isAligned(p,t)	((((size_t)(p)) & (sizeof (t)-1)) == 0)
 
 /*
  * Group 3 and Group 4 Decoding.
diff --git a/frmts/aigrid/aigdataset.cpp b/frmts/aigrid/aigdataset.cpp
index 8e41dcc..ab52ce6 100644
--- a/frmts/aigrid/aigdataset.cpp
+++ b/frmts/aigrid/aigdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $
+ * $Id: aigdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Binary Grid Driver
  * Purpose:  Implements GDAL interface to underlying library.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,8 +34,9 @@
 #include "gdal_rat.h"
 #include "aigrid.h"
 #include "avc.h"
+#include <vector>
 
-CPL_CVSID("$Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $");
+CPL_CVSID("$Id: aigdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_AIGrid(void);
@@ -102,7 +104,7 @@ class AIGRasterBand : public GDALPamRasterBand
 
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable *GetColorTable();
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
 };
 
 /************************************************************************/
@@ -202,7 +204,7 @@ CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
 
 {
     AIGDataset	*poODS = (AIGDataset *) poDS;
@@ -375,6 +377,34 @@ char **AIGDataset::GetFileList()
 }
 
 /************************************************************************/
+/*                          AIGErrorHandlerVATOpen()                    */
+/************************************************************************/
+
+class AIGErrorDescription
+{
+    public:
+        CPLErr eErr;
+        int    no;
+        CPLString osMsg;
+};
+
+static void CPL_STDCALL AIGErrorHandlerVATOpen(CPLErr eErr, int no, const char* msg)
+{
+    std::vector<AIGErrorDescription>* paoErrors =
+        (std::vector<AIGErrorDescription>* )CPLGetErrorHandlerUserData();
+    if( EQUALN(msg, "EOF encountered in", strlen("EOF encountered in")) &&
+        strstr(msg, "../info/arc.dir") != NULL )
+        return;
+    if( EQUALN(msg, "Failed to open table ", strlen("Failed to open table ")) )
+        return;
+    AIGErrorDescription oError;
+    oError.eErr = eErr;
+    oError.no = no;
+    oError.osMsg = msg;
+    paoErrors->push_back(oError);
+}
+
+/************************************************************************/
 /*                              ReadRAT()                               */
 /************************************************************************/
 
@@ -408,9 +438,23 @@ void AIGDataset::ReadRAT()
     osTableName = CPLGetFilename(psInfo->pszCoverName);
     osTableName += ".VAT";
 
+    /* Turn off errors that can be triggered if the info has no VAT */
+    /* table related with this coverage */
+    std::vector<AIGErrorDescription> aoErrors;
+    CPLPushErrorHandlerEx(AIGErrorHandlerVATOpen, &aoErrors );
+
     AVCBinFile *psFile = 
         AVCBinReadOpen( osInfoPath, osTableName,
                         AVCCoverTypeUnknown, AVCFileTABLE, NULL );
+    CPLPopErrorHandler();
+
+    /* Emit other errors */
+    std::vector<AIGErrorDescription>::const_iterator oIter;
+    for( oIter = aoErrors.begin(); oIter != aoErrors.end(); ++oIter )
+    {
+        const AIGErrorDescription& oError = *oIter;
+        CPLError( oError.eErr, oError.no, "%s", oError.osMsg.c_str() );
+    }
 
     CPLErrorReset();
     if( psFile == NULL )
@@ -423,7 +467,7 @@ void AIGDataset::ReadRAT()
 /* -------------------------------------------------------------------- */
     int iField;
 
-    poRAT = new GDALRasterAttributeTable();
+    poRAT = new GDALDefaultRasterAttributeTable();
 
     for( iField = 0; iField < psTableDef->numFields; iField++ )
     {
diff --git a/frmts/aigrid/aigopen.c b/frmts/aigrid/aigopen.c
index 83ac0d8..80e036a 100644
--- a/frmts/aigrid/aigopen.c
+++ b/frmts/aigrid/aigopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $
+ * $Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access cover API for non-GDAL use.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $");
+CPL_CVSID("$Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                              AIGOpen()                               */
diff --git a/frmts/aigrid/aigrid_format.html b/frmts/aigrid/aigrid_format.html
new file mode 100755
index 0000000..09a8b58
--- /dev/null
+++ b/frmts/aigrid/aigrid_format.html
@@ -0,0 +1,790 @@
+<html>
+
+<head>
+<title>Arc/Info Binary Grid Format</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>Arc/Info Binary Grid Format</h1>
+
+<i>by <a href="http://pobox.com/~warmerdam">Frank Warmerdam</a></i>
+(<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>)<p>
+
+The Arc/Info Binary Grid format is the internal working format of the
+Arc/Info Grid product.  It is also usable and creatable within the 
+spatial analyst component of ArcView.  It is a tiled (blocked) format with run
+length compression capable of holding raster data of up to 4 byte integers
+or 4 byte floating data. <p>
+
+This format should not be confused with the Arc/Info ASCII Grid format 
+which is the interchange format for grids.  Files can be converted between
+binary and ASCII format with the GRIDASCII and ASCIIGRID commands in
+Arc/Info.  This format is also different than the flat binary raster
+output of the GRIDFLOAT command.  The Arc/Info binary float, and ASCII
+formats are also accessable from within ArcView.<p>
+
+This format should also not be confused with what I know as ESRI BIL format.  
+This is really a standard ESRI way of creating a header file (.HDR) 
+describing the data layout a binary raster file containing raster data.<p>
+
+<!--------------------------------------------------------------------------->
+
+<h2>Version</h2>
+
+I am not sure yet how the versions work for grid files.  I have been
+working primarily with grid files generated by ArcView 3.x, and it's associated
+gridio API.  The hdr.adf files I have examined start with the string
+<b>GRID1.2</b> for what that's worth.  Certainly the file naming conventions
+seem to follow the Arc/Info 7.x conventions rather than that of earlier
+versions.<p>
+
+<!--------------------------------------------------------------------------->
+
+<h2>File Set</h2>
+
+A grid coverage actually consists of a number of files.  A grid normally
+lives in it's own directory named after the grid.  For instance, the 
+grid <b>nwgrd1</b> lives in the directory <b>nwgrd1</b>, and has the following 
+component files:<p>
+ 
+<pre>
+-rwxr--r--   1 warmerda users          32 Jan 22 16:07 nwgrd1/dblbnd.adf
+-rwxr--r--   1 warmerda users         308 Jan 22 16:07 nwgrd1/hdr.adf
+-rwxr--r--   1 warmerda users          32 Jan 22 16:07 nwgrd1/sta.adf
+-rwxr--r--   1 warmerda users        2048 Jan 22 16:07 nwgrd1/vat.adf
+-rwxr--r--   1 warmerda users      187228 Jan 22 16:07 nwgrd1/w001001.adf
+-rwxr--r--   1 warmerda users        6132 Jan 22 16:07 nwgrd1/w001001x.adf
+</pre>
+
+Sometimes datasets will also include a prj.adf files containing the projection
+definition in the usual ESRI format. Grids also normally have associated 
+tables in the info directory.  This is beyond the scope of my discussion 
+for now.<p>
+
+The files have the following roles:
+
+<ul>
+
+<li> <a href="#dblbnd">dblbnd.adf</a>: Contains the bounds 
+(LLX, LLY, URX, URY) of the portion of utilized portion of the grid.<p>
+
+<li> <a href="#hdr.adf">hdr.adf</a>: This is the header, and contains 
+information on the tile sizes, and number of tiles in the dataset.  It also 
+contains assorted other information I have yet to identify.<p>
+
+<li> <a href="#sta">sta.adf</a>: This contains raster statistics.  In
+particular, the raster min, max, mean and standard deviation.<p>
+
+<li> <b>vat.adf</b>: This relates to the value attribute table.  This is
+the table corresponding integer raster values with a set of attributes.  I
+presume it is really just a pointer into info in a manner similar to the
+pat.adf file in a vector coverage, but I haven't investigated yet. <p>
+
+<li> <a href="#w001001">w001001.adf</a>: 
+This is the file containing the actual raster data.
+<p>
+
+<li> <a href="#w001001x">w001001x.adf</a>: 
+This is an index file containing pointers to 
+each of the tiles in the w001001.adf raster file.<p>
+
+</ul> 
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2><a name="dblbnd">dblbnd.adf - Georef Bounds</a></h2>
+
+Fields:<p>
+
+<table border>
+<th>Start Byte
+<th># of Bytes
+<th>Format
+<th>Name
+<th>Description
+
+<tr>
+  <td> 0
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> D_LLX
+  </td><td> Lower left X (easting) of the grid.  Generally -0.5 for an 
+ungeoreferenced grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 8
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> D_LLY
+  </td><td> Lower left Y (northing) of the grid. Generally -0.5 for an 
+ungeoreferenced grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 16
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> D_URX
+  </td><td> Upper right X (easting) of the grid. Generally #Pixels-0.5 for an 
+ungeoreferenced grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 24
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> D_URY
+  </td><td> Upper right Y (northing) of the grid. Generally #Lines-0.5 for an 
+ungeoreferenced grid.
+  </td> 
+</tr>
+
+</table>
+
+This file is always 32 bytes long.  The bounds apply to the portion of the
+grid that is in use, not the whole thing.<p>
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2><a name="w001001x">w001001x.adf - Tile Index</a></h2>
+
+This is a binary dump of the first 320 bytes of a w001001x.adf
+file.  <p>
+
+<pre>
+       0: 0000270A FFFFFC14 00000000 00000000 ~~'~~~~~~~~~~~~~
+      16: 00000000 00000000 00000BFA 00000000 ~~~~~~~~~~~~~~~~
+      32: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      48: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      64: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      80: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      96: 00000000 00000032 00000202 00000235 ~~~~~~~2~~~~~~~5
+     112: 000001D4 0000040A 00000000 0000040B ~~~~~~~~~~~~~~~~
+     128: 00000000 0000040C 00000000 0000040D ~~~~~~~~~~~~~~~~
+     144: 00000000 0000040E 00000000 0000040F ~~~~~~~~~~~~~~~~
+     160: 00000000 00000410 00000202 00000613 ~~~~~~~~~~~~~~~~
+     176: 000001D4 000007E8 00000000 000007E9 ~~~~~~~~~~~~~~~~
+     192: 00000000 000007EA 00000000 000007EB ~~~~~~~~~~~~~~~~
+     208: 00000000 000007EC 00000000 000007ED ~~~~~~~~~~~~~~~~
+     224: 00000000 000007EE 00000202 000009F1 ~~~~~~~~~~~~~~~~
+     240: 000001D4 00000BC6 00000000 00000BC7 ~~~~~~~~~~~~~~~~
+     256: 00000000 00000BC8 00000000 00000BC9 ~~~~~~~~~~~~~~~~
+     272: 00000000 00000BCA 00000000 00000BCB ~~~~~~~~~~~~~~~~
+     288: 00000000 00000BCC 00000202 00000DCF ~~~~~~~~~~~~~~~~
+     304: 000001D4 00000FA4 00000000 00000FA5 ~~~~~~~~~~~~~~~~
+</pre>
+
+Fields:<p>
+
+<table border>
+<th>Start Byte
+<th># of Bytes
+<th>Format
+<th>Description
+
+<tr>
+  <td> 0
+  </td><td> 8
+  </td><td> 
+  </td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
+  </td>
+</tr>
+
+<tr>
+  <td> 8
+  </td><td> 16
+  </td><td> 
+  </td><td> zero fill
+  </td>
+</tr>
+
+<tr>
+  <td> 24
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> Size of whole file in shorts (multiply by two 
+            to get file size in bytes).
+  </td>
+</tr>
+
+<tr>
+  <td> 28
+  </td><td> 72
+  </td><td> 
+  </td><td> zero fill
+  </td>
+</tr>
+
+<tr>
+  <td> 100 + <b>t</b>*8
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> Offset to tile <b>t</b> in w001001.adf measured in two byte
+            shorts.
+  </td>
+</tr>
+
+<tr>
+  <td> 104 + <b>t</b>*8
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> Size of tile <b>t</b> in 2 byte shorts.
+
+  </td>
+</tr>
+
+</table>
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2><a name="sta">sta.adf - Raster Statistics</a></h2>
+
+Fields:<p>
+
+<table border>
+<th>Start Byte
+<th># of Bytes
+<th>Format
+<th>Name
+<th>Description
+
+<tr>
+  <td> 0
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> SMin
+  </td><td> Minimum value of a raster cell in this grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 8
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> SMax
+  </td><td> Maximum value of a raster cell in this grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 16
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> SMean
+  </td><td> Mean value of a raster cells in this grid.
+  </td> 
+</tr>
+
+<tr>
+  <td> 24
+  </td><td> 8
+  </td><td> MSB double
+  </td><td> SStdDev
+  </td><td> Standard deviation of raster cells in this grid.
+  </td> 
+</tr>
+
+</table>
+
+This file is always 32 bytes long. <p>
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2><a name="w001001">w001001.adf - Raster Data</a></h2>
+
+This is a binary dump of the first 320 bytes of a w001001.adf
+file.<p>
+
+<pre>
+       0: 0000270A FFFFFC14 00000000 00000000 ~~'~~~~~~~~~~~~~
+      16: 00000000 00000000 00016DAE 00000000 ~~~~~~~~~~m~~~~~
+      32: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      48: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      64: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      80: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
+      96: 00000000 02020800 00373D42 5C5A4D31 ~~~~~~~~~7=B\ZM1
+     112: 200A0108 0E1D4F89 9C9A9392 8C7E6653  ~~~~~O~~~~~~~fS
+     128: 5151596D 83919290 868A8B87 807A7A7B QQYm~~~~~~~~~zz{
+     144: 7C7A766F 64481D00 0406305F 6B6C6A5B |zvodH~~~~0_klj[
+     160: 5D53513C 2D2D2732 24293F54 40354C55 ]SQ<--'2$)?T at 5LU
+     176: 67686258 514E4943 5859534A 41394D70 ghbXQNICXYSJA9Mp
+     192: 75665659 66625A63 737A848E 9090979F ufVYfbZcsz~~~~~~
+     208: 9F908C8F 8F96998E 8778685B 53536274 ~~~~~~~~~xh[SSbt
+     224: 747B838A 8A8C8F92 8D979B94 8C8D9294 t{~~~~~~~~~~~~~~
+     240: 8D8D8D8D 8C8B8989 8B8E908F 8E8E9092 ~~~~~~~~~~~~~~~~
+     256: 90929394 989C9891 92939698 9B9B9C9C ~~~~~~~~~~~~~~~~
+     272: 8E8E8F8F 8E8E8F90 898E918F 8B8A8E93 ~~~~~~~~~~~~~~~~
+     288: 8B8D9093 94918C86 838DA1BC B7CEC9B0 ~~~~~~~~~~~~~~~~
+     304: D4B0BB96 A0929E99 9797999B 9D9C9C9B ~~~~~~~~~~~~~~~~
+</pre>
+
+Fields:<p>
+
+<table border>
+<th>Start Byte
+<th># of Bytes
+<th>Format
+<th>Name
+<th>Description
+
+<tr>
+  <td> 0
+  </td><td> 8
+  </td><td> 
+  </td><td> RMagic
+  </td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
+  </td>
+</tr>
+
+<tr>
+  <td> 8
+  </td><td> 16
+  </td><td> 
+  </td><td> 
+  </td><td> zero fill
+  </td>
+</tr>
+
+<tr>
+  <td> 24
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> RFileSize
+  </td><td> Size of whole file in shorts (multiply by two 
+            to get file size in bytes).
+  </td>
+</tr>
+
+<tr>
+  <td> 28
+  </td><td> 72
+  </td><td> 
+  </td><td> 
+  </td><td> zero fill
+  </td>
+</tr>
+
+<tr>
+  <td> 100, ...
+  </td><td> 2
+  </td><td> MSB Int16
+  </td><td> RTileSize
+  </td><td> Size of this tiles data measured in shorts.  This matches the size
+in the index file, and does not include the tile size itself.  The next
+tile starts <b>2*n+2</b> bytes after the start of this tile, where <b>n</b>
+is the value of this field.
+  </td>
+</tr>
+
+<tr>
+  <td> 102, ...
+  </td><td> 1
+  </td><td> byte
+  </td><td> RTileType
+  </td><td> Tile type code indicating the organization of the following
+data (integer coverages only).  
+  </td>
+</tr>
+<tr>
+  <td> 103, ...
+  </td><td> 1
+  </td><td> byte
+  </td><td> RMinSize
+  </td><td> Number of bytes following to form the minimum value for the tile
+(integer coverages only).
+  </td>
+</tr>
+
+<tr>
+  <td> 104, ...
+  </td><td> (RMinSize bytes)
+  </td><td> MSB Int (var size)
+  </td><td> RMin
+  </td><td> The minimum value pixels for this tile.  This number is added
+to the pixel values for each pixel in this tile (integer coverages only).  
+I must stress that if RMinSize is less than 4 this is still a signed quantity.
+For instance, if RMinSize is 2, the value is 65536 - byte0*256 - byte1 if
+byte0 is > 127. 
+  </td>
+</tr>
+
+<tr>
+  <td> 104+RMinSize, ...
+  </td><td> RTileSize*2 - 3 - RMinSize
+  </td><td> variable
+  </td><td> RTileData
+  </td><td> The data for this tile.  Format varies according to RTileType
+for integer coverages.
+  </td>
+</tr>
+
+</table>
+<p>
+
+The fields RTileSize, RTileType, RMinSize, RMin, and RTileData occur in the
+file for each tile of data present.  They are usually packed one after the
+other, but this isn't necessarily guaranteed.  The index file (w001001x.adf)
+should be used to establish the tile locations.  Note that tiles that
+appear in the index file with a size of zero will appear as just two
+bytes (zeros) for the RTileSize for that tile.<p>
+
+<!------------------------------------------>
+
+<h3>Raster Size</h3>
+
+The size of a the grid isn't as easy to deduce as one might expect.
+The hdr.adf file contains the HTilesPerRow, HTilesPerColumn, 
+HTileXSize, and HTileYSize fields which imply a particular raster
+space. However, it seems that this is created much larger than 
+necessary to hold the users raster data.  I have created 3x1 rasters
+which resulted in the standard 8x512 tiles of 256x4 pixels each.<p>
+
+It seems that the user portion of the raster has to be computed
+based on the georeferenced bounds in the dblbnd.adf file (assumed
+to be anchored at the top left of the total raster space), and 
+the HPixelSizeX, and HPixelSizeY fields from hdr.adf.<p>
+
+<b> #Pixels = (D_URX - D_LRX) / HPixelSizeX</b><p>
+<b> #Lines = (D_URY - D_LRY) / HPixelSizeY</b><p>
+
+Based on this number of pixels and lines, it is possible to establish
+what portion out of the top left of the raster is really <i>of 
+interest</i>.  All regions outside this appear to empty tiles, 
+or filled with no data markers.<p>
+
+<!------------------------------------------>
+
+<h3>RTileType/RTileData</h3>
+
+Each tile contains HBlockXSize * HBlockYSize pixels of data.  For floating
+point and uncompressed integer files the data is just the tile size (in two
+bytes) followed by the pixel data as 4 byte MSB order IEEE floating point 
+words.  For compressed integer
+tiles it is necessary to interpret the RTileType to establish the details
+of the tile organization:
+
+
+<h4>RTileType = 0x00 (constant block)</h4>
+
+All pixels take the value of the RMin.  Data is ignored.  It appears there is
+sometimes a bit of meaningless data (up to four bytes) in the block.<p>
+
+<h4>RTileType = 0x01 (raw 1bit data)</h4>
+
+One full tile worth of data pixel values follows the RMin field, with
+1bit per pixel.<p>
+
+<h4>RTileType = 0x04 (raw 4bit data)</h4>
+
+One full tiles worth of data pixel values follows the RMin field, with 
+4 bits per pixel.  The high order four bits of a byte comes before the low
+order four bits.<p>
+
+<h4>RTileType = 0x08 (raw byte data)</h4>
+
+One full tiles worth of data pixel values (one byte per pixel) follows the
+RMin field.<p>
+
+<h4>RTileType = 0x10 (raw 16bit data)</h4>
+
+One full tiles worth of data pixel values follows the RMin field, with 
+16 bits per pixel (MSB).<p>
+
+<h4>RTileType = 0x20 (raw 32bit data)</h4>
+
+One full tiles worth of data pixel values follows the RMin field, with 
+32 bits per pixel (MSB).<p>
+
+<h4>RTileType = 0xCF (16 bit literal runs/nodata runs)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as:
+
+<ul>
+<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
+literal data with two MSB bytes per pixel. <p>
+
+<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
+of <i>no data</i> pixels should be put into the output stream.  No data
+(other than the next marker) follows this marker. 
+
+</ul>
+
+<h4>RTileType = 0xD7 (literal runs/nodata runs)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as:
+
+<ul>
+<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
+literal data with one byte per pixel. <p>
+
+<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
+of <i>no data</i> pixels should be put into the output stream.  No data
+(other than the next marker) follows this marker. 
+
+</ul>
+
+<h4>RTileType = 0xDF (RMin runs/nodata runs)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as:
+
+<ul>
+<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
+literal data with one byte per pixel. <p>
+
+<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
+of <i>no data</i> pixels should be put into the output stream.  No data
+(other than the next marker) follows this marker. 
+
+</ul>
+
+This is similar to 0xD7, except that the data size is zero bytes instead of
+1, so only RMin values are inserted into the output stream.<p>
+
+<h4>RTileType = 0xE0 (run length encoded 32bit)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as a <b>count</b>.  The four bytes following the
+count should be interpreted as an MSB Int32 <b>value</b>.  They indicate
+that <b>count</b> pixels of <b>value</b> should be inserted into the output
+stream.<p>
+
+<h4>RTileType = 0xF0 (run length encoded 16bit)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as a <b>count</b>.  The two bytes following the
+count should be interpreted as an MSB Int16 <b>value</b>.  They indicate
+that <b>count</b> pixels of <b>value</b> should be inserted into the output
+stream.<p>
+
+<h4>RTileType = 0xFC/0xF8 (run length encoded 8bit)</h4>
+
+The data is organized in a series of runs.  Each run starts with a marker
+which should be interpreted as a <b>count</b>.  The following byte is the
+<b>value</b>.  They indicate
+that <b>count</b> pixels of <b>value</b> should be inserted into the output
+stream.<p>
+
+The intepretation is the same for 0xFC, and 0xF8.  I believe that 0xFC has
+a lower dynamic (2 bit) range than 0xF8 (4 or 8 bit).<p>
+
+<h4>RTileType = 0xFF (RMin CCITT RLE 1Bit)</h4>
+
+The data stream for this file is CCITT RLE (G1 fax) compressed.  The
+format is complex but source is provided with the sample program (derived
+from libtiff) for reading it. The result of uncompressing is 1bit data so
+which the RMin value should be added.<p>
+
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2><a name="hdr.adf">hdr.adf - Header</a></h2>
+
+This is a binary dump of the first 308 bytes of a hdr.adf
+file.<p>
+
+<pre>
+       0: 47524944 312E3200 00000000 FFFFFFFF GRID1.2~~~~~~~~~
+      16: 00000001 00000000 0000164E 3F800000 ~~~~~~~~~~~N?~~~
+      32: 00000F00 F6180000 90060000 3603D601 ~~~~~~~~~~~~6~~~
+      48: 6403E301 01000000 7620F808 43012B03 d~~~~~~~v ~~C~+~
+      64: D6019903 E3012B03 D6019903 E301F7BF ~~~~~~+~~~~~~~~~
+      80: 00007406 6E1FC2A4 7A370D00 0B004200 ~~t~n~~~z7~~~~B~
+      96: 4E1654A4 00000000 00000000 00000000 N~T~~~~~~~~~~~~~
+     112: 34A5A89D FF0414A5 A70F0002 00000000 4~~~~~~~~~~~~~~~
+     128: 00000000 3C0B5F06 A8C05F06 08005AC0 ~~~~<~_~~~_~~~Z~
+     144: 0A00E101 36035AC0 72085F06 FAA42F3C ~~~~6~Z~r~_~~~/<
+     160: 0A001667 02000E00 A80B0200 08370200 ~~~g~~~~~~~~~7~~
+     176: 0CA00200 9C0B0200 04370200 36A0E436 ~~~~~~~~~7~~6~~6
+     192: 84000000 36A00200 5F063EA5 0883FF04 ~~~~6~~~_~>~~~~~
+     208: 00008400 00000010 BD810200 5F010000 ~~~~~~~~~~~~_~~~
+     224: 670E0000 5F01560E 4C4F0001 84008CA5 g~~~_~V~LO~~~~~~
+     240: 28008F01 1000E00A 6628F7BF 4076FF04 (~~~~~~~f(~~@v~~
+     256: 3FF00000 00000000 3FF00000 00000000 ?~~~~~~~?~~~~~~~
+     272: C08FFC00 00000000 C0A1BF00 00000000 ~~~~~~~~~~~~~~~~
+     288: 00000008 00000200 00000100 00000001 ~~~~~~~~~~~~~~~~
+     304: 00000004                            ~~~~              
+</pre>
+
+Fields:<p>
+
+<table border>
+<th>Start Byte
+<th># of Bytes
+<th>Format
+<th>Name
+<th>Description
+
+<tr>
+  <td> 0
+  </td><td> 8
+  </td><td> Char
+  </td><td> HMagic
+  </td><td> Magic Number - always "GRID1.2\0"
+  </td> 
+</tr>
+
+<tr>
+  <td> 8
+  </td><td> 8
+  </td><td>  
+  </td><td>  
+  </td><td> assorted data, I don't know the purpose. 
+  </td>
+</tr>
+
+<tr>
+  <td> 16
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> HCellType
+  </td><td> 1 = int cover, 2 = float cover.
+  </td>
+</tr>
+
+<tr>
+  <td> 20
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> CompFlag
+  </td><td> 0 = compressed, 1 = uncompressed
+  </td>
+</tr>
+
+<tr>
+  <td> 24
+  </td><td> 232
+  </td><td>  
+  </td><td>  
+  </td><td> assorted data, I don't know the purpose. 
+  </td>
+</tr>
+
+<tr>
+  <td> 256
+  </td><td> 8
+  </td><td> MSB Double
+  </td><td> HPixelSizeX
+  </td><td> Width of a pixel in georeferenced coordinates.  Generally 1.0
+for ungeoreferenced rasters.
+  </td>
+</tr>
+
+<tr>
+  <td> 264
+  </td><td> 8
+  </td><td> MSB Double
+  </td><td> HPixelSizeY
+  </td><td> Height of a pixel in georeferenced coordinates.  Generally 1.0
+for ungeoreferenced rasters.
+  </td>
+</tr>
+
+<tr>
+  <td> 272
+  </td><td> 8
+  </td><td> MSB Double
+  </td><td> XRef
+  </td><td> dfLLX-(nBlocksPerRow*nBlockXSize*dfCellSizeX)/2.0
+  </td>
+</tr>
+
+<tr>
+  <td> 280
+  </td><td> 8
+  </td><td> MSB Double
+  </td><td> YRef
+  </td><td> dfURY-(3*nBlocksPerColumn*nBlockYSize*dfCellSizeY)/2.0
+  </td>
+</tr>
+
+<tr>
+  <td> 288
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> HTilesPerRow
+  </td><td> The width of the file in tiles (often 8 for files of 
+less than 2K in width). 
+  </td>
+</tr>
+
+<tr>
+  <td> 292
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> HTilesPerColumn
+  </td><td> The height of the file in tiles.  Note this may be much more than
+            the number of tiles actually represented in the index file.<p>
+  </td>
+</tr>
+
+<tr>
+  <td> 296
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> HTileXSize
+  </td><td> The width of a file in pixels.  Normally 256.  </td>
+</tr>
+
+<tr>
+  <td> 300
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> 
+  </td><td> Unknown, usually 1. 
+</tr>
+
+<tr>
+  <td> 304
+  </td><td> 4
+  </td><td> MSB Int32
+  </td><td> HTileYSize
+  </td><td> Height of a tile in pixels, usually 4.
+</tr>
+
+</table>
+
+<!--------------------------------------------------------------------------->
+
+<hr>
+
+<h2>Acknowledgements</h2>
+
+I would like to thank <a href="http://www.geosoft.com/">Geosoft Inc.</a> 
+for partial funding of my research into this
+format.  I would also like to thank:<p>
+
+<ul>
+<li> Kenneth R. McVay for providing the statistics file format.
+<li> Noureddine Farah of ThinkSpace who dug up lots of datasets that caused 
+problems.
+<li> Luciano Fonseca who worked out RTileType 0x01. 
+<li> Martin Manningham of Global Geomatics for additional problem sample files.
+<li> Harry Anderson of EDX Engineering, for showing me that floating point
+tiles don't have RTileType. 
+<li> Ian Turton for supplying a sample files demonstrating the need to be
+careful with the sign of "short" RMin values.
+<li> Duncan Chaundy at PCI for poking hard till I finally deduced 0xFF tiles.
+<li> Stephen Cheeseman of GeoSoft for yet more problem files. 
+<li> Geoffrey Williams for a files demonstrating tile type 0x20.  
+</ul>
+
+</body>
+</html>
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index d507306..b403dfd 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $
+ * $Id: gridlib.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $");
+CPL_CVSID("$Id: gridlib.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                    AIGProcessRaw32bitFloatBlock()                    */
diff --git a/frmts/airsar/airsardataset.cpp b/frmts/airsar/airsardataset.cpp
index 60eb476..818d2ec 100644
--- a/frmts/airsar/airsardataset.cpp
+++ b/frmts/airsar/airsardataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: airsardataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: airsardataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  AirSAR Reader
  * Purpose:  Implements read support for AirSAR Polarimetric data.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: airsardataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: airsardataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_AirSAR(void);
diff --git a/frmts/arg/GNUmakefile b/frmts/arg/GNUmakefile
index 18f6c60..08af072 100644
--- a/frmts/arg/GNUmakefile
+++ b/frmts/arg/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 
 OBJ	=	argdataset.o
 
-CPPFLAGS :=	-I../../ogr/ogrsf_frmts/geojson -I../raw $(GDAL_INCLUDE) $(CPPFLAGS)
+CPPFLAGS :=	$(JSON_INCLUDE) -I../raw $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/arg/argdataset.cpp b/frmts/arg/argdataset.cpp
index 884f3ef..f746a5d 100644
--- a/frmts/arg/argdataset.cpp
+++ b/frmts/arg/argdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: argdataset.cpp 24855 2012-08-25 21:12:55Z rouault $
+ * $Id: argdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Azavea Raster Grid format driver.
  * Purpose:  Implements support for reading and writing Azavea Raster Grid
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2012, David Zwarg <dzwarg at azavea.com>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +31,10 @@
 
 #include "rawdataset.h"
 #include "cpl_string.h"
-#include "jsonc/json.h"
-#include "jsonc/json_util.h"
+#include <json.h>
 #include <ogr_spatialref.h>
 
-CPL_CVSID("$Id: argdataset.cpp 24855 2012-08-25 21:12:55Z rouault $");
+CPL_CVSID("$Id: argdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define MAX_FILENAME_LEN 4096
 
@@ -136,9 +136,9 @@ CPLString GetJsonFilename(CPLString pszFilename)
 json_object * GetJsonObject(CPLString pszFilename) 
 {
     json_object * pJSONObject = NULL;
-    CPLString pszJSONFilename = GetJsonFilename(pszFilename);
+    CPLString osJSONFilename = GetJsonFilename(pszFilename);
 
-    pJSONObject = json_object_from_file((char *)pszJSONFilename.c_str());
+    pJSONObject = json_object_from_file((char *)osJSONFilename.c_str());
     if (pJSONObject == (struct json_object*)error_ptr(-1) || pJSONObject == NULL) {
         CPLDebug("ARGDataset", "GetJsonObject(): "
             "Could not parse JSON file.");
@@ -204,9 +204,9 @@ int GetJsonValueInt(json_object * pJSONObject, CPLString pszKey)
 char ** ARGDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
-    CPLString pszJSONFilename = GetJsonFilename(pszFilename);
+    CPLString osJSONFilename = GetJsonFilename(pszFilename);
 
-    papszFileList = CSLAddString( papszFileList, pszJSONFilename );
+    papszFileList = CSLAddString( papszFileList, osJSONFilename );
 
     return papszFileList;
 }
@@ -585,7 +585,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     int nYSize = poSrcDS->GetRasterYSize();
     int nXBlockSize, nYBlockSize, nPixelOffset;
     GDALDataType eType;
-    CPLString pszJSONFilename;
+    CPLString osJSONFilename;
     CPLString pszDataType;
     json_object * poJSONObject = NULL;
     double adfTransform[6];
@@ -674,12 +674,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     /********************************************************************/
     /* Create JSON companion file.                                      */
     /********************************************************************/
-    pszJSONFilename = GetJsonFilename(pszFilename);
-    if (pszJSONFilename == NULL) {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "ARG driver can't determine filename for companion file.");
-        return NULL;
-    }
+    osJSONFilename = GetJsonFilename(pszFilename);
 
     poJSONObject = json_object_new_object();
 
@@ -689,7 +684,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     if ( pszLayer == NULL) {
         // Set the layer
         json_object_object_add(poJSONObject, "layer", json_object_new_string(
-            CPLGetBasename(pszJSONFilename)
+            CPLGetBasename(osJSONFilename)
         ));
     }
     else {
@@ -728,7 +723,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
         json_object_object_add(poJSONObject, "epsg", json_object_new_int(nSrs));
     }
 
-    if (json_object_to_file((char *)pszJSONFilename.c_str(), poJSONObject) < 0) {
+    if (json_object_to_file((char *)osJSONFilename.c_str(), poJSONObject) < 0) {
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "ARG driver can't write companion file.");
 
@@ -748,7 +743,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
               "ARG driver can't create data file %s.", pszFilename);
 
         // remove JSON file
-        VSIUnlink( pszJSONFilename.c_str() );
+        VSIUnlink( osJSONFilename.c_str() );
 
         return NULL;
     }
diff --git a/frmts/arg/makefile.vc b/frmts/arg/makefile.vc
index 7d07983..c7d3078 100644
--- a/frmts/arg/makefile.vc
+++ b/frmts/arg/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ	=	argdataset.obj
 
-EXTRAFLAGS  =   -I..\..\ogr\ogrsf_frmts\geojson -I..\raw
+EXTRAFLAGS  =   -I..\..\ogr\ogrsf_frmts\geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I..\raw
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/blx/blx.c b/frmts/blx/blx.c
index 4fc01f4..ffee433 100644
--- a/frmts/blx/blx.c
+++ b/frmts/blx/blx.c
@@ -1,6 +1,7 @@
 /* libblx - Magellan BLX topo reader/writer library
  *
  * Copyright (c) 2008, Henrik Johansson <henrik at johome.net>
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
diff --git a/frmts/blx/blxdataset.cpp b/frmts/blx/blxdataset.cpp
index af23ce0..16632af 100644
--- a/frmts/blx/blxdataset.cpp
+++ b/frmts/blx/blxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: blxdataset.cpp 23619 2011-12-20 22:40:19Z rouault $
+ * $Id: blxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BLX Driver
  * Purpose:  GDAL BLX support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Henrik Johansson <henrik at johome.net>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: blxdataset.cpp 23619 2011-12-20 22:40:19Z rouault $");
+CPL_CVSID("$Id: blxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 #include <blx.h>
diff --git a/frmts/bmp/bmpdataset.cpp b/frmts/bmp/bmpdataset.cpp
index 4239066..6b05c9e 100644
--- a/frmts/bmp/bmpdataset.cpp
+++ b/frmts/bmp/bmpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bmpdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: bmpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Microsoft Windows Bitmap
  * Purpose:  Read/write MS Windows Device Independent Bitmap (DIB) files
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at remotesensing.org>
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bmpdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: bmpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_BMP(void);
diff --git a/frmts/bsb/bsb_read.c b/frmts/bsb/bsb_read.c
index 292eae3..0ac0f4b 100644
--- a/frmts/bsb/bsb_read.c
+++ b/frmts/bsb/bsb_read.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb_read.c 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: bsb_read.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BSB Reader
  * Purpose:  Low level BSB Access API Implementation (non-GDAL).
@@ -12,6 +12,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bsb_read.c 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: bsb_read.c 27044 2014-03-16 23:41:27Z rouault $");
 
 static int BSBReadHeaderLine( BSBInfo *psInfo, char* pszLine, int nLineMaxLen, int bNO1 );
 static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
@@ -378,10 +379,10 @@ BSBInfo *BSBOpen( const char *pszFilename )
 
     if( psInfo->nXSize <= 0 || psInfo->nYSize <= 0 )
     {
-        BSBClose( psInfo );
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Wrong dimensions found in header : %d x %d.",
                   psInfo->nXSize, psInfo->nYSize );
+        BSBClose( psInfo );
         return NULL;
     }
 
diff --git a/frmts/bsb/bsbdataset.cpp b/frmts/bsb/bsbdataset.cpp
index 9791726..6745b2e 100644
--- a/frmts/bsb/bsbdataset.cpp
+++ b/frmts/bsb/bsbdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsbdataset.cpp 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: bsbdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BSB Reader
  * Purpose:  BSBDataset implementation for BSB format.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: bsbdataset.cpp 25340 2012-12-21 20:30:21Z rouault $");
+CPL_CVSID("$Id: bsbdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_BSB(void);
diff --git a/frmts/ceos/ceosdataset.cpp b/frmts/ceos/ceosdataset.cpp
index 3bff592..bdb72dd 100644
--- a/frmts/ceos/ceosdataset.cpp
+++ b/frmts/ceos/ceosdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $
+ * $Id: ceosdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ceosopen.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: ceosdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $");
+CPL_CVSID("$Id: ceosdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_CEOS(void);
diff --git a/frmts/ceos/ceosopen.c b/frmts/ceos/ceosopen.c
index f90cb38..2feba2e 100644
--- a/frmts/ceos/ceosopen.c
+++ b/frmts/ceos/ceosopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.c 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: ceosopen.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CEOS Translator
  * Purpose:  Implementation of non-GDAL dependent CEOS support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "ceosopen.h"
 
-CPL_CVSID("$Id: ceosopen.c 25340 2012-12-21 20:30:21Z rouault $");
+CPL_CVSID("$Id: ceosopen.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            CEOSScanInt()                             */
diff --git a/frmts/ceos2/sar_ceosdataset.cpp b/frmts/ceos2/sar_ceosdataset.cpp
index 190e1b5..93a9faf 100644
--- a/frmts/ceos2/sar_ceosdataset.cpp
+++ b/frmts/ceos2/sar_ceosdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sar_ceosdataset.cpp 25657 2013-02-19 18:52:30Z warmerdam $
+ * $Id: sar_ceosdataset.cpp 27067 2014-03-20 22:20:43Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Atlantis Scientific Inc.
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: sar_ceosdataset.cpp 25657 2013-02-19 18:52:30Z warmerdam $");
+CPL_CVSID("$Id: sar_ceosdataset.cpp 27067 2014-03-20 22:20:43Z rouault $");
 
 CPL_C_START
 void	GDALRegister_SAR_CEOS(void);
@@ -161,6 +162,7 @@ class SAR_CEOSDataset : public GDALPamDataset
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
 
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char * pszDomain );
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -726,6 +728,16 @@ const GDAL_GCP *SAR_CEOSDataset::GetGCPs()
     return pasGCPList;
 }
 
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **SAR_CEOSDataset::GetMetadataDomainList()
+{
+    return CSLAddString(GDALDataset::GetMetadataDomainList(), "ceos-FFF-n-n-n-n:r");
+}
+
 /************************************************************************/
 /*                            GetMetadata()                             */
 /*                                                                      */
@@ -2149,9 +2161,13 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
             max_records--;
         if(max_bytes > 0)
         {
-            max_bytes -= record->Length;
-            if(max_bytes < 0)
+            if( record->Length <= max_bytes )
+                max_bytes -= record->Length;
+            else {
+                CPLDebug( "SAR_CEOS", "Partial record found.  %d > " CPL_FRMT_GUIB,
+                          record->Length, max_bytes );
                 max_bytes = 0;
+            }
         }
     }
 
diff --git a/frmts/coasp/coasp_dataset.cpp b/frmts/coasp/coasp_dataset.cpp
index eb7dfc5..9a5bc87 100644
--- a/frmts/coasp/coasp_dataset.cpp
+++ b/frmts/coasp/coasp_dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: coasp_dataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: coasp_dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DRDC Configurable Airborne SAR Processor (COASP) data reader
  * Purpose:  Support in GDAL for the DRDC COASP format data, both Metadata
@@ -12,6 +12,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Philippe Vachon
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -38,7 +39,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: coasp_dataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: coasp_dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_COASP(void);
diff --git a/frmts/ctg/ctgdataset.cpp b/frmts/ctg/ctgdataset.cpp
index 27b47fa..b690dc4 100644
--- a/frmts/ctg/ctgdataset.cpp
+++ b/frmts/ctg/ctgdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ctgdataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ctgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CTG driver
  * Purpose:  GDALDataset driver for CTG dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ctgdataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: ctgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_CTG(void);
diff --git a/frmts/dds/ddsdataset.cpp b/frmts/dds/ddsdataset.cpp
index c8a5381..635240e 100644
--- a/frmts/dds/ddsdataset.cpp
+++ b/frmts/dds/ddsdataset.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2013, Alan Boudreault
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/dimap/dimapdataset.cpp b/frmts/dimap/dimapdataset.cpp
index 9beb7c7..90828f5 100644
--- a/frmts/dimap/dimapdataset.cpp
+++ b/frmts/dimap/dimapdataset.cpp
@@ -9,6 +9,7 @@
  * 
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,15 +35,15 @@
 #include "ogr_spatialref.h"
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: dimapdataset.cpp 25110 2012-10-13 13:53:53Z rouault $");
+CPL_CVSID("$Id: dimapdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
-void	GDALRegister_DIMAP(void);
+void    GDALRegister_DIMAP(void);
 CPL_C_END
 
 /************************************************************************/
 /* ==================================================================== */
-/*				DIMAPDataset				*/
+/*                              DIMAPDataset                            */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -79,14 +80,15 @@ class DIMAPDataset : public GDALPamDataset
 
     void SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMetadataTranslation[]);
   public:
-		DIMAPDataset();
-	        ~DIMAPDataset();
+            DIMAPDataset();
+            ~DIMAPDataset();
     
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char *pszDomain );
     virtual char **GetFileList(void);
 
@@ -119,12 +121,12 @@ class DIMAPWrapperRasterBand : public GDALProxyRasterBand
 };
 /************************************************************************/
 /* ==================================================================== */
-/*				DIMAPDataset				*/
+/*                              DIMAPDataset                            */
 /* ==================================================================== */
 /************************************************************************/
 
 /************************************************************************/
-/*                             DIMAPDataset()                             */
+/*                             DIMAPDataset()                            */
 /************************************************************************/
 
 DIMAPDataset::DIMAPDataset()
@@ -147,7 +149,7 @@ DIMAPDataset::DIMAPDataset()
 }
 
 /************************************************************************/
-/*                            ~DIMAPDataset()                             */
+/*                            ~DIMAPDataset()                           */
 /************************************************************************/
 
 DIMAPDataset::~DIMAPDataset()
@@ -157,11 +159,10 @@ DIMAPDataset::~DIMAPDataset()
 
     CPLDestroyXMLNode( psProduct );
 
-    if( nProductVersion == 2 )
-    {
-	CPLDestroyXMLNode( psProductDim );
-	CPLDestroyXMLNode( psProductStrip );
-    }
+    if( psProductDim != NULL )
+        CPLDestroyXMLNode( psProductDim );
+    if( psProductStrip != NULL )
+        CPLDestroyXMLNode( psProductStrip );
 
     CPLFree( pszGCPProjection );
     if( nGCPCount > 0 )
@@ -204,6 +205,17 @@ int DIMAPDataset::CloseDependentDatasets()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **DIMAPDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:dimap", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /*                                                                      */
 /*      We implement special support for fetching the full product      */
@@ -283,7 +295,7 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
     {
       if( ( strstr((const char *) poOpenInfo->pabyHeader, 
                    "<Dimap_Document" ) == NULL ) &&
-	  ( strstr((const char *) poOpenInfo->pabyHeader, 
+          ( strstr((const char *) poOpenInfo->pabyHeader, 
                    "<PHR_DIMAP_Document" ) == NULL ) )
             return FALSE;
         else
@@ -293,7 +305,7 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
     {
         VSIStatBufL sStat;
 
-	/* DIMAP file */
+        /* DIMAP file */
         CPLString osMDFilename = 
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
         
@@ -311,16 +323,16 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
             }
         }
         else
-	{
-	  /* DIMAP 2 file */
-	  osMDFilename = 
-            CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
-	  
-	  if( VSIStatL( osMDFilename, &sStat ) == 0 )
-            return TRUE;
-	  else
-            return FALSE;
-	}
+        {
+            /* DIMAP 2 file */
+            osMDFilename = 
+                    CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
+            
+            if( VSIStatL( osMDFilename, &sStat ) == 0 )
+                    return TRUE;
+            else
+                    return FALSE;
+        }
     }
 
     return FALSE;
@@ -360,10 +372,10 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         osMDFilename = 
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
 
-	/* DIMAP2 */
-	if( VSIStatL( osMDFilename, &sStat ) != 0 )
-	  osMDFilename = 
-            CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
+        /* DIMAP2 */
+        if( VSIStatL( osMDFilename, &sStat ) != 0 )
+        osMDFilename = 
+                CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
     }
     else
         osMDFilename = poOpenInfo->pszFilename;
@@ -378,7 +390,7 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     psProduct = CPLParseXMLFile( osMDFilename );
     if( psProduct == NULL )
-	  return NULL;
+        return NULL;
 
     CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
     if( !psDoc )
@@ -387,113 +399,116 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     /* We check the for the tag Metadata_Identification.METADATA_FORMAT.
     *  The metadata will be set to 2.0 for DIMAP2 */
     nMetadataFormatVersion = atof( CPLGetXMLValue(CPLGetXMLNode(psDoc, "Metadata_Identification.METADATA_FORMAT"), 
-						  "version", "1") );
+                        "version", "1") );
     if( nMetadataFormatVersion >= 2.0 )
     {
-      nProductVersion = 2;
+        nProductVersion = 2;
     }
     
     /* Check needed information for the DIMAP format */ 
     if (nProductVersion == 1)
     {
         psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
-	if( psImageAttributes == NULL )
-	{
-	    CPLError( CE_Failure, CPLE_OpenFailed, 
-		      "Failed to find <Raster_Dimensions> in document." );
-	    return NULL;
-	}
+        if( psImageAttributes == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                "Failed to find <Raster_Dimensions> in document." );
+            CPLDestroyXMLNode(psProduct);
+            return NULL;
+        }
     }
     else /* DIMAP2 */
     {
         /* Verify the presence of the DIMAP product file */
         CPLXMLNode *psDatasetComponents = CPLGetXMLNode(psDoc, "Dataset_Content.Dataset_Components");
 
-	if( psDatasetComponents == NULL )
-	{
-	    CPLError( CE_Failure, CPLE_OpenFailed, 
-		      "Failed to find <Dataset_Components> in document." );
-	    return NULL;
-	}
-      
-	CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
+        if( psDatasetComponents == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                "Failed to find <Dataset_Components> in document." );
+            CPLDestroyXMLNode(psProduct);
+            return NULL;
+        }
+        
+        CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
 
         for( ; psDatasetComponent != NULL; psDatasetComponent = psDatasetComponent->psNext ) 
         {
-	    const char* pszComponentType = CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
-	    if( strcmp(pszComponentType, "DIMAP") == 0 )
-	    {
-		const char *pszHref = CPLGetXMLValue(
-	            psDatasetComponent, "COMPONENT_PATH.href", "" );
-
-		if( strlen(pszHref) > 0 ) /* DIMAP product found*/
-		{
-		    if( poOpenInfo->bIsDirectory )
-		    {
-			osDIMAPFilename = 
-			    CPLFormCIFilename( poOpenInfo->pszFilename, pszHref, NULL );
-		    }
-		    else
-		    {
-			CPLString osPath = CPLGetPath(osMDFilename);
-			osDIMAPFilename = 
-			    CPLFormFilename( osPath, pszHref, NULL );
-		    }
-		  
-		    /* Data file might be specified there */
-		    const char *pszDataFileHref = CPLGetXMLValue(
-   		        psDatasetComponent, "Data_Files.Data_File.DATA_FILE_PATH.href", "" );
-		    
-		    if( strlen(pszDataFileHref) > 0 )
-		    {
-			CPLString osPath = CPLGetPath(osMDFilename);
-			osImageDSFilename = 
-			    CPLFormFilename( osPath, pszDataFileHref, NULL );
-		    }
-
-		    break;
-		}
-	    }
-	}
-
-	psProductDim = CPLParseXMLFile( osDIMAPFilename );
-	if( psProductDim == NULL )
-	    return NULL;
-
-	/* We need the STRIP_<product_id>.XML file for a few metadata */
-	CPLXMLNode *psDocDim = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
-	if( !psDocDim )
+            const char* pszComponentType = CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
+            if( strcmp(pszComponentType, "DIMAP") == 0 )
+            {
+                const char *pszHref = CPLGetXMLValue(
+                        psDatasetComponent, "COMPONENT_PATH.href", "" );
+
+                if( strlen(pszHref) > 0 ) /* DIMAP product found*/
+                {
+                    if( poOpenInfo->bIsDirectory )
+                    {
+                        osDIMAPFilename = 
+                            CPLFormCIFilename( poOpenInfo->pszFilename, pszHref, NULL );
+                    }
+                    else
+                    {
+                        CPLString osPath = CPLGetPath(osMDFilename);
+                        osDIMAPFilename = 
+                            CPLFormFilename( osPath, pszHref, NULL );
+                    }
+                
+                    /* Data file might be specified there */
+                    const char *pszDataFileHref = CPLGetXMLValue(
+                        psDatasetComponent, "Data_Files.Data_File.DATA_FILE_PATH.href", "" );
+                    
+                    if( strlen(pszDataFileHref) > 0 )
+                    {
+                        CPLString osPath = CPLGetPath(osMDFilename);
+                        osImageDSFilename = 
+                            CPLFormFilename( osPath, pszDataFileHref, NULL );
+                    }
+
+                    break;
+                }
+            }
+        }
+
+        psProductDim = CPLParseXMLFile( osDIMAPFilename );
+        if( psProductDim == NULL )
+        {
+            CPLDestroyXMLNode(psProduct);
+            return NULL;
+        }
+
+        /* We need the STRIP_<product_id>.XML file for a few metadata */
+        CPLXMLNode *psDocDim = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
+        if( !psDocDim )
             psDocDim = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
 
         CPLXMLNode *psDatasetSources = CPLGetXMLNode(psDocDim, "Dataset_Sources");
-	if( psDatasetSources != NULL )
-	{
-	    CPLString osSTRIPFilename;
-	    CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
-	    
-	    for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext ) 
-	    {
-		const char* pszSourceType = CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
-		if( strcmp(pszSourceType, "Strip_Source") == 0 )
-		{
-		    const char *pszHref = CPLGetXMLValue(
-   		        psDatasetSource, "Component.COMPONENT_PATH.href", "" );
-		    
-		    if( strlen(pszHref) > 0 ) /* STRIP product found*/
-		    {	
-			CPLString osPath = CPLGetPath(osDIMAPFilename);
-			osSTRIPFilename = 
-			    CPLFormFilename( osPath, pszHref, NULL );
-			
-			break;
-		    }
-		}
-	    }
-
-	    psProductStrip = CPLParseXMLFile( osSTRIPFilename );
-	    if( psProductStrip == NULL )
-		return NULL;
-	}
+        if( psDatasetSources != NULL )
+        {
+            CPLString osSTRIPFilename;
+            CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
+            
+            for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext ) 
+            {
+                const char* pszSourceType = CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
+                if( strcmp(pszSourceType, "Strip_Source") == 0 )
+                {
+                    const char *pszHref = CPLGetXMLValue(
+                        psDatasetSource, "Component.COMPONENT_PATH.href", "" );
+                    
+                    if( strlen(pszHref) > 0 ) /* STRIP product found*/
+                    {
+                        CPLString osPath = CPLGetPath(osDIMAPFilename);
+                        osSTRIPFilename = 
+                            CPLFormFilename( osPath, pszHref, NULL );
+                        
+                        break;
+                    }
+                }
+            }
+
+            psProductStrip = CPLParseXMLFile( osSTRIPFilename );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -511,14 +526,14 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     int res = TRUE;
     if( nProductVersion == 2 )
-	res = poDS->ReadImageInformation2();
+        res = poDS->ReadImageInformation2();
     else
-	res = poDS->ReadImageInformation();
+        res = poDS->ReadImageInformation();
     
     if( res == FALSE )
     {
-	delete poDS;
-	return NULL;
+        delete poDS;
+        return NULL;
     }
 
     return( poDS );
@@ -603,7 +618,7 @@ int DIMAPDataset::ReadImageInformation()
 
     if( psGeoLoc != NULL )
     {
-        CPLXMLNode *psNode;					       
+        CPLXMLNode *psNode;
 
         // count gcps.
         nGCPCount = 0;
@@ -622,7 +637,7 @@ int DIMAPDataset::ReadImageInformation()
         for( psNode = psGeoLoc->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
-            char	szID[32];
+            char    szID[32];
             GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
             
             if( !EQUAL(psNode->pszValue,"Tie_Point") )
@@ -772,9 +787,9 @@ int DIMAPDataset::ReadImageInformation2()
     CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Data.Raster_Dimensions" );
     if( psImageAttributes == NULL )
     {
-	CPLError( CE_Failure, CPLE_OpenFailed, 
-		  "Failed to find <Raster_Dimensions> in document." );
-	return FALSE;
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+            "Failed to find <Raster_Dimensions> in document." );
+        return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -797,20 +812,20 @@ int DIMAPDataset::ReadImageInformation2()
     /* If the data file was not in the product file, it should be here */
     if ( osImageDSFilename.size() == 0 )
     {
-	const char *pszHref = CPLGetXMLValue(
-					     psDoc, "Raster_Data.Data_Access.Data_Files.Data_File.DATA_FILE_PATH.href", "" );
-	if( strlen(pszHref) > 0 )
-	{
-	    CPLString osPath = CPLGetPath( osDIMAPFilename );
-	    osImageDSFilename = 
-		CPLFormFilename( osPath, pszHref, NULL );
-	}
-	else
-	{
-	    CPLError( CE_Failure, CPLE_OpenFailed, 
-		      "Failed to find <DATA_FILE_PATH> in document." );
-	    return FALSE;
-	}
+        const char *pszHref = CPLGetXMLValue(
+                            psDoc, "Raster_Data.Data_Access.Data_Files.Data_File.DATA_FILE_PATH.href", "" );
+        if( strlen(pszHref) > 0 )
+        {
+            CPLString osPath = CPLGetPath( osDIMAPFilename );
+            osImageDSFilename = 
+                CPLFormFilename( osPath, pszHref, NULL );
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                "Failed to find <DATA_FILE_PATH> in document." );
+            return FALSE;
+        }
     }
 
 
@@ -894,15 +909,15 @@ int DIMAPDataset::ReadImageInformation2()
 
     static const char *apszMetadataTranslationDim[] = 
     {
-	    "Product_Information.Delivery_Identification", "DATASET_",
+        "Product_Information.Delivery_Identification", "DATASET_",
             "Product_Information.Producer_Information", "DATASET_",  
-	    "Dataset_Sources.Source_Identification.Strip_Source", "",
-	    "Processing_Information.Production_Facility", "FACILITY_",
-	    "Processing_Information.Product_Settings", "",
-	    "Processing_Information.Product_Settings.Geometric_Settings", "GEOMETRIC_",
-	    "Quality_Assessment.Imaging_Quality_Measurement", "CLOUDCOVER_",
+        "Dataset_Sources.Source_Identification.Strip_Source", "",
+        "Processing_Information.Production_Facility", "FACILITY_",
+        "Processing_Information.Product_Settings", "",
+        "Processing_Information.Product_Settings.Geometric_Settings", "GEOMETRIC_",
+        "Quality_Assessment.Imaging_Quality_Measurement", "CLOUDCOVER_",
             NULL, NULL
-        };
+    };
 
     SetMetadataFromXML(psProductDim, apszMetadataTranslationDim);
 
@@ -912,12 +927,13 @@ int DIMAPDataset::ReadImageInformation2()
 
     static const char *apszMetadataTranslationStrip[] = 
     {
-	    "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
-	    "Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
+        "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
+        "Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
             NULL, NULL
     };
 
-    SetMetadataFromXML(psProductStrip, apszMetadataTranslationStrip);
+    if( psProductStrip != NULL )
+        SetMetadataFromXML(psProductStrip, apszMetadataTranslationStrip);
 
 /* -------------------------------------------------------------------- */
 /*      Set Band metadata from the <Band_Radiance> and                  */
@@ -926,7 +942,7 @@ int DIMAPDataset::ReadImageInformation2()
     
     CPLXMLNode *psImageInterpretationNode = 
         CPLGetXMLNode( psDoc, 
-    		       "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
+                    "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
     if (psImageInterpretationNode != NULL)
     {
         CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
@@ -934,64 +950,64 @@ int DIMAPDataset::ReadImageInformation2()
         {
             if (psSpectralBandInfoNode->eType == CXT_Element &&
                 (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance") ||
-		 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range") ||
-		 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance")))
+                 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range") ||
+                 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance")))
             {
-    		CPLString osName;
-		
-    		if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance"))
-    		    osName = "RADIANCE_";
-    		else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range"))
-    		    osName = "SPECTRAL_RANGE_";
-    		else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance"))
-    		    osName = "SOLAR_IRRADIANCE_";
+                CPLString osName;
+            
+                if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance"))
+                    osName = "RADIANCE_";
+                else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range"))
+                    osName = "SPECTRAL_RANGE_";
+                else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance"))
+                    osName = "SOLAR_IRRADIANCE_";
 
                 CPLXMLNode *psTag = psSpectralBandInfoNode->psChild;
                 int nBandIndex = 0;
                 while(psTag != NULL)
-    		{
+                {
                     if (psTag->eType == CXT_Element && psTag->psChild != NULL &&
                         psTag->psChild->eType == CXT_Text && psTag->pszValue != NULL)
                     {
                         if (EQUAL(psTag->pszValue, "BAND_ID"))
                         {
-    			    /* BAND_ID is: B0, B1, .... P */
-    			    if (!EQUAL(psTag->psChild->pszValue, "P")) 
-    			    {
-    				if (strlen(psTag->psChild->pszValue) < 2) /* shouldn't happen */
-    				{
-    				    CPLError(CE_Warning, CPLE_AppDefined,
-    					     "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
-    				    nBandIndex = 0;
-    				}
-    				else 
-    				{
-    				    nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1; 
-    				    if (nBandIndex <= 0 ||
-    					nBandIndex > poImageDS->GetRasterCount())
-    				    {
-    					CPLError(CE_Warning, CPLE_AppDefined,
-    						 "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
-    					nBandIndex = 0;
-    				    }
-    				}
-    			    }
-    			}
-    			else if (nBandIndex >= 1)
-    			{
-    			  CPLString osMDName = osName;
-			  osMDName += psTag->pszValue;
-
-			  GetRasterBand(nBandIndex)->SetMetadataItem(
-   			      osMDName, psTag->psChild->pszValue);
-    			}
-
-    		    }
-    		    psTag = psTag->psNext;
-    		}
-    	    }
-    	    psSpectralBandInfoNode = psSpectralBandInfoNode->psNext;
-    	}
+                            /* BAND_ID is: B0, B1, .... P */
+                            if (!EQUAL(psTag->psChild->pszValue, "P")) 
+                            {
+                                if (strlen(psTag->psChild->pszValue) < 2) /* shouldn't happen */
+                                {
+                                    CPLError(CE_Warning, CPLE_AppDefined,
+                                        "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
+                                    nBandIndex = 0;
+                                }
+                                else 
+                                {
+                                    nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1; 
+                                    if (nBandIndex <= 0 ||
+                                    nBandIndex > poImageDS->GetRasterCount())
+                                    {
+                                    CPLError(CE_Warning, CPLE_AppDefined,
+                                        "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
+                                    nBandIndex = 0;
+                                    }
+                                }
+                            }
+                        }
+                        else if (nBandIndex >= 1)
+                        {
+                            CPLString osMDName = osName;
+                            osMDName += psTag->pszValue;
+
+                            GetRasterBand(nBandIndex)->SetMetadataItem(
+                                osMDName, psTag->psChild->pszValue);
+                        }
+
+                    }
+                    psTag = psTag->psNext;
+                }
+            }
+            psSpectralBandInfoNode = psSpectralBandInfoNode->psNext;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1046,29 +1062,30 @@ void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMet
             if( psTarget->eType == CXT_Element
                 && psTarget->psChild != NULL)
             {
-		CPLString osName = apszMetadataTranslation[iTrItem+1];
-
-		if (psTarget->psChild->eType == CXT_Text)
-		{		    
-		    osName += psTarget->pszValue;
-		    SetMetadataItem( osName, psTarget->psChild->pszValue );
-		} else if (psTarget->psChild->eType == CXT_Attribute)
-		{ 
-		    /* find the tag value, at the end of the attributes */
-		    CPLXMLNode *psNode = psTarget->psChild;
-		    for( ; psNode != NULL;  psNode = psNode->psNext ) 
-		    {
-			if (psNode->eType == CXT_Attribute)
-			    continue;
-			else if (psNode->eType == CXT_Text)
-			{
-			    osName += psTarget->pszValue;
-			    SetMetadataItem( osName, psNode->pszValue );
-			}   
-		    }
-		}
-	    } 
-	}
+                CPLString osName = apszMetadataTranslation[iTrItem+1];
+
+                if (psTarget->psChild->eType == CXT_Text)
+                {
+                    osName += psTarget->pszValue;
+                    SetMetadataItem( osName, psTarget->psChild->pszValue );
+                }
+                else if (psTarget->psChild->eType == CXT_Attribute)
+                {
+                    /* find the tag value, at the end of the attributes */
+                    CPLXMLNode *psNode = psTarget->psChild;
+                    for( ; psNode != NULL;  psNode = psNode->psNext ) 
+                    {
+                        if (psNode->eType == CXT_Attribute)
+                            continue;
+                        else if (psNode->eType == CXT_Text)
+                        {
+                            osName += psTarget->pszValue;
+                            SetMetadataItem( osName, psNode->pszValue );
+                        }
+                    }
+                }
+            } 
+        }
     }
 }
 
@@ -1109,7 +1126,7 @@ const GDAL_GCP *DIMAPDataset::GetGCPs()
 void GDALRegister_DIMAP()
 
 {
-    GDALDriver	*poDriver;
+    GDALDriver  *poDriver;
 
     if( GDALGetDriverByName( "DIMAP" ) == NULL )
     {
diff --git a/frmts/dods/dodsdataset2.cpp b/frmts/dods/dodsdataset2.cpp
index 0efa1bb..af0ff6c 100644
--- a/frmts/dods/dodsdataset2.cpp
+++ b/frmts/dods/dodsdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dodsdataset2.cpp 20634 2010-09-16 22:02:29Z rouault $
+ * $Id: dodsdataset2.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OPeNDAP Raster Driver
  * Purpose:  Implements DODSDataset and DODSRasterBand classes.
@@ -8,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2003 OPeNDAP, Inc.
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -70,7 +71,7 @@
 
 using namespace libdap;
 
-CPL_CVSID("$Id: dodsdataset2.cpp 20634 2010-09-16 22:02:29Z rouault $");
+CPL_CVSID("$Id: dodsdataset2.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void GDALRegister_DODS(void);
diff --git a/frmts/dted/dted_api.c b/frmts/dted/dted_api.c
index 582fe0d..20a7935 100644
--- a/frmts/dted/dted_api.c
+++ b/frmts/dted/dted_api.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.c 24603 2012-06-20 18:21:29Z rouault $
+ * $Id: dted_api.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTED/CDED access functions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "dted_api.h"
 
 #ifndef AVOID_CPL
-CPL_CVSID("$Id: dted_api.c 24603 2012-06-20 18:21:29Z rouault $");
+CPL_CVSID("$Id: dted_api.c 27044 2014-03-16 23:41:27Z rouault $");
 #endif
 
 static int bWarnedTwoComplement = FALSE;
diff --git a/frmts/dted/dted_api.h b/frmts/dted/dted_api.h
index cb422e5..ea76a65 100644
--- a/frmts/dted/dted_api.h
+++ b/frmts/dted/dted_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.h 24601 2012-06-19 20:29:36Z rouault $
+ * $Id: dted_api.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Public (C callable) interface for DTED/CDED reading.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/dted/dted_test.c b/frmts/dted/dted_test.c
index f744e90..6830498 100644
--- a/frmts/dted/dted_test.c
+++ b/frmts/dted/dted_test.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_test.c 12247 2007-09-27 18:18:06Z rouault $
+ * $Id: dted_test.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Test mainline for DTED writer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/dted/dteddataset.cpp b/frmts/dted/dteddataset.cpp
index 261448d..eedb6dc 100644
--- a/frmts/dted/dteddataset.cpp
+++ b/frmts/dted/dteddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dteddataset.cpp 24517 2012-05-30 21:07:47Z rouault $
+ * $Id: dteddataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  GDALDataset driver for DTED translator.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +31,9 @@
 #include "dted_api.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
+#include <algorithm>
 
-CPL_CVSID("$Id: dteddataset.cpp 24517 2012-05-30 21:07:47Z rouault $");
+CPL_CVSID("$Id: dteddataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_DTED(void);
@@ -136,21 +138,24 @@ CPLErr DTEDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if (nBlockXSize != 1)
     {
+        const int cbs = 32; // optimize for 64 byte cache line size
+        const int bsy = (nBlockYSize + cbs - 1) / cbs * cbs;
         panData = (GInt16 *) pImage;
-        GInt16* panBuffer = (GInt16*) CPLMalloc(sizeof(GInt16) * nBlockYSize);
-        int i;
-        for(i=0;i<nBlockXSize;i++)
-        {
-            if( !DTEDReadProfileEx( poDTED_DS->psDTED, i, panBuffer,
-                                    poDTED_DS->bVerifyChecksum ) )
-            {
-                CPLFree(panBuffer);
-                return CE_Failure;
+        GInt16* panBuffer = (GInt16*) CPLMalloc(sizeof(GInt16) * cbs * bsy);
+        for (int i = 0; i < nBlockXSize; i += cbs) {
+            int n = std::min(cbs, nBlockXSize - i);
+            for (int j = 0; j < n; ++j) {
+                if (!DTEDReadProfileEx(poDTED_DS->psDTED, i + j, panBuffer + j * bsy, poDTED_DS->bVerifyChecksum)) {
+                    CPLFree(panBuffer);
+                    return CE_Failure;
+                }
             }
-            int j;
-            for(j=0;j<nBlockYSize;j++)
-            {
-                panData[j * nBlockXSize + i] = panBuffer[nYSize - j - 1];
+            for (int y = 0; y < nBlockYSize; ++y) {
+                GInt16 *dst = panData + i + (nYSize - y - 1) * nBlockXSize;
+                GInt16 *src = panBuffer + y;
+                for (int j = 0; j < n; ++j) {
+                    dst[j] = src[j * bsy];
+                }
             }
         }
 
@@ -172,11 +177,7 @@ CPLErr DTEDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     for( int i = nYSize/2; i >= 0; i-- )
     {
-        GInt16  nTemp;
-
-        nTemp = panData[i];
-        panData[i] = panData[nYSize - i - 1];
-        panData[nYSize - i - 1] = nTemp;
+        std::swap(panData[i], panData[nYSize - i - 1]);
     }
 
     return CE_None;
diff --git a/frmts/e00grid/e00griddataset.cpp b/frmts/e00grid/e00griddataset.cpp
index fcc8f73..68e320a 100644
--- a/frmts/e00grid/e00griddataset.cpp
+++ b/frmts/e00grid/e00griddataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z rouault $
+ * $Id: e00griddataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  E00 grid driver
  * Purpose:  GDALDataset driver for E00 grid dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -46,7 +46,7 @@
 #define E00_DOUBLE_SIZE 21
 #define VALS_PER_LINE   5
 
-CPL_CVSID("$Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z rouault $");
+CPL_CVSID("$Id: e00griddataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_E00GRID(void);
diff --git a/frmts/ecw/ecwasyncreader.cpp b/frmts/ecw/ecwasyncreader.cpp
index 1bd5086..36c84bb 100644
--- a/frmts/ecw/ecwasyncreader.cpp
+++ b/frmts/ecw/ecwasyncreader.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/ecw/ecwcreatecopy.cpp b/frmts/ecw/ecwcreatecopy.cpp
index 00108c3..92bf42a 100644
--- a/frmts/ecw/ecwcreatecopy.cpp
+++ b/frmts/ecw/ecwcreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwcreatecopy.cpp 25924 2013-04-18 18:16:41Z rouault $
+ * $Id: ecwcreatecopy.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  ECW CreateCopy method implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,9 +29,10 @@
  ****************************************************************************/
 
 #include "gdal_ecw.h"
+#include "gdaljp2metadata.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ecwcreatecopy.cpp 25924 2013-04-18 18:16:41Z rouault $");
+CPL_CVSID("$Id: ecwcreatecopy.cpp 27182 2014-04-14 20:03:08Z rouault $");
 
 #if defined(FRMT_ecw) && defined(HAVE_COMPRESS)
 
@@ -90,7 +92,7 @@ public:
                         GDALDataType eType, 
                         const char *pszWKT, double *padfGeoTransform,
                         int nGCPCount, const GDAL_GCP *pasGCPList,
-                        int bIsJPEG2000 );
+                        int bIsJPEG2000, int bPixelIsPoint );
     CPLErr  CloseDown();
 
     CPLErr  PrepareCoverageBox( const char *pszWKT, double *padfGeoTransform );
@@ -195,6 +197,10 @@ CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
     GByte *pabyLineBuf;
     int nWordSize = GDALGetDataTypeSize( eWorkDT ) / 8;
 
+#ifdef DEBUG_VERBOSE
+    CPLDebug("ECW", "nNextLine = %d", nNextLine);
+#endif
+
     panBandMap = (int *) CPLMalloc(sizeof(int) * sFileInfo.nBands);
     for( iBand = 0; iBand < sFileInfo.nBands; iBand++ )
         panBandMap[iBand] = iBand+1;
@@ -509,7 +515,7 @@ CPLErr GDALECWCompressor::Initialize(
     GDALDataType eType, 
     const char *pszWKT, double *padfGeoTransform,
     int nGCPCount, const GDAL_GCP *pasGCPList,
-    int bIsJPEG2000 )
+    int bIsJPEG2000, int bPixelIsPoint )
 
 {
      const char *pszOption;
@@ -908,18 +914,30 @@ CPLErr GDALECWCompressor::Initialize(
 /* -------------------------------------------------------------------- */
 /*      Setup GML and GeoTIFF information.                              */
 /* -------------------------------------------------------------------- */
-    GDALJP2Metadata oJP2MD;
+    if( (pszWKT != NULL && pszWKT[0] != '\0') ||
+        !(padfGeoTransform[0] == 0.0 &&
+          padfGeoTransform[1] == 1.0 &&
+          padfGeoTransform[2] == 0.0 &&
+          padfGeoTransform[3] == 0.0 &&
+          padfGeoTransform[4] == 0.0 &&
+          padfGeoTransform[5] == 1.0) ||
+         nGCPCount > 0 )
+    {
+        GDALJP2Metadata oJP2MD;
+
+        oJP2MD.SetProjection( pszWKT );
+        oJP2MD.SetGeoTransform( padfGeoTransform );
+        oJP2MD.SetGCPs( nGCPCount, pasGCPList );
+        oJP2MD.bPixelIsPoint = bPixelIsPoint;
 
-    oJP2MD.SetProjection( pszWKT );
-    oJP2MD.SetGeoTransform( padfGeoTransform );
-    oJP2MD.SetGCPs( nGCPCount, pasGCPList );
-    if (bIsJPEG2000) {
+        if (bIsJPEG2000) {
 
-        if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
-            WriteJP2Box( oJP2MD.CreateGMLJP2(nXSize,nYSize) );
-        if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
-            WriteJP2Box( oJP2MD.CreateJP2GeoTIFF() );
+            if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
+                WriteJP2Box( oJP2MD.CreateGMLJP2(nXSize,nYSize) );
+            if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
+                WriteJP2Box( oJP2MD.CreateJP2GeoTIFF() );
 
+        }
     }
 /* -------------------------------------------------------------------- */
 /*      We handle all jpeg2000 files via the VSIIOStream, but ECW       */
@@ -941,7 +959,8 @@ CPLErr GDALECWCompressor::Initialize(
             return CE_Failure;
         }
 
-        m_OStream.Access( fpVSIL, TRUE, bSeekable, pszFilename, 0, -1 );
+        m_OStream.Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename, 
+			  0, -1 );
     }    
 
 /* -------------------------------------------------------------------- */
@@ -1181,12 +1200,16 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         /* by CPLSPrintf(), which has just a few rotating entries. */
         papszBandDescriptions[i] = CPLStrdup(ECWGetColorInterpretationName(poSrcDS->GetRasterBand(i+1)->GetColorInterpretation(), i));
     }
+
+    const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+    int bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
+
     if( oCompressor.Initialize( pszFilename, papszOptions, 
                                 nXSize, nYSize, nBands, papszBandDescriptions, bRGBColorSpace,
                                 eType, pszWKT, adfGeoTransform, 
                                 poSrcDS->GetGCPCount(), 
                                 poSrcDS->GetGCPs(),
-                                bIsJPEG2000 )
+                                bIsJPEG2000, bPixelIsPoint )
         != CE_None )
     {
         for (i=0;i<nBands;i++)
@@ -1720,7 +1743,7 @@ CPLErr ECWWriteDataset::Crystalize()
                                    eDataType, 
                                    pszProjection, adfGeoTransform, 
                                    0, NULL,
-                                   bIsJPEG2000 );
+                                   bIsJPEG2000, FALSE );
 
     if( eErr == CE_None )
         bCrystalized = TRUE;
diff --git a/frmts/ecw/ecwdataset.cpp b/frmts/ecw/ecwdataset.cpp
index b1e85a5..ce77e76 100644
--- a/frmts/ecw/ecwdataset.cpp
+++ b/frmts/ecw/ecwdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwdataset.cpp 26371 2013-08-26 18:42:34Z rouault $
+ * $Id: ecwdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_api.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: ecwdataset.cpp 26371 2013-08-26 18:42:34Z rouault $");
+CPL_CVSID("$Id: ecwdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #undef NOISY_DEBUG
 
@@ -908,22 +909,11 @@ ECWDataset::ECWDataset(int bIsJPEG2000)
 {
     this->bIsJPEG2000 = bIsJPEG2000;
     bUsingCustomStream = FALSE;
-    pszProjection = NULL;
     poFileView = NULL;
     bWinActive = FALSE;
     panWinBandList = NULL;
     eRasterDataType = GDT_Byte;
-    nGCPCount = 0;
-    pasGCPList = NULL;
     papszGMLMetadata = NULL;
-    
-    bGeoTransformValid = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
 
     bHdrDirty = FALSE;
     bGeoTransformChanged = FALSE;
@@ -994,8 +984,30 @@ ECWDataset::~ECWDataset()
     // to avoid an issue with the ECW SDK 3.3 where the destructor of CNCSJP2File::CNCSJP2FileVector CNCSJP2File::sm_Files;
     // static ressource allocated in NCJP2File.cpp can be called before GDALDestroy(), causing
     // ECW SDK resources ( CNCSJP2File files ) to be closed before we get here.
-    if( poFileView != NULL &&
-        (!bIsJPEG2000 || !GDALIsInGlobalDestructor()) )
+    //
+    // We also have an issue with ECW SDK 5.0 and ECW files on Linux when
+    // running a multi-threaded test under Java if there's still an ECW dataset
+    // not explicitely closed at process termination.
+    /*  #0  0x00007fffb26e7a80 in NCSAtomicAdd64 () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #1  0x00007fffb2aa7684 in NCS::SDK::CBuffer2D::Free() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #2  0x00007fffb2aa7727 in NCS::SDK::CBuffer2D::~CBuffer2D() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #3  0x00007fffb29aa7be in NCS::ECW::CReader::~CReader() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #4  0x00007fffb29aa819 in NCS::ECW::CReader::~CReader() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #5  0x00007fffb291fd3a in NCS::CView::Close(bool) () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #6  0x00007fffb2927529 in NCS::CView::~CView() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #7  0x00007fffb29277f9 in NCS::CView::~CView() () from /home/even/ecwjp2_sdk/redistributable/x64/libNCSEcw.so
+        #8  0x00007fffb71a9a53 in ECWDataset::~ECWDataset (this=0x7fff942cce10, __in_chrg=<optimized out>) at ecwdataset.cpp:1003
+        #9  0x00007fffb71a9cca in ECWDataset::~ECWDataset (this=0x7fff942cce10, __in_chrg=<optimized out>) at ecwdataset.cpp:1039
+        #10 0x00007fffb7551f98 in GDALDriverManager::~GDALDriverManager (this=0x7ffff01981a0, __in_chrg=<optimized out>) at gdaldrivermanager.cpp:196
+        #11 0x00007fffb7552140 in GDALDriverManager::~GDALDriverManager (this=0x7ffff01981a0, __in_chrg=<optimized out>) at gdaldrivermanager.cpp:288
+        #12 0x00007fffb7552e18 in GDALDestroyDriverManager () at gdaldrivermanager.cpp:824
+        #13 0x00007fffb7551c61 in GDALDestroy () at gdaldllmain.cpp:80
+        #14 0x00007ffff7de990e in _dl_fini () at dl-fini.c:254
+    */
+    // Not replicable with similar test in C++, but this might be just a matter of luck related
+    // to the order in which the libraries are unloaded, so just don't try
+    // to delete poFileView from the GDAL destructor.
+    if( poFileView != NULL && !GDALIsInGlobalDestructor() )
     {
         VSIIOStream *poUnderlyingIOStream = (VSIIOStream *)NULL;
 
@@ -1026,15 +1038,8 @@ ECWDataset::~ECWDataset()
     }
 #endif 
 
-    CPLFree( pszProjection );
     CSLDestroy( papszGMLMetadata );
 
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
-
     CPLFree(sCachedMultiBandIO.pabyData);
 }
 
@@ -1479,6 +1484,26 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 #endif
 
 /* -------------------------------------------------------------------- */
+/*      Do some validation of parameters.                               */
+/* -------------------------------------------------------------------- */
+
+    CPLErr eErr;
+    int bStopProcessing = FALSE;
+    eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing,
+                                                    nXOff, nYOff, nXSize, nYSize,
+                                                    nBufXSize, nBufYSize, 
+                                                    nBandCount, panBandList);
+    if( eErr != CE_None || bStopProcessing )
+        return eErr;
+    
+    if( nBandCount > 100 )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg,
+                     "AdviseRead(): Too many bands : %d", nBandCount);
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Adjust band numbers to be zero based.                           */
 /* -------------------------------------------------------------------- */
     panAdjustedBandList = (int *) 
@@ -1486,10 +1511,9 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     nBandIndexToPromoteTo8Bit = -1;
     for( int ii= 0; ii < nBandCount; ii++ )
     {
-        if( ((ECWRasterBand*)GetRasterBand(panBandList[ii]))->bPromoteTo8Bit )
+        panAdjustedBandList[ii] = (panBandList != NULL) ? panBandList[ii] - 1 : ii;
+        if( ((ECWRasterBand*)GetRasterBand(panAdjustedBandList[ii] + 1))->bPromoteTo8Bit )
             nBandIndexToPromoteTo8Bit = ii;
-
-        panAdjustedBandList[ii] = panBandList[ii] - 1;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1529,7 +1553,15 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     nWinBufYSize = nBufYSize;
 
     panWinBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
-    memcpy( panWinBandList, panBandList, sizeof(int)* nBandCount);
+    if( panBandList != NULL )
+        memcpy( panWinBandList, panBandList, sizeof(int)* nBandCount);
+    else
+    {
+        for( int ii= 0; ii < nBandCount; ii++ )
+        {
+            panWinBandList[ii] = ii + 1;
+        }
+    }
     nWinBandCount = nBandCount;
 
     nWinBufLoaded = -1;
@@ -1809,7 +1841,7 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
                                     (*panBandMap - 1) * nBufXSize * nBufYSize * nDataTypeSize +
                                     j * nBufXSize * nDataTypeSize,
                             eBufType, nDataTypeSize,
-                            ((GByte*)pData) + j * nLineSpace, eBufType, nDataTypeSize,
+                            ((GByte*)pData) + j * nLineSpace, eBufType, nPixelSpace,
                             nBufXSize);
             }
             return CE_None;
@@ -1973,7 +2005,7 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
                 GDALCopyWords(sCachedMultiBandIO.pabyData +
                                     j * nBufXSize * nDataTypeSize,
                               eBufType, nDataTypeSize,
-                              ((GByte*)pData) + j * nLineSpace, eBufType, nDataTypeSize,
+                              ((GByte*)pData) + j * nLineSpace, eBufType, nPixelSpace,
                               nBufXSize);
             }
             return CE_None;
@@ -2472,31 +2504,25 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 /* -------------------------------------------------------------------- */
     if( bIsJPEG2000 )
     {
-        GDALJP2Metadata oJP2Geo;
-        if ( oJP2Geo.ReadAndParse( osFilename ) )
-        {
-            poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-            poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
-            memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform,
-                    sizeof(double) * 6 );
-            poDS->nGCPCount = oJP2Geo.nGCPCount;
-            poDS->pasGCPList = oJP2Geo.pasGCPList;
-            oJP2Geo.pasGCPList = NULL;
-            oJP2Geo.nGCPCount = 0;
-        }
-
-        if (oJP2Geo.pszXMPMetadata)
-        {
-            char *apszMDList[2];
-            apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-            apszMDList[1] = NULL;
-            poDS->SetMetadata(apszMDList, "xml:XMP");
-        }
+        poDS->LoadJP2Metadata(poOpenInfo, osFilename);
     }
     else
     {
         poDS->ECW2WKTProjection();
-		
+
+    /* -------------------------------------------------------------------- */
+    /*      Check for world file.                                           */
+    /* -------------------------------------------------------------------- */
+        if( !poDS->bGeoTransformValid )
+        {
+            poDS->bGeoTransformValid |= 
+                GDALReadWorldFile2( osFilename, NULL,
+                                    poDS->adfGeoTransform,
+                                    poOpenInfo->papszSiblingFiles, NULL )
+                || GDALReadWorldFile2( osFilename, ".wld",
+                                    poDS->adfGeoTransform,
+                                    poOpenInfo->papszSiblingFiles, NULL );
+        }
     }
 
 	poDS->SetMetadataItem("COMPRESSION_RATE_TARGET", CPLString().Printf("%d", poDS->psFileInfo->nCompressionRate));
@@ -2515,20 +2541,6 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 #endif
 
 /* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
-/* -------------------------------------------------------------------- */
-    if( !poDS->bGeoTransformValid )
-    {
-        poDS->bGeoTransformValid |= 
-            GDALReadWorldFile2( osFilename, NULL,
-                                poDS->adfGeoTransform,
-                                poOpenInfo->papszSiblingFiles, NULL )
-            || GDALReadWorldFile2( osFilename, ".wld",
-                                   poDS->adfGeoTransform,
-                                   poOpenInfo->papszSiblingFiles, NULL );
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( osFilename );
@@ -2538,81 +2550,14 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 }
 
 /************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int ECWDataset::GetGCPCount()
-
-{
-    if( nGCPCount != 0 )
-        return nGCPCount;
-    else
-        return GDALPamDataset::GetGCPCount();
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *ECWDataset::GetGCPProjection()
-
-{
-    if( nGCPCount > 0 )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
-}
-
-/************************************************************************/
-/*                               GetGCP()                               */
-/************************************************************************/
-
-const GDAL_GCP *ECWDataset::GetGCPs()
-
-{
-    if( nGCPCount != 0 )
-        return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/*                                                                      */
-/*      We let PAM coordinate system override the one stored inside     */
-/*      our file.                                                       */
+/*                      GetMetadataDomainList()                         */
 /************************************************************************/
 
-const char *ECWDataset::GetProjectionRef() 
-
+char **ECWDataset::GetMetadataDomainList()
 {
-    const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
-
-    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
-        return pszProjection;
-    else
-        return pszPamPrj;
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/*                                                                      */
-/*      Let the PAM geotransform override the native one if it is       */
-/*      available.                                                      */
-/************************************************************************/
-
-CPLErr ECWDataset::GetGeoTransform( double * padfTransform )
-
-{
-    CPLErr eErr = GDALPamDataset::GetGeoTransform( padfTransform );
-
-    if( eErr != CE_None && bGeoTransformValid )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-        return( CE_None );
-    }
-    else
-        return eErr;
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "ECW", "GML", NULL);
 }
 
 /************************************************************************/
diff --git a/frmts/ecw/gdal_ecw.h b/frmts/ecw/gdal_ecw.h
index 0764571..4a90c11 100644
--- a/frmts/ecw/gdal_ecw.h
+++ b/frmts/ecw/gdal_ecw.h
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001-2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,9 +31,8 @@
 #ifndef GDAL_ECW_H_INCLUDED
 #define GDAL_ECW_H_INCLUDED
 
-#include "gdal_pam.h"
+#include "gdaljp2abstractdataset.h"
 #include "gdal_frmts.h"
-#include "gdaljp2metadata.h"
 #include "cpl_string.h"
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
@@ -367,7 +367,8 @@ class VSIIOStream : public CNCSJPCIOStream
             }
             else
             {
-                GByte prevBuffer[] = { nCOMLength >> 8, nCOMLength & 0xff };
+                GByte prevBuffer[] = 
+		  { (GByte)(nCOMLength >> 8), (GByte) (nCOMLength & 0xff) };
                 VSIFWriteL(prevBuffer, 2, 1, fpVSIL);
                 nCOMState = 0;
             }
@@ -455,7 +456,7 @@ typedef struct
     GByte* pabyData;
 } ECWCachedMultiBandIO;
 
-class CPL_DLL ECWDataset : public GDALPamDataset
+class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
 {
     friend class ECWRasterBand;
     friend class ECWAsyncReader;
@@ -479,12 +480,6 @@ class CPL_DLL ECWDataset : public GDALPamDataset
     int         nWinBufLoaded;
     void        **papCurLineBuf;
 
-    int         bGeoTransformValid;
-    double      adfGeoTransform[6];
-    char        *pszProjection;
-    int         nGCPCount;
-    GDAL_GCP    *pasGCPList;
-
     char        **papszGMLMetadata;
 
     ECWCachedMultiBandIO sCachedMultiBandIO;
@@ -559,13 +554,7 @@ class CPL_DLL ECWDataset : public GDALPamDataset
                               void *, int, int, GDALDataType,
                               int, int *, int, int, int );
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef();
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                      const char * pszDomain = "" );
     virtual char      **GetMetadata( const char * pszDomain = "" );
diff --git a/frmts/elas/elasdataset.cpp b/frmts/elas/elasdataset.cpp
index 13b704a..2cbce33 100644
--- a/frmts/elas/elasdataset.cpp
+++ b/frmts/elas/elasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $
+ * $Id: elasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ELAS Translator
  * Purpose:  Complete implementation of ELAS translator module for GDAL.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $");
+CPL_CVSID("$Id: elasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_ELAS(void);
diff --git a/frmts/envisat/EnvisatFile.c b/frmts/envisat/EnvisatFile.c
index e48b8b1..77ca5b3 100644
--- a/frmts/envisat/EnvisatFile.c
+++ b/frmts/envisat/EnvisatFile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.c 24765 2012-08-11 18:32:16Z rouault $
+ * $Id: EnvisatFile.c 27098 2014-03-27 00:16:11Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Atlantis Scientific, Inc.
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #  include "cpl_conv.h"
 #  include "EnvisatFile.h"
 
-CPL_CVSID("$Id: EnvisatFile.c 24765 2012-08-11 18:32:16Z rouault $");
+CPL_CVSID("$Id: EnvisatFile.c 27098 2014-03-27 00:16:11Z rouault $");
 
 #else
 #  include "APP/app.h"
@@ -1507,41 +1508,97 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
+int EnvisatFile_ReadDatasetRecordChunk(EnvisatFile*,int,int,void*,int,int);
+
 int EnvisatFile_ReadDatasetRecord( EnvisatFile *self, 
                                     int ds_index,
                                     int record_index,
                                     void *buffer )
+{
+    return EnvisatFile_ReadDatasetRecordChunk( self, 
+                ds_index, record_index, buffer, 0 , -1 ) ; 
+} 
+
+/*-----------------------------------------------------------------------------
+
+Name:
+    EnvisatFile_ReadDatasetRecordChunk()
+
+Purpose:
+    Read a part of an arbitrary dataset record.
+
+Description:
+    Note that no range checking is made on dataset's offset and size, 
+    and data may be read from outside the dataset if they are inappropriate.
+
+Inputs:
+    self -- the file to be searched.
+    ds_index -- the index of dataset to access.
+    record_index -- the record to write.
+    record_buffer -- buffer to load data into
+    offset -- chunk offset relative to the record start (zerro offset)
+    size -- chunk size (set -1 to read from offset to the records' end)  
+
+Outputs:
+
+Returns:
+    SUCCESS or FAILURE
 
+-----------------------------------------------------------------------------*/
+
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self, 
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer, 
+                                    int offset, int size )
 {
     int		absolute_offset;
     int         result;
+    int     dsr_size = self->ds_info[ds_index]->dsr_size ; 
+
+    if (( offset < 0 )||(offset > dsr_size))
+    {
+        SendError( "Invalid chunk offset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    } 
+
+    if ( size < 0 ) 
+        size = dsr_size - offset ; 
 
     if( ds_index < 0 || ds_index >= self->ds_count )
     {
-        SendError( "Attempt to write non-existant dataset in "
-                   "EnvisatFile_WriteDatasetRecord()" );
+        SendError( "Attempt to read non-existant dataset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
         return FAILURE;
     }
 
     if( record_index < 0
         || record_index >=  self->ds_info[ds_index]->num_dsr )
     {
-        SendError( "Attempt to write beyond end of dataset in "
-                   "EnvisatFile_WriteDatasetRecord()" );
+        SendError( "Attempt to read beyond end of dataset in "
+                   "EnvisatFile_ReadDatasetRecordChunk()" );
+        return FAILURE;
+    }
+
+    if( (offset + size) > dsr_size )
+    {
+        SendError( "Attempt to read beyond the record's boundary"
+                   "EnvisatFile_ReadDatasetRecord()" );
         return FAILURE;
     }
 
     absolute_offset = self->ds_info[ds_index]->ds_offset
-        + record_index * self->ds_info[ds_index]->dsr_size;
+        + record_index * dsr_size + offset ;
 
     if( VSIFSeekL( self->fp, absolute_offset, SEEK_SET ) != 0 )
     {
-        SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
+        SendError( "seek failed in EnvisatFile_ReadDatasetRecordChunk()" );
         return FAILURE;
     }
 
-    result = VSIFReadL( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
-    if( result != self->ds_info[ds_index]->dsr_size )
+    result = VSIFReadL( buffer, 1, size, self->fp );
+    if( result != size )
     {
         SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
         return FAILURE;
diff --git a/frmts/envisat/EnvisatFile.h b/frmts/envisat/EnvisatFile.h
index fb637fe..72c3810 100644
--- a/frmts/envisat/EnvisatFile.h
+++ b/frmts/envisat/EnvisatFile.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: EnvisatFile.h 27098 2014-03-27 00:16:11Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -101,6 +101,11 @@ int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
                                 int num_dsr,
                                 int dsr_size );
                               
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self, 
+                                    int ds_index,
+                                    int record_index,
+                                    void *buffer, 
+                                    int offset, int size ) ;
 int EnvisatFile_ReadDatasetRecord( EnvisatFile *self, 
                                    int ds_index,
                                    int record_index, 
diff --git a/frmts/envisat/GNUmakefile b/frmts/envisat/GNUmakefile
index 839fce0..5006bbc 100644
--- a/frmts/envisat/GNUmakefile
+++ b/frmts/envisat/GNUmakefile
@@ -1,5 +1,5 @@
 
-OBJ	=	EnvisatFile.o records.o envisatdataset.o
+OBJ	=	EnvisatFile.o records.o adsrange.o unwrapgcps.o envisatdataset.o
 
 include ../../GDALmake.opt
 
diff --git a/frmts/envisat/adsrange.cpp b/frmts/envisat/adsrange.cpp
new file mode 100644
index 0000000..d5d4889
--- /dev/null
+++ b/frmts/envisat/adsrange.cpp
@@ -0,0 +1,153 @@
+/******************************************************************************
+ * $Id: adsrange.cpp 27099 2014-03-27 00:49:30Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Detect range of ADS records matching the MDS records.
+ * Author:   Martin Paces, martin.paces at eox.at 
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, EOX IT Services, GmbH 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#include "adsrange.hpp"
+#include "timedelta.hpp"
+
+#include "cpl_string.h"
+
+CPL_C_START
+#include "EnvisatFile.h"
+#include "records.h"
+CPL_C_END
+
+#include <cmath>
+
+/* -------------------------------------------------------------------- */
+/* 
+ * data-set descriptor (private helper class) 
+ */
+
+class DataSet
+{ 
+  public:
+
+    EnvisatFile & envfile ;
+    int index ;
+    int nrec ; 
+
+    DataSet( EnvisatFile & envfile , int index ) : 
+        envfile(envfile), index(index), nrec(0)
+    { 
+        EnvisatFile_GetDatasetInfo( &envfile, index, NULL, NULL, NULL,
+                NULL , NULL, &nrec, NULL ) ;
+    } 
+
+    TimeDelta getMJD( int ridx ) 
+    { 
+        GUInt32 mjd[3] ; 
+
+        if ( ridx < 0 ) ridx += nrec ; 
+    
+        EnvisatFile_ReadDatasetRecordChunk(&envfile,index,ridx,mjd,0,12) ;
+
+        #define INT32(x)    ((GInt32)CPL_MSBWORD32(x)) 
+
+        return TimeDelta( INT32(mjd[0]), INT32(mjd[1]), INT32(mjd[2]) ) ;
+
+        #undef INT32 
+    } 
+
+} ; 
+
+/* -------------------------------------------------------------------- */
+/* 
+ * constructor of the ADSRangeLastAfter object 
+ *
+ */ 
+
+ADSRangeLastAfter::ADSRangeLastAfter( EnvisatFile & envfile, 
+    int  ads_idx , int mds_idx, const TimeDelta & line_interval )
+{ 
+    int idx ; 
+    TimeDelta t_mds , t_ads , t_ads_prev ; 
+
+    /* abs.time tolerance */ 
+    TimeDelta atol = line_interval * 0.5 ; 
+
+    /* MDS and ADS descriptor classes */
+    DataSet mds( envfile, mds_idx ) ; 
+    DataSet ads( envfile, ads_idx ) ; 
+
+    /* read the times of the first and last measurements */ 
+    mjd_m_first = mds.getMJD(0) ;  /* MDJ time of the first MDS record */
+    mjd_m_last  = mds.getMJD(-1) ;   /* MDJ time of the last MDS record */
+
+    /* look-up the the first applicable ADSR */ 
+
+    idx   = 0 ; 
+    t_mds = mjd_m_first + atol ; /*time of the first MDSR + tolerance */ 
+    t_ads  = ads.getMJD(0) ;     /*time of the first ADSR */
+    t_ads_prev = t_ads ;         /* holds previous ADSR */
+
+    if ( t_ads < t_mds ) 
+    { 
+        for( idx = 1 ; idx < ads.nrec ; ++idx )
+        { 
+            t_ads = ads.getMJD(idx) ; 
+        
+            if ( t_ads >= t_mds ) break ; 
+
+            t_ads_prev = t_ads ; 
+        } 
+    } 
+    
+    /* store the first applicable ASDR */
+    idx_first = idx - 1 ; /* sets -1 if no match */
+    mjd_first = t_ads_prev ; /* set time of the first rec. if no match */
+
+    /* look-up the the last applicable ADSR */ 
+
+    idx   = ads.nrec-2 ; 
+    t_mds = mjd_m_last - atol ;  /* time of the last MDSR - tolerance */ 
+    t_ads  = ads.getMJD(-1) ;    /* time of the first ADSR */
+    t_ads_prev = t_ads ;         /* holds previous ADSR */
+
+    if ( t_ads > t_mds ) 
+    { 
+        for( idx = ads.nrec-2 ; idx >= 0 ; --idx )
+        { 
+            t_ads = ads.getMJD(idx) ; 
+        
+            if ( t_ads <= t_mds ) break ; 
+
+            t_ads_prev = t_ads ; 
+        } 
+    } 
+   
+    /* store the last applicable ASDR */
+    idx_last = idx + 1 ; /* sets ads.nrec if no match */
+    mjd_last = t_ads_prev ; /* set time of the last rec. if no match */
+
+    /* valuate the line offsets */
+    off_first = (int)floor( 0.5 + ( mjd_m_first - mjd_first ) / line_interval ) ; 
+    off_last  = (int)floor( 0.5 + ( mjd_last  - mjd_m_last  ) / line_interval ) ; 
+
+} ;
+
diff --git a/frmts/envisat/adsrange.hpp b/frmts/envisat/adsrange.hpp
new file mode 100644
index 0000000..de4ca0d
--- /dev/null
+++ b/frmts/envisat/adsrange.hpp
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * $Id: adsrange.hpp 27098 2014-03-27 00:16:11Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Detect range of ADS records matching the MDS records
+ * Author:   Martin Paces, martin.paces at eox.at 
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, EOX IT Services, GmbH 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef adsrange_hpp
+#define adsrange_hpp
+
+#include "cpl_string.h"
+
+CPL_C_START
+#include "EnvisatFile.h"
+#include "records.h"
+CPL_C_END
+
+#include "timedelta.hpp"
+
+/* -------------------------------------------------------------------- */
+/*
+ * class ADSRange 
+ * 
+ * Range of ADS record matching the range of the MDS records. 
+ *
+ */
+
+class ADSRange 
+{ 
+
+  protected: 
+
+    int idx_first ; /* index of the first matched ADSR */
+    int idx_last ;  /* index of the last matched ADSR */
+    int off_first ; /* num. of lines from 1st matched ADSR to 1st MDSR */
+    int off_last ;  /* num. of lines from last MDSR to last matched ADSR*/
+
+    TimeDelta mjd_first ;  /* MDJ time of the first matched ADS record */
+    TimeDelta mjd_last ;   /* MDJ time of the last matched ADS record */
+    TimeDelta mjd_m_first ;  /* MDJ time of the first MDS record */
+    TimeDelta mjd_m_last ;   /* MDJ time of the last MDS record */
+
+  public: 
+
+    /* CONSTRUCTOR */ 
+    ADSRange() :
+        idx_first(0), idx_last(0), off_first(0), off_last(0),
+        mjd_first(0), mjd_last(0), mjd_m_first(0), mjd_m_last(0) 
+    { 
+    } 
+
+    ADSRange( const int idx_first, const int idx_last, 
+        const int off_first, const int off_last, 
+        const TimeDelta &mjd_first, const TimeDelta &mjd_last, 
+        const TimeDelta &mjd_m_first, const TimeDelta &mjd_m_last ) :
+        idx_first(idx_first), idx_last(idx_last), off_first(off_first),
+        off_last(off_last), mjd_first(mjd_first), mjd_last(mjd_last),
+        mjd_m_first(mjd_m_first), mjd_m_last(mjd_m_last) 
+    { 
+    } 
+    
+    /* get count of matched records */
+    inline int getDSRCount( void ) const 
+    { 
+        return ( idx_last - idx_first + 1 ) ; 
+    } 
+
+    /* GETTERS */ 
+
+    /* get index of the first matched ADS record */
+    inline int getFirstIndex( void ) 
+    { 
+        return this->idx_first ; 
+    } 
+
+    /* get index of the last matched ADS record */
+    inline int getLastIndex( void ) 
+    { 
+        return this->idx_last ; 
+    } 
+
+    /* get offset of the first matched ADS record */
+    inline int getFirstOffset( void ) 
+    { 
+        return this->off_first ; 
+    } 
+
+    /* get offset of the last matched ADS record */
+    inline int getLastOffset( void ) 
+    { 
+        return this->off_last ; 
+    } 
+
+    /* get MJD time of the first matched ADS record */
+    inline TimeDelta getFirstTime( void ) 
+    { 
+        return this->mjd_first ; 
+    } 
+
+    /* get MJD time of the last matched ADS record */
+    inline TimeDelta getLastTime( void ) 
+    { 
+        return this->mjd_last ; 
+    } 
+
+    /* get MJD time of the first MDS record */
+    inline TimeDelta getMDSRFirstTime( void ) 
+    { 
+        return this->mjd_m_first ; 
+    } 
+
+    /* get MJD time of the last MDS record */
+    inline TimeDelta getMDSRLastTime( void ) 
+    { 
+        return this->mjd_m_last ; 
+    } 
+
+} ;  
+
+
+/* -------------------------------------------------------------------- */
+/* 
+ * NOTE: There are two kinds of ADS records: 
+ *
+ *  1) One ADS record appliable to all consequent MDS records until replaced 
+ *     by another ADS record, i.e., last MDS records does no need to be 
+ *     followed by an ADS record.
+ *
+ *  2) Two ADS records applicable to all MDS records between them 
+ *     (e.g., tiepoints ADS), i.e., last MDS record should be followed 
+ *     by an ADS rescord having the same or later time-stamp.  
+ *  
+ *  The type of the ADS afects the way how the ADS records corresponding 
+ *  to a set of MDS records should be selected. 
+ */
+
+
+class ADSRangeLastAfter: public ADSRange
+{ 
+
+  public: 
+
+    /* CONSTRUCTOR */ 
+    ADSRangeLastAfter( EnvisatFile & envfile, int  ads_idx , int mds_idx,
+            const TimeDelta & line_interval ) ; 
+
+} ;  
+
+
+#endif /*tiepointrange_hpp*/
+
diff --git a/frmts/envisat/envisatdataset.cpp b/frmts/envisat/envisatdataset.cpp
index 2e6649d..ad29294 100644
--- a/frmts/envisat/envisatdataset.cpp
+++ b/frmts/envisat/envisatdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envisatdataset.cpp 24765 2012-08-11 18:32:16Z rouault $
+ * $Id: envisatdataset.cpp 27098 2014-03-27 00:16:11Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Reader for ENVISAT format image data.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Atlantis Scientific, Inc.
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,11 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "timedelta.hpp"
+#include "adsrange.hpp"
 #include "rawdataset.h"
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: envisatdataset.cpp 24765 2012-08-11 18:32:16Z rouault $");
+CPL_CVSID("$Id: envisatdataset.cpp 27098 2014-03-27 00:16:11Z rouault $");
 
 CPL_C_START
 #include "EnvisatFile.h"
@@ -168,6 +171,8 @@ class EnvisatDataset : public RawDataset
     void        ScanForGCPs_ASAR();
     void        ScanForGCPs_MERIS();
 
+    void        UnwrapGCPs(); 
+
     void	CollectMetadata( EnvisatFile_HeaderFlag );
     void        CollectDSDMetadata();
     void        CollectADSMetadata();
@@ -179,6 +184,7 @@ class EnvisatDataset : public RawDataset
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char * pszDomain );
 
 
@@ -262,6 +268,18 @@ const GDAL_GCP *EnvisatDataset::GetGCPs()
 }
 
 /************************************************************************/
+/*                         UnwrapGCPs()                                 */
+/************************************************************************/
+
+/* external C++ implementation of the in-place unwrapper */
+void EnvisatUnwrapGCPs( int nGCPCount, GDAL_GCP *pasGCPList ) ;
+
+void  EnvisatDataset::UnwrapGCPs()
+{ 
+    EnvisatUnwrapGCPs( nGCPCount, pasGCPList ) ;
+} 
+
+/************************************************************************/
 /*                          ScanForGCPs_ASAR()                          */
 /************************************************************************/
 
@@ -384,7 +402,8 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 void EnvisatDataset::ScanForGCPs_MERIS()
 
 {
-    int		nDatasetIndex, nNumDSR, nDSRSize, iRecord;
+    int		nDatasetIndex, nNumDSR, nDSRSize;
+    bool    isBrowseProduct ; 
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a meaningful geolocation grid?  Seach for a          */
@@ -426,41 +445,109 @@ void EnvisatDataset::ScanForGCPs_MERIS()
     nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1)
         / nSamplesPerTiePoint;
 
-    if( (GetRasterYSize() + nLinesPerTiePoint - 1)
-        / nLinesPerTiePoint != nTPPerColumn )
+/* -------------------------------------------------------------------- */
+/*      Find a Mesurement type dataset to use as a reference raster     */
+/*      band.                                                           */
+/* -------------------------------------------------------------------- */
+
+    int		nMDSIndex;
+
+    for( nMDSIndex = 0; TRUE; nMDSIndex++ )
     {
-        CPLDebug( "EnvisatDataset", "Got %d instead of %d nTPPerColumn.",
-                  (GetRasterYSize()+nLinesPerTiePoint-1)/nLinesPerTiePoint,
-                  nTPPerColumn );
-        return;
+        char *pszDSType;
+        if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nMDSIndex,
+            NULL, &pszDSType, NULL, NULL, NULL, NULL, NULL ) == FAILURE )
+        {
+            CPLDebug("EnvisatDataset",
+                            "Unable to find MDS in Envisat file.") ;
+            return ;
+    }
+        if( EQUAL(pszDSType,"M") ) break;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get subset of TP ADS records matching the MDS records	*/
+/* -------------------------------------------------------------------- */
+
+    /* get the MDS line sampling time interval */
+    TimeDelta tdMDSSamplingInterval( 0 , 0 ,  
+        EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
+                                      "LINE_TIME_INTERVAL", 0  ) );
+
+    /* get range of TiePoint ADS records matching the measurements */
+    ADSRangeLastAfter arTP( *hEnvisatFile , nDatasetIndex, 
+        nMDSIndex , tdMDSSamplingInterval ) ; 
+    
+    /* check if there are any TPs to be used */ 
+    if ( arTP.getDSRCount() <= 0 )
+    {
+        CPLDebug( "EnvisatDataset" , "No tiepoint covering "
+            "the measurement records." ) ;
+        return; /* No TPs - no extraction. */
+    } 
+
+    /* check if TPs cover the whole range of MDSRs */
+    if(( arTP.getFirstOffset() < 0 )||( arTP.getLastOffset() < 0 ))
+    {
+        CPLDebug( "EnvisatDataset" , "The tiepoints do not cover "
+            "whole range of measurement records." ) ;
+        /* Not good but we can still extract some of the TPS, can we? */
     }
 
-    if( 50*nTPPerLine + 13 != nDSRSize )
+    /* check TP records spacing */
+    if ((1+(arTP.getFirstOffset()+arTP.getLastOffset()+GetRasterYSize()-1) 
+           / nLinesPerTiePoint ) != arTP.getDSRCount() )
     {
-        CPLDebug( "EnvisatDataset",
-                  "DSRSize=%d instead of expected %d for tiepoints ADS.",
-                  nDSRSize, 50*nTPPerLine + 13 );
+        CPLDebug( "EnvisatDataset", "Not enough tieponts per column! "
+            "received=%d expected=%d", nTPPerColumn , 
+                1 + (arTP.getFirstOffset()+arTP.getLastOffset()+
+                      GetRasterYSize()-1) / nLinesPerTiePoint ) ; 
+        return; /* That is far more serious - we risk missplaces TPs. */
+    }
+
+    if ( 50*nTPPerLine + 13 == nDSRSize ) /* regular product */
+    {
+        isBrowseProduct = false ; 
+    } 
+    else if ( 8*nTPPerLine + 13 == nDSRSize ) /* browse product */
+    { 
+        /* although BPs are rare there is no reason not to support them */
+        isBrowseProduct = true ; 
+    } 
+    else 
+    {
+        CPLDebug( "EnvisatDataset", "Unexpectd size of 'Tie points ADS' !"
+                " received=%d expected=%d or %d" , nDSRSize ,
+                50*nTPPerLine+13, 8*nTPPerLine+13 ) ;
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Collect the first GCP set from each record.			*/
 /* -------------------------------------------------------------------- */
-    GByte	*pabyRecord = (GByte *) CPLMalloc(nDSRSize);
+
+    GByte	*pabyRecord = (GByte *) CPLMalloc(nDSRSize-13);
     int  	iGCP;
-    GUInt32 	unValue;
+
+    GUInt32 *tpLat = ((GUInt32*)pabyRecord) + nTPPerLine*0 ; /* latitude */  
+    GUInt32 *tpLon = ((GUInt32*)pabyRecord) + nTPPerLine*1 ; /* longitude */  
+    GUInt32 *tpLtc = ((GUInt32*)pabyRecord) + nTPPerLine*4 ; /* lat. DEM correction */
+    GUInt32 *tpLnc = ((GUInt32*)pabyRecord) + nTPPerLine*5 ; /* lon. DEM correction */ 
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *)
-        CPLCalloc(sizeof(GDAL_GCP),nNumDSR * nTPPerLine);
+    pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof(GDAL_GCP), 
+                                        arTP.getDSRCount() * nTPPerLine );
 
-    for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
+    for( int ir = 0 ; ir < arTP.getDSRCount() ; ir++ )
     {
-        if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
-                                           iRecord, pabyRecord ) != SUCCESS )
-            continue;
+        int iRecord = ir + arTP.getFirstIndex() ; 
+
+        double dfGCPLine = 0.5 + 
+            ( iRecord*nLinesPerTiePoint - arTP.getFirstOffset() ) ; 
 
-        memcpy( &unValue, pabyRecord + 13, 4 );
+        if( EnvisatFile_ReadDatasetRecordChunk( hEnvisatFile, nDatasetIndex,
+                    iRecord , pabyRecord, 13 , -1 ) != SUCCESS )
+            continue;
 
         for( iGCP = 0; iGCP < nTPPerLine; iGCP++ )
         {
@@ -473,17 +560,21 @@ void EnvisatDataset::ScanForGCPs_MERIS()
             sprintf( szId, "%d", nGCPCount+1 );
             pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
-            memcpy( &unValue, pabyRecord + 13 + nTPPerLine*4 + iGCP*4, 4 );
-            pasGCPList[nGCPCount].dfGCPX =
-                ((int)CPL_MSBWORD32(unValue))*0.000001;
-
-            memcpy( &unValue, pabyRecord + 13 + iGCP*4, 4 );
-            pasGCPList[nGCPCount].dfGCPY =
-                ((int)CPL_MSBWORD32(unValue))*0.000001;
+            #define INT32(x)    ((GInt32)CPL_MSBWORD32(x)) 
 
+            pasGCPList[nGCPCount].dfGCPX = 1e-6*INT32(tpLon[iGCP]) ; 
+            pasGCPList[nGCPCount].dfGCPY = 1e-6*INT32(tpLat[iGCP]) ; 
             pasGCPList[nGCPCount].dfGCPZ = 0.0;
 
-            pasGCPList[nGCPCount].dfGCPLine = iRecord*nLinesPerTiePoint + 0.5;
+            if( !isBrowseProduct ) /* add DEM corrections */
+            { 
+                pasGCPList[nGCPCount].dfGCPX += 1e-6*INT32(tpLnc[iGCP]) ; 
+                pasGCPList[nGCPCount].dfGCPY += 1e-6*INT32(tpLtc[iGCP]) ; 
+            } 
+
+            #undef INT32
+
+            pasGCPList[nGCPCount].dfGCPLine = dfGCPLine ; 
             pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5;
 
             nGCPCount++;
@@ -493,6 +584,15 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **EnvisatDataset::GetMetadataDomainList()
+{
+    return CSLAddString(GDALDataset::GetMetadataDomainList(), "envisat-ds-*-*");
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -1050,6 +1150,9 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
     else
         poDS->ScanForGCPs_ASAR();
 
+    /* unwrap GCPs for products crossing date border */
+    poDS->UnwrapGCPs();
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/envisat/makefile.vc b/frmts/envisat/makefile.vc
index 75cc756..e3ee2e8 100644
--- a/frmts/envisat/makefile.vc
+++ b/frmts/envisat/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	envisatdataset.obj EnvisatFile.obj records.obj
+OBJ	=	envisatdataset.obj EnvisatFile.obj records.obj adsrange.obj unwrapgcps.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/envisat/timedelta.hpp b/frmts/envisat/timedelta.hpp
new file mode 100644
index 0000000..e142a00
--- /dev/null
+++ b/frmts/envisat/timedelta.hpp
@@ -0,0 +1,221 @@
+/******************************************************************************
+ * $Id: timedelta.hpp 27098 2014-03-27 00:16:11Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  time difference class for handling of Envisat MJD time
+ * Author:   Martin Paces, martin.paces at eox.at 
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, EOX IT Services, GmbH 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef timedelta_hpp
+#define timedelta_hpp
+/* 
+ * TimeDelta class represents the time difference. It is used to 
+ * hold the Envisat MJD (Modified Julian Date - which is time 
+ * since 2000-01-01T00:00:00.000000Z) 
+ */
+
+class TimeDelta  
+{ 
+
+  private: 
+
+    int days ;     /* number of days */
+    int secs ;     /* number of seconds since day start */ 
+    int usecs ;    /* number of micro sec. since second start */
+
+    /* SETTERS */
+
+    /* set object using number of days, seconds and micro-seconds */
+    inline void set( int days , int secs , int usecs ) 
+    { 
+        int tmp0 , tmp1 ; 
+        /* overflow check with proper handling of negative values */ 
+        /* note that division and modulo for negative values is impl.dependent */ 
+
+        secs += ( tmp0 = usecs>=0 ? usecs/1000000 : -1-((-usecs)/1000000) ) ;  
+        days += ( tmp1 = secs>=0 ? secs/86400 : -1-((-secs)/86400) ) ;
+
+        this->usecs = usecs - 1000000*tmp0 ;
+        this->secs  = secs - 86400*tmp1 ; 
+        this->days  = days ;
+    } 
+
+    /* set object from floating point number of seconds */
+    inline void fromSeconds( double secs ) 
+    { 
+        int _days = (int)( secs / 86400 ) ;
+        int _secs = (int)( secs - 86400*_days ) ;
+        int _uscs = (int)(( secs - ((int)secs) )*1e6) ; 
+
+        this->set( _days , _secs , _uscs ) ;
+    } 
+
+  public: 
+
+    /* CONSTRUCTORS */
+    TimeDelta( void ) : days(0), secs(0), usecs(0) {} 
+
+    /* construct object using number of days, seconds and micro-seconds */
+    TimeDelta( int days , int secs , int usecs ) 
+    { 
+        this->set( days, secs, usecs ) ;
+    } 
+
+    /* construct object from floating point number of seconds */
+    TimeDelta( double secs ) 
+    { 
+        this->fromSeconds( secs ) ;
+    }
+
+    /* GETTERS */
+
+    inline int getDays( void ) const 
+    { 
+        return this->days ; 
+    } 
+
+    inline int getSeconds( void ) const
+    { 
+        return this->secs ; 
+    } 
+
+    inline int getMicroseconds( void ) const 
+    { 
+        return this->usecs ; 
+    } 
+
+    /* convert to seconds - can handle safely at least 250 years dif. */
+    /*  ... before loosing the microsecond precision */
+    inline operator double( void ) const  
+    { 
+        return (this->days*86400.0) + this->secs + (this->usecs*1e-6) ;
+    } 
+
+
+    /* OPERATORS */
+    
+    /* difference */
+    inline TimeDelta operator -( const TimeDelta & that ) const 
+    { 
+        return TimeDelta( this->days - that.days, this->secs - that.secs, 
+                                this->usecs - that.usecs ) ; 
+    }
+
+    /* addition */
+    inline TimeDelta operator +( const TimeDelta & that ) const 
+    { 
+        return TimeDelta( this->days + that.days, this->secs + that.secs, 
+                                this->usecs + that.usecs ) ; 
+    }
+
+    /* division */
+    inline double operator /( const TimeDelta & that ) const 
+    { 
+        return ( (double)*this / (double)that ) ;
+    }
+
+    /* integer multiplication */
+    inline TimeDelta operator *( const int i ) const 
+    { 
+        return TimeDelta( i*this->days, i*this->secs, i*this->usecs ) ;
+    }
+
+    /* float multiplication */
+    inline TimeDelta operator *( const double f ) const 
+    { 
+        return TimeDelta( f * (double)*this ) ;
+    }
+
+    /* comparisons operators */
+
+    inline bool operator ==( const TimeDelta & that ) const 
+    { 
+        return ( (this->usecs == that.usecs)&&(this->secs == that.secs)&&
+                 (this->days == that.days) )  ;  
+    } 
+
+
+    inline bool operator >( const TimeDelta & that ) const 
+    { 
+        return  (this->days > that.days)
+                ||(
+                    (this->days == that.days)
+                    &&(
+                        (this->secs > that.secs)
+                        ||(
+                            (this->secs == that.secs)
+                            &&(this->usecs > that.usecs)
+                        )
+                    )
+                ) ;
+    } 
+
+    inline bool operator <( const TimeDelta & that ) const 
+    { 
+        return  (this->days < that.days)
+                ||(
+                    (this->days == that.days)
+                    &&(
+                        (this->secs < that.secs)
+                        ||(
+                            (this->secs == that.secs)
+                            &&(this->usecs < that.usecs)
+                        )
+                    )
+                ) ;
+    } 
+
+
+    inline bool operator !=( const TimeDelta & that ) const 
+    { 
+        return !( *this == that ) ;
+    } 
+
+    inline bool operator >=( const TimeDelta & that ) const 
+    { 
+        return !( *this < that ) ;
+    } 
+
+    inline bool operator <=( const TimeDelta & that ) const 
+    { 
+        return !( *this > that ) ;
+    } 
+
+} ;  
+
+/*
+#include <iostream>
+
+std::ostream & operator<<( std::ostream & out, const TimeDelta & td ) 
+{
+
+    out << "TimeDelta(" << td.getDays() 
+        << "," << td.getSeconds() 
+        << "," << td.getMicroseconds() << ")" ; 
+
+    return out ;
+} 
+*/
+
+#endif /*timedelta_hpp*/
diff --git a/frmts/envisat/unwrapgcps.cpp b/frmts/envisat/unwrapgcps.cpp
new file mode 100644
index 0000000..7cceb81
--- /dev/null
+++ b/frmts/envisat/unwrapgcps.cpp
@@ -0,0 +1,182 @@
+/******************************************************************************
+ * $Id: unwrapgcps.cpp 27098 2014-03-27 00:16:11Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  GCPs Unwrapping for products crossing the WGS84 date-line  
+ * Author:   Martin Paces martin.paces at eox.at 
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, EOX IT Services, GmbH 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include <cmath>
+#include <cstdio>
+
+// number of histogram bins (36 a 10dg)
+#define NBIN  36  
+// number of empty bins to guess the flip-point
+#define NEMPY 7 
+
+// WGS84 bounds 
+#define XMIN  (-180.0)
+#define XMAX  (+180.0)
+#define XDIF  (+360.0)
+#define XCNT     (0.0)
+
+// max. allowed longitude extent of the GCP set 
+#define XLIM  (XDIF*(1.0-NEMPY*(1.0/NBIN)))
+
+
+// The algoright is based on assumption that the unwrapped 
+// GCPs ('flipped' values) have smaller extent along the longitude.
+// We further assume that the lenght of the striplines is limitted 
+// to one orbit and does not exceeded given limit along the longitude, 
+// e.i., the wrapped-arround coordinates have significantly larger 
+// extent the unwrapped. If the smaller extend exceedes the limit
+// the original tiepoints are returned. 
+
+static double _suggest_flip_point( const int cnt, GDAL_GCP *gcp ) 
+{ 
+    // the histogram array - it is expected to fit the stack
+    int hist[NBIN] ; 
+    
+    // reset the histogram counters
+    for( int i = 0 ; i < NBIN ; i++ ) hist[i] = 0 ; 
+
+    // accumulate the histogram 
+    for( int i = 0 ; i < cnt ; i++ ) 
+    { 
+        double x = (gcp[i].dfGCPX-XMIN)/XDIF ;
+        int idx = (int)(NBIN*(x-floor(x))) ; 
+
+        // the lattitudes should lay in the +/-180 bounds 
+        // although it should never happen we check the outliers
+        if (idx < 0) idx = 0 ; 
+        if (idx >= NBIN ) idx = NBIN-1; 
+
+        hist[idx] += 1 ; 
+    } 
+
+    // find a middle of at least NEMPTY consecutive empty bins and get its middle
+    int i0 = -1 , i1 = -1 , last_is_empty = 0 ; 
+    for( int i = 0 ; i < (2*NBIN-1) ; i++ ) 
+    { 
+        if ( 0 == hist[i%NBIN] ) // empty 
+        { 
+            if ( !last_is_empty ) // re-start counter 
+            { 
+                i0 = i ;
+                last_is_empty = 1 ; 
+            }
+        } 
+        else // non-empty 
+        {
+            if ( last_is_empty ) 
+            { 
+                i1 = i ;
+                last_is_empty = 0 ; 
+
+                // if the segment is long enough -> terminate 
+                if (( i1 - i0 )>=NEMPY) break ; 
+            } 
+        }
+    } 
+
+    // if all full or all empty the returning default value 
+    if ( i1 < 0 ) return XCNT ;
+
+    // return the flip-centre
+
+    double tmp = ((i1-i0)*0.5+i0)/((float)NBIN) ; 
+
+    return (tmp-floor(tmp))*XDIF + XMIN ;
+}
+    
+
+void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp ) 
+{ 
+    if ( cnt < 1 ) return ; 
+    
+    // suggest right flip-point 
+    double x_flip = _suggest_flip_point( cnt, gcp ); 
+
+    // find the limits allong the longitude (x) for flipped and unflipped values
+    
+    int cnt_flip = 0 ; // flipped values' counter
+    double x0_dif , x1_dif ; 
+
+    { 
+        double x0_min, x0_max, x1_min, x1_max ;
+
+        { 
+            double x0 = gcp[0].dfGCPX ;
+            int  flip = (x0>x_flip) ;
+            x0_min = x0_max = x0 ; 
+            x1_min = x1_max = x0 - flip*XDIF ; 
+            cnt_flip += flip ; // count the flipped values 
+        } 
+
+        for ( int i = 1 ; i < cnt ; ++i ) 
+        { 
+            double x0 = gcp[i].dfGCPX ;
+            int  flip = (x0>x_flip) ;
+            double x1 = x0 - flip*XDIF ; // flipped value
+            cnt_flip += flip ; // count the flipped values 
+
+            if ( x0 > x0_max ) x0_max = x0 ; 
+            if ( x0 < x0_min ) x0_min = x0 ; 
+            if ( x1 > x1_max ) x1_max = x1 ; 
+            if ( x1 < x1_min ) x1_min = x1 ; 
+        } 
+
+        x0_dif = x0_max - x0_min ; 
+        x1_dif = x1_max - x1_min ; 
+    } 
+
+    // in case all values either flipped or non-flipped 
+    // nothing is to be done 
+    if (( cnt_flip == 0 ) || ( cnt_flip == cnt )) return ; 
+
+    // check whether we need to split the segment 
+    // i.e., segment is too long decide the best option 
+    
+    if (( x0_dif > XLIM ) && ( x1_dif > XLIM )) 
+    { 
+        // this should not happen 
+        // we give-up and return the original tie-point set 
+
+        CPLError(CE_Warning,CPLE_AppDefined,"GCPs' set is too large"
+            " to perform the unwrapping! The unwrapping is not performed!"); 
+
+        return ; 
+    } 
+    else if ( x1_dif < x0_dif ) 
+    { 
+        // flipped GCPs' set has smaller extent -> unwrapping is performed
+        for ( int i = 1 ; i < cnt ; ++i ) 
+        { 
+            double x0 = gcp[i].dfGCPX ;
+
+            gcp[i].dfGCPX = x0 - (x0>XCNT)*XDIF ; 
+        } 
+    } 
+} 
diff --git a/frmts/epsilon/epsilondataset.cpp b/frmts/epsilon/epsilondataset.cpp
index de5f124..99fc6f2 100644
--- a/frmts/epsilon/epsilondataset.cpp
+++ b/frmts/epsilon/epsilondataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: epsilondataset.cpp 22363 2011-05-12 18:26:19Z rouault $
+ * $Id: epsilondataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Epsilon driver
  * Purpose:  Implement GDAL Epsilon support using Epsilon library
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "epsilon.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: epsilondataset.cpp 22363 2011-05-12 18:26:19Z rouault $");
+CPL_CVSID("$Id: epsilondataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
 #define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
diff --git a/frmts/ers/ersdataset.cpp b/frmts/ers/ersdataset.cpp
index 280e0ce..bd4b4ef 100644
--- a/frmts/ers/ersdataset.cpp
+++ b/frmts/ers/ersdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ersdataset.cpp 25995 2013-05-11 20:52:45Z rouault $
+ * $Id: ersdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of .ers driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "ershdrnode.h"
 
-CPL_CVSID("$Id: ersdataset.cpp 25995 2013-05-11 20:52:45Z rouault $");
+CPL_CVSID("$Id: ersdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -98,6 +99,7 @@ class ERSDataset : public RawDataset
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
                             const char *pszGCPProjection );
 
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                      const char * pszDomain = "" );
     virtual char      **GetMetadata( const char * pszDomain = "" );
@@ -219,6 +221,17 @@ void ERSDataset::FlushCache()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **ERSDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "ERS", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadataItem()                          */
 /************************************************************************/
 
diff --git a/frmts/fit/fitdataset.cpp b/frmts/fit/fitdataset.cpp
index 7233af3..feb78f2 100644
--- a/frmts/fit/fitdataset.cpp
+++ b/frmts/fit/fitdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
+ * $Id: fitdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Keyhole, Inc.
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
+CPL_CVSID("$Id: fitdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
  
diff --git a/frmts/fits/fitsdataset.cpp b/frmts/fits/fitsdataset.cpp
index 8cc8aac..8483d21 100644
--- a/frmts/fits/fitsdataset.cpp
+++ b/frmts/fits/fitsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitsdataset.cpp 25284 2012-12-03 21:07:56Z rouault $
+ * $Id: fitsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  FITS Driver
  * Purpose:  Implement FITS raster read/write support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Simon Perkins
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include <string.h>
 
-CPL_CVSID("$Id: fitsdataset.cpp 25284 2012-12-03 21:07:56Z rouault $");
+CPL_CVSID("$Id: fitsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 #include <fitsio.h>
diff --git a/frmts/formats_list.html b/frmts/formats_list.html
index e8ae34d..b208c81 100644
--- a/frmts/formats_list.html
+++ b/frmts/formats_list.html
@@ -59,6 +59,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <!--<a href="frmt_various.html#ARG"> -->Azavea Raster Grid<!-- </a> -->
+</td><td> ARG
+</td><td> Yes
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_blx.html">Magellan BLX Topo (.blx, .xlb)</a>
 </td><td> BLX
 </td><td> Yes
@@ -355,7 +363,7 @@
 </td><td> No, needs libnetcdf
 </td></tr>
 
-<tr><td> <a href="frmt_grass.html">GRASS Rasters</a>
+<tr><td> <a href="frmt_grass.html">GRASS Raster Format</a>
 </td><td> GRASS
 </td><td> No
 </td><td> Yes
@@ -603,6 +611,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#KRO">KRO</a>
+</td><td> KRO
+</td><td> Yes
+</td><td> No
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_l1b.html">NOAA Polar Orbiter Level 1b Data Set (AVHRR)</a>
 </td><td> L1B
 </td><td> No
@@ -621,7 +637,7 @@
 
 <tr><td> <a href="frmt_lcp.html">FARSITE v.4 LCP Format</a>
 </td><td> LCP
-</td><td> No
+</td><td> Yes
 </td><td> Yes
 </td><td> No limits
 </td><td> Yes
@@ -813,10 +829,10 @@
 
 <tr><td> <a href="frmt_pdf.html">Geospatial PDF</a>
 </td><td> PDF
-</td><td> No
+</td><td> Yes
 </td><td> Yes
 </td><td> --
-</td><td> No, needs libpoppler or libpodofo
+</td><td> Yes (but needs libpoppler or libpodofo for read support)
 </td></tr>
 
 <tr><td> <a href="frmt_pds.html">NASA Planetary Data System</a>
@@ -1083,7 +1099,7 @@
 </p>
 
 <p>
-$Id: formats_list.html 25803 2013-03-25 18:45:55Z rouault $
+$Id: formats_list.html 26905 2014-01-30 21:08:06Z rouault $
 </p>
 
 </body>
diff --git a/frmts/frmt_various.html b/frmts/frmt_various.html
index 66e0e7f..963506c 100644
--- a/frmts/frmt_various.html
+++ b/frmts/frmt_various.html
@@ -24,7 +24,8 @@ It is normally produced with the Arc/Info ASCIIGRID command.</p>
 limited.  Additional sample .prj files may be sent to the maintainer,
 <a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.</p>
 
-<p>The NODATA value for the grid read is also preserved when available.
+<p>The NODATA value for the grid read is also preserved when available in the
+same format as the band data.
 </p>
 
 <p>By default, the datatype returned for AAIGRID datasets by GDAL is autodetected,
@@ -41,11 +42,13 @@ ascii grid reading programs.  For force the X pixel size to be used as CELLSIZE
 use the FORCE_CELLSIZE=YES creation option or resample the input to have 
 square pixels.</p>
 
-<p>When writing floating-point values, the driver uses the "%6.20g" format
+<p>When writing floating-point values, the driver uses the "%.20g" format
 pattern as a default. You can consult a <a href="http://en.wikipedia.org/wiki/Printf">
 reference manual</a> for printf to have an idea of the exact behaviour of this ;-).
 You can alternatively specify the number of decimal places with the DECIMAL_PRECISION creation
-option. For example, DECIMAL_PRECISION=3 will output numbers with 3 decimal places.</p>
+option. For example, DECIMAL_PRECISION=3 will output numbers with 3 decimal
+places(using %lf format).  Starting with GDAL 1.11, another option is
+SIGNIFICANT_DIGITS=3, which will output 3 significant digits (using %g format).</p>
 
 <p>The <a href="#AIG">AIG</a> driver is also available
 for Arc/Info Binary Grid format.</p>
@@ -672,6 +675,22 @@ Institute (GSI) Web Site.</a></p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="KRO">KRO -- KOLOR Raw format</a></h2>
+
+<p>(GDAL >= 1.11)</p>
+
+<p>Supported for read access, update and creation.
+This format is a binary raw format, that supports data of several depths (
+8 bit, unsigned integer 16 bit and floating point 32 bit) and with several band
+number (3 or 4 typically, for RGB and RGBA). There is no file size limit,
+except the limitation of the file system.</p>
+
+<p><a href="http://www.autopano.net/wiki-en/Format_KRO">Specification of the format</a></p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/raw/krodataset.cpp</tt>.</p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="LAN">LAN -- Erdas 7.x .LAN and .GIS</a></h2>
 
 <p>GDAL supports reading and writing
@@ -924,6 +943,23 @@ pixel types other than 16bit unsigned will be written as eight bit.</p>
 <p>Starting with GDAL 1.9.0, XMP metadata can be extracted from the file, and will be
 stored as XML raw content in the xml:XMP metadata domain.</p>
 
+<h2>Color Profile Metadata</h2>
+
+<p>Starting with GDAL 1.11, GDAL can deal with the following color profile metadata in the COLOR_PROFILE domain:</p>
+<ul>
+<li>SOURCE_ICC_PROFILE (Base64 encoded ICC profile embedded in file. If available, other tags are ignored.)</li>
+<li>SOURCE_ICC_PROFILE_NAME : ICC profile name. sRGB is recognized as a special value.</li>
+<li>SOURCE_PRIMARIES_RED (xyY in "x,y,1" format for red primary.)</li>
+<li>SOURCE_PRIMARIES_GREEN (xyY in "x,y,1" format for green primary)</li>
+<li>SOURCE_PRIMARIES_BLUE (xyY in "x,y,1" format for blue primary)</li>
+<li>SOURCE_WHITEPOINT (xyY in "x,y,1" format for whitepoint)</li>
+<li>PNG_GAMMA</li>
+</ul>
+
+<p>Note that these metadata properties can only be used on the original raw pixel data. If automatic conversion to RGB has been done, the color profile information cannot be used.</p>
+
+<p>All these metadata tags can be used as creation options.</p>
+
 <p>Creation Options:</p>
 
 <ul>
@@ -1172,6 +1208,9 @@ file with a common basename.  The .IMG file should be selected to access the dat
 system) products are single band images with a palette and georeferencing.
 </p>
 
+<p>Starting with GDAL 1.11, the Transmission Header File (.THF) can also be used as an input to GDAL. If the THF references more than one image,
+GDAL will report the images it is composed of as subdatasets. If the THF references just one image, GDAL will open it directly.</p>
+
 <p>NOTE: Implemented as <tt>gdal/frmts/adrg/srpdataset.cpp</tt>.</p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
@@ -1286,7 +1325,7 @@ as reported by GDAL will be a half-pixel at the top and left of the values that
 </p>
 
 <p>
-$Id: frmt_various.html 25803 2013-03-25 18:45:55Z rouault $
+$Id: frmt_various.html 27110 2014-03-28 21:29:20Z rouault $
 </p>
 
 </body>
diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp
index 76009eb..c01300e 100644
--- a/frmts/gdalallregister.cpp
+++ b/frmts/gdalallregister.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalallregister.cpp 25798 2013-03-25 14:42:33Z aboudreault $
+ * $Id: gdalallregister.cpp 27196 2014-04-16 11:41:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllRegister(), primary format registration.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdal_priv.h"
 #include "gdal_frmts.h"
 
-CPL_CVSID("$Id: gdalallregister.cpp 25798 2013-03-25 14:42:33Z aboudreault $");
+CPL_CVSID("$Id: gdalallregister.cpp 27196 2014-04-16 11:41:24Z rouault $");
 
 #ifdef notdef
 // we may have a use for this some day
@@ -276,13 +277,6 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_JP2OpenJPEG();
 #endif
 
-#ifdef FRMT_jpeg2000
-// JPEG2000 support using JasPer toolkit
-// This one should always be placed after other JasPer supported formats,
-// such as BMP or PNM. In other case we will get bad side effects.
-    GDALRegister_JPEG2000();
-#endif
-
 #ifdef FRMT_l1b
     GDALRegister_L1B();
 #endif
@@ -299,6 +293,13 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_MrSID();
 #endif
 
+#ifdef FRMT_jpeg2000
+// JPEG2000 support using JasPer toolkit
+// This one should always be placed after other JasPer supported formats,
+// such as BMP or PNM. In other case we will get bad side effects.
+    GDALRegister_JPEG2000();
+#endif
+
 #ifdef FRMT_mrsid_lidar
     GDALRegister_MG4Lidar();
 #endif
@@ -399,6 +400,7 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_CTable2();
     GDALRegister_ACE2();
     GDALRegister_SNODAS();
+    GDALRegister_KRO();
 #endif
 
 #ifdef FRMT_arg
diff --git a/frmts/georaster/frmt_georaster.html b/frmts/georaster/frmt_georaster.html
index 960d1b0..21f715a 100644
--- a/frmts/georaster/frmt_georaster.html
+++ b/frmts/georaster/frmt_georaster.html
@@ -1,8 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
   <title>GeoRaster --- Oracle Spatial GeoRaster</title>
-  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8">
+  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8">
   <meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)">
   <style type="text/css">
 	<!--
@@ -120,11 +119,15 @@ gdal_translate -of georaster landsat_825.tif
 geor:scott/tiger at orcl,landsat,raster \<br>
   -co INSERT="ID, RASTER VALUES (2,</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">)"</span><br>
 <ul>
-  <li><strong>COMPRESS</strong>: Compression options, JPEG-F, JPEG-B,
+  <li><strong>COMPRESS</strong>: Compression options, JPEG-F,
 DEFLATE or NONE. The two JPEG options are lossy, meaning that the
-original pixel values are changed. The JPEG-F store a full JPEG
-structure on each block while JPEG-B are smaller since they don't store
-Huffman and Quantization tables.</li>
+original pixel values are changed.</li>
+  <li><strong>GENPYRAMID</strong>: Generate pyramid after a GeoRaster object have been loaded to the database. 
+The content of that parameter must be the resampling method of 
+choice NN (nearest neighbor) , BILINEAR, BIQUADRATIC, CUBIC, AVERAGE4 or AVERAGE16. If GENPYRLEVELS is not 
+informed the PL/SQL function sdo_geor.generatePyramid will calculate the number of levels to generate.</li>
+  <li><strong>GENPYRLEVELS</strong>: Define the number of pyramid levels to be generated.
+If GENPYRAMID is not informed the resample method NN (nearest neighbor) will apply.</li>
   <li><strong>QUALITY</strong>: Quality compression option for JPEG 
 ranging from 0 to 100. The default is 75.</li>
   <li><strong>NBITS</strong>: Sub byte data type, options: 1, 2 or 4.</li>
@@ -135,6 +138,8 @@ the same SRID as the GeoGeoraster object.</li>
   <li><strong>EXTENTSRID</strong>: SRID code to be used on the Spatial Extent geometry. 
 If the table/column has already a spatial extent, the value informed should be the same as the 
 SRID on the Spatial Extent of the other existing GeoRaster.</li>
+  <li><strong>OBJECTTABLE</strong>: To create RDT as SDO_RASTER object inform TRUE otherwise, the default 
+  is FALSE and the RDT will be created as regular relational tables. That does not apply for Oracle version older than 11.</li>
 </ul>
 <strong></strong>
 <h3>Importing GeoRaster</h3>
@@ -153,7 +158,7 @@ MDSYS.SDO_GEORASTER)" \<br>
 </font><font face="Courier, monospace">
   -co "INSERT=VALUES(1,'West fields', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><font face="Courier, monospace">)" \<br>
 </font><font face="Courier, monospace">  -co "BLOCKXSIZE=512</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "BLOCKYSIZE=512" -co "BLOCKBSIZE=3" \<br>
-  -co "INTERLEAVE=PIXEL</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "COMPRESS=JPEG-B"</font></p>
+  -co "INTERLEAVE=PIXEL</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "COMPRESS=JPEG-F"</font></p>
 <p style="margin-bottom: 0in;">Note that the create option DESCRIPTION
 requires to inform table name (in bold). And column name
 (underlined) should match the description:</p>
@@ -182,7 +187,7 @@ a default table named GDAL_IMPORT with just one GeoRaster column
 named RASTER and a table GDAL_RDT as the RDT, the RID will be given automatically by the server, example:</p>
 <p style="margin-bottom: 0in;"><font face="Courier, monospace">%
 gdal_translate -of georaster input.tif
-“geor:scott/tiger at dbdemo”</font><br>
+“geor:scott/tiger at dbdemo”</font><br>
 </p>
 <h3>Exporting GeoRaster</h3>
 A GeoRaster can be identified by a Where clause or by a pair of RDT
@@ -271,5 +276,6 @@ geor:scott/tiger at dbdemo,landsat,scene,id=54 view_54.vrt<br>
 <br>
 </span><span style="font-family: Courier New,Courier,monospace;"></span><br>
 <h3></h3>
-</body>
-</html>
+
+
+</body></html>
\ No newline at end of file
diff --git a/frmts/georaster/georaster_dataset.cpp b/frmts/georaster/georaster_dataset.cpp
index 2952c40..97091f0 100644
--- a/frmts/georaster/georaster_dataset.cpp
+++ b/frmts/georaster/georaster_dataset.cpp
@@ -4,10 +4,11 @@
  * Name:     georaster_dataset.cpp
  * Project:  Oracle Spatial GeoRaster Driver
  * Purpose:  Implement GeoRasterDataset Methods
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
  *
  ******************************************************************************
  * Copyright (c) 2008, Ivan Lucena
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
@@ -182,7 +183,7 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
     }
 
     //  -------------------------------------------------------------------
-    //  Assign GeoRaster informationf
+    //  Assign GeoRaster information
     //  -------------------------------------------------------------------
 
     poGRD->poGeoRaster   = poGRW;
@@ -676,6 +677,24 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         }
     }
 
+    pszFetched = CSLFetchNameValue( papszOptions, "OBJECTTABLE" );
+
+    if( pszFetched )
+    {
+        int nVersion = poGRW->poConnection->GetVersion();
+        if( nVersion <= 11 )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, 
+                "Driver create-option OBJECTTABLE not "
+                "supported on Oracle %d", nVersion );
+            delete poGRD;
+            return NULL;
+        }
+    }
+
+    poGRD->poGeoRaster->bCreateObjectTable = (bool)
+        CSLFetchBoolean( papszOptions, "OBJECTTABLE", FALSE );
+
     //  -------------------------------------------------------------------
     //  Create a SDO_GEORASTER object on the server
     //  -------------------------------------------------------------------
@@ -717,6 +736,13 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
     //  Load aditional options
     //  -------------------------------------------------------------------
 
+    pszFetched = CSLFetchNameValue( papszOptions, "VATNAME" );
+
+    if( pszFetched )
+    {
+        poGRW->sValueAttributeTab = pszFetched;
+    }
+
     pszFetched = CSLFetchNameValue( papszOptions, "SRID" );
 
     if( pszFetched )
@@ -725,7 +751,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         poGRD->poGeoRaster->SetGeoReference( atoi( pszFetched ) );
     }
 
-    poGRD->poGeoRaster->bGenSpatialIndex = 
+    poGRD->poGeoRaster->bGenSpatialIndex = (bool)
         CSLFetchBoolean( papszOptions, "SPATIALEXTENT", TRUE );
 
     pszFetched = CSLFetchNameValue( papszOptions, "EXTENTSRID" );
@@ -759,6 +785,33 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         poGRD->poGeoRaster->nCompressQuality = nQuality;
     }
 
+
+    pszFetched = CSLFetchNameValue( papszOptions, "GENPYRAMID" );
+
+    if( pszFetched != NULL )
+    {
+        if (!(EQUAL(pszFetched, "NN") ||
+              EQUAL(pszFetched, "BILINEAR") ||
+              EQUAL(pszFetched, "BIQUADRATIC") ||
+              EQUAL(pszFetched, "CUBIC") ||
+              EQUAL(pszFetched, "AVERAGE4") ||
+              EQUAL(pszFetched, "AVERAGE16")))
+        {
+            CPLError( CE_Warning, CPLE_IllegalArg, "Wrong resample method for pyramid (%s)", pszFetched);
+        }
+
+        poGRD->poGeoRaster->bGenPyramid = true;
+        poGRD->poGeoRaster->sPyramidResampling = pszFetched;
+    }
+
+    pszFetched = CSLFetchNameValue( papszOptions, "GENPYRLEVELS" );
+
+    if( pszFetched != NULL )
+    {
+        poGRD->poGeoRaster->bGenPyramid = true;
+        poGRD->poGeoRaster->nPyramidLevels = atoi(pszFetched);
+    }
+
     //  -------------------------------------------------------------------
     //  Return a new Dataset
     //  -------------------------------------------------------------------
@@ -813,9 +866,18 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     double adfTransform[6];
 
-    poSrcDS->GetGeoTransform( adfTransform );
-
-    poDstDS->SetGeoTransform( adfTransform );
+    if ( poSrcDS->GetGeoTransform( adfTransform ) == CE_None )
+    {
+        if ( ! ( adfTransform[0] == 0.0 && 
+                 adfTransform[1] == 1.0 &&
+                 adfTransform[2] == 0.0 &&
+                 adfTransform[3] == 0.0 &&
+                 adfTransform[4] == 0.0 &&
+                 adfTransform[5] == 1.0 ) ) 
+        {
+            poDstDS->SetGeoTransform( adfTransform );
+        }
+    }
 
     if( ! poDstDS->bForcedSRID ) /* forced by create option SRID */
     {
@@ -840,14 +902,20 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     int    bHasNoDataValue = FALSE;
     double dfNoDataValue = 0.0;
-    double dfMin, dfMax, dfStdDev, dfMean;
+    double dfMin = 0.0, dfMax = 0.0, dfStdDev = 0.0, dfMean = 0.0;
+    double dfMedian = 0.0, dfMode = 0.0;
     int    iBand = 0;
 
     for( iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
     {
-        GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand( iBand );
+        GDALRasterBand*      poSrcBand = poSrcDS->GetRasterBand( iBand );
         GeoRasterRasterBand* poDstBand = (GeoRasterRasterBand*) 
-                                    poDstDS->GetRasterBand( iBand );
+                                         poDstDS->GetRasterBand( iBand );
+
+        // ----------------------------------------------------------------
+        //  Copy Color Table
+        // ----------------------------------------------------------------
+
         GDALColorTable* poColorTable = poSrcBand->GetColorTable(); 
 
         if( poColorTable )
@@ -855,19 +923,75 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
             poDstBand->SetColorTable( poColorTable );
         }
 
+        // ----------------------------------------------------------------
+        //  Copy statitics information, without median and mode
+        // ----------------------------------------------------------------
+
         if( poSrcBand->GetStatistics( false, false, &dfMin, &dfMax,
-            &dfStdDev, &dfMean ) == CE_None )
+            &dfMean, &dfStdDev ) == CE_None )
+        {
+            poDstBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
+
+            /* That will not be recorded in the GeoRaster metadata since it
+             * doesn't have median and mode, so those values are only useful
+             * at runtime.
+             */
+        }
+
+        // ----------------------------------------------------------------
+        //  Copy statitics metadata information, including median and mode
+        // ----------------------------------------------------------------
+
+        const char *pszMin     = poSrcBand->GetMetadataItem( "STATISTICS_MINIMUM" );
+        const char *pszMax     = poSrcBand->GetMetadataItem( "STATISTICS_MAXIMUM" );
+        const char *pszMean    = poSrcBand->GetMetadataItem( "STATISTICS_MEAN" );
+        const char *pszMedian  = poSrcBand->GetMetadataItem( "STATISTICS_MEDIAN" );
+        const char *pszMode    = poSrcBand->GetMetadataItem( "STATISTICS_MODE" );
+        const char *pszStdDev  = poSrcBand->GetMetadataItem( "STATISTICS_STDDEV" );
+        const char *pszSkipFX  = poSrcBand->GetMetadataItem( "STATISTICS_SKIPFACTORX" );
+        const char *pszSkipFY  = poSrcBand->GetMetadataItem( "STATISTICS_SKIPFACTORY" );
+
+        if ( pszMin    != NULL && pszMax  != NULL && pszMean   != NULL &&
+             pszMedian != NULL && pszMode != NULL && pszStdDev != NULL )
         {
-            poDstBand->SetStatistics( dfMin, dfMax, dfStdDev, dfMean );
+            dfMin        = CPLScanDouble( pszMin, MAX_DOUBLE_STR_REP );
+            dfMax        = CPLScanDouble( pszMax, MAX_DOUBLE_STR_REP );
+            dfMean       = CPLScanDouble( pszMean, MAX_DOUBLE_STR_REP );
+            dfMedian     = CPLScanDouble( pszMedian, MAX_DOUBLE_STR_REP );
+            dfMode       = CPLScanDouble( pszMode, MAX_DOUBLE_STR_REP );
+
+            if ( ! ( ( dfMin    > dfMax ) ||
+                     ( dfMean   > dfMax ) || ( dfMean   < dfMin ) ||
+                     ( dfMedian > dfMax ) || ( dfMedian < dfMin ) ||
+                     ( dfMode   > dfMax ) || ( dfMode   < dfMin ) ) )
+            {
+                if ( ! pszSkipFX )
+                {
+                    pszSkipFX = pszSkipFY != NULL ? pszSkipFY : "1";
+                }
+
+                poDstBand->poGeoRaster->SetStatistics( iBand,
+                                                       pszMin, pszMax, pszMean, 
+                                                       pszMedian, pszMode,
+                                                       pszStdDev, pszSkipFX );
+            }
         }
 
-        const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
+        // ----------------------------------------------------------------
+        //  Copy Raster Attribute Table (RAT)
+        // ----------------------------------------------------------------
+
+        GDALRasterAttributeTableH poRAT = GDALGetDefaultRAT( poSrcBand );
 
         if( poRAT != NULL )
         {
-            poDstBand->SetDefaultRAT( poRAT );
+            poDstBand->SetDefaultRAT( (GDALRasterAttributeTable*) poRAT );
         }
 
+        // ----------------------------------------------------------------
+        //  Copy NoData Value
+        // ----------------------------------------------------------------
+
         dfNoDataValue = poSrcBand->GetNoDataValue( &bHasNoDataValue );
 
         if( bHasNoDataValue )
@@ -1101,18 +1225,11 @@ CPLErr GeoRasterDataset::GetGeoTransform( double *padfTransform )
         return CE_Failure;
     }
 
-    memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-    
-    if( bGeoTransform )
-    {
-        return CE_None;
-    }
-
-    if( ! poGeoRaster->bIsReferenced )
+    if( poGeoRaster->nSRID == 0 )
     {
         return CE_Failure;
     }
-
+    
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
 
     bGeoTransform = true;
@@ -1309,7 +1426,7 @@ CPLErr GeoRasterDataset::SetGeoTransform( double *padfTransform )
     poGeoRaster->dfYCoefficient[2] = adfGeoTransform[3];
 
     bGeoTransform = true;
-
+    
     return CE_None;
 }
 
@@ -1327,7 +1444,7 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
 
     if( eOGRErr != OGRERR_NONE )
     {
-        poGeoRaster->SetGeoReference( UNKNOWN_CRS );
+        poGeoRaster->SetGeoReference( DEFAULT_CRS );
 
         return CE_Failure;
     }
@@ -1433,6 +1550,17 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
     return eError;
 }
 
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GeoRasterDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
 //  ---------------------------------------------------------------------------
 //                                                                GetMetadata()
 //  ---------------------------------------------------------------------------
@@ -1922,51 +2050,57 @@ void CPL_DLL GDALRegister_GEOR()
                                    "Float64 CFloat32 CFloat64" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
-"  <Option name='DESCRIPTION' type='string' description='Table Description' "
-                                           "default='(RASTER MDSYS.SDO_GEORASTER)'/>"
-"  <Option name='INSERT'      type='string' description='Column Values' "
-                                           "default='(SDO_GEOR.INIT())'/>"
+"  <Option name='DESCRIPTION' type='string' description='Table Description'/>"
+"  <Option name='INSERT'      type='string' description='Column Values'/>"
 "  <Option name='BLOCKXSIZE'  type='int'    description='Column Block Size' "
                                            "default='512'/>"
 "  <Option name='BLOCKYSIZE'  type='int'    description='Row Block Size' "
                                            "default='512'/>"
-"  <Option name='BLOCKBSIZE'  type='int'    description='Band Block Size' "
-                                           "default='1'/>"
-"  <Option name='SRID'        type='int'    description='Overwrite EPSG code' "
-                                           "default='0'/>"
+"  <Option name='BLOCKBSIZE'  type='int'    description='Band Block Size'/>"
+"  <Option name='BLOCKING'    type='string-select' default='YES'>"
+"       <Value>YES</Value>"
+"       <Value>NO</Value>"
+"       <Value>OPTIMALPADDING</Value>"
+"  </Option>"
+"  <Option name='SRID'        type='int'    description='Overwrite EPSG code'/>"
+"  <Option name='GENPYRAMID'  type='string-select' "
+" description='Generate Pyramid, inform resampling method'>"
+"       <Value>NN</Value>"
+"       <Value>BILINEAR</Value>"
+"       <Value>BIQUADRATIC</Value>"
+"       <Value>CUBIC</Value>"
+"       <Value>AVERAGE4</Value>"
+"       <Value>AVERAGE16</Value>"
+"  </Option>"
+"  <Option name='GENPYRLEVELS'  type='int'  description='Number of pyramid level to generate'/>"
+"  <Option name='OBJECTTABLE' type='boolean' "
+                                           "description='Create RDT as object table'/>"
 "  <Option name='SPATIALEXTENT' type='boolean' "
                                            "description='Generate Spatial Extent' "
                                            "default='TRUE'/>"
-"  <Option name='EXTENTSRID'  type='int'    description='Spatial ExtentSRID code' "
-                                           "default='0'/>"
+"  <Option name='EXTENTSRID'  type='int'    description='Spatial ExtentSRID code'/>"
+"  <Option name='COORDLOCATION'    type='string-select' default='CENTER'>"
+"       <Value>CENTER</Value>"
+"       <Value>UPPERLEFT</Value>"
+"  </Option>"
+"  <Option name='VATNAME'     type='string' description='Value Attribute Table Name'/>"
 "  <Option name='NBITS'       type='int'    description='BITS for sub-byte "
                                            "data types (1,2,4) bits'/>"
-"  <Option name='INTERLEAVE'  type='string-select' default='BAND'>"
-"       <Value>BAND</Value>"
-"       <Value>PIXEL</Value>"
-"       <Value>LINE</Value>"
+"  <Option name='INTERLEAVE'  type='string-select'>"
 "       <Value>BSQ</Value>"
 "       <Value>BIP</Value>"
 "       <Value>BIL</Value>"
 "   </Option>"
-"  <Option name='COMPRESS'    type='string-select' default='NONE'>"
+"  <Option name='COMPRESS'    type='string-select'>"
 "       <Value>NONE</Value>"
 "       <Value>JPEG-B</Value>"
 "       <Value>JPEG-F</Value>"
 "       <Value>DEFLATE</Value>"
 "  </Option>"
-"  <Option name='BLOCKING'    type='string-select' default='YES'>"
-"       <Value>YES</Value>"
-"       <Value>NO</Value>"
-"       <Value>OPTIMALPADDING</Value>"
-"  </Option>"
-"  <Option name='COORDLOCATION'    type='string-select' default='CENTER'>"
-"       <Value>CENTER</Value>"
-"       <Value>UPPERLEFT</Value>"
-"  </Option>"
 "  <Option name='QUALITY'     type='int'    description='JPEG quality 0..100' "
                                            "default='75'/>"
 "</CreationOptionList>" );
+
         poDriver->pfnOpen       = GeoRasterDataset::Open;
         poDriver->pfnCreate     = GeoRasterDataset::Create;
         poDriver->pfnCreateCopy = GeoRasterDataset::CreateCopy;
diff --git a/frmts/georaster/georaster_priv.h b/frmts/georaster/georaster_priv.h
index 41ad2c0..9ed33db 100644
--- a/frmts/georaster/georaster_priv.h
+++ b/frmts/georaster/georaster_priv.h
@@ -1,450 +1,471 @@
-/******************************************************************************
- * $Id: $
- *
- * Name:     georaster_priv.h
- * Project:  Oracle Spatial GeoRaster Driver
- * Purpose:  Define C++/Private declarations
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
- *
- ******************************************************************************
- * Copyright (c) 2008, Ivan Lucena
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files ( the "Software" ),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-#ifndef _GEORASTER_PRIV_H_INCLUDED
-#define _GEORASTER_PRIV_H_INCLUDED
-
-#include "gdal.h"
-#include "gdal_priv.h"
-#include "gdal_alg.h"
-#include "gdal_rat.h"
-#include "ogr_spatialref.h"
-#include "cpl_minixml.h"
-#include "cpl_list.h"
-
-//  ---------------------------------------------------------------------------
-//  DEFLATE compression support
-//  ---------------------------------------------------------------------------
-
-#include <zlib.h>
-
-//  ---------------------------------------------------------------------------
-//  JPEG compression support
-//  ---------------------------------------------------------------------------
-
-CPL_C_START
-#include <jpeglib.h>
-CPL_C_END
-
-void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile);
-void jpeg_vsiio_dest (j_compress_ptr cinfo, VSILFILE * outfile);
-
-//  ---------------------------------------------------------------------------
-//  System constants
-//  ---------------------------------------------------------------------------
-
-//  VAT maximum string len
-
-#define MAXLEN_VATSTR 128
-
-//  Geographic system without EPSG parameters
-
-#define UNKNOWN_CRS 999999
-
-//  Bitmap Mask for the whole dataset start with -99999
-
-#define DEFAULT_BMP_MASK -99999
-
-//  Default block size
-
-#define DEFAULT_BLOCK_ROWS 256
-#define DEFAULT_BLOCK_COLUMNS 256
-
-//  Default Model Coordinate Location (internal pixel geo-reference)
-
-#define MCL_CENTER      0
-#define MCL_UPPERLEFT   1
-#define MCL_DEFAULT     MCL_CENTER
-
-struct hLevelDetails {
-    int             nColumnBlockSize;
-    int             nRowBlockSize;
-    int             nTotalColumnBlocks;
-    int             nTotalRowBlocks;
-    unsigned long   nBlockCount;
-    unsigned long   nBlockBytes;
-    unsigned long   nGDALBlockBytes;
-    unsigned long   nOffset;
-};
-
-//  ---------------------------------------------------------------------------
-//  Support for multi-values NoData support
-//  ---------------------------------------------------------------------------
-
-struct hNoDataItem {
-    int             nBand;
-    double          dfLower;
-    double          dfUpper;
-};
-
-//  ---------------------------------------------------------------------------
-//  GeoRaster wrapper classe definitions
-//  ---------------------------------------------------------------------------
-
-#include "oci_wrapper.h"
-
-class GeoRasterDataset;
-class GeoRasterRasterBand;
-class GeoRasterWrapper;
-
-//  ---------------------------------------------------------------------------
-//  GeoRasterDataset, extends GDALDataset to support GeoRaster Datasets
-//  ---------------------------------------------------------------------------
-
-class GeoRasterDataset : public GDALDataset
-{
-    friend class GeoRasterRasterBand;
-
-public:
-                        GeoRasterDataset();
-    virtual            ~GeoRasterDataset();
-
-private:
-
-    GeoRasterWrapper*   poGeoRaster;
-    bool                bGeoTransform;
-    bool                bForcedSRID;
-    char*               pszProjection;
-    char**              papszSubdatasets;
-    double              adfGeoTransform[6];
-    int                 nGCPCount;
-    GDAL_GCP*           pasGCPList;
-    GeoRasterRasterBand*
-                        poMaskBand;
-    bool                bApplyNoDataArray;
-
-public:
-
-    void                SetSubdatasets( GeoRasterWrapper* poGRW );
-
-    static int          Identify( GDALOpenInfo* poOpenInfo );
-    static GDALDataset* Open( GDALOpenInfo* poOpenInfo );
-    static CPLErr       Delete( const char *pszFilename );
-    static GDALDataset* Create( const char* pszFilename,
-                            int nXSize,
-                            int nYSize,
-                            int nBands,
-                            GDALDataType eType,
-                            char** papszOptions );
-    static GDALDataset* CreateCopy( const char* pszFilename, 
-                            GDALDataset* poSrcDS,
-                            int bStrict,
-                            char** papszOptions,
-                            GDALProgressFunc pfnProgress, 
-                            void* pProgressData );
-    virtual CPLErr      GetGeoTransform( double* padfTransform );
-    virtual CPLErr      SetGeoTransform( double* padfTransform );
-    virtual const char* GetProjectionRef( void );
-    virtual CPLErr      SetProjection( const char* pszProjString );
-    virtual char**      GetMetadata( const char* pszDomain );
-    virtual void        FlushCache( void );
-    virtual CPLErr      IRasterIO( GDALRWFlag eRWFlag, 
-                            int nXOff, int nYOff, int nXSize, int nYSize,
-                            void *pData, int nBufXSize, int nBufYSize, 
-                            GDALDataType eBufType,
-                            int nBandCount, int *panBandMap, 
-                            int nPixelSpace, int nLineSpace, int nBandSpace );
-    virtual int         GetGCPCount() { return nGCPCount; }
-    virtual const char* GetGCPProjection();
-    virtual const GDAL_GCP*
-                        GetGCPs() { return pasGCPList; }
-    virtual CPLErr      SetGCPs(
-                            int nGCPCount,
-                            const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
-    virtual CPLErr      IBuildOverviews(
-                            const char* pszResampling,
-                            int nOverviews,
-                            int* panOverviewList,
-                            int nListBandsover,
-                            int* panBandList,
-                            GDALProgressFunc pfnProgress,
-                            void* pProgresoversData );
-    virtual CPLErr      CreateMaskBand( int nFlags );
-    void                AssignGeoRaster( GeoRasterWrapper* poGRW );
-};
-
-//  ---------------------------------------------------------------------------
-//  GeoRasterRasterBand, extends GDALRasterBand to support GeoRaster Band
-//  ---------------------------------------------------------------------------
-
-class GeoRasterRasterBand : public GDALRasterBand
-{
-    friend class GeoRasterDataset;
-
-public:
-                        GeoRasterRasterBand( GeoRasterDataset* poGDS, 
-                            int nBand,
-                            int nLevel );
-    virtual            ~GeoRasterRasterBand();
-
-private:
-
-    GeoRasterWrapper*   poGeoRaster;
-    GDALColorTable*     poColorTable;
-    GDALRasterAttributeTable*
-                        poDefaultRAT;
-    double              dfMin;
-    double              dfMax;
-    double              dfMean;
-    double              dfStdDev;
-    bool                bValidStats;
-    double              dfNoData;
-    char*               pszVATName;
-    int                 nOverviewLevel;
-    GeoRasterRasterBand** papoOverviews;
-    int                 nOverviewCount;
-    hNoDataItem*        pahNoDataArray;
-    int                 nNoDataArraySz;
-    bool                bHasNoDataArray;
-    
-    void                ApplyNoDataArry( void* pBuffer );
-
-public:
-
-    virtual double      GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr      SetNoDataValue( double dfNoDataValue );
-    virtual double      GetMinimum( int* pbSuccess = NULL );
-    virtual double      GetMaximum( int* pbSuccess = NULL );
-    virtual GDALColorTable* 
-                        GetColorTable();
-    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable ); 
-    virtual GDALColorInterp   
-                        GetColorInterpretation();
-    virtual CPLErr      IReadBlock( int nBlockXOff, int nBlockYOff, 
-                            void *pImage );
-    virtual CPLErr      IWriteBlock( int nBlockXOff, int nBlockYOff, 
-                            void *pImage );
-    virtual CPLErr      SetStatistics( double dfMin, double dfMax, 
-                            double dfMean, double dfStdDev );
-    virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
-                            double* pdfMin, double* pdfMax, 
-                            double* pdfMean, double* pdfStdDev );
-    virtual const       GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr      SetDefaultRAT( const GDALRasterAttributeTable * );
-    virtual int         GetOverviewCount();
-    virtual GDALRasterBand*
-                        GetOverview( int );
-    virtual CPLErr      CreateMaskBand( int nFlags );
-    virtual GDALRasterBand*
-                        GetMaskBand();
-    virtual int         GetMaskFlags();
-};
-
-//  ---------------------------------------------------------------------------
-//  GeoRasterWrapper, an interface for Oracle Spatial SDO_GEORASTER objects
-//  ---------------------------------------------------------------------------
-
-class GeoRasterWrapper
-{
-
-public:
-
-                        GeoRasterWrapper();
-    virtual            ~GeoRasterWrapper();
-
-private:
-
-    OCILobLocator**     pahLocator;
-    unsigned long       nBlockCount;
-    unsigned long       nBlockBytes;
-    unsigned long       nGDALBlockBytes;
-    GByte*              pabyBlockBuf;
-    GByte*              pabyCompressBuf;
-    OWStatement*        poBlockStmt;
-    OWStatement*        poStmtWrite;
-
-    int                 nCurrentLevel;
-    long                nLevelOffset;
-
-    long                nCacheBlockId;
-    bool                bFlushBlock;
-    unsigned long       nFlushBlockSize;
-
-    bool                bWriteOnly;
-
-    hLevelDetails*      pahLevels;
-
-    int                 nCellSizeBits;
-    int                 nGDALCellBytes;
-
-    bool                bUpdate;
-    bool                bInitializeIO;
-    bool                bFlushMetadata;
-
-    void                InitializeLayersNode( void );
-    bool                InitializeIO( void );
-    void                InitializeLevel( int nLevel );
-    bool                FlushMetadata( void );
-
-    void                LoadNoDataValues( void );
-
-    void                UnpackNBits( GByte* pabyData );
-    void                PackNBits( GByte* pabyData );
-    unsigned long       CompressJpeg( void );
-    unsigned long       CompressDeflate( void );
-    void                UncompressJpeg( unsigned long nBufferSize );
-    bool                UncompressDeflate( unsigned long nBufferSize );
-
-    struct jpeg_decompress_struct sDInfo;
-    struct jpeg_compress_struct sCInfo;
-    struct jpeg_error_mgr sJErr;
-
-public:
-
-    static char**       ParseIdentificator( const char* pszStringID );
-    static GeoRasterWrapper*
-                        Open( 
-                            const char* pszStringID,
-                            bool bUpdate );
-    bool                Create(
-                            char* pszDescription,
-                            char* pszInsert,
-                            bool bUpdate );
-    bool                Delete( void );
-    void                GetRasterInfo( void );
-    bool                GetStatistics( int nBand,
-                            double dfMin,
-                            double dfMax,
-                            double dfMean,
-                            double dfStdDev );
-    bool                SetStatistics( double dfMin,
-                            double dfMax,
-                            double dfMean,
-                            double dfStdDev,
-                            int nBand );
-    bool                HasColorMap( int nBand );
-    void                GetColorMap( int nBand, GDALColorTable* poCT );
-    void                SetColorMap( int nBand, GDALColorTable* poCT );
-    void                SetGeoReference( int nSRIDIn );
-    bool                GetDataBlock(
-                            int nBand,
-                            int nLevel,
-                            int nXOffset,
-                            int nYOffset,
-                            void* pData );
-    bool                SetDataBlock(
-                            int nBand,
-                            int nLevel,
-                            int nXOffset,
-                            int nYOffset,
-                            void* pData );
-    long                GetBlockNumber( int nB, int nX, int nY )
-                        {
-                            return nLevelOffset +
-                                   (long) ( ( ceil( (double)
-                                   ( ( nB - 1 ) / nBandBlockSize ) ) *
-                                   nTotalColumnBlocks * nTotalRowBlocks ) +
-                                   ( nY * nTotalColumnBlocks ) + nX );
-                        }
-
-    bool                FlushBlock( long nCacheBlock );
-    bool                GetNoData( int nLayer, double* pdfNoDataValue );
-    bool                SetNoData( int nLayer, const char* pszValue );
-    CPLXMLNode*         GetMetadata() { return phMetadata; };
-    bool                SetVAT( int nBand, const char* pszName );
-    char*               GetVAT( int nBand );
-    bool                GeneratePyramid(
-                            int nLevels,
-                            const char* pszResampling,
-                            bool bInternal = false );
-    bool                DeletePyramid();
-    void                PrepareToOverwrite( void );
-    bool                InitializeMask( int nLevel,
-                                                int nBlockColumns,
-                                                int nBlockRows,
-                                                int nColumnBlocks,
-                                                int nRowBlocks,
-                                                int nBandBlocks );
-    void                SetWriteOnly( bool value ) { bWriteOnly = value; };
-    void                SetRPC();
-    void                GetRPC();
-
-public:
-
-    OWConnection*       poConnection;
-
-    CPLString           sTable;
-    CPLString           sSchema;
-    CPLString           sOwner;
-    CPLString           sColumn;
-    CPLString           sDataTable;
-    int                 nRasterId;
-    CPLString           sWhere;
-    CPLString           sValueAttributeTab;
-
-    int                 nSRID;
-    int                 nExtentSRID;
-    bool                bGenSpatialIndex;
-    CPLXMLNode*         phMetadata;
-    CPLString           sCellDepth;
-    CPLString           sCompressionType;
-    int                 nCompressQuality;
-    CPLString           sWKText;
-    CPLString           sAuthority;
-    CPLList*            psNoDataList;
-
-    int                 nRasterColumns;
-    int                 nRasterRows;
-    int                 nRasterBands;
-
-    CPLString           sInterleaving;
-    bool                bIsReferenced;
-
-    bool                bBlocking;
-    bool                bAutoBlocking;
-
-    double              dfXCoefficient[3];
-    double              dfYCoefficient[3];
-
-    int                 nColumnBlockSize;
-    int                 nRowBlockSize;
-    int                 nBandBlockSize;
-
-    int                 nTotalColumnBlocks;
-    int                 nTotalRowBlocks;
-    int                 nTotalBandBlocks;
-
-    int                 iDefaultRedBand;
-    int                 iDefaultGreenBand;
-    int                 iDefaultBlueBand;
-
-    int                 nPyramidMaxLevel;
-
-    bool                bHasBitmapMask;
-    bool                bUniqueFound;
-    
-    int                 eModelCoordLocation;
-    unsigned int        anULTCoordinate[3];
-
-    GDALRPCInfo*        phRPC;
-};
-
-#endif /* ifndef _GEORASTER_PRIV_H_INCLUDED */
+/******************************************************************************
+ * $Id: $
+ *
+ * Name:     georaster_priv.h
+ * Project:  Oracle Spatial GeoRaster Driver
+ * Purpose:  Define C++/Private declarations
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
+ *
+ ******************************************************************************
+ * Copyright (c) 2008, Ivan Lucena
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files ( the "Software" ),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef _GEORASTER_PRIV_H_INCLUDED
+#define _GEORASTER_PRIV_H_INCLUDED
+
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "gdal_alg.h"
+#include "gdal_rat.h"
+#include "ogr_spatialref.h"
+#include "cpl_minixml.h"
+#include "cpl_list.h"
+
+//  ---------------------------------------------------------------------------
+//  DEFLATE compression support
+//  ---------------------------------------------------------------------------
+
+#include <zlib.h>
+
+//  ---------------------------------------------------------------------------
+//  JPEG compression support
+//  ---------------------------------------------------------------------------
+
+CPL_C_START
+#include <jpeglib.h>
+CPL_C_END
+
+void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile);
+void jpeg_vsiio_dest (j_compress_ptr cinfo, VSILFILE * outfile);
+
+//  ---------------------------------------------------------------------------
+//  System constants
+//  ---------------------------------------------------------------------------
+
+//  VAT maximum string len
+
+#define MAXLEN_VATSTR 128
+
+//  Geographic system without EPSG parameters
+
+#define UNKNOWN_CRS     999999
+#define NO_CRS          0
+#define DEFAULT_CRS     NO_CRS
+
+//  Bitmap Mask for the whole dataset start with -99999
+
+#define DEFAULT_BMP_MASK -99999
+
+//  Default block size
+
+#define DEFAULT_BLOCK_ROWS 256
+#define DEFAULT_BLOCK_COLUMNS 256
+
+//  Default Model Coordinate Location (internal pixel geo-reference)
+
+#define MCL_CENTER      0
+#define MCL_UPPERLEFT   1
+#define MCL_DEFAULT     MCL_CENTER
+
+// MAX double string representation
+
+#define MAX_DOUBLE_STR_REP 20
+
+struct hLevelDetails {
+    int             nColumnBlockSize;
+    int             nRowBlockSize;
+    int             nTotalColumnBlocks;
+    int             nTotalRowBlocks;
+    unsigned long   nBlockCount;
+    unsigned long   nBlockBytes;
+    unsigned long   nGDALBlockBytes;
+    unsigned long   nOffset;
+};
+
+//  ---------------------------------------------------------------------------
+//  Support for multi-values NoData support
+//  ---------------------------------------------------------------------------
+
+struct hNoDataItem {
+    int             nBand;
+    double          dfLower;
+    double          dfUpper;
+};
+
+//  ---------------------------------------------------------------------------
+//  GeoRaster wrapper classe definitions
+//  ---------------------------------------------------------------------------
+
+#include "oci_wrapper.h"
+
+class GeoRasterDataset;
+class GeoRasterRasterBand;
+class GeoRasterWrapper;
+
+//  ---------------------------------------------------------------------------
+//  GeoRasterDataset, extends GDALDataset to support GeoRaster Datasets
+//  ---------------------------------------------------------------------------
+
+class GeoRasterDataset : public GDALDataset
+{
+    friend class GeoRasterRasterBand;
+
+public:
+                        GeoRasterDataset();
+    virtual            ~GeoRasterDataset();
+
+private:
+
+    GeoRasterWrapper*   poGeoRaster;
+    bool                bGeoTransform;
+    bool                bForcedSRID;
+    char*               pszProjection;
+    char**              papszSubdatasets;
+    double              adfGeoTransform[6];
+    int                 nGCPCount;
+    GDAL_GCP*           pasGCPList;
+    GeoRasterRasterBand*
+                        poMaskBand;
+    bool                bApplyNoDataArray;
+
+public:
+
+    void                SetSubdatasets( GeoRasterWrapper* poGRW );
+
+    static int          Identify( GDALOpenInfo* poOpenInfo );
+    static GDALDataset* Open( GDALOpenInfo* poOpenInfo );
+    static CPLErr       Delete( const char *pszFilename );
+    static GDALDataset* Create( const char* pszFilename,
+                            int nXSize,
+                            int nYSize,
+                            int nBands,
+                            GDALDataType eType,
+                            char** papszOptions );
+    static GDALDataset* CreateCopy( const char* pszFilename, 
+                            GDALDataset* poSrcDS,
+                            int bStrict,
+                            char** papszOptions,
+                            GDALProgressFunc pfnProgress, 
+                            void* pProgressData );
+    virtual CPLErr      GetGeoTransform( double* padfTransform );
+    virtual CPLErr      SetGeoTransform( double* padfTransform );
+    virtual const char* GetProjectionRef( void );
+    virtual CPLErr      SetProjection( const char* pszProjString );
+    virtual char      **GetMetadataDomainList();
+    virtual char**      GetMetadata( const char* pszDomain );
+    virtual void        FlushCache( void );
+    virtual CPLErr      IRasterIO( GDALRWFlag eRWFlag, 
+                            int nXOff, int nYOff, int nXSize, int nYSize,
+                            void *pData, int nBufXSize, int nBufYSize, 
+                            GDALDataType eBufType,
+                            int nBandCount, int *panBandMap, 
+                            int nPixelSpace, int nLineSpace, int nBandSpace );
+    virtual int         GetGCPCount() { return nGCPCount; }
+    virtual const char* GetGCPProjection();
+    virtual const GDAL_GCP*
+                        GetGCPs() { return pasGCPList; }
+    virtual CPLErr      SetGCPs(
+                            int nGCPCount,
+                            const GDAL_GCP *pasGCPList,
+                            const char *pszGCPProjection );
+    virtual CPLErr      IBuildOverviews(
+                            const char* pszResampling,
+                            int nOverviews,
+                            int* panOverviewList,
+                            int nListBandsover,
+                            int* panBandList,
+                            GDALProgressFunc pfnProgress,
+                            void* pProgresoversData );
+    virtual CPLErr      CreateMaskBand( int nFlags );
+    void                AssignGeoRaster( GeoRasterWrapper* poGRW );
+};
+
+//  ---------------------------------------------------------------------------
+//  GeoRasterRasterBand, extends GDALRasterBand to support GeoRaster Band
+//  ---------------------------------------------------------------------------
+
+class GeoRasterRasterBand : public GDALRasterBand
+{
+    friend class GeoRasterDataset;
+
+public:
+                        GeoRasterRasterBand( GeoRasterDataset* poGDS, 
+                            int nBand,
+                            int nLevel );
+    virtual            ~GeoRasterRasterBand();
+
+private:
+
+    GeoRasterWrapper*   poGeoRaster;
+    GDALColorTable*     poColorTable;
+    GDALRasterAttributeTable*
+                        poDefaultRAT;
+    double              dfMin;
+    double              dfMax;
+    double              dfMean;
+    double              dfMedian;
+    double              dfMode;
+    double              dfStdDev;
+    bool                bValidStats;
+    double              dfNoData;
+    char*               pszVATName;
+    int                 nOverviewLevel;
+    GeoRasterRasterBand** papoOverviews;
+    int                 nOverviewCount;
+    hNoDataItem*        pahNoDataArray;
+    int                 nNoDataArraySz;
+    bool                bHasNoDataArray;
+    
+    void                ApplyNoDataArry( void* pBuffer );
+
+public:
+
+    virtual double      GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr      SetNoDataValue( double dfNoDataValue );
+    virtual double      GetMinimum( int* pbSuccess = NULL );
+    virtual double      GetMaximum( int* pbSuccess = NULL );
+    virtual GDALColorTable* 
+                        GetColorTable();
+    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable ); 
+    virtual GDALColorInterp   
+                        GetColorInterpretation();
+    virtual CPLErr      IReadBlock( int nBlockXOff, int nBlockYOff, 
+                            void *pImage );
+    virtual CPLErr      IWriteBlock( int nBlockXOff, int nBlockYOff, 
+                            void *pImage );
+    virtual CPLErr      SetStatistics( double dfMin, double dfMax, 
+                            double dfMean, double dfStdDev );
+    virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
+                            double* pdfMin, double* pdfMax, 
+                            double* pdfMean, double* pdfStdDev );
+    virtual             GDALRasterAttributeTable *GetDefaultRAT();
+    virtual CPLErr      SetDefaultRAT( const GDALRasterAttributeTable *poRAT );
+    virtual int         GetOverviewCount();
+    virtual GDALRasterBand*
+                        GetOverview( int );
+    virtual CPLErr      CreateMaskBand( int nFlags );
+    virtual GDALRasterBand*
+                        GetMaskBand();
+    virtual int         GetMaskFlags();
+};
+
+//  ---------------------------------------------------------------------------
+//  GeoRasterWrapper, an interface for Oracle Spatial SDO_GEORASTER objects
+//  ---------------------------------------------------------------------------
+
+class GeoRasterWrapper
+{
+
+public:
+
+                        GeoRasterWrapper();
+    virtual            ~GeoRasterWrapper();
+
+private:
+
+    OCILobLocator**     pahLocator;
+    unsigned long       nBlockCount;
+    unsigned long       nBlockBytes;
+    unsigned long       nGDALBlockBytes;
+    GByte*              pabyBlockBuf;
+    GByte*              pabyCompressBuf;
+    OWStatement*        poBlockStmt;
+    OWStatement*        poStmtWrite;
+
+    int                 nCurrentLevel;
+    long                nLevelOffset;
+
+    long                nCacheBlockId;
+    bool                bFlushBlock;
+    unsigned long       nFlushBlockSize;
+
+    bool                bWriteOnly;
+
+    hLevelDetails*      pahLevels;
+
+    int                 nCellSizeBits;
+    int                 nGDALCellBytes;
+
+    bool                bUpdate;
+    bool                bInitializeIO;
+    bool                bFlushMetadata;
+
+    void                InitializeLayersNode( void );
+    bool                InitializeIO( void );
+    void                InitializeLevel( int nLevel );
+    bool                FlushMetadata( void );
+
+    void                LoadNoDataValues( void );
+
+    void                UnpackNBits( GByte* pabyData );
+    void                PackNBits( GByte* pabyData );
+    unsigned long       CompressJpeg( void );
+    unsigned long       CompressDeflate( void );
+    void                UncompressJpeg( unsigned long nBufferSize );
+    bool                UncompressDeflate( unsigned long nBufferSize );
+
+    struct jpeg_decompress_struct sDInfo;
+    struct jpeg_compress_struct sCInfo;
+    struct jpeg_error_mgr sJErr;
+
+public:
+
+    static char**       ParseIdentificator( const char* pszStringID );
+    static GeoRasterWrapper*
+                        Open( 
+                            const char* pszStringID,
+                            bool bUpdate );
+    bool                Create(
+                            char* pszDescription,
+                            char* pszInsert,
+                            bool bUpdate );
+    bool                Delete( void );
+    void                GetRasterInfo( void );
+    bool                GetStatistics( int nBand,
+                                       char* pszMin,
+                                       char* pszMax,
+                                       char* pszMean,
+                                       char* pszMedian,
+                                       char* pszMode,
+                                       char* pszStdDev,
+                                       char* pszSampling );
+    bool                SetStatistics( int nBand,
+                                       const char* pszMin,
+                                       const char* pszMax,
+                                       const char* pszMean,
+                                       const char* pszMedian,
+                                       const char* pszMode,
+                                       const char* pszStdDev,
+                                       const char* pszSampling );
+    bool                HasColorMap( int nBand );
+    void                GetColorMap( int nBand, GDALColorTable* poCT );
+    void                SetColorMap( int nBand, GDALColorTable* poCT );
+    void                SetGeoReference( int nSRIDIn );
+    bool                GetDataBlock(
+                            int nBand,
+                            int nLevel,
+                            int nXOffset,
+                            int nYOffset,
+                            void* pData );
+    bool                SetDataBlock(
+                            int nBand,
+                            int nLevel,
+                            int nXOffset,
+                            int nYOffset,
+                            void* pData );
+    long                GetBlockNumber( int nB, int nX, int nY )
+                        {
+                            return nLevelOffset +
+                                   (long) ( ( ceil( (double)
+                                   ( ( nB - 1 ) / nBandBlockSize ) ) *
+                                   nTotalColumnBlocks * nTotalRowBlocks ) +
+                                   ( nY * nTotalColumnBlocks ) + nX );
+                        }
+
+    bool                FlushBlock( long nCacheBlock );
+    bool                GetNoData( int nLayer, double* pdfNoDataValue );
+    bool                SetNoData( int nLayer, const char* pszValue );
+    CPLXMLNode*         GetMetadata() { return phMetadata; };
+    bool                SetVAT( int nBand, const char* pszName );
+    char*               GetVAT( int nBand );
+    bool                GeneratePyramid(
+                            int nLevels,
+                            const char* pszResampling,
+                            bool bInternal = false );
+    bool                DeletePyramid();
+    void                PrepareToOverwrite( void );
+    bool                InitializeMask( int nLevel,
+                                                int nBlockColumns,
+                                                int nBlockRows,
+                                                int nColumnBlocks,
+                                                int nRowBlocks,
+                                                int nBandBlocks );
+    void                SetWriteOnly( bool value ) { bWriteOnly = value; };
+    void                SetRPC();
+    void                GetRPC();
+
+public:
+
+    OWConnection*       poConnection;
+
+    CPLString           sTable;
+    CPLString           sSchema;
+    CPLString           sOwner;
+    CPLString           sColumn;
+    CPLString           sDataTable;
+    int                 nRasterId;
+    CPLString           sWhere;
+    CPLString           sValueAttributeTab;
+
+    int                 nSRID;
+    int                 nExtentSRID;
+    bool                bGenSpatialIndex;
+    bool                bCreateObjectTable;
+    CPLXMLNode*         phMetadata;
+    CPLString           sCellDepth;
+
+    bool                bGenPyramid;
+    CPLString           sPyramidResampling;
+    int                 nPyramidLevels;
+
+    CPLString           sCompressionType;
+    int                 nCompressQuality;
+    CPLString           sWKText;
+    CPLString           sAuthority;
+    CPLList*            psNoDataList;
+
+    int                 nRasterColumns;
+    int                 nRasterRows;
+    int                 nRasterBands;
+
+    CPLString           sInterleaving;
+    bool                bIsReferenced;
+
+    bool                bBlocking;
+    bool                bAutoBlocking;
+
+    double              dfXCoefficient[3];
+    double              dfYCoefficient[3];
+
+    int                 nColumnBlockSize;
+    int                 nRowBlockSize;
+    int                 nBandBlockSize;
+
+    int                 nTotalColumnBlocks;
+    int                 nTotalRowBlocks;
+    int                 nTotalBandBlocks;
+
+    int                 iDefaultRedBand;
+    int                 iDefaultGreenBand;
+    int                 iDefaultBlueBand;
+
+    int                 nPyramidMaxLevel;
+
+    bool                bHasBitmapMask;
+    bool                bUniqueFound;
+    
+    int                 eModelCoordLocation;
+    unsigned int        anULTCoordinate[3];
+
+    GDALRPCInfo*        phRPC;
+};
+
+#endif /* ifndef _GEORASTER_PRIV_H_INCLUDED */
diff --git a/frmts/georaster/georaster_rasterband.cpp b/frmts/georaster/georaster_rasterband.cpp
index e5ad59e..498d07f 100644
--- a/frmts/georaster/georaster_rasterband.cpp
+++ b/frmts/georaster/georaster_rasterband.cpp
@@ -4,7 +4,7 @@
  * Name:     georaster_rasterband.cpp
  * Project:  Oracle Spatial GeoRaster Driver
  * Purpose:  Implement GeoRasterRasterBand methods
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
  *
  ******************************************************************************
  * Copyright (c) 2008, Ivan Lucena
@@ -376,14 +376,41 @@ CPLErr GeoRasterRasterBand::GetStatistics( int bApproxOK, int bForce,
     (void) bForce;
     (void) bApproxOK;
 
+    char szMin[MAX_DOUBLE_STR_REP + 1];
+    char szMax[MAX_DOUBLE_STR_REP + 1];
+    char szMean[MAX_DOUBLE_STR_REP + 1];
+    char szMedian[MAX_DOUBLE_STR_REP + 1];
+    char szMode[MAX_DOUBLE_STR_REP + 1];
+    char szStdDev[MAX_DOUBLE_STR_REP + 1];
+    char szSampling[MAX_DOUBLE_STR_REP + 1];
+
     if( ! bValidStats )
     {
         bValidStats = poGeoRaster->GetStatistics( nBand,
-                          dfMin, dfMax, dfMean, dfStdDev );
+                                                  szMin,  szMax,
+                                                  szMean, szMedian,
+                                                  szMode, szStdDev,
+                                                  szSampling );
     }
 
     if( bValidStats )
     {
+        dfMin        = CPLScanDouble( szMin,    MAX_DOUBLE_STR_REP );
+        dfMax        = CPLScanDouble( szMax,    MAX_DOUBLE_STR_REP );
+        dfMean       = CPLScanDouble( szMean,   MAX_DOUBLE_STR_REP );
+        dfMedian     = CPLScanDouble( szMedian, MAX_DOUBLE_STR_REP );
+        dfMode       = CPLScanDouble( szMode,   MAX_DOUBLE_STR_REP );
+        dfStdDev     = CPLScanDouble( szStdDev, MAX_DOUBLE_STR_REP );
+
+        SetMetadataItem( "STATISTICS_MINIMUM",     szMin );
+        SetMetadataItem( "STATISTICS_MAXIMUM",     szMax );
+        SetMetadataItem( "STATISTICS_MEAN",        szMean );
+        SetMetadataItem( "STATISTICS_MEDIAN",      szMedian );
+        SetMetadataItem( "STATISTICS_MODE",        szMode );
+        SetMetadataItem( "STATISTICS_STDDEV",      szStdDev );
+        SetMetadataItem( "STATISTICS_SKIPFACTORX", szSampling );
+        SetMetadataItem( "STATISTICS_SKIPFACTORY", szSampling ); 
+
         *pdfMin     = dfMin;
         *pdfMax     = dfMax;
         *pdfMean    = dfMean;
@@ -402,13 +429,10 @@ CPLErr GeoRasterRasterBand::GetStatistics( int bApproxOK, int bForce,
 CPLErr GeoRasterRasterBand::SetStatistics( double dfMin, double dfMax,
                                            double dfMean, double dfStdDev )
 {
-    dfMin       = dfMin;
-    dfMax       = dfMax;
-    dfMean      = dfMax;
-    dfStdDev    = dfStdDev;
-    bValidStats = true;
-
-    poGeoRaster->SetStatistics( dfMin, dfMax, dfMean, dfStdDev, nBand );
+    this->dfMin       = dfMin;
+    this->dfMax       = dfMax;
+    this->dfMean      = dfMean;
+    this->dfStdDev    = dfStdDev;
 
     return CE_None;
 }
@@ -493,6 +517,10 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
 
     if( nColCount < 2 )
     {
+        delete poDefaultRAT;
+
+        poDefaultRAT = NULL;
+
         return CE_None;
     }
 
@@ -519,7 +547,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
         }
         if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
         {
-            strcpy( szDescription, CPLSPrintf( "%s FLOAT",
+            strcpy( szDescription, CPLSPrintf( "%s NUMBER",
                 szDescription ) );
         }
         if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
@@ -534,6 +562,11 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
     // Create VAT named based on RDT and RID and Layer (nBand)
     // ----------------------------------------------------------
 
+    if ( poGeoRaster->sValueAttributeTab.length() > 0 )
+    {
+        pszVATName = CPLStrdup( poGeoRaster->sValueAttributeTab.c_str() );
+    }
+
     if( ! pszVATName )
     {
         pszVATName = CPLStrdup( CPLSPrintf(
@@ -638,7 +671,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
             }
             if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
             {
-                ((double *)(papWriteFields[iCol]))[iEntry + 1] =
+                ((double *)(papWriteFields[iCol + 1]))[iEntry] =
                     poRAT->GetValueAsDouble(iEntry, iCol);
             }
         }
@@ -713,15 +746,15 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
 //                                                              GetDefaultRAT()
 //  ---------------------------------------------------------------------------
 
-const GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
 {
     if( poDefaultRAT )
     {
-        return poDefaultRAT->Clone();
+        return poDefaultRAT;
     }
     else
     {
-        poDefaultRAT = new GDALRasterAttributeTable();
+        poDefaultRAT = new GDALDefaultRasterAttributeTable();
     }
 
     GeoRasterDataset* poGDS = (GeoRasterDataset*) poDS;
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index 80c55b7..47fa93d 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -4,7 +4,7 @@
  * Name:     georaster_wrapper.cpp
  * Project:  Oracle Spatial GeoRaster Driver
  * Purpose:  Implement GeoRasterWrapper methods
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
  *
  ******************************************************************************
  * Copyright (c) 2008, Ivan Lucena
@@ -62,6 +62,9 @@ GeoRasterWrapper::GeoRasterWrapper()
     dfYCoefficient[2]   = 0.0;
     sCompressionType    = "NONE";
     nCompressQuality    = 75;
+    bGenPyramid         = false;
+    nPyramidLevels      = 0;
+    sPyramidResampling  = "NN";
     pahLocator          = NULL;
     pabyBlockBuf        = NULL;
     pabyCompressBuf     = NULL;
@@ -78,6 +81,7 @@ GeoRasterWrapper::GeoRasterWrapper()
     nSRID               = 0;
     nExtentSRID         = 0;
     bGenSpatialIndex    = false;
+    bCreateObjectTable  = false;
     nPyramidMaxLevel    = 0;
     nBlockCount         = 0L;
     nGDALBlockBytes     = 0L;
@@ -922,6 +926,40 @@ bool GeoRasterWrapper::Create( char* pszDescription,
     int  nBindRID = 0;
     szBindRDT[0] = '\0';
 
+    CPLString sObjectTable;
+    CPLString sSecureFile;
+
+    // For version > 11 create RDT as relational table by default,
+    // if it is not specified by create-option OBJECTTABLE=TRUE
+
+    if( poConnection->GetVersion() <= 11 || bCreateObjectTable )
+    {
+        sObjectTable = "OF MDSYS.SDO_RASTER\n      (";
+    }
+    else
+    {
+        sObjectTable = CPLSPrintf("(\n"
+                       "      RASTERID           NUMBER,\n"
+                       "      PYRAMIDLEVEL       NUMBER,\n"
+                       "      BANDBLOCKNUMBER    NUMBER,\n"
+                       "      ROWBLOCKNUMBER     NUMBER,\n"
+                       "      COLUMNBLOCKNUMBER  NUMBER,\n"
+                       "      BLOCKMBR           SDO_GEOMETRY,\n"
+                       "      RASTERBLOCK        BLOB,\n"
+                       "      CONSTRAINT '||:rdt||'_RDT_PK ");
+    }
+
+    // For version >= 11 create RDT rasterBlock as securefile
+
+    if( poConnection->GetVersion() >= 11 )
+    {
+        sSecureFile = "SECUREFILE(CACHE)";
+    }
+    else
+    {
+        sSecureFile = "(NOCACHE NOLOGGING)";
+    }
+
     if( poConnection->GetVersion() > 10 )
     {
         poStmt = poConnection->CreateStatement( CPLSPrintf(
@@ -951,10 +989,10 @@ bool GeoRasterWrapper::Create( char* pszDescription,
             "  END IF;\n"
             "\n"
             "  IF CNT = 0 THEN\n"
-            "    EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' OF MDSYS.SDO_RASTER\n"
-            "      (PRIMARY KEY (RASTERID, PYRAMIDLEVEL, BANDBLOCKNUMBER,\n"
-            "      ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
-            "      LOB(RASTERBLOCK) STORE AS (NOCACHE NOLOGGING)';\n"
+            "    EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' %s"
+            "PRIMARY KEY (RASTERID, PYRAMIDLEVEL,\n"
+            "      BANDBLOCKNUMBER, ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
+            "      LOB(RASTERBLOCK) STORE AS %s';\n"
             "  END IF;\n"
             "\n"
             "  SDO_GEOR.createTemplate(GR1, %s, null, 'TRUE');\n"
@@ -979,6 +1017,8 @@ bool GeoRasterWrapper::Create( char* pszDescription,
                 sOwner.c_str(),
                 sCommand.c_str(),
                 sSchema.c_str(),
+                sObjectTable.c_str(),
+                sSecureFile.c_str(),
                 sFormat.c_str(),
                 sSchema.c_str(),
                 sTable.c_str(),
@@ -1118,7 +1158,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
             sSchema.c_str(), sTable.c_str(),
             sColumn.c_str(), sColumn.c_str(), sColumn.c_str(),
             sSchema.c_str(), sSchema.c_str(), sSchema.c_str(),
-            UNKNOWN_CRS, MCL_DEFAULT,
+            DEFAULT_CRS, MCL_DEFAULT,
             sSchema.c_str(), sTable.c_str(),
             sColumn.c_str(), sColumn.c_str(), sColumn.c_str() ) );
 
@@ -1171,6 +1211,9 @@ void GeoRasterWrapper::PrepareToOverwrite( void )
     dfYCoefficient[2]   = 0.0;
     sCompressionType    = "NONE";
     nCompressQuality    = 75;
+    bGenPyramid         = false;
+    nPyramidLevels      = 0;
+    sPyramidResampling  = "NN";
     bIsReferenced       = false;
     nCacheBlockId       = -1;
     nCurrentLevel       = -1;
@@ -1183,6 +1226,7 @@ void GeoRasterWrapper::PrepareToOverwrite( void )
     nSRID               = 0;
     nExtentSRID         = 0;
     bGenSpatialIndex    = false;
+    bCreateObjectTable  = false;
     nPyramidMaxLevel    = 0;
     nBlockCount         = 0L;
     sDInfo.global_state = 0;
@@ -1418,12 +1462,6 @@ void GeoRasterWrapper::GetRasterInfo( void )
 
     nSRID               = atoi( CPLGetXMLValue( phMetadata,
                             "spatialReferenceInfo.SRID", "0" ) );
-
-    if( nSRID == 0 ||
-        nSRID == UNKNOWN_CRS )
-    {
-        bIsReferenced   = false;
-    }
 }
 
 //  ---------------------------------------------------------------------------
@@ -1431,10 +1469,13 @@ void GeoRasterWrapper::GetRasterInfo( void )
 //  ---------------------------------------------------------------------------
 
 bool GeoRasterWrapper::GetStatistics( int nBand,
-                                      double dfMin,
-                                      double dfMax,
-                                      double dfMean,
-                                      double dfStdDev )
+                                      char* pszMin,
+                                      char* pszMax,
+                                      char* pszMean,
+                                      char* pszMedian,
+                                      char* pszMode,
+                                      char* pszStdDev,
+                                      char* pszSampling )
 {
     int n = 1;
 
@@ -1444,15 +1485,20 @@ bool GeoRasterWrapper::GetStatistics( int nBand,
     {
         if( n == nBand && CPLGetXMLNode( phSubLayer, "statisticDataset" ) )
         {
-            dfMin    = atoi( CPLGetXMLValue( phSubLayer,
-                                "statisticDataset.MIM",  "0.0" ) );
-            dfMax    = atoi( CPLGetXMLValue( phSubLayer,
-                                "statisticDataset.MAX",  "0.0" ) );
-            dfMean   = atoi( CPLGetXMLValue( phSubLayer,
-                                "statisticDataset.MEAN", "0.0" ) );
-            dfStdDev = atoi( CPLGetXMLValue( phSubLayer,
-                                "statisticDataset.STD",  "0.0" ) );
-            CPLDestroyXMLNode( phSubLayer );
+            strncpy( pszSampling, CPLGetXMLValue( phSubLayer, 
+                "statisticDataset.samplingFactor",  "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszMin, CPLGetXMLValue( phSubLayer, 
+                "statisticDataset.MIN",  "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszMax, CPLGetXMLValue( phSubLayer,
+                "statisticDataset.MAX",  "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszMean, CPLGetXMLValue( phSubLayer,
+                "statisticDataset.MEAN", "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszMedian, CPLGetXMLValue( phSubLayer,
+                "statisticDataset.MEDIAN", "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszMode, CPLGetXMLValue( phSubLayer,
+                "statisticDataset.MODEVALUE", "0.0" ), MAX_DOUBLE_STR_REP );
+            strncpy( pszStdDev, CPLGetXMLValue( phSubLayer,
+                "statisticDataset.STD",  "0.0" ), MAX_DOUBLE_STR_REP );
             return true;
         }
     }
@@ -1463,11 +1509,14 @@ bool GeoRasterWrapper::GetStatistics( int nBand,
 //                                                              SetStatistics()
 //  ---------------------------------------------------------------------------
 
-bool GeoRasterWrapper::SetStatistics( double dfMin,
-                                      double dfMax,
-                                      double dfMean,
-                                      double dfStdDev,
-                                      int nBand )
+bool GeoRasterWrapper::SetStatistics( int nBand,
+                                      const char* pszMin,
+                                      const char* pszMax,
+                                      const char* pszMean,
+                                      const char* pszMedian,
+                                      const char* pszMode,
+                                      const char* pszStdDev,
+                                      const char* pszSampling )
 {
     InitializeLayersNode();
 
@@ -1494,13 +1543,13 @@ bool GeoRasterWrapper::SetStatistics( double dfMin,
 
         psSDaset = CPLCreateXMLNode(phSubLayer,CXT_Element,"statisticDataset");
 
-        CPLCreateXMLElementAndValue(psSDaset,"samplingFactor", "1" );
-        CPLCreateXMLElementAndValue(psSDaset,"MIN", CPLSPrintf("%f",dfMin) );
-        CPLCreateXMLElementAndValue(psSDaset,"MAX", CPLSPrintf("%f",dfMax) );
-        CPLCreateXMLElementAndValue(psSDaset,"MEAN",CPLSPrintf("%f",dfMean) );
-        CPLCreateXMLElementAndValue(psSDaset,"MEDIAN",         "0");
-        CPLCreateXMLElementAndValue(psSDaset,"MODEVALUE",      "0");
-        CPLCreateXMLElementAndValue(psSDaset,"STD", CPLSPrintf("%f",dfStdDev));
+        CPLCreateXMLElementAndValue(psSDaset,"samplingFactor", pszSampling );
+        CPLCreateXMLElementAndValue(psSDaset,"MIN", pszMin );
+        CPLCreateXMLElementAndValue(psSDaset,"MAX", pszMax );
+        CPLCreateXMLElementAndValue(psSDaset,"MEAN", pszMean );
+        CPLCreateXMLElementAndValue(psSDaset,"MEDIAN", pszMedian );
+        CPLCreateXMLElementAndValue(psSDaset,"MODEVALUE", pszMode );
+        CPLCreateXMLElementAndValue(psSDaset,"STD", pszStdDev );
 
         return true;
     }
@@ -1557,8 +1606,7 @@ void GeoRasterWrapper::InitializeLayersNode()
             CPLCreateXMLElementAndValue( psSLayer, "layerDimensionOrdinate",
                 CPLSPrintf( "%d", n ) );
 
-            CPLCreateXMLElementAndValue( psSLayer, "layerID",
-                CPLSPrintf( "subLayer%d", n + 1 ) );
+            CPLCreateXMLElementAndValue( psSLayer, "layerID", "" );
         }
     }
 }
@@ -1742,16 +1790,24 @@ bool GeoRasterWrapper::InitializeIO( void )
 
         if( nXSize <= nXBlock && nYSize <= nYBlock )
         {
+            // ------------------------------------------------------------
+            // Calculate the size of the singe small blocks
+            // ------------------------------------------------------------
+
             nCBS = nXSize;
             nRBS = nYSize;
+            nTCB = 1;
+            nTRB = 1;
         }
+        else
+        {
+            // ------------------------------------------------------------
+            // Recalculate blocks quantity
+            // ------------------------------------------------------------
 
-        // ----------------------------------------------------------------
-        // Recalculate blocks quantity
-        // ----------------------------------------------------------------
-
-        nTCB = (int) MAX( 1, (int) ceil( (double) nTCB / dfScale ) );
-        nTRB = (int) MAX( 1, (int) ceil( (double) nTRB / dfScale ) );
+            nTCB = (int) ceil( (double) nXSize / nCBS );
+            nTRB = (int) ceil( (double) nYSize / nRBS );
+        }
 
         // --------------------------------------------------------------------
         // Save level datails
@@ -1762,8 +1818,8 @@ bool GeoRasterWrapper::InitializeIO( void )
         pahLevels[iLevel].nTotalColumnBlocks = nTCB;
         pahLevels[iLevel].nTotalRowBlocks    = nTRB;
         pahLevels[iLevel].nBlockCount        = (unsigned long ) ( nTCB * nTRB * nTotalBandBlocks );
-        pahLevels[iLevel].nBlockBytes        = (unsigned long ) ( nCBS * nRBS * nBandBlockSize ) *
-                                               (unsigned long ) ( nCellSizeBits / 8L );
+        pahLevels[iLevel].nBlockBytes        = (unsigned long ) ( nCBS * nRBS * nBandBlockSize *
+                                                                  nCellSizeBits / 8L );
         pahLevels[iLevel].nGDALBlockBytes    = (unsigned long ) ( nCBS * nRBS * nGDALCellBytes );
         pahLevels[iLevel].nOffset            = 0L;
     }
@@ -3215,6 +3271,18 @@ bool GeoRasterWrapper::FlushMetadata()
             "Cannot generate spatialExtent! (ORA-%d) ", nException );
     }
 
+    if (bGenPyramid) 
+    {
+        if (GeneratePyramid( nPyramidLevels, sPyramidResampling.c_str(), true ))
+        {
+            CPLDebug("GEOR", "Generated pyramid successfully.");
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_AppDefined, "Error generating pyramid!");
+        }
+    }
+
     return true;
 }
 
@@ -3230,19 +3298,26 @@ bool GeoRasterWrapper::GeneratePyramid( int nLevels,
 
     if( bInternal )
     {
+        CPLString sLevels = "";
+
+        if (nLevels > 0)
+        {
+            sLevels = CPLSPrintf("rlevel=%d", nLevels);
+        }
+
         OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
             "DECLARE\n"
             "  gr sdo_georaster;\n"
             "BEGIN\n"
             "  SELECT %s INTO gr FROM %s t WHERE %s FOR UPDATE;\n"
-            "  sdo_geor.generatePyramid(gr, 'rlevel=%d resampling=%s');\n"
+            "  sdo_geor.generatePyramid(gr, '%s resampling=%s');\n"
             "  UPDATE %s t SET %s = gr WHERE %s;\n"
             "  COMMIT;\n"
             "END;\n",
                 sColumn.c_str(),
                 sTable.c_str(),
                 sWhere.c_str(),
-                nLevels,
+                sLevels.c_str(),
                 pszResampling,
                 sTable.c_str(),
                 sColumn.c_str(),
@@ -3824,12 +3899,12 @@ unsigned long GeoRasterWrapper::CompressJpeg( void )
     VSIFCloseL( fpImage );
 
     fpImage = VSIFOpenL( pszMemFile, "rb" );
-    unsigned long nSize = VSIFReadL( pabyCompressBuf, 1, nBlockBytes, fpImage );
+    size_t nSize = VSIFReadL( pabyCompressBuf, 1, nBlockBytes, fpImage );
     VSIFCloseL( fpImage );
 
     VSIUnlink( pszMemFile );
 
-    return nSize;
+    return (unsigned long) nSize;
 }
 
 //  ---------------------------------------------------------------------------
diff --git a/frmts/georaster/oci_wrapper.cpp b/frmts/georaster/oci_wrapper.cpp
index 4434ef2..2c2f3cc 100644
--- a/frmts/georaster/oci_wrapper.cpp
+++ b/frmts/georaster/oci_wrapper.cpp
@@ -4,7 +4,7 @@
  * Name:     oci_wrapper.cpp
  * Project:  Oracle Spatial GeoRaster Driver
  * Purpose:  Limited wrapper for OCI (Oracle Call Interfaces)
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
  *
  ******************************************************************************
  * Copyright (c) 2008, Ivan Lucena
@@ -142,7 +142,7 @@ OWConnection::OWConnection( const char* pszUserIn,
     // ------------------------------------------------------
 
     if( CheckError( OCIServerAttach( hServer, hError, (text*) pszServer,
-        strlen((char*) pszServer), 0), hError ) )
+        (sb4) strlen((char*) pszServer), (ub4) 0), hError ) )
     {
         return;
     }
@@ -1521,76 +1521,6 @@ bool OWIsNumeric( const char *pszText )
 }
 
 /*****************************************************************************/
-/*                            Replace String at given token                  */
-/*****************************************************************************/
-
-/* Input Examples:
- *
- * "ID, RASTER, NAME VALUES (102, SDO_GEOR.INIT('RDT_80', 80), 'Nashua')"
- * "SDO_GEOR.INIT"
- * "SDO_GEOR.createBlank(20001, SDO_NUMBER_ARRAY(0, 0)..."
- */
-const char* OWReplaceString( const char* pszBaseString,
-                             const char* pszToken,
-                             const char* pszStopToken,
-                             const char* pszOWReplaceToken )
-{
-    char szUpcaseBase[OWTEXT];
-    char szUpcaseToken[OWTEXT];
-    char szUpcaseStopT[OWTEXT];
-    char szResult[OWTEXT];
-
-    strcpy( szUpcaseBase, pszBaseString );
-    strcpy( szUpcaseToken, pszToken );
-    strcpy( szUpcaseStopT, pszStopToken );
-    strcpy( szResult, pszBaseString );
-
-    char* pszIn = NULL;
-
-    // Upper case a copy of the base string
-
-    for( pszIn = szUpcaseBase; *pszIn != '\0'; pszIn++ )
-    {
-        *pszIn = (char) toupper( *pszIn );
-    }
-
-    // Upper case a copy of the token
-
-    for( pszIn = szUpcaseToken; *pszIn != '\0'; pszIn++ )
-    {
-        *pszIn = (char) toupper( *pszIn );
-    }
-
-    // Upper case a copy of the stop token
-
-    for( pszIn = szUpcaseStopT; *pszIn != '\0'; pszIn++ )
-    {
-        *pszIn = (char) toupper( *pszIn );
-    }
-
-    // Search for Token, Stop Token on the Base String
-
-    char* pszStart = strstr( szUpcaseBase, szUpcaseToken );
-
-    if( pszStart )
-    {
-        char* pszEnd = strstr( pszStart, szUpcaseStopT );
-
-        // Concatenate the result
-
-        int nStart = (int) ( pszStart - szUpcaseBase );
-        int nEnd   = (int) ( pszEnd   - szUpcaseBase );
-
-        strncpy( szResult, pszBaseString, nStart );
-        szResult[nStart] = '\0';
-        strcat( szResult, pszOWReplaceToken );
-        strcat( szResult, &pszBaseString[nEnd + 1] );
-    }
-
-    return szResult;
-}
-
-/*****************************************************************************/
 /*                     Parse Value after a Hint on a string                  */
 /*****************************************************************************/
 
diff --git a/frmts/georaster/oci_wrapper.h b/frmts/georaster/oci_wrapper.h
index e2edc92..3b01732 100644
--- a/frmts/georaster/oci_wrapper.h
+++ b/frmts/georaster/oci_wrapper.h
@@ -4,7 +4,7 @@
  * Name:     oci_wrapper.h
  * Project:  Oracle Spatial GeoRaster Driver
  * Purpose:  Limited wrapper for OCI (Oracle Call Interfaces)
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena [ivan.lucena at oracle.com]
  *
  ******************************************************************************
  * Copyright (c) 2008, Ivan Lucena
@@ -65,10 +65,6 @@ int                 OWParseServerVersion( const char* pszText );
 int                 OWParseEPSG( const char* pszText );
 bool                OWIsNumeric( const char *pszText );
 const char*         OWParseSDO_GEOR_INIT( const char* pszInsert, int nField );
-const char*         OWReplaceString( const char* pszBaseString,
-                        const char* pszToken,
-                        const char* pszStopToken,
-                        const char* pszOWReplaceToken );
 
 /***************************************************************************/
 /*                            Arbitrary limits                             */
diff --git a/frmts/gff/gff_dataset.cpp b/frmts/gff/gff_dataset.cpp
index 1e19360..c46cecd 100644
--- a/frmts/gff/gff_dataset.cpp
+++ b/frmts/gff/gff_dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gff_dataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: gff_dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Ground-based SAR Applitcations Testbed File Format driver
  * Purpose:  Support in GDAL for Sandia National Laboratory's GFF format
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Philippe Vachon
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gff_dataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: gff_dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /*******************************************************************
  * Declaration of the GFFDataset class                             *
diff --git a/frmts/gif/biggifdataset.cpp b/frmts/gif/biggifdataset.cpp
index 7d9ff46..f996508 100644
--- a/frmts/gif/biggifdataset.cpp
+++ b/frmts/gif/biggifdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: biggifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $
+ * $Id: biggifdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BIGGIF Driver
  * Purpose:  Implement GDAL support for reading large GIF files in a 
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001-2008, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: biggifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $");
+CPL_CVSID("$Id: biggifdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_BIGGIF(void);
@@ -310,12 +311,13 @@ int BIGGIFDataset::CloseDependentDatasets()
         bHasDroppedRef = TRUE;
 
         CPLString osTempFilename = poWorkDS->GetDescription();
+        GDALDriver* poDrv = poWorkDS->GetDriver();
 
         GDALClose( (GDALDatasetH) poWorkDS );
         poWorkDS = NULL;
 
-        GDALDriver *poGTiff = (GDALDriver *) GDALGetDriverByName( "GTiff" );
-        poGTiff->Delete( osTempFilename );
+        if( poDrv != NULL )
+            poDrv->Delete( osTempFilename );
 
         poWorkDS = NULL;
     }
diff --git a/frmts/gif/gifabstractdataset.cpp b/frmts/gif/gifabstractdataset.cpp
index d3b02e3..81c6ec3 100644
--- a/frmts/gif/gifabstractdataset.cpp
+++ b/frmts/gif/gifabstractdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gifabstractdataset.cpp 25287 2012-12-05 21:17:14Z rouault $
+ * $Id: gifabstractdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ****************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifabstractdataset.cpp 25287 2012-12-05 21:17:14Z rouault $");
+CPL_CVSID("$Id: gifabstractdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -211,6 +211,17 @@ void GIFAbstractDataset::CollectXMPMetadata()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GIFAbstractDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:XMP", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 
diff --git a/frmts/gif/gifabstractdataset.h b/frmts/gif/gifabstractdataset.h
index 2c64091..d61485b 100644
--- a/frmts/gif/gifabstractdataset.h
+++ b/frmts/gif/gifabstractdataset.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gifabstractdataset.h 24340 2012-04-28 23:07:09Z rouault $
+ * $Id: gifabstractdataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ****************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -71,6 +71,7 @@ class GIFAbstractDataset : public GDALPamDataset
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
 
+    virtual char      **GetMetadataDomainList();
     virtual char  **GetMetadata( const char * pszDomain = "" );
 
     static int          Identify( GDALOpenInfo * );
diff --git a/frmts/gif/gifdataset.cpp b/frmts/gif/gifdataset.cpp
index 2808734..62a8793 100644
--- a/frmts/gif/gifdataset.cpp
+++ b/frmts/gif/gifdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $
+ * $Id: gifdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  Implement GDAL GIF Support using libungif code.  
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $");
+CPL_CVSID("$Id: gifdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GIF(void);
diff --git a/frmts/grass/frmt_grass.html b/frmts/grass/frmt_grass.html
index b35aa42..6cffa8a 100644
--- a/frmts/grass/frmt_grass.html
+++ b/frmts/grass/frmt_grass.html
@@ -1,76 +1,91 @@
 <html>
 <head>
-<title>GRASS -- GRASS Rasters</title>
+<title>GRASS Raster Format</title>
 </head>
 
 <body bgcolor="#ffffff">
 
-<h1>GRASS -- GRASS Rasters</h1>
+<h1>GRASS Raster Format</h1>
 
-GDAL optionally supports reading of existing GRASS raster layers (cells, and
-image groups), but not writing or export.  The support for GRASS raster 
-layers is determined when the library is configured, and requires libgrass
-to be pre-installed (see Notes below). <p>
+GDAL optionally supports reading of existing GRASS raster maps or
+imagery groups, but not writing or export. The support for GRASS
+raster format is determined when the library is configured, and
+requires libgrass to be pre-installed (see Notes below).
 
-GRASS rasters can be selected in several ways.<p>
+<p>
+GRASS raster maps/imagery groups can be selected in several ways.
 
 <ol>
-<li> The full path to the cellhd file for the cell can be specified.  This
-is not a relative path, or at least it must contain all the path components
-within the database including the database root itself.  The following
-example opens the cell "proj_tm" within the mapset "PERMANENT" of the
-location "proj_tm" in the grass database located at /u/data/grassdb.<p>
-eg.<br>
-<pre>
-  % gdalinfo /u/data/grassdb/proj_tm/PERMANENT/cellhd/proj_tm
-</pre>
-<li> The full path to the directory containing information about an imagery
-group (or the REF file within it) can be specified to refer to the whole
-group as a single dataset.  The following examples do the same thing.<p>
-eg.<br>
+<li> The full path to the <tt>cellhd</tt> file can be specified. This
+is not a relative path, or at least it must contain all the path
+components within the GRASS database including the database root
+itself. The following example opens the raster map "proj_tm"
+within the GRASS mapset "PERMANENT" of the GRASS location
+"proj_tm" in the GRASS database located at
+<tt>/u/data/grassdb</tt>.
+
+<p>
+For example:
+
 <pre>
-  % gdalinfo /usr2/data/grassdb/imagery/raw/group/testmff/REF
-  % gdalinfo /usr2/data/grassdb/imagery/raw/group/testmff
+gdalinfo /u/data/grassdb/proj_tm/PERMANENT/cellhd/proj_tm
 </pre>
-<li>  If there is a correct .grassrc5
-setup in the users home directory then cells or imagery groups may be opened 
-just by the cell name.  This only works for cells or images in the current 
-location and mapset as defined in the .grassrc5 file. <p>
-</ol>
 
+<li> The full path to the directory containing information about an
+imagery group (or the REF file within it) can be specified to refer to
+the whole group as a single dataset.  The following examples do the
+same thing.
 
+<p>
+For example:
 
+<pre>
+gdalinfo /usr2/data/grassdb/imagery/raw/group/testmff/REF
+gdalinfo /usr2/data/grassdb/imagery/raw/group/testmff
+</pre>
 
-The following features are supported by the GDAL/GRASS link.<p>
+<li> If there is a correct <tt>.grassrc5</tt> (GRASS
+5), <tt>.grassrc6</tt> (GRASS 6) <tt>.grass7/rc</tt> (GRASS 7) setup
+file in the users home directory then raster maps or imagery groups
+may be opened just by the cell name. This only works for raster maps
+or imagery groups in the current GRASS location and mapset as defined
+in the GRASS setup file.
+</ol>
+
+<p>
+The following features are supported by the GDAL/GRASS link.
 
 <ul>
-<li> Up to 256 entries from cell colormaps are read (0-255).  
-<li> Compressed and uncompressed integer, floating point and double precision
-cells are all supported.  Integer cells are classified with a band type of
-"Byte" if the 1-byte per pixel format is used, or UInt16 if the two byte
-per pixel format is used.  Otherwise integer cells are treated as UInt32.
-<li> Georeferencing information is properly read from GRASS.
-<li> An attempt is made to translate coordinate systems, but some conversions
-may be flawed, in particular in handling of datums and units.
+<li> Up to 256 entries from raster colormaps are read (0-255).  
+<li> Compressed and uncompressed integer (CELL), floating point
+(FCELL) and double precision (DCELL) raster maps are all
+supported. Integer raster maps are classified with a band type of
+"Byte" if the 1-byte per pixel format is used, or
+"UInt16" if the two byte per pixel format is used. Otherwise
+integer raster maps are treated as "UInt32".
+<li> Georeferencing information is properly read from GRASS format.
+<li> An attempt is made to translate coordinate systems, but some
+conversions may be flawed, in particular in handling of datums and
+units.
 </ul>
 
-See Also:<p>
+<h2>Notes on driver variations</h2>
+
+For GRASS 5.7 Radim Blazek has moved the driver to using the GRASS
+shared libraries directly instead of using libgrass.  Currently (GDAL
+1.2.2 and later) both version of the driver are available and can be
+configured using "--with-libgrass" for the libgrass variant
+or "--with-grass=<dir>" for the new GRASS 5.7+ library
+based version. The GRASS 5.7+ driver version is currently not
+supporting coordinate system access, though it is hoped that will be
+corrected at some point.
+
+<h2>See Also</h2>
 
 <ul>
-<li> <a href="http://grass.itc.it/">GRASS GIS Home Page</a>
+<li> <a href="http://grass.osgeo.org">GRASS GIS home page</a>
 <li> <a href="http://home.gdal.org/projects/grass/">libgrass page</a>
 </ul>
 
-<hr>
-<h2>NOTES on driver variations</h2>
-
-For GRASS 5.7 Radim Blazek has moved the driver to using the GRASS
-shared libraries directly instead of using libgrass.  Currently (GDAL 1.2.2 and later)
-both version of the driver are available and can be configured using
-"--with-libgrass" for the libgrass variant or "--with-grass=<dir>" for the 
-new GRASS 5.7 library based version.  The GRASS 5.7 driver version is currently
-not supporting coordinate system access, though it is hoped that will be
-corrected at some point.<p>
-
 </body>
 </html>
diff --git a/frmts/grass/grass57dataset.cpp b/frmts/grass/grass57dataset.cpp
index a2a3dbf..06a142f 100644
--- a/frmts/grass/grass57dataset.cpp
+++ b/frmts/grass/grass57dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grass57dataset.cpp 20157 2010-07-28 19:32:04Z rouault $
+ * $Id: grass57dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000 Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -45,9 +46,15 @@ extern "C" {
 #include <grass/gprojects.h>
 #include <grass/gis.h>
 
-char *GPJ_grass_to_wkt(struct Key_Value *proj_info,
-		       struct Key_Value *proj_units,
-		       int esri_style, int prettify);
+#if GRASS_VERSION_MAJOR  >= 7
+char *GPJ_grass_to_wkt(const struct Key_Value *,
+		       const struct Key_Value *,
+		       int, int);
+#else
+char *GPJ_grass_to_wkt(struct Key_Value *,
+		       struct Key_Value *,
+		       int, int);
+#endif
 }
 
 #include "gdal_priv.h"
@@ -56,7 +63,7 @@ char *GPJ_grass_to_wkt(struct Key_Value *proj_info,
 
 #define GRASS_MAX_COLORS 100000  // what is the right value
 
-CPL_CVSID("$Id: grass57dataset.cpp 20157 2010-07-28 19:32:04Z rouault $");
+CPL_CVSID("$Id: grass57dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GRASS(void);
diff --git a/frmts/grass/grassdataset.cpp b/frmts/grass/grassdataset.cpp
index 34baa6d..95e9d1f 100644
--- a/frmts/grass/grassdataset.cpp
+++ b/frmts/grass/grassdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grassdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: grassdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: grassdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: grassdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GRASS(void);
diff --git a/frmts/grib/degrib18/degrib/myutil.c b/frmts/grib/degrib18/degrib/myutil.c
index a9f20a4..394c0ea 100644
--- a/frmts/grib/degrib18/degrib/myutil.c
+++ b/frmts/grib/degrib18/degrib/myutil.c
@@ -10,6 +10,9 @@
  * NOTES
  *****************************************************************************
  */
+
+/* For S_IFDIR */
+#define _XOPEN_SOURCE 500
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
diff --git a/frmts/grib/gribdataset.cpp b/frmts/grib/gribdataset.cpp
index 0c15592..d2d3871 100644
--- a/frmts/grib/gribdataset.cpp
+++ b/frmts/grib/gribdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gribdataset.cpp 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: gribdataset.cpp 27116 2014-04-02 19:29:50Z rouault $
  *
  * Project:  GRIB Driver
  * Purpose:  GDALDataset driver for GRIB translator for read support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, ITC
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,7 +41,7 @@
 
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gribdataset.cpp 25627 2013-02-10 10:17:19Z rouault $");
+CPL_CVSID("$Id: gribdataset.cpp 27116 2014-04-02 19:29:50Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GRIB(void);
@@ -121,6 +122,21 @@ private:
     int      nGribDataYSize;
 };
 
+/************************************************************************/
+/*                         ConvertUnitInText()                          */
+/************************************************************************/
+
+static CPLString ConvertUnitInText(int bMetricUnits, const char* pszTxt)
+{
+    if( !bMetricUnits )
+        return pszTxt;
+
+    CPLString osRes(pszTxt);
+    size_t iPos = osRes.find("[K]");
+    if( iPos != std::string::npos )
+        osRes = osRes.substr(0, iPos) + "[C]" + osRes.substr(iPos + 3);
+    return osRes;
+}
 
 /************************************************************************/
 /*                           GRIBRasterBand()                            */
@@ -144,8 +160,11 @@ GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDS, int nBand,
     nGribDataXSize = poDS->nRasterXSize;
     nGribDataYSize = poDS->nRasterYSize;
 
-    SetMetadataItem( "GRIB_UNIT", psInv->unitName );
-    SetMetadataItem( "GRIB_COMMENT", psInv->comment );
+    const char* pszGribNormalizeUnits = CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
+    int bMetricUnits = CSLTestBoolean(pszGribNormalizeUnits);
+
+    SetMetadataItem( "GRIB_UNIT", ConvertUnitInText(bMetricUnits, psInv->unitName) );
+    SetMetadataItem( "GRIB_COMMENT", ConvertUnitInText(bMetricUnits, psInv->comment) );
     SetMetadataItem( "GRIB_ELEMENT", psInv->element );
     SetMetadataItem( "GRIB_SHORT_NAME", psInv->shortFstLevel );
     SetMetadataItem( "GRIB_REF_TIME", 
@@ -415,8 +434,8 @@ void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum, do
 
     IS_Init (&is);
 
-    const char* pszGribNormalizeUnits = CPLGetConfigOption("GRIB_NORMALIZE_UNITS", NULL);
-    if ( pszGribNormalizeUnits != NULL && ( STRCASECMP(pszGribNormalizeUnits,"NO")==0 ) )
+    const char* pszGribNormalizeUnits = CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
+    if ( !CSLTestBoolean(pszGribNormalizeUnits) )
         f_unit = 0; /* do not normalize units to metric */
 
     /* Read GRIB message from file position "start". */
diff --git a/frmts/gsg/gs7bgdataset.cpp b/frmts/gsg/gs7bgdataset.cpp
index 00be63b..08fb04f 100644
--- a/frmts/gsg/gs7bgdataset.cpp
+++ b/frmts/gsg/gs7bgdataset.cpp
@@ -1,5 +1,5 @@
 /****************************************************************************
- * $Id: gs7bgdataset.cpp 24584 2012-06-16 10:24:03Z rouault $
+ * $Id: gs7bgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Surfer 7 Binary Grid Format.
@@ -9,6 +9,7 @@
  *
  ****************************************************************************
  * Copyright (c) 2007, Adam Guernsey <adam at ctech.com>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -60,7 +61,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gs7bgdataset.cpp 24584 2012-06-16 10:24:03Z rouault $");
+CPL_CVSID("$Id: gs7bgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_GS7BG(void);
diff --git a/frmts/gsg/gsagdataset.cpp b/frmts/gsg/gsagdataset.cpp
index 9c007d9..2933c9b 100644
--- a/frmts/gsg/gsagdataset.cpp
+++ b/frmts/gsg/gsagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsagdataset.cpp 25215 2012-11-08 08:25:05Z rouault $
+ * $Id: gsagdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software ASCII Grid Format.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Kevin Locke <kwl7 at cornell.edu>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,7 +50,7 @@
 # define INT_MAX 2147483647
 #endif /* INT_MAX */
 
-CPL_CVSID("$Id: gsagdataset.cpp 25215 2012-11-08 08:25:05Z rouault $");
+CPL_CVSID("$Id: gsagdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GSAG(void);
diff --git a/frmts/gsg/gsbgdataset.cpp b/frmts/gsg/gsbgdataset.cpp
index b004a30..be20cb0 100644
--- a/frmts/gsg/gsbgdataset.cpp
+++ b/frmts/gsg/gsbgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsbgdataset.cpp 24585 2012-06-16 10:27:04Z rouault $
+ * $Id: gsbgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Binary Grid Format.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Kevin Locke <kwl7 at cornell.edu>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -60,7 +61,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gsbgdataset.cpp 24585 2012-06-16 10:27:04Z rouault $");
+CPL_CVSID("$Id: gsbgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GSBG(void);
@@ -907,7 +908,7 @@ GDALDataset *GSBGDataset::Create( const char * pszFilename,
         && eType != GDT_Int16 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-		  "Golden Software ASCII Grid only supports Byte, Int16, "
+		  "Golden Software Binary Grid only supports Byte, Int16, "
 		  "Uint16, and Float32 datatypes.  Unable to create with "
 		  "type %s.\n", GDALGetDataTypeName( eType ) );
 
diff --git a/frmts/gta/gtadataset.cpp b/frmts/gta/gtadataset.cpp
index eb49a92..891842e 100644
--- a/frmts/gta/gtadataset.cpp
+++ b/frmts/gta/gtadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtadataset.cpp 23475 2011-12-05 22:44:57Z rouault $
+ * $Id: gtadataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GTA read/write Driver
  * Purpose:  GDAL bindings over GTA library.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, 2011, Martin Lambers <marlam at marlam.de>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -90,7 +91,7 @@
 #include <gta/gta.hpp>
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: gtadataset.cpp 23475 2011-12-05 22:44:57Z rouault $");
+CPL_CVSID("$Id: gtadataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_GTA(void);
@@ -853,7 +854,7 @@ CPLErr GTADataset::ReadBlock( int nBlockXOff, int nBlockYOff )
 
         try
         {
-            uintmax_t lo[2] = { nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize};
+            uintmax_t lo[2] = { (uintmax_t)nBlockXOff * nBlockXSize, (uintmax_t)nBlockYOff * nBlockYSize};
             uintmax_t hi[2] = { lo[0] + nBlockXSize - 1, lo[1] + nBlockYSize - 1 };
             oHeader.read_block( oGTAIO, DataOffset, lo, hi, pBlock );
         }
@@ -883,7 +884,7 @@ CPLErr GTADataset::WriteBlock( )
     // Write the block (nLastBlockXOff, nLastBlockYOff) stored in pBlock.
     try
     {
-        uintmax_t lo[2] = { nLastBlockXOff * nBlockXSize, nLastBlockYOff * nBlockYSize};
+        uintmax_t lo[2] = { (uintmax_t)nLastBlockXOff * nBlockXSize, (uintmax_t)nLastBlockYOff * nBlockYSize};
         uintmax_t hi[2] = { lo[0] + nBlockXSize - 1, lo[1] + nBlockYSize - 1 };
         oHeader.write_block( oGTAIO, DataOffset, lo, hi, pBlock );
     }
diff --git a/frmts/gtiff/GNUmakefile b/frmts/gtiff/GNUmakefile
index 21890d7..441632c 100644
--- a/frmts/gtiff/GNUmakefile
+++ b/frmts/gtiff/GNUmakefile
@@ -8,7 +8,7 @@ SUBLIBS 	=
 
 ifeq ($(TIFF_SETTING),internal)
 SUBLIBS	:= lib-tiff $(SUBLIBS) 
-TIFF_OPTS	:=	-Ilibtiff $(TIFF_OPTS)
+TIFF_OPTS	:=	-DINTERNAL_LIBTIFF -Ilibtiff $(TIFF_OPTS)
 ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
 TIFF_OPTS	:=	-DRENAME_INTERNAL_LIBTIFF_SYMBOLS $(TIFF_OPTS)
 endif
diff --git a/frmts/gtiff/frmt_gtiff.html b/frmts/gtiff/frmt_gtiff.html
index c326a10..45e34d7 100644
--- a/frmts/gtiff/frmt_gtiff.html
+++ b/frmts/gtiff/frmt_gtiff.html
@@ -41,8 +41,7 @@ pixel size, a transformation matrix, or a list of GCPs.</p>
 <p>If no georeferencing
 information is available in the TIFF file itself, GDAL will also check for,
 and use an ESRI <a href="frmt_various.html#WLD">world file</a> with the
-extention .tfw, .tifw/.tiffw or .wld, as well as a MapInfo .tab file (only control
-points used, Coordsys ignored).</p>
+extension .tfw, .tifw/.tiffw or .wld, as well as a MapInfo .tab file.</p>
 
 <p>GDAL can read and write the <i>RPCCoefficientTag</i> as described in the <a href="http://geotiff.maptools.org/rpc_prop.html">
 RPCs in GeoTIFF</a> proposed extension. The tag is written only for
@@ -132,6 +131,26 @@ stored as XML raw content in the xml:XMP metadata domain.</p>
 <p>Starting with GDAL 1.10, EXIF metadata can be extracted from the file, and will be
 stored the EXIF metadata domain.</p>
 
+<h2>Color Profile Metadata</h2>
+
+<p>Starting with GDAL 1.11, GDAL can deal with the following color profile metadata in the COLOR_PROFILE domain:</p>
+<ul>
+<li>SOURCE_ICC_PROFILE (Base64 encoded ICC profile embedded in file. If available, other tags are ignored.)</li>
+<li>SOURCE_PRIMARIES_RED (xyY in "x,y,1" format for red primary.)</li>
+<li>SOURCE_PRIMARIES_GREEN (xyY in "x,y,1" format for green primary)</li>
+<li>SOURCE_PRIMARIES_BLUE (xyY in "x,y,1" format for blue primary)</li>
+<li>SOURCE_WHITEPOINT (xyY in "x,y,1" format for whitepoint)</li>
+<li>TIFFTAG_TRANSFERFUNCTION_RED (Red table of TIFFTAG_TRANSFERFUNCTION)</li>
+<li>TIFFTAG_TRANSFERFUNCTION_GREEN (Green table of TIFFTAG_TRANSFERFUNCTION)</li>
+<li>TIFFTAG_TRANSFERFUNCTION_BLUE (Blue table of TIFFTAG_TRANSFERFUNCTION)</li>
+<li>TIFFTAG_TRANSFERRANGE_BLACK (Min range of TIFFTAG_TRANSFERRANGE)</li>
+<li>TIFFTAG_TRANSFERRANGE_WHITE (Max range of TIFFTAG_TRANSFERRANGE)</li>
+</ul>
+
+<p>Note that these metadata properties can only be used on the original raw pixel data. If automatic conversion to RGB has been done, the color profile information cannot be used.</p>
+
+<p>All these metadata tags can be overriden and/or used as creation options.</p>
+
 <h2>Nodata value</h2>
 
 <p>GDAL stores band nodata value in the non standard TIFFTAG_GDAL_NODATA ASCII tag (code 42113) for
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index fb325ff..e7eafa5 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 25974 2013-05-03 04:05:55Z rcoup $
+ * $Id: geotiff.cpp 27107 2014-03-28 20:22:20Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -53,8 +54,17 @@
 #include "cpl_multiproc.h"
 #include "cplkeywordparser.h"
 #include "gt_jpeg_copy.h"
+#include <set>
 
-CPL_CVSID("$Id: geotiff.cpp 25974 2013-05-03 04:05:55Z rcoup $");
+#ifdef INTERNAL_LIBTIFF
+#include "tiffiop.h"
+#endif
+
+CPL_CVSID("$Id: geotiff.cpp 27107 2014-03-28 20:22:20Z rouault $");
+
+#if SIZEOF_VOIDP == 4
+static int bGlobalStripIntegerOverflow = FALSE;
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -298,6 +308,7 @@ class GTiffDataset : public GDALPamDataset
     double      dfNoDataValue;
 
     int	        bMetadataChanged;
+    int         bColorProfileMetadataChanged;
 
     int         bNeedsRewrite;
 
@@ -355,6 +366,9 @@ class GTiffDataset : public GDALPamDataset
     int           bEXIFMetadataLoaded;
     void          LoadEXIFMetadata();
 
+    int           bICCMetadataLoaded;
+    void          LoadICCProfile();
+
     int           bHasWarnedDisableAggressiveBandCaching;
 
     int           bDontReloadFirstBlock; /* Hack for libtiff 3.X and #3633 */
@@ -377,9 +391,14 @@ class GTiffDataset : public GDALPamDataset
 
     int           bIgnoreReadErrors;
 
-    CPLString     osWldFilename;
+    CPLString     osGeorefFilename;
 
     int           bDirectIO;
+    
+    int           nSetPhotometricFromBandColorInterp;
+
+    CPLVirtualMem *pBaseMapping;
+    int            nRefBaseMapping;
 
   protected:
     virtual int         CloseDependentDatasets();
@@ -421,6 +440,7 @@ class GTiffDataset : public GDALPamDataset
                                     void * pProgressData );
     virtual void    FlushCache( void );
 
+    virtual char      **GetMetadataDomainList();
     virtual CPLErr  SetMetadata( char **, const char * = "" );
     virtual char  **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr  SetMetadataItem( const char*, const char*, 
@@ -443,6 +463,8 @@ class GTiffDataset : public GDALPamDataset
                               char **papszParmList );
 
     CPLErr   WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data, int bPreserveDataBuffer);
+
+    static void SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszParmList, uint32 nBitsPerSample);
 };
 
 /************************************************************************/
@@ -489,6 +511,12 @@ class GTiffRasterBand : public GDALPamRasterBand
                                   GDALDataType eBufType,
                                   int nPixelSpace, int nLineSpace );
 
+    std::set<GTiffRasterBand **> aSetPSelf;
+    static void     DropReferenceVirtualMem(void* pUserData);
+    CPLVirtualMem * GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
+                                               int *pnPixelSpace,
+                                               GIntBig *pnLineSpace,
+                                               char **papszOptions );
 protected:
     GTiffDataset       *poGDS;
     GDALMultiDomainMetadata oGTiffMDMD;
@@ -501,6 +529,7 @@ protected:
 
 public:
                    GTiffRasterBand( GTiffDataset *, int );
+                  ~GTiffRasterBand();
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
@@ -528,6 +557,7 @@ public:
     virtual CPLErr SetUnitType( const char *pszNewValue );
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
 
+    virtual char      **GetMetadataDomainList();
     virtual CPLErr  SetMetadata( char **, const char * = "" );
     virtual char  **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr  SetMetadataItem( const char*, const char*, 
@@ -540,6 +570,11 @@ public:
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
     virtual CPLErr          CreateMaskBand( int nFlags );
+
+    virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                               int *pnPixelSpace,
+                                               GIntBig *pnLineSpace,
+                                               char **papszOptions );
 };
 
 /************************************************************************/
@@ -688,6 +723,24 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
 }
 
 /************************************************************************/
+/*                          ~GTiffRasterBand()                          */
+/************************************************************************/
+
+GTiffRasterBand::~GTiffRasterBand()
+{
+    /* So that any future DropReferenceVirtualMem() will not try to access the */
+    /* raster band object, but this wouldn't conform the advertized contract */
+    if( aSetPSelf.size() != 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Virtual memory objects still exist at GTiffRasterBand destruction");
+        std::set<GTiffRasterBand**>::iterator oIter = aSetPSelf.begin();
+        for(; oIter != aSetPSelf.end(); ++oIter )
+            *(*oIter) = NULL;
+    }
+}
+
+/************************************************************************/
 /*                           DirectIO()                                 */
 /************************************************************************/
 
@@ -873,6 +926,289 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
+/*                           GetVirtualMemAuto()                        */
+/************************************************************************/
+
+CPLVirtualMem* GTiffRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                                  int *pnPixelSpace,
+                                                  GIntBig *pnLineSpace,
+                                                  char **papszOptions )
+{
+    CPLVirtualMem* psRet;
+
+    if( !CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
+    {
+        psRet = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
+                                        papszOptions);
+        if( psRet != NULL )
+        {
+            CPLDebug("GTiff", "GetVirtualMemAuto(): Using memory file mapping");
+            return psRet;
+        }
+    }
+
+    CPLDebug("GTiff", "GetVirtualMemAuto(): Defaulting to base implementation");
+    return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                             pnLineSpace, papszOptions);
+}
+
+/************************************************************************/
+/*                     DropReferenceVirtualMem()                        */
+/************************************************************************/
+
+void GTiffRasterBand::DropReferenceVirtualMem(void* pUserData)
+{
+    /* This function may also be called when the dataset and rasterband */
+    /* objects have been destroyed */
+    /* If they are still alive, it updates the reference counter of the */
+    /* base mapping to invalidate the pointer to it if needed */
+
+    GTiffRasterBand** ppoSelf = (GTiffRasterBand**) pUserData;
+    GTiffRasterBand* poSelf = *ppoSelf;
+    if( poSelf != NULL )
+    {
+        if( --(poSelf->poGDS->nRefBaseMapping) == 0 )
+        {
+            poSelf->poGDS->pBaseMapping = NULL;
+        }
+        poSelf->aSetPSelf.erase(ppoSelf);
+    }
+    CPLFree(pUserData);
+}
+
+/************************************************************************/
+/*                     GetVirtualMemAutoInternal()                      */
+/************************************************************************/
+
+CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
+                                                           int *pnPixelSpace,
+                                                           GIntBig *pnLineSpace,
+                                                           char **papszOptions )
+{
+    int nLineSize = nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8);
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+        nLineSize *= poGDS->nBands;
+
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+    {
+        /* In case of a pixel interleaved file, we save virtual memory space */
+        /* by reusing a base mapping that embraces the whole imagery */
+        if( poGDS->pBaseMapping != NULL )
+        {
+            /* Offset between the base mapping and the requested mapping */
+            vsi_l_offset nOffset = (vsi_l_offset)(nBand - 1) * GDALGetDataTypeSize(eDataType) / 8;
+
+            GTiffRasterBand** ppoSelf = (GTiffRasterBand** )CPLCalloc(1, sizeof(GTiffRasterBand*));
+            *ppoSelf = this;
+
+            CPLVirtualMem* pVMem = CPLVirtualMemDerivedNew(
+                    poGDS->pBaseMapping,
+                    nOffset,
+                    CPLVirtualMemGetSize(poGDS->pBaseMapping) - nOffset,
+                    GTiffRasterBand::DropReferenceVirtualMem,
+                    ppoSelf);
+            if( pVMem == NULL )
+            {
+                CPLFree(ppoSelf);
+                return NULL;
+            }
+
+            /* Mechanism used so that the memory mapping object can be */
+            /* destroyed after the raster band */
+            aSetPSelf.insert(ppoSelf);
+            poGDS->nRefBaseMapping ++;
+            *pnPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
+            if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+                *pnPixelSpace *= poGDS->nBands;
+            *pnLineSpace = nLineSize;
+            return pVMem;
+        }
+    }
+
+    VSILFILE* fp = (VSILFILE*) TIFFClientdata( poGDS->hTIFF );
+
+    vsi_l_offset nLength = (vsi_l_offset)nRasterYSize * nLineSize;
+
+    if( !(CPLIsVirtualMemFileMapAvailable() &&
+          VSIFGetNativeFileDescriptorL(fp) != NULL &&
+          nLength == (size_t)nLength &&
+          poGDS->nCompression == COMPRESSION_NONE &&
+          (poGDS->nBitsPerSample == 8 || poGDS->nBitsPerSample == 16 ||
+           poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
+          poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
+          !TIFFIsTiled( poGDS->hTIFF ) && !TIFFIsByteSwapped(poGDS->hTIFF)) )
+    {
+        return NULL;
+    }
+
+    if (!poGDS->SetDirectory())
+        return NULL;
+
+    /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
+    if (poGDS->GetAccess() == GA_Update)
+        poGDS->FlushCache();
+
+    /* Get strip offsets */
+    toff_t *panTIFFOffsets = NULL;
+    if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
+         panTIFFOffsets == NULL )
+    {
+        return NULL;
+    }
+
+    int nBlockSize =
+        nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eDataType) / 8;
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+        nBlockSize *= poGDS->nBands;
+
+    int nBlocks = poGDS->nBlocksPerBand;
+    if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
+        nBlocks *= poGDS->nBands;
+    int i;
+    for(i = 0; i < nBlocks; i ++)
+    {
+        if( panTIFFOffsets[i] != 0 )
+            break;
+    }
+    if( i == nBlocks )
+    {
+        /* All zeroes */
+        if( poGDS->eAccess == GA_Update )
+        {
+            /* Initialize the file with empty blocks so that the file has */
+            /* the appropriate size */
+
+            toff_t* panByteCounts = NULL;
+            if( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ||
+                panByteCounts == NULL )
+            {
+                return NULL;
+            }
+            VSIFSeekL(fp, 0, SEEK_END);
+            vsi_l_offset nBaseOffset = VSIFTellL(fp);
+
+            /* Just write one tile with libtiff to put it in appropriate state */
+            GByte* pabyData = (GByte*)VSICalloc(1, nBlockSize);
+            if( pabyData == NULL )
+            {
+                return NULL;
+            }
+            int ret = TIFFWriteEncodedStrip(poGDS->hTIFF, 0, pabyData, nBlockSize);
+            VSIFree(pabyData);
+            if( ret != nBlockSize )
+            {
+                return NULL;
+            }
+            CPLAssert(panTIFFOffsets[0] == nBaseOffset);
+            CPLAssert(panByteCounts[0] == (toff_t)nBlockSize);
+
+            /* Now simulate the writing of other blocks */
+            vsi_l_offset nDataSize = (vsi_l_offset)nBlockSize * nBlocks;
+            VSIFSeekL(fp, nBaseOffset + nDataSize - 1, SEEK_SET);
+            char ch = 0;
+            if( VSIFWriteL(&ch, 1, 1, fp) != 1 )
+            {
+                return NULL;
+            }
+
+            for(i = 1; i < nBlocks; i ++)
+            {
+                panTIFFOffsets[i] = nBaseOffset + i * (toff_t)nBlockSize;
+                panByteCounts[i] = nBlockSize;
+            }
+        }
+        else
+        {
+            CPLDebug("GTiff", "Sparse files not supported in file mapping");
+            return NULL;
+        }
+    }
+
+    GIntBig nBlockSpacing = 0;
+    int bCompatibleSpacing = TRUE;
+    toff_t nPrevOffset = 0;
+    for(i = 0; i < poGDS->nBlocksPerBand; i ++)
+    {
+        toff_t nCurOffset;
+        if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
+            nCurOffset = panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1) + i];
+        else
+            nCurOffset = panTIFFOffsets[i];
+        if( nCurOffset == 0 )
+        {
+            bCompatibleSpacing = FALSE;
+            break;
+        }
+        if( i > 0 )
+        {
+            GIntBig nCurSpacing = nCurOffset - nPrevOffset;
+            if( i == 1 )
+            {
+                if( nCurSpacing != (GIntBig)nBlockYSize * nLineSize )
+                {
+                    bCompatibleSpacing = FALSE;
+                    break;
+                }
+                nBlockSpacing = nCurSpacing;
+            }
+            else if( nBlockSpacing != nCurSpacing )
+            {
+                bCompatibleSpacing = FALSE;
+                break;
+            }
+        }
+        nPrevOffset = nCurOffset;
+    }
+
+    if( !bCompatibleSpacing )
+    {
+        return NULL;
+    }
+    else
+    {
+        vsi_l_offset nOffset;
+        if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+        {
+            CPLAssert( poGDS->pBaseMapping == NULL );
+            nOffset = panTIFFOffsets[0];
+        }
+        else
+            nOffset = panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1)];
+        CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
+            fp, nOffset, nLength,
+            (eRWFlag == GF_Write) ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
+            NULL, NULL);
+        if( pVMem == NULL )
+        {
+            return NULL;
+        }
+        else
+        {
+            if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+            {
+                poGDS->pBaseMapping = pVMem;
+                pVMem = GetVirtualMemAutoInternal( eRWFlag,
+                                                   pnPixelSpace,
+                                                   pnLineSpace,
+                                                   papszOptions );
+                /* drop ref on base mapping */
+                CPLVirtualMemFree(poGDS->pBaseMapping);
+                if( pVMem == NULL )
+                    poGDS->pBaseMapping = NULL;
+            }
+            else
+            {
+                *pnPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
+                if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+                    *pnPixelSpace *= poGDS->nBands;
+                *pnLineSpace = nLineSize;
+            }
+            return pVMem;
+        }
+    }
+}
+
+/************************************************************************/
 /*                            IRasterIO()                               */
 /************************************************************************/
 
@@ -1489,6 +1825,15 @@ CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GTiffRasterBand::GetMetadataDomainList()
+{
+    return CSLDuplicate(oGTiffMDMD.GetDomainList());
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -1583,9 +1928,15 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
 {
     if( eInterp == eBandInterp )
         return CE_None;
-    
+
+    eBandInterp = eInterp;
+
     if( poGDS->bCrystalized )
+    {
+        CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
+                 GDALGetColorInterpretationName(eInterp), nBand);
         return GDALPamRasterBand::SetColorInterpretation( eInterp );
+    }
 
     /* greyscale + alpha */
     else if( eInterp == GCI_AlphaBand 
@@ -1598,7 +1949,6 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
                                   DEFAULT_ALPHA_TYPE);
 
         TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
-        eBandInterp = eInterp;
         return CE_None;
     }
 
@@ -1613,12 +1963,64 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
                                   DEFAULT_ALPHA_TYPE);
 
         TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
-        eBandInterp = eInterp;
         return CE_None;
     }
     
     else
-        return GDALPamRasterBand::SetColorInterpretation( eInterp );
+    {
+        /* Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible */
+        if( poGDS->nCompression != COMPRESSION_JPEG &&
+            poGDS->nSetPhotometricFromBandColorInterp >= 0 &&
+            CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
+            (poGDS->nBands == 3 || poGDS->nBands == 4) &&
+            ((nBand == 1 && eInterp == GCI_RedBand) ||
+             (nBand == 2 && eInterp == GCI_GreenBand) ||
+             (nBand == 3 && eInterp == GCI_BlueBand) ||
+             (nBand == 4 && eInterp == GCI_AlphaBand)) )
+        {
+            poGDS->nSetPhotometricFromBandColorInterp ++;
+            if( poGDS->nSetPhotometricFromBandColorInterp == poGDS->nBands )
+            {
+                poGDS->nPhotometric = PHOTOMETRIC_RGB;
+                TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
+                if( poGDS->nSetPhotometricFromBandColorInterp == 4 )
+                {
+                    uint16 v[1];
+                    v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
+                                            DEFAULT_ALPHA_TYPE);
+
+                    TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
+                }
+            }
+            return CE_None;
+        }
+        else
+        {
+            if( poGDS->nPhotometric != PHOTOMETRIC_MINISBLACK &&
+                CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL )
+            {
+                poGDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
+                TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
+            }
+            if( poGDS->nSetPhotometricFromBandColorInterp > 0 )
+            {
+                for(int i=1;i<=poGDS->nBands;i++)
+                {
+                    if( i != nBand )
+                    {
+                        ((GDALPamRasterBand*)poGDS->GetRasterBand(i))->GDALPamRasterBand::SetColorInterpretation(
+                            poGDS->GetRasterBand(i)->GetColorInterpretation() );
+                        CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
+                                 GDALGetColorInterpretationName(poGDS->GetRasterBand(i)->GetColorInterpretation()), i);
+                    }
+                }
+            }
+            poGDS->nSetPhotometricFromBandColorInterp = -1;
+            CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
+                     GDALGetColorInterpretationName(eInterp), nBand);
+            return GDALPamRasterBand::SetColorInterpretation( eInterp );
+        }
+    }
 }
 
 /************************************************************************/
@@ -3042,6 +3444,7 @@ GTiffDataset::GTiffDataset()
     hTIFF = NULL;
     bNeedsRewrite = FALSE;
     bMetadataChanged = FALSE;
+    bColorProfileMetadataChanged = FALSE;
     bGeoTIFFInfoChanged = FALSE;
     bForceUnsetGT = FALSE;
     bForceUnsetProjection = FALSE;
@@ -3107,10 +3510,15 @@ GTiffDataset::GTiffDataset()
     bHasSearchedIMD = FALSE;
     bHasSearchedPVL = FALSE;
     bEXIFMetadataLoaded = FALSE;
+    bICCMetadataLoaded = FALSE;
 
     bScanDeferred = TRUE;
 
     bDirectIO = CSLTestBoolean(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
+    nSetPhotometricFromBandColorInterp = 0;
+
+    pBaseMapping = NULL;
+    nRefBaseMapping = 0;
 }
 
 /************************************************************************/
@@ -3136,6 +3544,12 @@ int GTiffDataset::Finalize()
 
     Crystalize();
 
+    if ( bColorProfileMetadataChanged )
+    {
+        SaveICCProfile(this, NULL, NULL, 0);
+        bColorProfileMetadataChanged = FALSE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Handle forcing xml:ESRI data to be written to PAM.              */
 /* -------------------------------------------------------------------- */
@@ -3720,6 +4134,78 @@ void GTiffDataset::Crystalize()
     }
 }
 
+#ifdef INTERNAL_LIBTIFF
+
+#define IO_CACHE_PAGE_SIZE      4096
+
+static
+void GTiffCacheOffsetOrCount4(VSILFILE* fp,
+                              vsi_l_offset nBaseOffset,
+                              int nBlockId,
+                              uint32 nstrips,
+                              uint64* panVals)
+{
+    uint32 val;
+    int i, iStartBefore;
+    vsi_l_offset nOffset, nOffsetStartPage, nOffsetEndPage;
+    GByte buffer[2 * IO_CACHE_PAGE_SIZE];
+
+    nOffset = nBaseOffset + sizeof(val) * nBlockId;
+    nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
+    nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
+
+    if( nOffset + sizeof(val) > nOffsetEndPage )
+        nOffsetEndPage += IO_CACHE_PAGE_SIZE;
+    VSIFSeekL(fp, nOffsetStartPage, SEEK_SET);
+    VSIFReadL(buffer, 1, nOffsetEndPage - nOffsetStartPage, fp);
+    iStartBefore = - ((nOffset - nOffsetStartPage) / sizeof(val));
+    if( nBlockId + iStartBefore < 0 )
+        iStartBefore = -nBlockId;
+    for(i=iStartBefore; (uint32)(nBlockId + i) < nstrips &&
+        (GIntBig)nOffset + (i+1) * (int)sizeof(val) <= (GIntBig)nOffsetEndPage; i++)
+    {
+        memcpy(&val,
+            buffer + (nOffset - nOffsetStartPage) + i * sizeof(val),
+            sizeof(val));
+        panVals[nBlockId + i] = val;
+    }
+}
+
+/* Same code as GTiffCacheOffsetOrCount4 except the 'val' declaration */
+static
+void GTiffCacheOffsetOrCount8(VSILFILE* fp,
+                              vsi_l_offset nBaseOffset,
+                              int nBlockId,
+                              uint32 nstrips,
+                              uint64* panVals)
+{
+    uint64 val;
+    int i, iStartBefore;
+    vsi_l_offset nOffset, nOffsetStartPage, nOffsetEndPage;
+    GByte buffer[2 * IO_CACHE_PAGE_SIZE];
+
+    nOffset = nBaseOffset + sizeof(val) * nBlockId;
+    nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
+    nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
+
+    if( nOffset + sizeof(val) > nOffsetEndPage )
+        nOffsetEndPage += IO_CACHE_PAGE_SIZE;
+    VSIFSeekL(fp, nOffsetStartPage, SEEK_SET);
+    VSIFReadL(buffer, 1, nOffsetEndPage - nOffsetStartPage, fp);
+    iStartBefore = - ((nOffset - nOffsetStartPage) / sizeof(val));
+    if( nBlockId + iStartBefore < 0 )
+        iStartBefore = -nBlockId;
+    for(i=iStartBefore; (uint32)(nBlockId + i) < nstrips &&
+        (GIntBig)nOffset + (i+1) * (int)sizeof(val) <= (GIntBig)nOffsetEndPage; i++)
+    {
+        memcpy(&val,
+            buffer + (nOffset - nOffsetStartPage) + i * sizeof(val),
+            sizeof(val));
+        panVals[nBlockId + i] = val;
+    }
+}
+
+#endif
 
 /************************************************************************/
 /*                          IsBlockAvailable()                          */
@@ -3732,6 +4218,90 @@ void GTiffDataset::Crystalize()
 int GTiffDataset::IsBlockAvailable( int nBlockId )
 
 {
+#ifdef INTERNAL_LIBTIFF
+
+    /* Optimization to avoid fetching the whole Strip/TileCounts and Strip/TileOffsets arrays */
+    if( eAccess == GA_ReadOnly &&
+        !(hTIFF->tif_flags & TIFF_SWAB) &&
+        hTIFF->tif_dir.td_nstrips > 2 &&
+        (hTIFF->tif_dir.td_stripoffset_entry.tdir_type == TIFF_LONG ||
+         hTIFF->tif_dir.td_stripoffset_entry.tdir_type == TIFF_LONG8) &&
+        (hTIFF->tif_dir.td_stripbytecount_entry.tdir_type == TIFF_LONG ||
+         hTIFF->tif_dir.td_stripbytecount_entry.tdir_type == TIFF_LONG8) &&
+        strcmp(GetDescription(), "/vsistdin/") != 0 )
+    {
+        if( hTIFF->tif_dir.td_stripoffset == NULL )
+        {
+            hTIFF->tif_dir.td_stripoffset =
+                (uint64*) _TIFFmalloc( sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
+            hTIFF->tif_dir.td_stripbytecount =
+                (uint64*) _TIFFmalloc( sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
+            if( hTIFF->tif_dir.td_stripoffset && hTIFF->tif_dir.td_stripbytecount )
+            {
+                memset(hTIFF->tif_dir.td_stripoffset, 0xFF,
+                       sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
+                memset(hTIFF->tif_dir.td_stripbytecount, 0xFF,
+                       sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
+            }
+            else
+            {
+                _TIFFfree(hTIFF->tif_dir.td_stripoffset);
+                hTIFF->tif_dir.td_stripoffset = NULL;
+                _TIFFfree(hTIFF->tif_dir.td_stripbytecount);
+                hTIFF->tif_dir.td_stripbytecount = NULL;
+            }
+        }
+        if( hTIFF->tif_dir.td_stripbytecount == NULL )
+            return FALSE;
+        if( ~(hTIFF->tif_dir.td_stripoffset[nBlockId]) == 0 ||
+            ~(hTIFF->tif_dir.td_stripbytecount[nBlockId]) == 0 )
+        {
+            VSILFILE* fp = (VSILFILE*)hTIFF->tif_clientdata;
+            vsi_l_offset nCurOffset = VSIFTellL(fp);
+            if( ~(hTIFF->tif_dir.td_stripoffset[nBlockId]) == 0 )
+            {
+                if( hTIFF->tif_dir.td_stripoffset_entry.tdir_type == TIFF_LONG )
+                {
+                    GTiffCacheOffsetOrCount4(fp,
+                                             hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long,
+                                             nBlockId,
+                                             hTIFF->tif_dir.td_nstrips,
+                                             hTIFF->tif_dir.td_stripoffset);
+                }
+                else
+                {
+                    GTiffCacheOffsetOrCount8(fp,
+                                             hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8,
+                                             nBlockId,
+                                             hTIFF->tif_dir.td_nstrips,
+                                             hTIFF->tif_dir.td_stripoffset);
+                }
+            }
+
+            if( ~(hTIFF->tif_dir.td_stripbytecount[nBlockId]) == 0 )
+            {
+                if( hTIFF->tif_dir.td_stripbytecount_entry.tdir_type == TIFF_LONG )
+                {
+                    GTiffCacheOffsetOrCount4(fp,
+                                             hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long,
+                                             nBlockId,
+                                             hTIFF->tif_dir.td_nstrips,
+                                             hTIFF->tif_dir.td_stripbytecount);
+                }
+                else
+                {
+                    GTiffCacheOffsetOrCount8(fp,
+                                             hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8,
+                                             nBlockId,
+                                             hTIFF->tif_dir.td_nstrips,
+                                             hTIFF->tif_dir.td_stripbytecount);
+                }
+            }
+            VSIFSeekL(fp, nCurOffset, SEEK_SET);
+        }
+        return hTIFF->tif_dir.td_stripbytecount[nBlockId] != 0;
+    }
+#endif
     toff_t *panByteCounts = NULL;
 
     if( ( TIFFIsTiled( hTIFF ) 
@@ -4987,6 +5557,8 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
 
         if( EQUAL(papszDomainList[iDomain], "IMAGE_STRUCTURE") )
             continue; // ignored
+        if( EQUAL(papszDomainList[iDomain], "COLOR_PROFILE") )
+            continue; // ignored
         if( EQUAL(papszDomainList[iDomain], "RPC") )
             continue; // handled elsewhere
         if( EQUAL(papszDomainList[iDomain], "xml:ESRI") 
@@ -5290,7 +5862,8 @@ void GTiffDataset::PushMetadataToPam()
             if( EQUAL(papszDomainList[iDomain],"RPC")
                 || EQUAL(papszDomainList[iDomain],"IMD") 
                 || EQUAL(papszDomainList[iDomain],"_temporary_")
-                || EQUAL(papszDomainList[iDomain],"IMAGE_STRUCTURE") )
+                || EQUAL(papszDomainList[iDomain],"IMAGE_STRUCTURE")
+                || EQUAL(papszDomainList[iDomain],"COLOR_PROFILE") )
                 continue;
 
             papszMD = CSLDuplicate(papszMD);
@@ -5376,9 +5949,9 @@ void GTiffDataset::ReadRPCTag()
 
 {
     double *padfRPCTag;
-    char **papszMD = NULL;
     CPLString osField;
     CPLString osMultiField;
+    CPLStringList asMD;
     int i;
     uint16 nCount;
 
@@ -5386,35 +5959,16 @@ void GTiffDataset::ReadRPCTag()
         || nCount != 92 )
         return;
 
-    osField.Printf( "%.15g", padfRPCTag[2] );
-    papszMD = CSLSetNameValue( papszMD, "LINE_OFF", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[3] );
-    papszMD = CSLSetNameValue( papszMD, "SAMP_OFF", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[4] );
-    papszMD = CSLSetNameValue( papszMD, "LAT_OFF", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[5] );
-    papszMD = CSLSetNameValue( papszMD, "LONG_OFF", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[6] );
-    papszMD = CSLSetNameValue( papszMD, "HEIGHT_OFF", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[7] );
-    papszMD = CSLSetNameValue( papszMD, "LINE_SCALE", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[8] );
-    papszMD = CSLSetNameValue( papszMD, "SAMP_SCALE", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[9] );
-    papszMD = CSLSetNameValue( papszMD, "LAT_SCALE", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[10] );
-    papszMD = CSLSetNameValue( papszMD, "LONG_SCALE", osField );
-
-    osField.Printf( "%.15g", padfRPCTag[11] );
-    papszMD = CSLSetNameValue( papszMD, "HEIGHT_SCALE", osField );
+    asMD.SetNameValue("LINE_OFF", CPLOPrintf("%.15g", padfRPCTag[2]));
+    asMD.SetNameValue("SAMP_OFF", CPLOPrintf("%.15g", padfRPCTag[3]));
+    asMD.SetNameValue("LAT_OFF", CPLOPrintf("%.15g", padfRPCTag[4]));
+    asMD.SetNameValue("LONG_OFF", CPLOPrintf("%.15g", padfRPCTag[5]));
+    asMD.SetNameValue("HEIGHT_OFF", CPLOPrintf("%.15g", padfRPCTag[6]));
+    asMD.SetNameValue("LINE_SCALE", CPLOPrintf("%.15g", padfRPCTag[7]));
+    asMD.SetNameValue("SAMP_SCALE", CPLOPrintf("%.15g", padfRPCTag[8]));
+    asMD.SetNameValue("LAT_SCALE", CPLOPrintf("%.15g", padfRPCTag[9]));
+    asMD.SetNameValue("LONG_SCALE", CPLOPrintf("%.15g", padfRPCTag[10]));
+    asMD.SetNameValue("HEIGHT_SCALE", CPLOPrintf("%.15g", padfRPCTag[11]));
 
     for( i = 0; i < 20; i++ )
     {
@@ -5425,7 +5979,7 @@ void GTiffDataset::ReadRPCTag()
             osMultiField = "";
         osMultiField += osField;
     }
-    papszMD = CSLSetNameValue( papszMD, "LINE_NUM_COEFF", osMultiField );
+    asMD.SetNameValue("LINE_NUM_COEFF", osMultiField );
 
     for( i = 0; i < 20; i++ )
     {
@@ -5436,7 +5990,7 @@ void GTiffDataset::ReadRPCTag()
             osMultiField = "";
         osMultiField += osField;
     }
-    papszMD = CSLSetNameValue( papszMD, "LINE_DEN_COEFF", osMultiField );
+    asMD.SetNameValue( "LINE_DEN_COEFF", osMultiField );
 
     for( i = 0; i < 20; i++ )
     {
@@ -5447,7 +6001,7 @@ void GTiffDataset::ReadRPCTag()
             osMultiField = "";
         osMultiField += osField;
     }
-    papszMD = CSLSetNameValue( papszMD, "SAMP_NUM_COEFF", osMultiField );
+    asMD.SetNameValue( "SAMP_NUM_COEFF", osMultiField );
 
     for( i = 0; i < 20; i++ )
     {
@@ -5458,10 +6012,9 @@ void GTiffDataset::ReadRPCTag()
             osMultiField = "";
         osMultiField += osField;
     }
-    papszMD = CSLSetNameValue( papszMD, "SAMP_DEN_COEFF", osMultiField );
+    asMD.SetNameValue( "SAMP_DEN_COEFF", osMultiField );
 
-    oGTiffMDMD.SetMetadata( papszMD, "RPC" );
-    CSLDestroy( papszMD );
+    oGTiffMDMD.SetMetadata( asMD, "RPC" );
 }
 
 /************************************************************************/
@@ -5651,8 +6204,32 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* Disable strip chop for now */
     hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "rc" : "r+c" );
+#if SIZEOF_VOIDP == 4
+    if( hTIFF == NULL )
+    {
+        /* Case of one-strip file where the strip size is > 2GB (#5403) */
+        if( bGlobalStripIntegerOverflow )
+        {
+            hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "r" : "r+" );
+            bGlobalStripIntegerOverflow = FALSE;
+            if( hTIFF == NULL )
+            {
+                return( NULL );
+            }
+        }
+        else
+        {
+            return( NULL );
+        }
+    }
+    else
+    {
+        bGlobalStripIntegerOverflow = FALSE;
+    }
+#else
     if( hTIFF == NULL )
         return( NULL );
+#endif
 
     uint32  nXSize, nYSize;
     uint16  nPlanarConfig;
@@ -5765,8 +6342,13 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
             if (pszUnitType)
                 poBand->osUnitType = pszUnitType;
         }
+
+        GDALColorInterp ePAMColorInterp = poBand->GDALPamRasterBand::GetColorInterpretation();
+        if( ePAMColorInterp != GCI_Undefined )
+            poBand->eBandInterp = ePAMColorInterp;
     }
 
+    poDS->bColorProfileMetadataChanged = FALSE;
     poDS->bMetadataChanged = FALSE;
     poDS->bGeoTIFFInfoChanged = FALSE;
     poDS->bForceUnsetGT = FALSE;
@@ -6171,6 +6753,377 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
+/*                   ConvertTransferFunctionToString()                  */
+/*                                                                      */
+/*      Convert a transfer function table into a string.                */
+/*      Used by LoadICCProfile().                                       */
+/************************************************************************/
+static CPLString ConvertTransferFunctionToString( const uint16 *pTable, uint32 nTableEntries )
+{
+    CPLString sValue;
+
+    for(uint32 i = 0; i < nTableEntries; i++)
+    {
+        if (i == 0)
+            sValue = sValue.Printf("%d", (uint32)pTable[i]);
+        else
+        sValue = sValue.Printf("%s, %d", (const char*)sValue, (uint32)pTable[i]);
+    }
+
+    return sValue;
+}
+
+/************************************************************************/
+/*                             LoadICCProfile()                         */
+/*                                                                      */
+/*      Load ICC Profile or colorimetric data into metadata             */
+/************************************************************************/
+
+void GTiffDataset::LoadICCProfile()
+{
+    uint32 nEmbedLen;
+    uint8* pEmbedBuffer;
+    float* pCHR;
+    float* pWP;
+    uint16 *pTFR, *pTFG, *pTFB;
+    uint16 *pTransferRange = NULL;
+    const int TIFFTAG_TRANSFERRANGE = 0x0156;
+
+    if (bICCMetadataLoaded)
+        return;
+    bICCMetadataLoaded = TRUE;
+
+    if (!SetDirectory())
+        return;
+
+    if (TIFFGetField(hTIFF, TIFFTAG_ICCPROFILE, &nEmbedLen, &pEmbedBuffer)) 
+    {
+        char *pszBase64Profile = CPLBase64Encode(nEmbedLen, (const GByte*)pEmbedBuffer);
+
+        oGTiffMDMD.SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
+
+        CPLFree(pszBase64Profile);
+
+        return;
+    }
+
+    /* Check for colorimetric tiff */
+    if (TIFFGetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, &pCHR)) 
+    {
+        if (TIFFGetField(hTIFF, TIFFTAG_WHITEPOINT, &pWP)) 
+        {
+            if (!TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERFUNCTION, &pTFR, &pTFG, &pTFB))
+                return;
+
+            TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERRANGE, &pTransferRange);
+
+            // Set all the colorimetric metadata.
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_RED", 
+                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[0], (double)pCHR[1] ) , "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_GREEN", 
+                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[2], (double)pCHR[3] ) , "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_BLUE", 
+                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[4], (double)pCHR[5] ) , "COLOR_PROFILE" );
+
+            oGTiffMDMD.SetMetadataItem( "SOURCE_WHITEPOINT", 
+                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pWP[0], (double)pWP[1] ) , "COLOR_PROFILE" );
+
+            /* Set transfer function metadata */
+
+            /* Get length of table. */
+            const uint32 nTransferFunctionLength = 1 << nBitsPerSample;
+
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_RED", 
+                ConvertTransferFunctionToString( pTFR, nTransferFunctionLength), "COLOR_PROFILE" );
+
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_GREEN", 
+                ConvertTransferFunctionToString( pTFG, nTransferFunctionLength), "COLOR_PROFILE" );
+
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_BLUE", 
+                ConvertTransferFunctionToString( pTFB, nTransferFunctionLength), "COLOR_PROFILE" );
+
+            /* Set transfer range */
+            if (pTransferRange)
+            {
+                oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_BLACK",
+                    CPLString().Printf( "%d, %d, %d", 
+                        (int)pTransferRange[0], (int)pTransferRange[2], (int)pTransferRange[4]), "COLOR_PROFILE" );
+                oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_WHITE",
+                    CPLString().Printf( "%d, %d, %d", 
+                        (int)pTransferRange[1], (int)pTransferRange[3], (int)pTransferRange[5]), "COLOR_PROFILE" );
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                             SaveICCProfile()                         */
+/*                                                                      */
+/*      Save ICC Profile or colorimetric data into file                 */
+/* pDS:                                                                 */
+/*      Dataset that contains the metadata with the ICC or colorimetric */ 
+/*      data. If this argument is specified, all other arguments are    */
+/*      ignored. Set them to NULL or 0.                                 */
+/* hTIFF:                                                               */
+/*      Pointer to TIFF handle. Only needed if pDS is NULL or           */
+/*      pDS->hTIFF is NULL.                                             */
+/* papszParmList:                                                       */
+/*      Options containing the ICC profile or colorimetric metadata.    */
+/*      Ignored if pDS is not NULL.                                     */
+/* nBitsPerSample:                                                      */
+/*      Bits per sample. Ignored if pDS is not NULL.                    */
+/************************************************************************/
+
+void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszParmList, uint32 nBitsPerSample)
+{
+    if ((pDS != NULL) && (pDS->eAccess != GA_Update))
+        return;
+
+    if (hTIFF == NULL)
+    {
+        if (pDS == NULL)
+            return;
+
+        hTIFF = pDS->hTIFF;
+        if (hTIFF == NULL)
+            return;
+    }
+
+    if ((papszParmList == NULL) && (pDS == NULL))
+        return;
+
+    const char *pszValue = NULL;
+    if (pDS != NULL)
+        pszValue = pDS->GetMetadataItem("SOURCE_ICC_PROFILE", "COLOR_PROFILE");
+    else
+        pszValue = CSLFetchNameValue(papszParmList, "SOURCE_ICC_PROFILE");
+    if( pszValue != NULL )
+    {
+        int32 nEmbedLen;
+        char *pEmbedBuffer = CPLStrdup(pszValue);
+        nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+
+        TIFFSetField(hTIFF, TIFFTAG_ICCPROFILE, nEmbedLen, pEmbedBuffer);
+
+        CPLFree(pEmbedBuffer);        
+    }
+    else
+    {
+        /* Output colorimetric data. */
+        const int TIFFTAG_TRANSFERRANGE = 0x0156;
+
+        float pCHR[6]; // Primaries
+        float pWP[2];  // Whitepoint
+        uint16 pTXR[6]; // Transfer range
+        const char* pszCHRNames[] = {
+            "SOURCE_PRIMARIES_RED",
+            "SOURCE_PRIMARIES_GREEN",
+            "SOURCE_PRIMARIES_BLUE"
+        };
+        const char* pszTXRNames[] = {
+            "TIFFTAG_TRANSFERRANGE_BLACK",
+            "TIFFTAG_TRANSFERRANGE_WHITE"
+        };
+
+        /* Output chromacities */
+        bool bOutputCHR = true;
+        for(int i = 0; ((i < 3) && bOutputCHR); i++)
+        {
+            if (pDS != NULL)
+                pszValue = pDS->GetMetadataItem(pszCHRNames[i], "COLOR_PROFILE");
+            else
+                pszValue = CSLFetchNameValue(papszParmList, pszCHRNames[i]);
+            if (pszValue == NULL)
+            {
+                bOutputCHR = false;
+                break;
+            }
+
+            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+
+            if (CSLCount( papszTokens ) != 3)
+            {
+                bOutputCHR = false;
+                CSLDestroy( papszTokens );
+                break;
+            }
+
+            int j;
+            for( j = 0; j < 3; j++ )
+            {
+                float v = (float)atof(papszTokens[j]);
+
+                if (j == 2)
+                {
+                    /* Last term of xyY color must be 1.0 */
+                    if (v != 1.0)
+                    {
+                        bOutputCHR = false;
+                        break;
+                    }
+                }
+                else
+                {
+                    pCHR[i * 2 + j] = v;
+                }
+            }
+
+            CSLDestroy( papszTokens );
+        }
+        
+        if (bOutputCHR)
+        {
+            TIFFSetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, pCHR);
+        }
+
+        /* Output whitepoint */
+        bool bOutputWhitepoint = true;
+        if (pDS != NULL)
+            pszValue = pDS->GetMetadataItem("SOURCE_WHITEPOINT", "COLOR_PROFILE");
+        else
+            pszValue = CSLFetchNameValue(papszParmList, "SOURCE_WHITEPOINT");
+        if (pszValue != NULL)
+        {
+            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+
+            if (CSLCount( papszTokens ) != 3)
+            {
+                bOutputWhitepoint = false;
+            }
+            else
+            {
+                int j;
+                for( j = 0; j < 3; j++ )
+                {
+                    float v = (float)atof(papszTokens[j]);
+
+                    if (j == 2)
+                    {
+                        /* Last term of xyY color must be 1.0 */
+                        if (v != 1.0)
+                        {
+                            bOutputWhitepoint = false;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        pWP[j] = v;
+                    }
+                }
+            }
+            CSLDestroy( papszTokens );
+
+            if (bOutputWhitepoint)
+            {
+                TIFFSetField(hTIFF, TIFFTAG_WHITEPOINT, pWP);
+            }
+        }
+        
+        /* Set transfer function metadata */
+        char const *pszTFRed = NULL;
+        char const *pszTFGreen = NULL;
+        char const *pszTFBlue = NULL;
+        if (pDS != NULL)
+            pszTFRed = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_RED", "COLOR_PROFILE");
+        else
+            pszTFRed = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_RED");
+
+        if (pDS != NULL)
+            pszTFGreen = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_GREEN", "COLOR_PROFILE");
+        else
+            pszTFGreen = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_GREEN");
+
+        if (pDS != NULL)
+            pszTFBlue = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_BLUE", "COLOR_PROFILE");
+        else
+            pszTFBlue = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_BLUE");
+
+        if ((pszTFRed != NULL) && (pszTFGreen != NULL) && (pszTFBlue != NULL))
+        {
+            /* Get length of table. */
+            const int nTransferFunctionLength = 1 << ((pDS!=NULL)?pDS->nBitsPerSample:nBitsPerSample);
+
+            char** papszTokensRed = CSLTokenizeString2( pszTFRed, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char** papszTokensGreen = CSLTokenizeString2( pszTFGreen, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char** papszTokensBlue = CSLTokenizeString2( pszTFBlue, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+
+            if ((CSLCount( papszTokensRed ) == nTransferFunctionLength) &&
+                (CSLCount( papszTokensGreen ) == nTransferFunctionLength) &&
+                (CSLCount( papszTokensBlue ) == nTransferFunctionLength))
+            {
+                uint16 *pTransferFuncRed, *pTransferFuncGreen, *pTransferFuncBlue;
+                pTransferFuncRed = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
+                pTransferFuncGreen = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
+                pTransferFuncBlue = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
+
+                /* Convert our table in string format into int16 format. */
+                for(int i = 0; i < nTransferFunctionLength; i++)
+                {
+                    pTransferFuncRed[i] = (uint16)atoi(papszTokensRed[i]);
+                    pTransferFuncGreen[i] = (uint16)atoi(papszTokensGreen[i]);
+                    pTransferFuncBlue[i] = (uint16)atoi(papszTokensBlue[i]);
+                }
+
+                TIFFSetField(hTIFF, TIFFTAG_TRANSFERFUNCTION, 
+                    pTransferFuncRed, pTransferFuncGreen, pTransferFuncBlue);
+
+                CPLFree(pTransferFuncRed);
+                CPLFree(pTransferFuncGreen);
+                CPLFree(pTransferFuncBlue);
+            }
+
+            CSLDestroy( papszTokensRed );
+            CSLDestroy( papszTokensGreen );
+            CSLDestroy( papszTokensBlue );
+        }
+
+        /* Output transfer range */
+        bool bOutputTransferRange = true;
+        for(int i = 0; ((i < 2) && bOutputTransferRange); i++)
+        {
+            if (pDS != NULL)
+                pszValue = pDS->GetMetadataItem(pszTXRNames[i], "COLOR_PROFILE");
+            else
+                pszValue = CSLFetchNameValue(papszParmList, pszTXRNames[i]);
+            if (pszValue == NULL)
+            {
+                bOutputTransferRange = false;
+                break;
+            }
+
+            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+
+            if (CSLCount( papszTokens ) != 3)
+            {
+                bOutputTransferRange = false;
+                CSLDestroy( papszTokens );
+                break;
+            }
+            
+            int j;
+            for( j = 0; j < 3; j++ )
+            {
+                pTXR[i + j * 2] = (uint16)atoi(papszTokens[j]);
+            }
+
+            CSLDestroy( papszTokens );
+        }
+        
+        if (bOutputTransferRange)
+        {
+            TIFFSetField(hTIFF, TIFFTAG_TRANSFERRANGE, pTXR);
+        }
+    }
+}
+
+/************************************************************************/
 /*                             OpenOffset()                             */
 /*                                                                      */
 /*      Initialize the GTiffDataset based on a passed in file           */
@@ -6580,38 +7533,44 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         }
 
 /* -------------------------------------------------------------------- */
-/*      Otherwise try looking for a .tfw, .tifw or .wld file.           */
+/*      Otherwise try looking for a .tab, .tfw, .tifw or .wld file.     */
 /* -------------------------------------------------------------------- */
         else
         {
-            char* pszWldFilename = NULL;
+            char* pszGeorefFilename = NULL;
 
-            bGeoTransformValid =
-                GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
-                                    papszSiblingFiles, &pszWldFilename);
+            /* Begin with .tab since it can also have projection info */
+            int bTabFileOK =
+                GDALReadTabFile2( osFilename, adfGeoTransform,
+                                    &pszTabWKT, &nGCPCount, &pasGCPList,
+                                    papszSiblingFiles, &pszGeorefFilename );
 
-            if( !bGeoTransformValid )
+            if( bTabFileOK )
             {
-                bGeoTransformValid =
-                    GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
-                                        papszSiblingFiles, &pszWldFilename);
+                if( nGCPCount == 0 )
+                    bGeoTransformValid = TRUE;
             }
-
-            if( !bGeoTransformValid )
+            else
             {
-                int bTabFileOK =
-                    GDALReadTabFile2( osFilename, adfGeoTransform,
-                                      &pszTabWKT, &nGCPCount, &pasGCPList,
-                                      papszSiblingFiles, &pszWldFilename );
+                if( !bGeoTransformValid )
+                {
+                    bGeoTransformValid =
+                        GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
+                                            papszSiblingFiles, &pszGeorefFilename);
+                }
 
-                if( bTabFileOK && nGCPCount == 0 )
-                    bGeoTransformValid = TRUE;
+                if( !bGeoTransformValid )
+                {
+                    bGeoTransformValid =
+                        GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
+                                            papszSiblingFiles, &pszGeorefFilename);
+                }
             }
 
-            if (pszWldFilename)
+            if (pszGeorefFilename)
             {
-                osWldFilename = pszWldFilename;
-                CPLFree(pszWldFilename);
+                osGeorefFilename = pszGeorefFilename;
+                CPLFree(pszGeorefFilename);
             }
         }
 
@@ -7642,6 +8601,12 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
         CPLFree(v);
     }
     
+    /* Set the ICC color profile. */
+    if (!EQUAL(pszProfile,"BASELINE"))
+    {
+        SaveICCProfile(NULL, hTIFF, papszParmList, nBitsPerSample);
+    }
+
     /* Set the compression method before asking the default strip size */
     /* This is usefull when translating to a JPEG-In-TIFF file where */
     /* the default strip size is 8 or 16 depending on the photometric value */
@@ -8034,6 +8999,47 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                  "PIXELTYPE", "IMAGE_STRUCTURE" ) );
     }
     
+/* -------------------------------------------------------------------- */
+/*      Color profile.  Copy from band metadata if found.              */
+/* -------------------------------------------------------------------- */
+    if (bGeoTIFF)
+    {
+        const char* pszOptionsMD[] = {
+            "SOURCE_ICC_PROFILE",
+            "SOURCE_PRIMARIES_RED",
+            "SOURCE_PRIMARIES_GREEN",
+            "SOURCE_PRIMARIES_BLUE",
+            "SOURCE_WHITEPOINT",
+            "TIFFTAG_TRANSFERFUNCTION_RED",
+            "TIFFTAG_TRANSFERFUNCTION_GREEN",
+            "TIFFTAG_TRANSFERFUNCTION_BLUE",
+            "TIFFTAG_TRANSFERRANGE_BLACK",
+            "TIFFTAG_TRANSFERRANGE_WHITE",
+            NULL
+        };
+
+        /* Copy all the tags. Options will override tags in the source */
+        int i = 0;
+        while(pszOptionsMD[i] != NULL)
+        {
+            char const *pszMD = CSLFetchNameValue(papszOptions, pszOptionsMD[i]);
+            if (pszMD == NULL)
+                pszMD = poSrcDS->GetMetadataItem( pszOptionsMD[i], "COLOR_PROFILE" );
+
+            if ((pszMD != NULL) && !EQUAL(pszMD, "") )
+            {
+                papszCreateOptions = 
+                    CSLSetNameValue( papszCreateOptions, pszOptionsMD[i], pszMD );
+
+                /* If an ICC profile exists, other tags are not needed */
+                if (EQUAL(pszOptionsMD[i], "SOURCE_ICC_PROFILE"))
+                    break;
+            }
+
+            i++;
+        }
+    }
+
     int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
     double dfExtraSpaceForOverviews = 0;
     if (nSrcOverviews != 0 &&
@@ -8124,15 +9130,33 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
     TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerSample );
 
+    uint16      nCompression;
+
+    if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
+        nCompression = COMPRESSION_NONE;
+
+    int bForcePhotometric = 
+        CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If the source is RGB, then set the PHOTOMETRIC_RGB value        */
+/* -------------------------------------------------------------------- */
+    if( nBands == 3 && !bForcePhotometric &&
+        nCompression != COMPRESSION_JPEG &&
+        poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_RedBand &&
+        poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_GreenBand &&
+        poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
+    {
+        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Are we really producing an RGBA image?  If so, set the          */
 /*      associated alpha information.                                   */
 /* -------------------------------------------------------------------- */
-    int bForcePhotometric = 
-        CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
-
-    if( nBands == 4 && !bForcePhotometric
-        && poSrcDS->GetRasterBand(4)->GetColorInterpretation()==GCI_AlphaBand)
+    else if( nBands == 4 && !bForcePhotometric &&
+             nCompression != COMPRESSION_JPEG &&
+             poSrcDS->GetRasterBand(4)->GetColorInterpretation()==GCI_AlphaBand)
     {
         uint16 v[1];
 
@@ -8143,14 +9167,19 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
     }
 
+    else if( !bForcePhotometric && nBands == 3 &&
+             nCompression != COMPRESSION_JPEG &&
+             (poSrcDS->GetRasterBand(1)->GetColorInterpretation() != GCI_Undefined ||
+              poSrcDS->GetRasterBand(2)->GetColorInterpretation() != GCI_Undefined ||
+              poSrcDS->GetRasterBand(3)->GetColorInterpretation() != GCI_Undefined) )
+    {
+        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      If the output is jpeg compressed, and the input is RGB make     */
 /*      sure we note that.                                              */
 /* -------------------------------------------------------------------- */
-    uint16      nCompression;
-
-    if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
-        nCompression = COMPRESSION_NONE;
 
     if( nCompression == COMPRESSION_JPEG )
     {
@@ -9053,6 +10082,18 @@ CPLErr GTiffDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GTiffDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(CSLDuplicate(oGTiffMDMD.GetDomainList()),
+                                   TRUE,
+                                   "", "ProxyOverviewRequest", "RPC", "IMD", "SUBDATASETS", "EXIF",
+                                   "xml:XMP", "COLOR_PROFILE", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -9074,6 +10115,9 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
     else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
         LoadEXIFMetadata();
 
+    else if( pszDomain != NULL && EQUAL(pszDomain,"COLOR_PROFILE") )
+        LoadICCProfile();
+
     else if( pszDomain == NULL || EQUAL(pszDomain, "") )
         LoadMDAreaOrPoint(); /* to set GDALMD_AREA_OR_POINT */
 
@@ -9086,7 +10130,9 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
 CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
 
 {
-    if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
+    if ((papszMD != NULL) && (pszDomain != NULL) && EQUAL(pszDomain, "COLOR_PROFILE"))
+        bColorProfileMetadataChanged = TRUE;
+    else if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
         bMetadataChanged = TRUE;
 
     if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
@@ -9130,6 +10176,9 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
     else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
         LoadEXIFMetadata();
 
+    else if( pszDomain != NULL && EQUAL(pszDomain,"COLOR_PROFILE") )
+        LoadICCProfile();
+
     else if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
     {
@@ -9148,7 +10197,9 @@ CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
                                       const char *pszDomain )
 
 {
-    if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
+    if ((pszDomain != NULL) && EQUAL(pszDomain, "COLOR_PROFILE"))
+        bColorProfileMetadataChanged = TRUE;
+    else if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
         bMetadataChanged = TRUE;
 
     if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
@@ -9423,10 +10474,10 @@ char **GTiffDataset::GetFileList()
     if (osRPCFile.size() != 0)
         papszFileList = CSLAddString( papszFileList, osRPCFile );
 
-    if (osWldFilename.size() != 0 &&
-        CSLFindString(papszFileList, osWldFilename) == -1)
+    if (osGeorefFilename.size() != 0 &&
+        CSLFindString(papszFileList, osGeorefFilename) == -1)
     {
-        papszFileList = CSLAddString( papszFileList, osWldFilename );
+        papszFileList = CSLAddString( papszFileList, osGeorefFilename );
     }
 
     return papszFileList;
@@ -9620,6 +10671,28 @@ GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
 {
     char *pszModFmt;
 
+#if SIZEOF_VOIDP == 4
+    /* Case of one-strip file where the strip size is > 2GB (#5403) */
+    if( strcmp(module, "TIFFStripSize") == 0 &&
+        strstr(fmt, "Integer overflow") != NULL )
+    {
+        bGlobalStripIntegerOverflow = TRUE;
+        return;
+    }
+    if( bGlobalStripIntegerOverflow &&
+        strstr(fmt, "Cannot handle zero strip size") != NULL )
+    {
+        return;
+    }
+#endif
+
+#ifdef BIGTIFF_SUPPORT
+    if( strcmp(fmt, "Maximum TIFF file size exceeded") == 0 )
+    {
+        fmt = "Maximum TIFF file size exceeded. Use BIGTIFF=YES creation option.";
+    }
+#endif
+
     pszModFmt = PrepareTIFFErrorFormat( module, fmt );
     CPLErrorV( CE_Failure, CPLE_AppDefined, pszModFmt, ap );
     CPLFree( pszModFmt );
@@ -9790,7 +10863,7 @@ void GDALRegister_GTiff()
     if( GDALGetDriverByName( "GTiff" ) == NULL )
     {
         GDALDriver	*poDriver;
-        char szCreateOptions[3072];
+        char szCreateOptions[4556];
         char szOptionalCompressItems[500];
         int bHasJPEG = FALSE, bHasLZW = FALSE, bHasDEFLATE = FALSE, bHasLZMA = FALSE;
 
@@ -9936,6 +11009,16 @@ void GDALRegister_GTiff()
 "       <Value>BIG</Value>"
 "   </Option>"
 "   <Option name='COPY_SRC_OVERVIEWS' type='boolean' default='NO' description='Force copy of overviews of source dataset (CreateCopy())'/>"
+"   <Option name='SOURCE_ICC_PROFILE' type='string' description='ICC profile'/>"
+"   <Option name='SOURCE_PRIMARIES_RED' type='string' description='x,y,1.0 (xyY) red chromaticity'/>"
+"   <Option name='SOURCE_PRIMARIES_GREEN' type='string' description='x,y,1.0 (xyY) green chromaticity'/>"
+"   <Option name='SOURCE_PRIMARIES_BLUE' type='string' description='x,y,1.0 (xyY) blue chromaticity'/>"
+"   <Option name='SOURCE_WHITEPOINT' type='string' description='x,y,1.0 (xyY) whitepoint'/>"
+"   <Option name='TIFFTAG_TRANSFERFUNCTION_RED' type='string' description='Transfer function for red'/>"
+"   <Option name='TIFFTAG_TRANSFERFUNCTION_GREEN' type='string' description='Transfer function for green'/>"
+"   <Option name='TIFFTAG_TRANSFERFUNCTION_BLUE' type='string' description='Transfer function for blue'/>"
+"   <Option name='TIFFTAG_TRANSFERRANGE_BLACK' type='string' description='Transfer range for black'/>"
+"   <Option name='TIFFTAG_TRANSFERRANGE_WHITE' type='string' description='Transfer range for white'/>"
 "</CreationOptionList>" );
                  
 /* -------------------------------------------------------------------- */
@@ -9963,3 +11046,4 @@ void GDALRegister_GTiff()
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
 }
+
diff --git a/frmts/gtiff/gt_citation.cpp b/frmts/gtiff/gt_citation.cpp
index 3e08e90..361a962 100644
--- a/frmts/gtiff/gt_citation.cpp
+++ b/frmts/gtiff/gt_citation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.cpp 25773 2013-03-20 20:13:40Z rouault $
+ * $Id: gt_citation.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Xiuguang Zhou (ESRI)
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "geovalues.h"
 #include "gt_citation.h"
 
-CPL_CVSID("$Id: gt_citation.cpp 25773 2013-03-20 20:13:40Z rouault $");
+CPL_CVSID("$Id: gt_citation.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const char *apszUnitMap[] = {
     "meters", "1.0",
@@ -697,7 +698,7 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
 /*                                                                      */
 /*        Check utm proj code by its name.                              */
 /************************************************************************/
-void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
+void CheckUTM( GTIFDefn * psDefn, const char * pszCtString )
 {
     if(!psDefn || !pszCtString)
         return;
@@ -716,19 +717,23 @@ void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
         "PSAD56", "22S", "16122",
         NULL, NULL, NULL};
 
-    char* p = strstr(pszCtString, "Datum = ");
+    const char* p = strstr(pszCtString, "Datum = ");
     char datumName[128];
     if(p)
     {
         p += strlen("Datum = ");
-        char* p1 = strchr(p, '|');
-        if(p1)
+        const char* p1 = strchr(p, '|');
+        if(p1 && p1-p < (int)sizeof(datumName))
         {
             strncpy(datumName, p, (p1-p));
             datumName[p1-p] = '\0';
         }
         else
-            strcpy(datumName, p);
+            CPLStrlcpy(datumName, p, sizeof(datumName));
+    }
+    else
+    {
+        datumName[0] = '\0';
     }
 
     char utmName[64];
@@ -736,29 +741,30 @@ void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
     if(p)
     {
         p += strlen("UTM Zone ");
-        char* p1 = strchr(p, '|');
-        if(p1)
+        const char* p1 = strchr(p, '|');
+        if(p1 && p1-p < (int)sizeof(utmName))
         {
             strncpy(utmName, p, (p1-p));
             utmName[p1-p] = '\0';
         }
         else
-            strcpy(utmName, p);
-    }
+            CPLStrlcpy(utmName, p, sizeof(utmName));
 
-    for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
-    {
-        if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
-           EQUAL(datumName, apszUtmProjCode[i]) )
+        for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
         {
-            if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
+            if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
+            EQUAL(datumName, apszUtmProjCode[i]) )
             {
-                psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
-                GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
-                                    psDefn->ProjParm );
-                break;
+                if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
+                {
+                    psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
+                    GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
+                                        psDefn->ProjParm );
+                    break;
+                }
             }
         }
     }
+
     return;
 }
diff --git a/frmts/gtiff/gt_citation.h b/frmts/gtiff/gt_citation.h
index 5aa5b25..8a43c9a 100644
--- a/frmts/gtiff/gt_citation.h
+++ b/frmts/gtiff/gt_citation.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.h 21929 2011-03-11 03:58:42Z warmerdam $
+ * $Id: gt_citation.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Xiuguang Zhou (ESRI)
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -66,7 +67,7 @@ void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
                           char	**ppszPMName,
                           char	**ppszSpheroidName,
                           char	**ppszAngularUnits);
-void CheckUTM( GTIFDefn * psDefn, char * pszCtString );
+void CheckUTM( GTIFDefn * psDefn, const char * pszCtString );
 
 
 #endif // GT_CITATION_H_INCLUDED
diff --git a/frmts/gtiff/gt_jpeg_copy.cpp b/frmts/gtiff/gt_jpeg_copy.cpp
index dd0c6fa..5b11e18 100644
--- a/frmts/gtiff/gt_jpeg_copy.cpp
+++ b/frmts/gtiff/gt_jpeg_copy.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.cpp 24337 2012-04-28 15:06:01Z rouault $
+ * $Id: gt_jpeg_copy.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 /* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
 /* usefull for debugging purposes */
 
-CPL_CVSID("$Id: gt_jpeg_copy.cpp 24337 2012-04-28 15:06:01Z rouault $");
+CPL_CVSID("$Id: gt_jpeg_copy.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #if defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
 
diff --git a/frmts/gtiff/gt_jpeg_copy.h b/frmts/gtiff/gt_jpeg_copy.h
index b043e14..053dd0f 100644
--- a/frmts/gtiff/gt_jpeg_copy.h
+++ b/frmts/gtiff/gt_jpeg_copy.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.h 24274 2012-04-21 12:52:45Z rouault $
+ * $Id: gt_jpeg_copy.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp
index 04fba42..df75ecb 100644
--- a/frmts/gtiff/gt_overview.cpp
+++ b/frmts/gtiff/gt_overview.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_overview.cpp 24525 2012-05-31 22:22:25Z rouault $
+ * $Id: gt_overview.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Code to build overviews of external databases as a TIFF file. 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "gt_overview.h"
 #include "gtiff.h"
 
-CPL_CVSID("$Id: gt_overview.cpp 24525 2012-05-31 22:22:25Z rouault $");
+CPL_CVSID("$Id: gt_overview.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         GTIFFWriteDirectory()                        */
diff --git a/frmts/gtiff/gt_overview.h b/frmts/gtiff/gt_overview.h
index a11133b..1843162 100644
--- a/frmts/gtiff/gt_overview.h
+++ b/frmts/gtiff/gt_overview.h
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gtiff/gt_wkt_srs.cpp b/frmts/gtiff/gt_wkt_srs.cpp
index 7179453..4f6e8bd 100644
--- a/frmts/gtiff/gt_wkt_srs.cpp
+++ b/frmts/gtiff/gt_wkt_srs.cpp
@@ -1,15 +1,15 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.cpp 25659 2013-02-19 22:51:46Z warmerdam $
+ * $Id: gt_wkt_srs.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
- *           definitions and OpenGIS WKT SRS format.  This code is
- *           deliberately GDAL free, and it is intended to be moved into
- *           libgeotiff someday if possible.
+ *           definitions and OpenGIS WKT SRS format.  This code is intended to
+ *           be moved into libgeotiff someday if possible.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,9 +30,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_serv.h"
-#include "geo_tiffp.h"
-#define CPL_ERROR_H_INCLUDED
+#include "cpl_error.h"
+#include "cpl_conv.h"
+#include "cpl_csv.h"
+#include "gdal_csv.h"
 
 #include "geovalues.h"
 #include "ogr_spatialref.h"
@@ -44,7 +45,7 @@
 #include "gt_wkt_srs_for_gdal.h"
 #include "gt_citation.h"
 
-CPL_CVSID("$Id: gt_wkt_srs.cpp 25659 2013-02-19 22:51:46Z warmerdam $")
+CPL_CVSID("$Id: gt_wkt_srs.cpp 27182 2014-04-14 20:03:08Z rouault $")
 
 #define ProjLinearUnitsInterpCorrectGeoKey   3059
 
@@ -52,69 +53,14 @@ CPL_CVSID("$Id: gt_wkt_srs.cpp 25659 2013-02-19 22:51:46Z warmerdam $")
 #  define CT_HotineObliqueMercatorAzimuthCenter 9815
 #endif
 
+#if !defined(GTIFAtof)
+#  define GTIFAtof CPLAtof
+#endif
 
 CPL_C_START
 void CPL_DLL LibgeotiffOneTimeInit();
 void    LibgeotiffOneTimeCleanupMutex();
 
-// replicated from gdal_csv.h. 
-const char * GDALDefaultCSVFilename( const char *pszBasename );
-
-#ifndef CPL_SERV_H_INTERNAL
-/* Make VSIL_STRICT_ENFORCE active in DEBUG builds */
-#ifdef DEBUG
-#define VSIL_STRICT_ENFORCE
-#endif
-
-#ifdef VSIL_STRICT_ENFORCE
-typedef struct _VSILFILE VSILFILE;
-#else
-typedef FILE VSILFILE;
-#endif
-
-// ensure compatability with older libgeotiffs. 
-#if !defined(GTIFAtof)
-#  define GTIFAtof atof
-#endif
-
-int CPL_DLL VSIFCloseL( VSILFILE * );
-int CPL_DLL VSIUnlink( const char * );
-VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename,
-                                    GByte *pabyData, 
-                                    GUIntBig nDataLength,
-                                    int bTakeOwnership );
-GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, 
-                                    GUIntBig *pnDataLength, 
-                                    int bUnlinkAndSeize );
-
-int CPL_DLL CSLTestBoolean( const char *pszValue );
-const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
-									
-/* Those stuff are redefined in external libgeotiff cpl_serv.h */
-/* as macros. Let's use GDAL functions instead */
-/* E.Rouault : I'm wondering why we just don't #define CPL_SERV_H_INCLUDED */
-/* at the beginning of this file to avoid cpl_serv.h to be used at all ??? */
-
-#undef CSVReadParseLine
-char CPL_DLL  **CSVReadParseLine( FILE *fp);
-#undef CSLDestroy
-void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
-#undef VSIFree
-void CPL_DLL    VSIFree( void * );
-#undef CPLFree
-#define CPLFree VSIFree
-#undef CPLMalloc
-void CPL_DLL *CPLMalloc( size_t );
-#undef CPLCalloc
-void CPL_DLL *CPLCalloc( size_t, size_t );
-#undef CPLStrdup
-char CPL_DLL *CPLStrdup( const char * );
-
-#endif /* CPL_SERV_H_INTERNAL */
-
-const char CPL_DLL * CPL_STDCALL CPLGetConfigOption( const char *, const char * );
-void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... );
-
 CPL_C_END
 
 // To remind myself not to use CPLString in this file!
@@ -263,11 +209,11 @@ static void WKTMassageDatum( char ** ppszDatum )
 /************************************************************************/
 
 /* For example:
-   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 14:51:46 -0800 (Tue, 19 Feb 2013) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
+   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 27182 $ $Date: 2014-04-14 13:03:08 -0700 (Mon, 14 Apr 2014) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
 
-   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 14:51:46 -0800 (Tue, 19 Feb 2013) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
+   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 27182 $ $Date: 2014-04-14 13:03:08 -0700 (Mon, 14 Apr 2014) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
 
-   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 25659 $ $Date: 2013-02-19 14:51:46 -0800 (Tue, 19 Feb 2013) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
+   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 27182 $ $Date: 2014-04-14 13:03:08 -0700 (Mon, 14 Apr 2014) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
  
 */
 
@@ -623,6 +569,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     dfSemiMajor = psDefn->SemiMajor;
     if( dfSemiMajor == 0.0 )
     {
+        CPLFree(pszSpheroidName);
         pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
         dfSemiMajor = SRS_WGS84_SEMIMAJOR;
         dfInvFlattening = SRS_WGS84_INVFLATTENING;
@@ -2384,8 +2331,20 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, 
                           char **ppszWKT, double *padfGeoTransform,
                           int *pnGCPCount, GDAL_GCP **ppasGCPList )
+{
+    return GTIFWktFromMemBufEx(nSize, pabyBuffer, ppszWKT, padfGeoTransform,
+                               pnGCPCount, ppasGCPList, NULL);
+}
+
+CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer, 
+                            char **ppszWKT, double *padfGeoTransform,
+                            int *pnGCPCount, GDAL_GCP **ppasGCPList,
+                            int *pbPixelIsPoint )
 
 {
+    bool    bPixelIsPoint = false;
+    int     bPointGeoIgnore = FALSE;
+    short nRasterType;
     char szFilename[100];
 
     sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif",
@@ -2426,12 +2385,25 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
 
     hGTIF = GTIFNew(hTIFF);
 
+    if( hGTIF != NULL && GTIFKeyGet(hGTIF, GTRasterTypeGeoKey, &nRasterType,
+                0, 1 ) == 1
+        && nRasterType == (short) RasterPixelIsPoint )
+    {
+        bPixelIsPoint = true;
+        bPointGeoIgnore =
+            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
+                                            "FALSE") );
+    }
+    if( pbPixelIsPoint )
+        *pbPixelIsPoint = bPixelIsPoint;
+
 #if LIBGEOTIFF_VERSION >= 1410
     psGTIFDefn = GTIFAllocDefn();
 #else
     psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
 #endif    
 
+                
     if( hGTIF != NULL && GTIFGetDefn( hGTIF, psGTIFDefn ) )
         *ppszWKT = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
     else
@@ -2475,6 +2447,13 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                 padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1];
             padfGeoTransform[3] =
                 padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
+        
+            // adjust for pixel is point in transform
+            if( bPixelIsPoint && !bPointGeoIgnore )
+            {
+                padfGeoTransform[0] -= (padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5);
+                padfGeoTransform[3] -= (padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5);
+            }
         }
     }
 
@@ -2531,6 +2510,16 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
 CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
                           int nGCPCount, const GDAL_GCP *pasGCPList,
                           int *pnSize, unsigned char **ppabyBuffer )
+{
+    return GTIFMemBufFromWktEx(pszWKT, padfGeoTransform,
+                               nGCPCount,pasGCPList,
+                               pnSize, ppabyBuffer, FALSE);
+}
+
+CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
+                            int nGCPCount, const GDAL_GCP *pasGCPList,
+                            int *pnSize, unsigned char **ppabyBuffer,
+                            int bPixelIsPoint )
 
 {
     TIFF        *hTIFF;
@@ -2572,10 +2561,26 @@ CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
 /*      Get the projection definition.                                  */
 /* -------------------------------------------------------------------- */
 
-    if( pszWKT != NULL )
+    int  bPointGeoIgnore = FALSE;
+    if( bPixelIsPoint )
+    {
+        bPointGeoIgnore = 
+            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
+                                               "FALSE") );
+    }
+
+    if( pszWKT != NULL || bPixelIsPoint )
     {
         hGTIF = GTIFNew(hTIFF);
-        GTIFSetFromOGISDefn( hGTIF, pszWKT );
+        if( pszWKT != NULL )
+            GTIFSetFromOGISDefn( hGTIF, pszWKT );
+
+        if( bPixelIsPoint )
+        {
+            GTIFKeySet(hGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
+                       RasterPixelIsPoint);
+        }
+
         GTIFWriteKeys( hGTIF );
         GTIFFree( hGTIF );
     }
@@ -2583,6 +2588,7 @@ CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
 /* -------------------------------------------------------------------- */
 /*      Set the geotransform, or GCPs.                                  */
 /* -------------------------------------------------------------------- */
+
     if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0
         || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0
         || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 )
@@ -2604,7 +2610,13 @@ CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
             adfTiePoints[3] = padfGeoTransform[0];
             adfTiePoints[4] = padfGeoTransform[3];
             adfTiePoints[5] = 0.0;
-        
+
+            if( bPixelIsPoint && !bPointGeoIgnore )
+            {
+                adfTiePoints[3] += padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
+                adfTiePoints[4] += padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
+            }
+
             TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
         }
         else
@@ -2621,6 +2633,12 @@ CPLErr GTIFMemBufFromWkt( const char *pszWKT, const double *padfGeoTransform,
             adfMatrix[7] = padfGeoTransform[3];
             adfMatrix[15] = 1.0;
 
+            if( bPixelIsPoint && !bPointGeoIgnore )
+            {
+                adfMatrix[3] += padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
+                adfMatrix[7] += padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
+            }
+
             TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
         }
     }
diff --git a/frmts/gtiff/gt_wkt_srs.h b/frmts/gtiff/gt_wkt_srs.h
index 38f6e78..e1791c2 100644
--- a/frmts/gtiff/gt_wkt_srs.h
+++ b/frmts/gtiff/gt_wkt_srs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.h 21929 2011-03-11 03:58:42Z warmerdam $
+ * $Id: gt_wkt_srs.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -9,7 +9,7 @@
  * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gtiff/gt_wkt_srs_for_gdal.h b/frmts/gtiff/gt_wkt_srs_for_gdal.h
index 2d9ef3e..9f54cf6 100644
--- a/frmts/gtiff/gt_wkt_srs_for_gdal.h
+++ b/frmts/gtiff/gt_wkt_srs_for_gdal.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gt_wkt_srs_for_gdal.h 23791 2012-01-23 22:14:47Z rouault $
+ * $Id: gt_wkt_srs_for_gdal.h 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Read/Write in-memory GeoTIFF file
  * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,10 +39,22 @@ CPLErr CPL_DLL GTIFMemBufFromWkt( const char *pszWKT,
                                   const double *padfGeoTransform,
                                   int nGCPCount, const GDAL_GCP *pasGCPList,
                                   int *pnSize, unsigned char **ppabyBuffer );
+
+CPLErr GTIFMemBufFromWktEx( const char *pszWKT,
+                            const double *padfGeoTransform,
+                            int nGCPCount, const GDAL_GCP *pasGCPList,
+                            int *pnSize, unsigned char **ppabyBuffer,
+                            int bPixelIsPoint );
+
 CPLErr CPL_DLL GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                           char **ppszWKT, double *padfGeoTransform,
                           int *pnGCPCount, GDAL_GCP **ppasGCPList );
 
+CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer, 
+                            char **ppszWKT, double *padfGeoTransform,
+                            int *pnGCPCount, GDAL_GCP **ppasGCPList,
+                            int *pbPixelIsPoint );
+
 CPL_C_END;
 
 #endif // GT_WKT_SRS_FOR_GDAL_H_INCLUDED
diff --git a/frmts/gtiff/gtiff.h b/frmts/gtiff/gtiff.h
index dc74bfe..cb2a8da 100644
--- a/frmts/gtiff/gtiff.h
+++ b/frmts/gtiff/gtiff.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtiff.h 25659 2013-02-19 22:51:46Z warmerdam $
+ * $Id: gtiff.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
index 49ac16b..9f030dd 100644
--- a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
+++ b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
@@ -1,4 +1,5 @@
 /* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */
+#define add_ms gdal_add_ms
 #define buildMap gdal_buildMap
 #define BuildMapBitdepth16To8 gdal_BuildMapBitdepth16To8
 #define BuildMapUaToAa gdal_BuildMapUaToAa
diff --git a/frmts/gtiff/libtiff/tif_codec.c b/frmts/gtiff/libtiff/tif_codec.c
index e201667..703e87d 100644
--- a/frmts/gtiff/libtiff/tif_codec.c
+++ b/frmts/gtiff/libtiff/tif_codec.c
@@ -1,4 +1,4 @@
-/* $Id: tif_codec.c,v 1.15 2010-12-14 12:53:00 dron Exp $ */
+/* $Id: tif_codec.c,v 1.16 2013-05-02 14:44:29 tgl Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -108,7 +108,8 @@ _notConfigured(TIFF* tif)
 	const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
         char compression_code[20];
         
-        sprintf( compression_code, "%d", tif->tif_dir.td_compression );
+        snprintf(compression_code, sizeof(compression_code), "%d",
+		 tif->tif_dir.td_compression );
 	TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                      "%s compression support is not configured", 
                      c ? c->name : compression_code );
diff --git a/frmts/gtiff/libtiff/tif_dir.c b/frmts/gtiff/libtiff/tif_dir.c
index 8bf3ea7..acff7b8 100644
--- a/frmts/gtiff/libtiff/tif_dir.c
+++ b/frmts/gtiff/libtiff/tif_dir.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dir.c,v 1.113 2012-06-14 20:32:53 fwarmerdam Exp $ */
+/* $Id: tif_dir.c,v 1.116 2013-11-30 20:24:36 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -1344,6 +1344,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off)
 			if (((uint64)poffa!=poff)||(poffb<poffa)||(poffb<(tmsize_t)sizeof(uint16))||(poffb>tif->tif_size))
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
+                                  *nextdir=0;
 				return(0);
 			}
 			_TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16));
@@ -1470,6 +1471,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off)
 uint16
 TIFFNumberOfDirectories(TIFF* tif)
 {
+	static const char module[] = "TIFFNumberOfDirectories";
 	uint64 nextdir;
 	uint16 n;
 	if (!(tif->tif_flags&TIFF_BIGTIFF))
@@ -1478,7 +1480,14 @@ TIFFNumberOfDirectories(TIFF* tif)
 		nextdir = tif->tif_header.big.tiff_diroff;
 	n = 0;
 	while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
-		n++;
+        {
+		if(++n == 0)
+                {
+                        TIFFErrorExt(tif->tif_clientdata, module,
+                                     "Directory count exceeded 65535 limit, giving up on counting.");
+                        return (65535);
+                }
+        }
 	return (n);
 }
 
diff --git a/frmts/gtiff/libtiff/tif_dirinfo.c b/frmts/gtiff/libtiff/tif_dirinfo.c
index d319931..4dae5e5 100644
--- a/frmts/gtiff/libtiff/tif_dirinfo.c
+++ b/frmts/gtiff/libtiff/tif_dirinfo.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirinfo.c,v 1.117 2012-08-19 16:56:34 bfriesen Exp $ */
+/* $Id: tif_dirinfo.c,v 1.118 2013-05-02 14:44:29 tgl Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -711,7 +711,7 @@ _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type)
 	 * note that this name is a special sign to TIFFClose() and
 	 * _TIFFSetupFields() to free the field
 	 */
-	sprintf(fld->field_name, "Tag %d", (int) tag);
+	snprintf(fld->field_name, 32, "Tag %d", (int) tag);
 
 	return fld;    
 }
diff --git a/frmts/gtiff/libtiff/tif_read.c b/frmts/gtiff/libtiff/tif_read.c
index fe36e68..acca0b8 100644
--- a/frmts/gtiff/libtiff/tif_read.c
+++ b/frmts/gtiff/libtiff/tif_read.c
@@ -1,4 +1,4 @@
-/* $Id: tif_read.c,v 1.41 2012-07-06 19:22:58 bfriesen Exp $ */
+/* $Id: tif_read.c,v 1.42 2013-01-18 21:37:13 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -47,7 +47,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
 {
 	static const char module[] = "TIFFFillStripPartial";
 	register TIFFDirectory *td = &tif->tif_dir;
-        uint64 unused_data;
+        tmsize_t unused_data;
         uint64 read_offset;
         tmsize_t cc, to_read;
         /* tmsize_t bytecountm; */
@@ -117,7 +117,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
         if( (uint64) to_read > td->td_stripbytecount[strip] 
             - tif->tif_rawdataoff - tif->tif_rawdataloaded )
         {
-                to_read = td->td_stripbytecount[strip]
+                to_read = (tmsize_t) td->td_stripbytecount[strip]
                         - tif->tif_rawdataoff - tif->tif_rawdataloaded;
         }
 
diff --git a/frmts/gtiff/libtiff/tif_write.c b/frmts/gtiff/libtiff/tif_write.c
index 8792123..cb610fc 100644
--- a/frmts/gtiff/libtiff/tif_write.c
+++ b/frmts/gtiff/libtiff/tif_write.c
@@ -1,4 +1,4 @@
-/* $Id: tif_write.c,v 1.37 2012-08-13 22:10:17 fwarmerdam Exp $ */
+/* $Id: tif_write.c,v 1.38 2013-01-18 21:57:12 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -233,7 +233,7 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
             /* more bytes available in the output buffer than the previous byte count, */
             /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
             /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
-            if( tif->tif_rawdatasize <= td->td_stripbytecount[strip] )
+            if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] )
             {
                 if( !(TIFFWriteBufferSetup(tif, NULL,
                     (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) )
@@ -379,7 +379,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
             /* more bytes available in the output buffer than the previous byte count, */
             /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
             /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
-            if( tif->tif_rawdatasize <= td->td_stripbytecount[tile] )
+            if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] )
             {
                 if( !(TIFFWriteBufferSetup(tif, NULL,
                     (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) )
@@ -391,8 +391,8 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
             tif->tif_curoff = 0;
         }
 
-    tif->tif_rawcc = 0;
-    tif->tif_rawcp = tif->tif_rawdata;
+	tif->tif_rawcc = 0;
+	tif->tif_rawcp = tif->tif_rawdata;
 
 	/* 
 	 * Compute tiles per row & per column to compute
diff --git a/frmts/gtiff/makefile.vc b/frmts/gtiff/makefile.vc
index 6885f83..a274be3 100644
--- a/frmts/gtiff/makefile.vc
+++ b/frmts/gtiff/makefile.vc
@@ -11,7 +11,7 @@ GDAL_ROOT	=	..\..
 !IFDEF TIFF_INC
 SUB_TIFF_TARGET =
 !ELSE
-TIFF_INC   =	-Ilibtiff -DBIGTIFF_SUPPORT
+TIFF_INC   =	-Ilibtiff -DINTERNAL_LIBTIFF -DBIGTIFF_SUPPORT
 SUB_TIFF_TARGET =	tiff
 !ENDIF
 
diff --git a/frmts/gtiff/tif_float.h b/frmts/gtiff/tif_float.h
index 6b44adf..0916283 100644
--- a/frmts/gtiff/tif_float.h
+++ b/frmts/gtiff/tif_float.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_float.h 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: tif_float.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Floating point conversion functions. Convert 16- and 24-bit
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Andrey Kiselev <dron at remotesensing.org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This code is based on the code from OpenEXR project with the following
  * copyright:
diff --git a/frmts/gtiff/tifvsi.cpp b/frmts/gtiff/tifvsi.cpp
index 0295dcc..3618da0 100644
--- a/frmts/gtiff/tifvsi.cpp
+++ b/frmts/gtiff/tifvsi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.cpp 24411 2012-05-13 20:16:08Z rouault $
+ * $Id: tifvsi.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam, warmerdam at pobox.com
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gtiff/tifvsi.h b/frmts/gtiff/tifvsi.h
index bd0f447..17a30c5 100644
--- a/frmts/gtiff/tifvsi.h
+++ b/frmts/gtiff/tifvsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.h 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: tifvsi.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam, warmerdam at pobox.com
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/gxf/gxf_ogcwkt.c b/frmts/gxf/gxf_ogcwkt.c
index 2e6a7a9..57e33bb 100644
--- a/frmts/gxf/gxf_ogcwkt.c
+++ b/frmts/gxf/gxf_ogcwkt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxf_ogcwkt.c 25164 2012-10-20 13:42:32Z rouault $
+ * $Id: gxf_ogcwkt.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Handle GXF to OGC WKT projection transformation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxf_ogcwkt.c 25164 2012-10-20 13:42:32Z rouault $");
+CPL_CVSID("$Id: gxf_ogcwkt.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /* the following #defines come from ogr_spatialref.h in the GDAL/OGR	*/
diff --git a/frmts/gxf/gxfdataset.cpp b/frmts/gxf/gxfdataset.cpp
index 9cac8cb..0f1d76e 100644
--- a/frmts/gxf/gxfdataset.cpp
+++ b/frmts/gxf/gxfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfdataset.cpp 25164 2012-10-20 13:42:32Z rouault $
+ * $Id: gxfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  GDAL binding for GXF reader.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gxfopen.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: gxfdataset.cpp 25164 2012-10-20 13:42:32Z rouault $");
+CPL_CVSID("$Id: gxfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #  define PI 3.14159265358979323846
diff --git a/frmts/gxf/gxfopen.c b/frmts/gxf/gxfopen.c
index 747e029..40d46ab 100644
--- a/frmts/gxf/gxfopen.c
+++ b/frmts/gxf/gxfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.c 25164 2012-10-20 13:42:32Z rouault $
+ * $Id: gxfopen.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Majority of Geosoft GXF reading code.
@@ -8,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 1998, Global Geomatics
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include <ctype.h>
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfopen.c 25164 2012-10-20 13:42:32Z rouault $");
+CPL_CVSID("$Id: gxfopen.c 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /* this is also defined in gdal.h which we avoid in this separable component */
diff --git a/frmts/hdf4/GNUmakefile b/frmts/hdf4/GNUmakefile
index db19494..c49e0af 100644
--- a/frmts/hdf4/GNUmakefile
+++ b/frmts/hdf4/GNUmakefile
@@ -17,3 +17,11 @@ lib-hdfeos:
 	(cd hdf-eos; $(MAKE) install-obj)
 
 install-obj:	$(SUBLIBS) $(O_OBJ:.o=.$(OBJ_EXT))
+
+PLUGIN_SO       = gdal_HDF4.so
+
+plugin: $(PLUGIN_SO)
+
+$(PLUGIN_SO):   $(OBJ)
+	$(LD_SHARED) $(LNK_FLAGS) $(OBJ) $(CONFIG_LIBS_INS) $(LIBS) \
+		-o $(PLUGIN_SO)
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index 30c71dc..ef1d4ad 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 25847 2013-04-03 09:45:20Z dron $
+ * $Id: hdf4dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,7 +42,7 @@
 #include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 25847 2013-04-03 09:45:20Z dron $");
+CPL_CVSID("$Id: hdf4dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HDF4(void);
@@ -97,6 +98,17 @@ HDF4Dataset::~HDF4Dataset()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **HDF4Dataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -813,7 +825,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         } 
         nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
-#if DEBUG
+#ifdef DEBUG
         CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets );
 #endif
         if ( nSubDatasets > 0 && nStrBufSize > 0 )
@@ -825,7 +837,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
             pszSwathList[nStrBufSize] = '\0';
 
-#if DEBUG
+#ifdef DEBUG
             CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList );
 #endif
 
@@ -859,7 +871,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
                 SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType );
 
-#if DEBUG
+#ifdef DEBUG
                 {
                     char *pszTmp =
                         SPrintArray( GDT_UInt32, paiRank, nFields, "," );
@@ -923,7 +935,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ );
         nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize );
-#if DEBUG
+#ifdef DEBUG
         CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", (int)nSubDatasets );
 #endif
         if ( nSubDatasets > 0 && nStrBufSize > 0 )
@@ -934,7 +946,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             pszGridList = (char *)CPLMalloc( nStrBufSize + 1 );
             GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize );
 
-#if DEBUG
+#ifdef DEBUG
             CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList );
 #endif
 
@@ -969,7 +981,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
                 GDinqfields( hGD, pszFieldList, paiRank, paiNumType );
 
-#if DEBUG
+#ifdef DEBUG
                 {
                     char* pszTmp =
                             SPrintArray( GDT_UInt32, paiRank, nFields, "," );
diff --git a/frmts/hdf4/hdf4dataset.h b/frmts/hdf4/hdf4dataset.h
index 3d8c840..0353e03 100644
--- a/frmts/hdf4/hdf4dataset.h
+++ b/frmts/hdf4/hdf4dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.h 18945 2010-02-27 20:39:31Z rouault $
+ * $Id: hdf4dataset.h 26569 2013-10-29 23:51:12Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Header file for HDF4 datasets reader.
@@ -97,6 +97,7 @@ class HDF4Dataset : public GDALPamDataset
                 HDF4Dataset();
 		~HDF4Dataset();
     
+    virtual char      **GetMetadataDomainList();
     virtual char        **GetMetadata( const char * pszDomain = "" );
     static GDALDataset  *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp
index d46a3ef..2433971 100644
--- a/frmts/hdf4/hdf4imagedataset.cpp
+++ b/frmts/hdf4/hdf4imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4imagedataset.cpp 25848 2013-04-03 11:35:16Z dron $
+ * $Id: hdf4imagedataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Read subdatasets of HDF4 file.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -46,7 +47,7 @@
 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: hdf4imagedataset.cpp 25848 2013-04-03 11:35:16Z dron $");
+CPL_CVSID("$Id: hdf4imagedataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_HDF4(void);
@@ -2161,6 +2162,11 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     {
         char    **papszGeoDimList = NULL;
 
+        // Skip "SceneLineNumber" table if present in the list of geolocation
+        // fields. It is not needed to fetch geocoding data.
+        if ( EQUAL(papszGeolocations[i], "SceneLineNumber") )
+            continue;
+
         if ( SWfieldinfo( hSW, papszGeolocations[i], &iRank,
                           aiDimSizes, &iWrkNumType, szGeoDimList ) < 0 )
         {
diff --git a/frmts/hdf4/makefile.vc b/frmts/hdf4/makefile.vc
index c838943..84d8f38 100644
--- a/frmts/hdf4/makefile.vc
+++ b/frmts/hdf4/makefile.vc
@@ -4,6 +4,8 @@ GDAL_ROOT	=	..\..
 
 OBJ	=	hdf4dataset.obj hdf4imagedataset.obj
 
+PLUGIN_DLL 	=	gdal_HDF4.dll
+
 EXTRAFLAGS = 	-I..\pds -I$(HDF4_DIR)\include -Ihdf-eos -DFRMT_hdf4 
 
 default:	$(OBJ)
@@ -16,3 +18,13 @@ clean:
 	cd hdf-eos
 	$(MAKE) /f makefile.vc clean
 	cd ..
+
+plugin:	$(PLUGIN_DLL)
+
+$(PLUGIN_DLL): $(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) ..\o\SWapi.obj ..\o\GDapi.obj ..\o\EHapi.obj ..\o\gctp_wrap.obj ..\o\nasakeywordhandler.obj $(GDALLIB) $(HDF4_LIB)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
\ No newline at end of file
diff --git a/frmts/hdf5/bagdataset.cpp b/frmts/hdf5/bagdataset.cpp
index f79e46d..1013f93 100644
--- a/frmts/hdf5/bagdataset.cpp
+++ b/frmts/hdf5/bagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bagdataset.cpp 26062 2013-06-04 21:16:21Z rouault $
+ * $Id: bagdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read BAG datasets.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bagdataset.cpp 26062 2013-06-04 21:16:21Z rouault $");
+CPL_CVSID("$Id: bagdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_BAG(void);
@@ -69,6 +70,7 @@ public:
     
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef(void);
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
 
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -821,6 +823,17 @@ const char *BAGDataset::GetProjectionRef()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **BAGDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:BAG", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/frmts/hdf5/gh5_convenience.cpp b/frmts/hdf5/gh5_convenience.cpp
index d079318..ca48e90 100644
--- a/frmts/hdf5/gh5_convenience.cpp
+++ b/frmts/hdf5/gh5_convenience.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gh5_convenience.cpp 26011 2013-05-17 23:39:30Z warmerdam $
+ * $Id: gh5_convenience.cpp 26010 2013-05-17 23:31:00Z warmerdam $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 convenience functions.
@@ -29,7 +29,7 @@
 
 #include "gh5_convenience.h"
 
-CPL_CVSID("$Id: gh5_convenience.cpp 26011 2013-05-17 23:39:30Z warmerdam $");
+CPL_CVSID("$Id: gh5_convenience.cpp 26010 2013-05-17 23:31:00Z warmerdam $");
 
 /************************************************************************/
 /*                    GH5_FetchAttribute(CPLString)                     */
diff --git a/frmts/hdf5/hdf5dataset.cpp b/frmts/hdf5/hdf5dataset.cpp
index bb28a8a..f98b0a7 100644
--- a/frmts/hdf5/hdf5dataset.cpp
+++ b/frmts/hdf5/hdf5dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.cpp 26062 2013-06-04 21:16:21Z rouault $
+ * $Id: hdf5dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 Datasets. Open HDF5 file, fetch metadata and list of
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,7 +40,7 @@
 #include "cpl_string.h"
 #include "hdf5dataset.h"
 
-CPL_CVSID("$Id: hdf5dataset.cpp 26062 2013-06-04 21:16:21Z rouault $");
+CPL_CVSID("$Id: hdf5dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void GDALRegister_HDF5(void);
@@ -634,7 +635,7 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
     {
         papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS );
 
-        for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
+        for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
         {
             if( i != 0)
                 osKey += '_';
@@ -646,7 +647,7 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
     // Convert whitespaces into "_" for the attribute name component
     papszTokens = CSLTokenizeString2( pszAttrName, " ",
                             CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-    for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
+    for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
     {
         if(!osKey.empty())
             osKey += '_';
diff --git a/frmts/hdf5/hdf5dataset.h b/frmts/hdf5/hdf5dataset.h
index 07d7d81..f73cd48 100644
--- a/frmts/hdf5/hdf5dataset.h
+++ b/frmts/hdf5/hdf5dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.h 26062 2013-06-04 21:16:21Z rouault $
+ * $Id: hdf5dataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Header file for HDF5 datasets reader.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/hdf5/hdf5imagedataset.cpp b/frmts/hdf5/hdf5imagedataset.cpp
index 1424a1d..a107622 100644
--- a/frmts/hdf5/hdf5imagedataset.cpp
+++ b/frmts/hdf5/hdf5imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5imagedataset.cpp 26062 2013-06-04 21:16:21Z rouault $
+ * $Id: hdf5imagedataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read subdatasets of HDF5 file.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 #include "hdf5dataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hdf5imagedataset.cpp 26062 2013-06-04 21:16:21Z rouault $");
+CPL_CVSID("$Id: hdf5imagedataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void GDALRegister_HDF5Image(void);
@@ -88,9 +89,12 @@ class HDF5ImageDataset : public HDF5Dataset
     hid_t        datatype;
     hid_t        native;
     H5T_class_t  clas;
-    int          iSubdatasetType;
+    Hdf5ProductType    iSubdatasetType;
+    HDF5CSKProductEnum iCSKProductType;
     double       adfGeoTransform[6];
     bool         bHasGeoTransform;
+    
+    CPLErr CreateODIMH5Projection();
 
 public:
     HDF5ImageDataset();
@@ -106,6 +110,18 @@ public:
     virtual const GDAL_GCP *GetGCPs( ); 
     virtual CPLErr GetGeoTransform( double * padfTransform );
 
+    Hdf5ProductType GetSubdatasetType() const {return iSubdatasetType;}
+    HDF5CSKProductEnum GetCSKProductType() const {return iCSKProductType;}
+
+    int     IsComplexCSKL1A() const
+    {
+        return (GetSubdatasetType() == CSK_PRODUCT) &&
+               (GetCSKProductType() == PROD_CSK_L1A) &&
+               (ndims == 3);
+    }
+    int     GetYIndex() const { return IsComplexCSKL1A() ? 0 : ndims - 2; }
+    int     GetXIndex() const { return IsComplexCSKL1A() ? 1 : ndims - 1; }
+
     /**
      * Identify if the subdataset has a known product format
      * It stores a product identifier in iSubdatasetType,
@@ -165,6 +181,7 @@ HDF5ImageDataset::HDF5ImageDataset()
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
     iSubdatasetType    = UNKNOWN_PRODUCT;
+    iCSKProductType    = PROD_UNKNOWN;
     bHasGeoTransform   = false;
     dataset_id         = -1;
     dataspace_id       = -1;
@@ -288,9 +305,11 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
         {
             hsize_t panChunkDims[3];
             int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            nBlockXSize   = (int) panChunkDims[nDimSize-1];
-            nBlockYSize   = (int) panChunkDims[nDimSize-2];
+            CPLAssert(nDimSize == poDS->ndims);
+            nBlockXSize   = (int) panChunkDims[poDS->GetXIndex()];
+            nBlockYSize   = (int) panChunkDims[poDS->GetYIndex()];
         }
+        
         H5Pclose(listid);
     }
 
@@ -348,30 +367,38 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_None;
     }
 
-    rank=2;
-
-    if( poGDS->ndims == 3 ){
+    if( poGDS->IsComplexCSKL1A() )
+    {
+        rank = 3; 
+        offset[2]   = nBand-1;
+        count[2]    = 1;
+        col_dims[2] = 1;
+    }
+    else if( poGDS->ndims == 3 )
+    {
         rank=3;
         offset[0]   = nBand-1;
         count[0]    = 1;
         col_dims[0] = 1;
     }
+    else
+        rank = 2;
 
-    offset[poGDS->ndims - 2] = nBlockYOff*nBlockYSize;
-    offset[poGDS->ndims - 1] = nBlockXOff*nBlockXSize;
-    count[poGDS->ndims - 2]  = nBlockYSize;
-    count[poGDS->ndims - 1]  = nBlockXSize;
+    offset[poGDS->GetYIndex()] = nBlockYOff*nBlockYSize;
+    offset[poGDS->GetXIndex()] = nBlockXOff*nBlockXSize;
+    count[poGDS->GetYIndex()]  = nBlockYSize;
+    count[poGDS->GetXIndex()]  = nBlockXSize;
 
     nSizeOfData = H5Tget_size( poGDS->native );
     memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
 
     /*  blocksize may not be a multiple of imagesize */
-    count[poGDS->ndims - 2]  = MIN( size_t(nBlockYSize),
+    count[poGDS->GetYIndex()]  = MIN( size_t(nBlockYSize),
                                     poDS->GetRasterYSize() -
-                                            offset[poGDS->ndims - 2]);
-    count[poGDS->ndims - 1]  = MIN( size_t(nBlockXSize),
+                                    offset[poGDS->GetYIndex()]);
+    count[poGDS->GetXIndex()]  = MIN( size_t(nBlockXSize),
                                     poDS->GetRasterXSize()-
-                                            offset[poGDS->ndims - 1]);
+                                    offset[poGDS->GetXIndex()]);
 
 /* -------------------------------------------------------------------- */
 /*      Select block from file space                                    */
@@ -384,8 +411,9 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Create memory space to receive the data                         */
 /* -------------------------------------------------------------------- */
-    col_dims[poGDS->ndims-2]=nBlockYSize;
-    col_dims[poGDS->ndims-1]=nBlockXSize;
+    col_dims[poGDS->GetYIndex()]=nBlockYSize;
+    col_dims[poGDS->GetXIndex()]=nBlockXSize;
+
     memspace = H5Screate_simple( (int) rank, col_dims, NULL );
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
@@ -540,6 +568,11 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->dataset_id   = H5Dopen( poDS->hHDF5,poDS->poH5Objects->pszPath );
     poDS->dataspace_id = H5Dget_space( poDS->dataset_id );
     poDS->ndims        = H5Sget_simple_extent_ndims( poDS->dataspace_id );
+    if( poDS->ndims < 0 )
+    {
+        delete poDS;
+        return NULL;
+    }
     poDS->dims         = (hsize_t*)CPLCalloc( poDS->ndims, sizeof(hsize_t) );
     poDS->maxdims      = (hsize_t*)CPLCalloc( poDS->ndims, sizeof(hsize_t) );
     poDS->dimensions   = H5Sget_simple_extent_dims( poDS->dataspace_id,
@@ -551,13 +584,27 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->address = H5Dget_offset( poDS->dataset_id );
     poDS->native  = H5Tget_native_type( poDS->datatype, H5T_DIR_ASCEND );
 
-    poDS->nRasterYSize=(int)poDS->dims[poDS->ndims-2];   // Y
-    poDS->nRasterXSize=(int)poDS->dims[poDS->ndims-1];   // X alway last
-
-    poDS->nBands=1;
+    // CSK code in IdentifyProductType() and CreateProjections() 
+    // uses dataset metadata.
+    poDS->SetMetadata( poDS->papszMetadata );
 
-    if( poDS->ndims == 3 ) poDS->nBands=(int) poDS->dims[0];
+    // Check if the hdf5 is a well known product type
+    poDS->IdentifyProductType();
 
+    poDS->nRasterYSize=(int)poDS->dims[poDS->GetYIndex()];   // nRows
+    poDS->nRasterXSize=(int)poDS->dims[poDS->GetXIndex()];   // nCols
+    if( poDS->IsComplexCSKL1A() )
+    {
+        poDS->nBands=(int) poDS->dims[2]; // nBands
+    }
+    else if( poDS->ndims == 3 )
+    {
+        poDS->nBands=(int) poDS->dims[0];
+    }
+    else
+    {
+        poDS->nBands=1;
+    }
 
     for(  i = 1; i <= poDS->nBands; i++ ) {
         HDF5ImageRasterBand *poBand =
@@ -569,13 +616,6 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
             poBand->SetNoDataValue( 255 );
     }
 
-    // CSK code in IdentifyProductType() and CreateProjections() 
-    // uses dataset metadata.
-    poDS->SetMetadata( poDS->papszMetadata );
-
-    // Check if the hdf5 is a well known product type
-    poDS->IdentifyProductType();
-
     poDS->CreateProjections( );
 
 /* -------------------------------------------------------------------- */
@@ -620,6 +660,71 @@ void GDALRegister_HDF5Image( )
 }
 
 /************************************************************************/
+/*                       CreateODIMH5Projection()                       */
+/************************************************************************/
+
+/* Reference : http://www.knmi.nl/opera/opera3/OPERA_2008_03_WP2.1b_ODIM_H5_v2.1.pdf */
+/* 4.3.2 where for geographically referenced image Groups */
+/* We don't use the where_xscale and where_yscale parameters, but recompute them */
+/* from the lower-left and upper-right coordinates. There's some difference. */
+/* As all those parameters are linked together, I'm not sure which one should be */
+/* considered as the reference */
+
+CPLErr HDF5ImageDataset::CreateODIMH5Projection()
+{
+    const char* pszProj4String = GetMetadataItem("where_projdef");
+    const char* pszLL_lon = GetMetadataItem("where_LL_lon");
+    const char* pszLL_lat = GetMetadataItem("where_LL_lat");
+    const char* pszUR_lon = GetMetadataItem("where_UR_lon");
+    const char* pszUR_lat = GetMetadataItem("where_UR_lat");
+    if( pszProj4String == NULL ||
+        pszLL_lon == NULL || pszLL_lat == NULL ||
+        pszUR_lon == NULL || pszUR_lat == NULL )
+        return CE_Failure;
+
+    if( oSRS.importFromProj4( pszProj4String ) != OGRERR_NONE )
+        return CE_Failure;
+
+    OGRSpatialReference oSRSWGS84;
+    oSRSWGS84.SetWellKnownGeogCS( "WGS84" );
+
+    OGRCoordinateTransformation* poCT =
+        OGRCreateCoordinateTransformation( &oSRSWGS84, &oSRS );
+    if( poCT == NULL )
+        return CE_Failure;
+
+    /* Reproject corners from long,lat WGS84 to the target SRS */
+    double dfLLX = CPLAtof(pszLL_lon);
+    double dfLLY = CPLAtof(pszLL_lat);
+    double dfURX = CPLAtof(pszUR_lon);
+    double dfURY = CPLAtof(pszUR_lat);
+    if( !poCT->Transform(1, &dfLLX, &dfLLY) ||
+        !poCT->Transform(1, &dfURX, &dfURY) )
+    {
+        delete poCT;
+        return CE_Failure;
+    }
+    delete poCT;
+
+    /* Compute the geotransform now */
+    double dfPixelX = (dfURX - dfLLX) / nRasterXSize;
+    double dfPixelY = (dfURY - dfLLY) / nRasterYSize;
+
+    bHasGeoTransform = TRUE;
+    adfGeoTransform[0] = dfLLX;
+    adfGeoTransform[1] = dfPixelX;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = dfURY;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = -dfPixelY;
+
+    CPLFree( pszProjection );
+    oSRS.exportToWkt( &pszProjection );
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                         CreateProjections()                          */
 /************************************************************************/
 CPLErr HDF5ImageDataset::CreateProjections()
@@ -684,6 +789,8 @@ CPLErr HDF5ImageDataset::CreateProjections()
     /* -------------------------------------------------------------------- */
     poH5Objects=HDF5FindDatasetObjects( poH5RootGroup,  "Latitude" );
     if( !poH5Objects ) {
+        if( GetMetadataItem("where_projdef") != NULL )
+            return CreateODIMH5Projection();
         return CE_None;
     }
     /* -------------------------------------------------------------------- */
@@ -857,17 +964,44 @@ void HDF5ImageDataset::IdentifyProductType()
 /************************************************************************/
 /*                               COSMO-SKYMED                           */
 /************************************************************************/
-   const char *pszMissionId;
+    const char *pszMissionId;
 
     //Get the Mission Id as a char *, because the
     //field may not exist
     pszMissionId = HDF5Dataset::GetMetadataItem("Mission_ID");
 
     //If there is a Mission_ID field
-     if(pszMissionId != NULL && strstr(GetDescription(), "QLK") == NULL)
-         //Check if the mission type is CSK
-         if(EQUAL(pszMissionId,"CSK"))
-             iSubdatasetType = CSK_PRODUCT;
+    if(pszMissionId != NULL && strstr(GetDescription(), "QLK") == NULL)
+    {
+        //Check if the mission type is CSK
+        if(EQUAL(pszMissionId,"CSK"))
+        {
+            iSubdatasetType = CSK_PRODUCT;
+             
+            const char *osMissionLevel = NULL;
+
+            if(GetMetadataItem("Product_Type")!=NULL)
+            {
+                //Get the format's level
+                osMissionLevel = HDF5Dataset::GetMetadataItem("Product_Type");
+
+                if(EQUALN(osMissionLevel,"RAW",3))
+                    iCSKProductType  = PROD_CSK_L0;
+
+                if(EQUALN(osMissionLevel,"SCS",3))
+                    iCSKProductType  = PROD_CSK_L1A;
+                
+                if(EQUALN(osMissionLevel,"DGM",3))
+                    iCSKProductType  = PROD_CSK_L1B;
+
+                if(EQUALN(osMissionLevel,"GEC",3))
+                    iCSKProductType  = PROD_CSK_L1C;
+
+                if(EQUALN(osMissionLevel,"GTC",3))
+                    iCSKProductType  = PROD_CSK_L1D;
+            }
+        }
+    }
 }
 
 /************************************************************************/
diff --git a/frmts/hdf5/iso19115_srs.cpp b/frmts/hdf5/iso19115_srs.cpp
index 521c1e9..78dd88a 100644
--- a/frmts/hdf5/iso19115_srs.cpp
+++ b/frmts/hdf5/iso19115_srs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: iso19115_srs.cpp 26160 2013-07-10 00:27:52Z warmerdam $
+ * $Id: iso19115_srs.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BAG Driver
  * Purpose:  Implements code to parse ISO 19115 metadata to extract a
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_minixml.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: iso19115_srs.cpp 26160 2013-07-10 00:27:52Z warmerdam $");
+CPL_CVSID("$Id: iso19115_srs.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                     OGR_SRS_ImportFromISO19115()                     */
diff --git a/frmts/hf2/hf2dataset.cpp b/frmts/hf2/hf2dataset.cpp
index f9948cb..3b4c414 100644
--- a/frmts/hf2/hf2dataset.cpp
+++ b/frmts/hf2/hf2dataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: hf2dataset.cpp 24593 2012-06-16 18:58:42Z rouault $
+ * $Id: hf2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  HF2 driver
  * Purpose:  GDALDataset driver for HF2/HFZ dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hf2dataset.cpp 24593 2012-06-16 18:58:42Z rouault $");
+CPL_CVSID("$Id: hf2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_HF2(void);
diff --git a/frmts/hfa/frmt_hfa.html b/frmts/hfa/frmt_hfa.html
index 097f7dc..c2b3477 100644
--- a/frmts/hfa/frmt_hfa.html
+++ b/frmts/hfa/frmt_hfa.html
@@ -54,6 +54,20 @@ the original .img) set the global config option HFA_USE_RRD=YES).<p>
 
 Layer names can be set and retrieved with the GDALSetDescription/GDALGetDescription calls on the Raster Band objects. <p>
 
+<h2>Configuration Options</h2> 
+Currently only one <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration option</a> is supported by the HFA driver: 
+
+<ul> 
+<li> <b>HFA_COMPRESS_OVR=YES/NO</b> : (GDAL >= 1.11) Whether to create compressed overviews.
+Default is to only create compressed overviews when the file is compressed. <p> 
+This configuration option can be used when building .aux external overviews for a base image not in Erdas Imagine format.
+<pre>
+gdaladdo out.tif --config USE_RRD YES 2 --config HFA_COMPRESS_OVR YES 
+</pre>
+
+</li>
+</ul> 
+
 See Also:<p>
 
 <ul>
diff --git a/frmts/hfa/hfaband.cpp b/frmts/hfa/hfaband.cpp
index c919f98..322b55f 100644
--- a/frmts/hfa/hfaband.cpp
+++ b/frmts/hfa/hfaband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaband.cpp 24206 2012-04-07 15:43:21Z rouault $
+ * $Id: hfaband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFABand, for accessing one Eimg_Layer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 
 /* include the compression code */
 
-CPL_CVSID("$Id: hfaband.cpp 24206 2012-04-07 15:43:21Z rouault $");
+CPL_CVSID("$Id: hfaband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                              HFABand()                               */
@@ -2059,12 +2060,29 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Are we compressed? If so, overview should be too (unless        */
+/*      HFA_COMPRESS_OVR is defined).                                   */
+/*      Check RasterDMS like HFAGetBandInfo                             */
+/* -------------------------------------------------------------------- */
+    int bCompressionType = FALSE;
+    const char* pszCompressOvr = CPLGetConfigOption("HFA_COMPRESS_OVR", NULL);
+    if( pszCompressOvr != NULL )
+        bCompressionType = CSLTestBoolean(pszCompressOvr);
+    else
+    {
+        HFAEntry *poDMS = poNode->GetNamedChild( "RasterDMS" );
+
+        if( poDMS != NULL )
+            bCompressionType = poDMS->GetIntField( "compressionType" ) != 0;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Create the layer.                                               */
 /* -------------------------------------------------------------------- */
     osLayerName.Printf( "_ss_%d_", nOverviewLevel );
 
     if( !HFACreateLayer( psRRDInfo, poParent, osLayerName, 
-                         TRUE, 64, FALSE, bCreateLargeRaster, FALSE,
+                         TRUE, 64, bCompressionType, bCreateLargeRaster, FALSE,
                          nOXSize, nOYSize, nOverviewDataType, NULL,
                          nValidFlagsOffset, nDataOffset, 1, 0 ) )
         return -1;
diff --git a/frmts/hfa/hfadataset.cpp b/frmts/hfa/hfadataset.cpp
index b863cdc..270b85b 100644
--- a/frmts/hfa/hfadataset.cpp
+++ b/frmts/hfa/hfadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadataset.cpp 25815 2013-03-30 17:22:41Z rouault $
+ * $Id: hfadataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "hfa_p.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hfadataset.cpp 25815 2013-03-30 17:22:41Z rouault $");
+CPL_CVSID("$Id: hfadataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HFA(void);
@@ -338,6 +339,7 @@ class CPL_DLL HFADataset : public GDALPamDataset
 class HFARasterBand : public GDALPamRasterBand
 {
     friend class HFADataset;
+    friend class HFARasterAttributeTable;
 
     GDALColorTable *poCT;
 
@@ -361,43 +363,1564 @@ class HFARasterBand : public GDALPamRasterBand
     CPLErr      WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT );
 
 
-    GDALRasterAttributeTable* ReadNamedRAT( const char *pszName );
+  public:
+
+                   HFARasterBand( HFADataset *, int, int );
+    virtual        ~HFARasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IWriteBlock( int, int, void * );
+
+    virtual const char *GetDescription() const;
+    virtual void        SetDescription( const char * );
+
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr          SetColorTable( GDALColorTable * );
+    virtual int    GetOverviewCount();
+    virtual GDALRasterBand *GetOverview( int );
+
+    virtual double GetMinimum( int *pbSuccess = NULL );
+    virtual double GetMaximum(int *pbSuccess = NULL );
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr SetNoDataValue( double dfValue );
+
+    virtual CPLErr SetMetadata( char **, const char * = "" );
+    virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
+    virtual CPLErr BuildOverviews( const char *, int, int *,
+                                   GDALProgressFunc, void * );
+
+    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                        int *pnBuckets, int ** ppanHistogram,
+                                        int bForce,
+                                        GDALProgressFunc, void *pProgressData);
+
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+};
+
+class HFAAttributeField
+{
+public:
+    CPLString         sName;
+    GDALRATFieldType  eType;
+    GDALRATFieldUsage eUsage;
+    int               nDataOffset;
+    int               nElementSize;
+    HFAEntry         *poColumn;
+    int               bIsBinValues; // handled differently
+    int               bConvertColors; // map 0-1 floats to 0-255 ints
+};
+
+class HFARasterAttributeTable : public GDALRasterAttributeTable
+{
+private:
+
+    HFAHandle	hHFA;
+    HFAEntry   *poDT;
+    CPLString   osName;
+    int         nBand;
+    GDALAccess  eAccess;
+
+    std::vector<HFAAttributeField>  aoFields;
+    int         nRows;
+
+    int bLinearBinning;
+    double dfRow0Min;
+    double dfBinSize;
+
+    CPLString osWorkingResult;
+
+    void AddColumn(const char *pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage, 
+                int nDataOffset, int nElementSize, HFAEntry *poColumn, int bIsBinValues=FALSE,
+                int bConvertColors=FALSE)
+    {
+        HFAAttributeField aField;
+        aField.sName = pszName;
+        aField.eType = eType;
+        aField.eUsage = eUsage;
+        aField.nDataOffset = nDataOffset;
+        aField.nElementSize = nElementSize;
+        aField.poColumn = poColumn;
+        aField.bIsBinValues = bIsBinValues;
+        aField.bConvertColors = bConvertColors;
+
+        this->aoFields.push_back(aField);
+    }
+
+    void CreateDT()
+    {
+        this->poDT = new HFAEntry( this->hHFA->papoBand[this->nBand-1]->psInfo, 
+                             this->osName, "Edsc_Table",
+                             this->hHFA->papoBand[this->nBand-1]->poNode );
+        this->poDT->SetIntField( "numrows", nRows );
+    }
+
+public:
+    HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName);
+    ~HFARasterAttributeTable();
+
+    GDALDefaultRasterAttributeTable *Clone() const;
+    
+    virtual int           GetColumnCount() const;
+
+    virtual const char   *GetNameOfCol( int ) const;
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
+    virtual GDALRATFieldType GetTypeOfCol( int ) const;
+    
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
+
+    virtual int           GetRowCount() const;
+
+    virtual const char   *GetValueAsString( int iRow, int iField ) const;
+    virtual int           GetValueAsInt( int iRow, int iField ) const;
+    virtual double        GetValueAsDouble( int iRow, int iField ) const;
+
+    virtual void          SetValue( int iRow, int iField, const char *pszValue );
+    virtual void          SetValue( int iRow, int iField, double dfValue);
+    virtual void          SetValue( int iRow, int iField, int nValue );
+
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData);
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList);
+
+    virtual int           ChangesAreWrittenToFile();
+    virtual void          SetRowCount( int iCount );
+
+    virtual int           GetRowOfValue( double dfValue ) const;
+    virtual int           GetRowOfValue( int nValue ) const;
+
+    virtual CPLErr        CreateColumn( const char *pszFieldName, 
+                                GDALRATFieldType eFieldType, 
+                                GDALRATFieldUsage eFieldUsage );
+    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
+    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
+
+    virtual CPLXMLNode   *Serialize() const;
+
+protected:
+    CPLErr                ColorsIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
+};
+
+/************************************************************************/
+/*                     HFARasterAttributeTable()                        */
+/************************************************************************/
+
+HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName)
+{
+    this->hHFA = poBand->hHFA;
+    this->poDT = poBand->hHFA->papoBand[poBand->nBand-1]->poNode->GetNamedChild(pszName);
+    this->nBand = poBand->nBand;
+    this->eAccess = poBand->GetAccess();
+    this->osName = pszName;
+    this->nRows = 0;
+    this->bLinearBinning = FALSE;
+
+    if( this->poDT != NULL )
+    {
+        this->nRows = this->poDT->GetIntField( "numRows" );
+
+/* -------------------------------------------------------------------- */
+/*      Scan under table for columns.                                   */
+/* -------------------------------------------------------------------- */
+       HFAEntry *poDTChild;
+
+        for( poDTChild = poDT->GetChild(); 
+             poDTChild != NULL; 
+             poDTChild = poDTChild->GetNext() )
+        {
+            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
+            {
+                double dfMax = poDTChild->GetDoubleField( "maxLimit" );
+                double dfMin = poDTChild->GetDoubleField( "minLimit" );
+                int    nBinCount = poDTChild->GetIntField( "numBins" );
+
+                if( nBinCount == this->nRows
+                    && dfMax != dfMin && nBinCount != 0 )
+                {
+                    // can't call SetLinearBinning since it will re-write
+                    // which we might not have permission to do
+                    this->bLinearBinning = TRUE;
+                    this->dfRow0Min = dfMin;
+                    this->dfBinSize = (dfMax-dfMin) / (nBinCount-1);
+                }
+            }
+
+            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") 
+                && EQUAL(poDTChild->GetStringField( "binFunction.type.string" ),
+                         "BFUnique") )
+            {
+                AddColumn( "BinValues", GFT_Real, GFU_MinMax, 0, 0, poDTChild, TRUE);
+            }
+
+            if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
+                continue;
+
+            int nOffset = poDTChild->GetIntField( "columnDataPtr" );
+            const char * pszType = poDTChild->GetStringField( "dataType" );
+            GDALRATFieldUsage eUsage = GFU_Generic;
+            int bConvertColors = FALSE;
+
+            if( pszType == NULL || nOffset == 0 )
+                continue;
+
+            GDALRATFieldType eType;
+            if( EQUAL(pszType,"real") )
+                eType = GFT_Real;
+            else if( EQUAL(pszType,"string") )
+                eType = GFT_String;
+            else if( EQUALN(pszType,"int",3) )
+                eType = GFT_Integer;
+            else
+                continue;
+        
+            if( EQUAL(poDTChild->GetName(),"Histogram") )
+                eUsage = GFU_PixelCount;
+            else if( EQUAL(poDTChild->GetName(),"Red") )
+            {
+                eUsage = GFU_Red;
+                // treat color columns as ints regardless
+                // of how they are stored
+                bConvertColors = (eType == GFT_Real);
+                eType = GFT_Integer;
+            }
+            else if( EQUAL(poDTChild->GetName(),"Green") )
+            {
+                eUsage = GFU_Green;
+                bConvertColors = (eType == GFT_Real);
+                eType = GFT_Integer;
+            }
+            else if( EQUAL(poDTChild->GetName(),"Blue") )
+            {
+                eUsage = GFU_Blue;
+                bConvertColors = (eType == GFT_Real);
+                eType = GFT_Integer;
+            }
+            else if( EQUAL(poDTChild->GetName(),"Opacity") )
+            {
+                eUsage = GFU_Alpha;
+                bConvertColors = (eType == GFT_Real);
+                eType = GFT_Integer;
+            }
+            else if( EQUAL(poDTChild->GetName(),"Class_Names") )
+                eUsage = GFU_Name;
+
+            if( eType == GFT_Real )
+            {
+                AddColumn(poDTChild->GetName(), GFT_Real, eUsage, nOffset, sizeof(double), poDTChild);
+            }
+            else if( eType == GFT_String )
+            {
+                int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
+                AddColumn(poDTChild->GetName(), GFT_String, eUsage, nOffset, nMaxNumChars, poDTChild);
+            }
+            else if( eType == GFT_Integer )
+            {
+                int nSize = sizeof(GInt32);
+                if( bConvertColors )
+                    nSize = sizeof(double);
+                AddColumn(poDTChild->GetName(), GFT_Integer, eUsage, nOffset, nSize, poDTChild, 
+                                        FALSE, bConvertColors);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                    ~HFARasterAttributeTable()                        */
+/************************************************************************/
+
+HFARasterAttributeTable::~HFARasterAttributeTable()
+{
+
+}
+
+/************************************************************************/
+/*                              Clone()                                 */
+/************************************************************************/
+
+GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
+{
+    if( ( GetRowCount() * GetColumnCount() ) > RAT_MAX_ELEM_FOR_CLONE )
+        return NULL;
+
+    GDALDefaultRasterAttributeTable *poRAT = new GDALDefaultRasterAttributeTable();
+
+    for( int iCol = 0; iCol < (int)aoFields.size(); iCol++)
+    {
+        poRAT->CreateColumn(aoFields[iCol].sName, aoFields[iCol].eType, aoFields[iCol].eUsage);
+        poRAT->SetRowCount(this->nRows);
+
+        if( aoFields[iCol].eType == GFT_Integer )
+        {
+            int *panColData = (int*)VSIMalloc2(sizeof(int), this->nRows);
+            if( panColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
+                delete poRAT;
+                return NULL;
+            }
+
+            if( ((GDALDefaultRasterAttributeTable*)this)->
+                        ValuesIO(GF_Read, iCol, 0, this->nRows, panColData ) != CE_None )
+            {
+                CPLFree(panColData);
+                delete poRAT;
+                return NULL;
+            }           
+
+            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            {
+                poRAT->SetValue(iRow, iCol, panColData[iRow]);            
+            }
+            CPLFree(panColData);
+        }
+        if( aoFields[iCol].eType == GFT_Real )
+        {
+            double *padfColData = (double*)VSIMalloc2(sizeof(double), this->nRows);
+            if( padfColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
+                delete poRAT;
+                return NULL;
+            }
+
+            if( ((GDALDefaultRasterAttributeTable*)this)->
+                        ValuesIO(GF_Read, iCol, 0, this->nRows, padfColData ) != CE_None )
+            {
+                CPLFree(padfColData);
+                delete poRAT;
+                return NULL;
+            }           
+
+            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            {
+                poRAT->SetValue(iRow, iCol, padfColData[iRow]);            
+            }
+            CPLFree(padfColData);
+        }
+        if( aoFields[iCol].eType == GFT_String )
+        {
+            char **papszColData = (char**)VSIMalloc2(sizeof(char*), this->nRows);
+            if( papszColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
+                delete poRAT;
+                return NULL;
+            }
+
+            if( ((GDALDefaultRasterAttributeTable*)this)->
+                    ValuesIO(GF_Read, iCol, 0, this->nRows, papszColData ) != CE_None )
+            {
+                CPLFree(papszColData);
+                delete poRAT;
+                return NULL;
+            }           
+
+            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            {
+                poRAT->SetValue(iRow, iCol, papszColData[iRow]);
+                CPLFree(papszColData[iRow]);
+            }
+            CPLFree(papszColData);
+        }
+    }
+
+    if( this->bLinearBinning )
+        poRAT->SetLinearBinning( this->dfRow0Min, this->dfBinSize );
+
+    return poRAT;
+}
+    
+/************************************************************************/
+/*                          GetColumnCount()                            */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetColumnCount() const
+{
+    return this->aoFields.size();
+}
+
+/************************************************************************/
+/*                          GetNameOfCol()                              */
+/************************************************************************/
+
+const char *HFARasterAttributeTable::GetNameOfCol( int nCol ) const
+{
+    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+        return NULL;
+
+    return this->aoFields[nCol].sName;
+}
+
+/************************************************************************/
+/*                          GetUsageOfCol()                             */
+/************************************************************************/
+
+GDALRATFieldUsage HFARasterAttributeTable::GetUsageOfCol( int nCol ) const
+{
+    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+        return GFU_Generic;
+
+    return this->aoFields[nCol].eUsage;
+}
+
+/************************************************************************/
+/*                          GetTypeOfCol()                              */
+/************************************************************************/
+
+GDALRATFieldType HFARasterAttributeTable::GetTypeOfCol( int nCol ) const
+{
+    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+        return GFT_Integer;
+
+    return this->aoFields[nCol].eType;
+}
+    
+/************************************************************************/
+/*                          GetColOfUsage()                             */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
+{
+    unsigned int i;
+
+    for( i = 0; i < this->aoFields.size(); i++ )
+    {
+        if( this->aoFields[i].eUsage == eUsage )
+            return i;
+    }
+
+    return -1;
+
+}
+/************************************************************************/
+/*                          GetRowCount()                               */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetRowCount() const
+{
+    return this->nRows;
+}
+
+/************************************************************************/
+/*                      GetValueAsString()                              */
+/************************************************************************/
+
+const char *HFARasterAttributeTable::GetValueAsString( int iRow, int iField ) const
+{
+    // Get ValuesIO do do the work
+    char *apszStrList[1];
+    if( ((HFARasterAttributeTable*)this)->
+                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CPLE_None )
+    {
+        return "";
+    }
+
+    ((HFARasterAttributeTable *) this)->osWorkingResult = apszStrList[0];
+    CPLFree(apszStrList[0]);
+
+    return osWorkingResult;
+}
+
+/************************************************************************/
+/*                        GetValueAsInt()                               */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
+{
+    // Get ValuesIO do do the work
+    int nValue;
+    if( ((HFARasterAttributeTable*)this)->
+                ValuesIO(GF_Read, iField, iRow, 1, &nValue ) != CE_None )
+    {
+        return 0;
+    }
+
+    return nValue;
+}
+
+/************************************************************************/
+/*                      GetValueAsDouble()                              */
+/************************************************************************/
+
+double HFARasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
+{
+    // Get ValuesIO do do the work
+    double dfValue;
+    if( ((HFARasterAttributeTable*)this)->
+                ValuesIO(GF_Read, iField, iRow, 1, &dfValue ) != CE_None )
+    {
+        return 0;
+    }
+
+    return dfValue;
+}
+
+/************************************************************************/
+/*                          SetValue()                                  */
+/************************************************************************/
+
+void HFARasterAttributeTable::SetValue( int iRow, int iField, const char *pszValue )
+{
+    // Get ValuesIO do do the work
+    ValuesIO(GF_Write, iField, iRow, 1, (char**)&pszValue );
+}
+
+/************************************************************************/
+/*                          SetValue()                                  */
+/************************************************************************/
+
+void HFARasterAttributeTable::SetValue( int iRow, int iField, double dfValue)
+{
+    // Get ValuesIO do do the work
+    ValuesIO(GF_Write, iField, iRow, 1, &dfValue );
+}
+
+/************************************************************************/
+/*                          SetValue()                                  */
+/************************************************************************/
+
+void HFARasterAttributeTable::SetValue( int iRow, int iField, int nValue )
+{
+    // Get ValuesIO do do the work
+    ValuesIO(GF_Write, iField, iRow, 1, &nValue );
+}
+
+/************************************************************************/
+/*                          ValuesIO()                                  */
+/************************************************************************/
+
+CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
+{
+    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return CE_Failure;
+    }
+
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return CE_Failure;
+    }
+
+    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+
+        return CE_Failure;
+    }
+
+    if( aoFields[iField].bConvertColors )
+    {
+        // convert to/from float color field
+        int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+        if( panColData == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+            CPLFree(panColData);
+            return CE_Failure;
+        }
+
+        if( eRWFlag == GF_Write )
+        {
+            for( int i = 0; i < iLength; i++ )
+                panColData[i] = pdfData[i];
+        }
+
+        CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
+
+        if( eRWFlag == GF_Read )
+        {
+            // copy them back to doubles
+            for( int i = 0; i < iLength; i++ )
+                pdfData[i] = panColData[i];
+        }
+
+        CPLFree(panColData);
+        return ret;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+        case GFT_Integer:
+        {
+            // allocate space for ints
+            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            if( panColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                CPLFree(panColData);
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Write )
+            {
+                // copy the application supplied doubles to ints
+                for( int i = 0; i < iLength; i++ )
+                    panColData[i] = pdfData[i];
+            }
+
+            // do the ValuesIO as ints
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData );
+            if( eVal != CE_None )
+            {
+                CPLFree(panColData);
+                return eVal;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                // copy them back to doubles
+                for( int i = 0; i < iLength; i++ )
+                    pdfData[i] = panColData[i];
+            }
+
+            CPLFree(panColData);
+        }
+        break;
+        case GFT_Real:
+        {
+            if( (eRWFlag == GF_Read ) && aoFields[iField].bIsBinValues )
+            {
+                // probably could change HFAReadBFUniqueBins to only read needed rows
+                double *padfBinValues = HFAReadBFUniqueBins( aoFields[iField].poColumn, iStartRow+iLength );
+                memcpy(pdfData, &padfBinValues[iStartRow], sizeof(double) * iLength);
+                CPLFree(padfBinValues);
+            }
+            else
+            {
+                VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+
+                if( eRWFlag == GF_Read )
+                {
+                    if ((int)VSIFReadL(pdfData, sizeof(double), iLength, hHFA->fp ) != iLength)
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                            "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                        return CE_Failure;
+                    }
+#ifdef CPL_MSB
+                    GDALSwapWords( pdfData, 8, iLength, 8 );
+#endif
+                }
+                else
+                {
+#ifdef CPL_MSB
+                    GDALSwapWords( pdfData, 8, iLength, 8 );
+#endif
+                    // Note: HFAAllocateSpace now called by CreateColumn so space should exist
+                    if((int)VSIFWriteL(pdfData, sizeof(double), iLength, hHFA->fp) != iLength)
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                            "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                        return CE_Failure;
+                    }
+#ifdef CPL_MSB
+                    // swap back
+                    GDALSwapWords( pdfData, 8, iLength, 8 );
+#endif
+                }
+            }
+        }
+        break;
+        case GFT_String:
+        {
+            // allocate space for string pointers
+            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            if( papszColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Write )
+            {
+                // copy the application supplied doubles to strings
+                for( int i = 0; i < iLength; i++ )
+                {
+                    osWorkingResult.Printf( "%.16g", pdfData[i] );
+                    papszColData[i] = CPLStrdup(osWorkingResult);
+                }
+            }
+
+            // do the ValuesIO as strings
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
+            if( eVal != CE_None )
+            {
+                if( eRWFlag == GF_Write )
+                {
+                    for( int i = 0; i < iLength; i++ )
+                        CPLFree(papszColData[i]);
+                }
+                CPLFree(papszColData);
+                return eVal;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                // copy them back to doubles
+                for( int i = 0; i < iLength; i++ )
+                    pdfData[i] = atof(papszColData[i]);
+            }
+
+            // either we allocated them for write, or they were allocated
+            // by ValuesIO on read
+            for( int i = 0; i < iLength; i++ )
+                CPLFree(papszColData[i]);
+
+            CPLFree(papszColData);
+        }
+        break;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          ValuesIO()                                  */
+/************************************************************************/
+
+CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
+{
+    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return CE_Failure;
+    }
+
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return CE_Failure;
+    }
+
+    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+
+        return CE_Failure;
+    }
+
+    if( aoFields[iField].bConvertColors )
+    {
+        // convert to/from float color field
+        return ColorsIO(eRWFlag, iField, iStartRow, iLength, pnData);
+    }
+
+    switch( aoFields[iField].eType )
+    {
+        case GFT_Integer:
+        {
+            VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+            GInt32 *panColData = (GInt32*)VSIMalloc2(iLength, sizeof(GInt32));
+            if( panColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                if ((int)VSIFReadL( panColData, sizeof(GInt32), iLength, hHFA->fp ) != iLength)
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                    CPLFree(panColData);
+                    return CE_Failure;
+                }
+#ifdef CPL_MSB
+                GDALSwapWords( panColData, 4, iLength, 4 );
+#endif
+                // now copy into application buffer. This extra step
+                // may not be necessary if sizeof(int) == sizeof(GInt32)
+                for( int i = 0; i < iLength; i++ )
+                    pnData[i] = panColData[i];
+            }
+            else
+            {
+                // copy from application buffer
+                for( int i = 0; i < iLength; i++ )
+                    panColData[i] = pnData[i];
+
+#ifdef CPL_MSB
+                GDALSwapWords( panColData, 4, iLength, 4 );
+#endif
+                // Note: HFAAllocateSpace now called by CreateColumn so space should exist
+                if((int)VSIFWriteL(panColData, sizeof(GInt32), iLength, hHFA->fp) != iLength)
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                    CPLFree(panColData);
+                    return CE_Failure;
+                }
+            }
+            CPLFree(panColData);
+        }
+        break;
+        case GFT_Real:
+        {
+            // allocate space for doubles
+            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            if( padfColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Write )
+            {
+                // copy the application supplied ints to doubles
+                for( int i = 0; i < iLength; i++ )
+                    padfColData[i] = pnData[i];
+            }
+
+            // do the ValuesIO as doubles
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData );
+            if( eVal != CE_None )
+            {
+                CPLFree(padfColData);
+                return eVal;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                // copy them back to ints
+                for( int i = 0; i < iLength; i++ )
+                    pnData[i] = padfColData[i];
+            }
+
+            CPLFree(padfColData);
+        }
+        break;
+        case GFT_String:
+        {
+            // allocate space for string pointers
+            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            if( papszColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Write )
+            {
+                // copy the application supplied ints to strings
+                for( int i = 0; i < iLength; i++ )
+                {
+                    osWorkingResult.Printf( "%d", pnData[i] );
+                    papszColData[i] = CPLStrdup(osWorkingResult);
+                }
+            }
+
+            // do the ValuesIO as strings
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
+            if( eVal != CE_None )
+            {
+                if( eRWFlag == GF_Write )
+                {
+                    for( int i = 0; i < iLength; i++ )
+                        CPLFree(papszColData[i]);
+                }
+                CPLFree(papszColData);
+                return eVal;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                // copy them back to ints
+                for( int i = 0; i < iLength; i++ )
+                    pnData[i] = atol(papszColData[i]);
+            }
+
+            // either we allocated them for write, or they were allocated
+            // by ValuesIO on read
+            for( int i = 0; i < iLength; i++ )
+                CPLFree(papszColData[i]);
+
+            CPLFree(papszColData);
+        }
+        break;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          ValuesIO()                                  */
+/************************************************************************/
+
+CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList)
+{
+    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return CE_Failure;
+    }
+
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return CE_Failure;
+    }
+
+    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+
+        return CE_Failure;
+    }
+
+    if( aoFields[iField].bConvertColors )
+    {
+        // convert to/from float color field
+        int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+        if( panColData == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+            CPLFree(panColData);
+            return CE_Failure;
+        }
+
+        if( eRWFlag == GF_Write )
+        {
+            for( int i = 0; i < iLength; i++ )
+                panColData[i] = atol(papszStrList[i]);
+        }
+
+        CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
+
+        if( eRWFlag == GF_Read )
+        {
+            // copy them back to strings
+            for( int i = 0; i < iLength; i++ )
+            {
+                osWorkingResult.Printf( "%d", panColData[i]);
+                papszStrList[i] = CPLStrdup(osWorkingResult);
+            }
+        }
+
+        CPLFree(panColData);
+        return ret;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+        case GFT_Integer:
+        {
+            // allocate space for ints
+            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            if( panColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+            
+            if( eRWFlag == GF_Write )
+            {
+                // convert user supplied strings to ints
+                for( int i = 0; i < iLength; i++ )
+                    panColData[i] = atol(papszStrList[i]);
+            }
+
+            // call values IO to read/write ints
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
+            if( eVal != CE_None )
+            {
+                CPLFree(panColData);
+                return eVal;
+            }
+
+
+            if( eRWFlag == GF_Read )
+            {
+                // convert ints back to strings
+                for( int i = 0; i < iLength; i++ )
+                {
+                    osWorkingResult.Printf( "%d", panColData[i]);
+                    papszStrList[i] = CPLStrdup(osWorkingResult);
+                }
+            }
+            CPLFree(panColData);
+        }
+        break;
+        case GFT_Real:
+        {
+            // allocate space for doubles
+            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            if( padfColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+            
+            if( eRWFlag == GF_Write )
+            {
+                // convert user supplied strings to doubles
+                for( int i = 0; i < iLength; i++ )
+                    padfColData[i] = atof(papszStrList[i]);
+            }
+
+            // call value IO to read/write doubles
+            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
+            if( eVal != CE_None )
+            {
+                CPLFree(padfColData);
+                return eVal;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                // convert doubles back to strings
+                for( int i = 0; i < iLength; i++ )
+                {
+                    osWorkingResult.Printf( "%.16g", padfColData[i]);
+                    papszStrList[i] = CPLStrdup(osWorkingResult);
+                }
+            }
+            CPLFree(padfColData);
+        }
+        break;
+        case GFT_String:
+        {
+            VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+            char *pachColData = (char*)VSIMalloc2(iLength, aoFields[iField].nElementSize);
+            if( pachColData == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                return CE_Failure;
+            }
+
+            if( eRWFlag == GF_Read )
+            {
+                if ((int)VSIFReadL( pachColData, aoFields[iField].nElementSize, iLength, hHFA->fp ) != iLength)
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                    CPLFree(pachColData);
+                    return CE_Failure;
+                }
+
+                // now copy into application buffer
+                for( int i = 0; i < iLength; i++ )
+                {
+                    osWorkingResult.assign(pachColData+aoFields[iField].nElementSize*i, aoFields[iField].nElementSize );
+                    papszStrList[i] = CPLStrdup(osWorkingResult);
+                }
+            }
+            else
+            {
+                // we need to check that these strings will fit in the allocated space
+                int nNewMaxChars = aoFields[iField].nElementSize, nStringSize;
+                for( int i = 0; i < iLength; i++ )
+                {
+                    nStringSize = strlen(papszStrList[i]) + 1;
+                    if( nStringSize > nNewMaxChars )
+                        nNewMaxChars = nStringSize;
+                }
+
+                if( nNewMaxChars > aoFields[iField].nElementSize )
+                {
+                    // OK we have a problem - the allocated space is not big enough
+                    // we need to re-allocate the space and update the pointers
+                    // and copy accross the old data
+                    int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                                            this->nRows * nNewMaxChars);
+                    char *pszBuffer = (char*)VSIMalloc2(aoFields[iField].nElementSize, sizeof(char));
+                    char cNullByte = '\0';
+                    for( int i = 0; i < this->nRows; i++ )
+                    {
+                        // seek to the old place
+                        VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (i*aoFields[iField].nElementSize), SEEK_SET );
+                        // read in old data
+                        VSIFReadL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp );
+                        // seek to new place
+                        VSIFSeekL( hHFA->fp, nNewOffset + (i*nNewMaxChars), SEEK_SET );
+                        // write data to new place
+                        VSIFWriteL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp);
+                        // make sure there is a terminating null byte just to be safe
+                        VSIFWriteL(&cNullByte, sizeof(char), 1, hHFA->fp);
+                    }
+                    // update our data structures
+                    aoFields[iField].nElementSize = nNewMaxChars;
+                    aoFields[iField].nDataOffset = nNewOffset;
+                    // update file
+                    aoFields[iField].poColumn->SetIntField( "columnDataPtr", nNewOffset );
+                    aoFields[iField].poColumn->SetIntField( "maxNumChars", nNewMaxChars );
+
+                    // Note: there isn't an HFAFreeSpace so we can't un-allocate the old space in the file
+                    CPLFree(pszBuffer);
+
+                    // re-allocate our buffer
+                    CPLFree(pachColData);
+                    pachColData = (char*)VSIMalloc2(iLength, nNewMaxChars);
+                    if(pachColData == NULL )
+                    {
+                        CPLError( CE_Failure, CPLE_OutOfMemory,
+                            "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
+                        return CE_Failure;
+                    }
+
+                    // lastly seek to the right place in the new space ready to write
+                    VSIFSeekL( hHFA->fp, nNewOffset + (iStartRow*nNewMaxChars), SEEK_SET );
+                }
+
+                // copy from application buffer
+                for( int i = 0; i < iLength; i++ )
+                    strcpy(&pachColData[nNewMaxChars*i], papszStrList[i]);
+
+                // Note: HFAAllocateSpace now called by CreateColumn so space should exist
+                if((int)VSIFWriteL(pachColData, aoFields[iField].nElementSize, iLength, hHFA->fp) != iLength)
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                    CPLFree(pachColData);
+                    return CE_Failure;
+                }
+            }
+            CPLFree(pachColData);
+        }
+        break;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                               ColorsIO()                              */
+/************************************************************************/
+
+// Handle the fact that HFA stores colours as floats, but we need to 
+// read them in as ints 0...255
+CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
+{
+    // allocate space for doubles
+    double *padfData = (double*)VSIMalloc2(iLength, sizeof(double) );
+    if( padfData == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+            "Memory Allocation failed in HFARasterAttributeTable::ColorsIO");
+        return CE_Failure;
+    }
+
+    if( eRWFlag == GF_Write )
+    {
+        // copy the application supplied ints to doubles
+        // and convert 0..255 to 0..1 in the same manner 
+        // as the color table
+        for( int i = 0; i < iLength; i++ )
+            padfData[i] = pnData[i] / 255.0;
+    }
+
+    VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+
+    if( eRWFlag == GF_Read )
+    {
+        if ((int)VSIFReadL(padfData, sizeof(double), iLength, hHFA->fp ) != iLength)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                "HFARasterAttributeTable::ColorsIO : Cannot read values");
+            return CE_Failure;
+        }
+#ifdef CPL_MSB
+        GDALSwapWords( padfData, 8, iLength, 8 );
+#endif
+    }
+    else
+    {
+#ifdef CPL_MSB
+        GDALSwapWords( padfData, 8, iLength, 8 );
+#endif
+        // Note: HFAAllocateSpace now called by CreateColumn so space should exist
+        if((int)VSIFWriteL(padfData, sizeof(double), iLength, hHFA->fp) != iLength)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                "HFARasterAttributeTable::ColorsIO : Cannot write values");
+            return CE_Failure;
+        }
+    }
+
+    if( eRWFlag == GF_Read )
+    {
+        // copy them back to ints converting 0..1 to 0..255 in
+        // the same manner as the color table 
+        for( int i = 0; i < iLength; i++ )
+            pnData[i] = MIN(255,(int) (padfData[i] * 256));
+    }
+
+    CPLFree(padfData);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       ChangesAreWrittenToFile()                      */
+/************************************************************************/
+
+int HFARasterAttributeTable::ChangesAreWrittenToFile()
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          SetRowCount()                               */
+/************************************************************************/
+
+void HFARasterAttributeTable::SetRowCount( int iCount )
+{
+    if( this->eAccess == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return;
+    }
+
+    if( iCount > this->nRows )
+    {
+        // making the RAT larger - a bit hard
+        // We need to re-allocate space on disc
+        for( int iCol = 0; iCol < (int)this->aoFields.size(); iCol++ )
+        {
+            // new space 
+            int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                                            iCount * aoFields[iCol].nElementSize);
+
+            // only need to bother if there are actually rows
+            if( this->nRows > 0 )
+            {
+                // temp buffer for this column
+                void *pData = VSIMalloc2(this->nRows, aoFields[iCol].nElementSize);
+                if( pData == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_OutOfMemory,
+                        "Memory Allocation failed in HFARasterAttributeTable::SetRowCount");
+                    return;
+                }
+                // read old data
+                VSIFSeekL( hHFA->fp, aoFields[iCol].nDataOffset, SEEK_SET );
+                if((int)VSIFReadL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "HFARasterAttributeTable::SetRowCount : Cannot read values");
+                    CPLFree(pData);
+                    return;                
+                }
+
+                // write data - new space will be uninitialised
+                VSIFSeekL( hHFA->fp, nNewOffset, SEEK_SET );
+                if((int)VSIFWriteL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                            "HFARasterAttributeTable::SetRowCount : Cannot write values");
+                    CPLFree(pData);
+                    return;                
+                }
+                CPLFree(pData);
+            }
 
-  public:
+            // update our data structures
+            aoFields[iCol].nDataOffset = nNewOffset;
+            // update file
+            aoFields[iCol].poColumn->SetIntField( "columnDataPtr", nNewOffset );
+            aoFields[iCol].poColumn->SetIntField( "numRows", iCount);
+        }
+    }
+    else if( iCount < this->nRows )
+    {
+        // update the numRows
+        for( int iCol = 0; iCol < (int)this->aoFields.size(); iCol++ )
+        {
+            aoFields[iCol].poColumn->SetIntField( "numRows", iCount);
+        }
+    }
 
-                   HFARasterBand( HFADataset *, int, int );
-    virtual        ~HFARasterBand();
+    this->nRows = iCount;
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    if( ( this->poDT != NULL ) && ( EQUAL(this->poDT->GetType(),"Edsc_Table")))
+    {
+        this->poDT->SetIntField( "numrows", iCount );
+    }
+}
 
-    virtual const char *GetDescription() const;
-    virtual void        SetDescription( const char * );
+/************************************************************************/
+/*                          GetRowOfValue()                             */
+/************************************************************************/
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr          SetColorTable( GDALColorTable * );
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
+int HFARasterAttributeTable::GetRowOfValue( double dfValue ) const
+{
+/* -------------------------------------------------------------------- */
+/*      Handle case of regular binning.                                 */
+/* -------------------------------------------------------------------- */
+    if( bLinearBinning )
+    {
+        int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
+        if( iBin < 0 || iBin >= this->nRows )
+            return -1;
+        else
+            return iBin;
+    }
 
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr SetNoDataValue( double dfValue );
+/* -------------------------------------------------------------------- */
+/*      Do we have any information?                                     */
+/* -------------------------------------------------------------------- */
+    int nMinCol = GetColOfUsage( GFU_Min );
+    if( nMinCol == -1 )
+        nMinCol = GetColOfUsage( GFU_MinMax );
 
-    virtual CPLErr SetMetadata( char **, const char * = "" );
-    virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
-    virtual CPLErr BuildOverviews( const char *, int, int *,
-                                   GDALProgressFunc, void * );
+    int nMaxCol = GetColOfUsage( GFU_Max );
+    if( nMaxCol == -1 )
+        nMaxCol = GetColOfUsage( GFU_MinMax );
 
-    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                        int *pnBuckets, int ** ppanHistogram,
-                                        int bForce,
-                                        GDALProgressFunc, void *pProgressData);
+    if( nMinCol == -1 && nMaxCol == -1 )
+        return -1;
 
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
-};
+/* -------------------------------------------------------------------- */
+/*      Search through rows for match.                                  */
+/* -------------------------------------------------------------------- */
+    int   iRow;
+
+    for( iRow = 0; iRow < this->nRows; iRow++ )
+    {
+        if( nMinCol != -1 )
+        {
+            while( iRow < this->nRows && dfValue < GetValueAsDouble(iRow, nMinCol) ) 
+                    iRow++;
+
+            if( iRow == this->nRows )
+                break;
+        }
+
+        if( nMaxCol != -1 )
+        {
+            if( dfValue > GetValueAsDouble(iRow, nMaxCol) )
+                continue;
+        }
+
+        return iRow;
+    }
+
+    return -1;
+}
+
+/************************************************************************/
+/*                          GetRowOfValue()                             */
+/*                                                                      */
+/*      Int arg for now just converted to double.  Perhaps we will      */
+/*      handle this in a special way some day?                          */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetRowOfValue( int nValue ) const
+{
+    return GetRowOfValue( (double) nValue );
+}
+
+/************************************************************************/
+/*                          CreateColumn()                              */
+/************************************************************************/
+
+CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName, 
+                                GDALRATFieldType eFieldType, 
+                                GDALRATFieldUsage eFieldUsage )
+{
+    if( this->eAccess == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return CE_Failure;
+    }
+
+    // do we have a descriptor table already?
+    if( this->poDT == NULL || !EQUAL(this->poDT->GetType(),"Edsc_Table") )
+        CreateDT();
+
+    int bConvertColors = FALSE;
+
+    // Imagine doesn't have a concept of usage - works of the names instead.
+    // must make sure name matches use
+    if( eFieldUsage == GFU_Red )
+    {
+        pszFieldName = "Red";
+        // create a real column in the file, but make it
+        // available as int to GDAL
+        bConvertColors = TRUE;
+        eFieldType = GFT_Real;
+    }
+    else if( eFieldUsage == GFU_Green )
+    {
+        pszFieldName = "Green";
+        bConvertColors = TRUE;
+        eFieldType = GFT_Real;
+    }
+    else if( eFieldUsage == GFU_Blue )
+    {
+        pszFieldName = "Blue";
+        bConvertColors = TRUE;
+        eFieldType = GFT_Real;
+    }
+    else if( eFieldUsage == GFU_Alpha )
+    {
+        pszFieldName = "Opacity";
+        bConvertColors = TRUE;
+        eFieldType = GFT_Real;
+    }
+    else if( eFieldUsage == GFU_PixelCount )
+    {
+        pszFieldName = "Histogram";
+        // histogram is always float in HFA
+        eFieldType = GFT_Real;
+    }
+    else if( eFieldUsage == GFU_Name )
+    {
+        pszFieldName = "Class_Names";
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check to see if a column with pszFieldName exists and create it */
+/*      if necessary.                                                   */
+/* -------------------------------------------------------------------- */
+
+    HFAEntry        *poColumn;
+    poColumn = poDT->GetNamedChild(pszFieldName);
+        
+    if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
+        poColumn = new HFAEntry( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                                     pszFieldName, "Edsc_Column",
+                                     this->poDT );
+
+
+    poColumn->SetIntField( "numRows", this->nRows );
+    int nElementSize = 0;
+
+    if( eFieldType == GFT_Integer )
+    {
+        nElementSize = sizeof(GInt32);
+        poColumn->SetStringField( "dataType", "integer" );
+    }
+    else if( eFieldType == GFT_Real )
+    {
+        nElementSize = sizeof(double);
+        poColumn->SetStringField( "dataType", "real" );
+    }
+    else if( eFieldType == GFT_String )
+    {
+        // just have to guess here since we don't have any
+        // strings to check
+        nElementSize = 10;
+        poColumn->SetStringField( "dataType", "string" );
+        poColumn->SetIntField( "maxNumChars", nElementSize);
+    }
+    else
+    {
+        /* can't deal with any of the others yet */
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Writing this data type in a column is not supported for this Raster Attribute Table.");
+        return CE_Failure;
+    }
+
+    int nOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                                        this->nRows * nElementSize );
+    poColumn->SetIntField( "columnDataPtr", nOffset );
+
+    if( bConvertColors )
+        // GDAL Int column 
+        eFieldType = GFT_Integer;
+
+    AddColumn(pszFieldName, eFieldType, eFieldUsage, nOffset, nElementSize, poColumn, FALSE, bConvertColors);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          SetLinearBinning()                          */
+/************************************************************************/
+
+CPLErr HFARasterAttributeTable::SetLinearBinning( double dfRow0MinIn, double dfBinSizeIn )
+{
+    if( this->eAccess == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+            "Dataset not open in update mode");
+        return CE_Failure;
+    }
+
+    this->bLinearBinning = TRUE;
+    this->dfRow0Min = dfRow0MinIn;
+    this->dfBinSize = dfBinSizeIn;
+
+    // do we have a descriptor table already?
+    if( this->poDT == NULL || !EQUAL(this->poDT->GetType(),"Edsc_Table") )
+        CreateDT();
+
+    /* we should have an Edsc_BinFunction */
+    HFAEntry *poBinFunction = this->poDT->GetNamedChild( "#Bin_Function#" );
+    if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
+        poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+                                      "#Bin_Function#", "Edsc_BinFunction",
+                                      this->poDT );
+
+    // Because of the BaseData we have to hardcode the size. 
+    poBinFunction->MakeData( 30 );
+       
+    poBinFunction->SetStringField("binFunction", "direct");
+    poBinFunction->SetDoubleField("minLimit",this->dfRow0Min);
+    poBinFunction->SetDoubleField("maxLimit",(this->nRows -1)*this->dfBinSize+this->dfRow0Min);
+    poBinFunction->SetIntField("numBins",this->nRows);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetLinearBinning()                          */
+/************************************************************************/
+
+int HFARasterAttributeTable::GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const
+{
+    if( !bLinearBinning )
+        return FALSE;
+
+    *pdfRow0Min = dfRow0Min;
+    *pdfBinSize = dfBinSize;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              Serialize()                             */
+/************************************************************************/
+
+CPLXMLNode *HFARasterAttributeTable::Serialize() const
+{
+    if( ( GetRowCount() * GetColumnCount() ) > RAT_MAX_ELEM_FOR_CLONE )
+        return NULL;
+
+    return GDALRasterAttributeTable::Serialize();
+}
 
 /************************************************************************/
 /*                           HFARasterBand()                            */
@@ -559,7 +2082,6 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
         }
     }
 
-    poDefaultRAT = ReadNamedRAT( "Descriptor_Table" );
 }
 
 /************************************************************************/
@@ -1513,196 +3035,16 @@ CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
 
 {		
+    if( poDefaultRAT == NULL )
+        poDefaultRAT = new HFARasterAttributeTable(this, "Descriptor_Table" );
+ 
     return poDefaultRAT;
 }
 
 /************************************************************************/
-/*                            ReadNamedRAT()                            */
-/************************************************************************/
-
-GDALRasterAttributeTable *HFARasterBand::ReadNamedRAT( const char *pszName )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Find the requested table.                                       */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild(pszName);
-
-    if( poDT == NULL )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding RAT.                                     */
-/* -------------------------------------------------------------------- */
-    GDALRasterAttributeTable *poRAT = NULL;
-    int nRowCount = poDT->GetIntField( "numRows" );
-
-    poRAT = new GDALRasterAttributeTable();
-
-/* -------------------------------------------------------------------- */
-/*      Scan under table for columns.                                   */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poDTChild;
-
-    for( poDTChild = poDT->GetChild(); 
-         poDTChild != NULL; 
-         poDTChild = poDTChild->GetNext() )
-    {
-        int i;
-
-        if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
-        {
-            double dfMax = poDTChild->GetDoubleField( "maxLimit" );
-            double dfMin = poDTChild->GetDoubleField( "minLimit" );
-            int    nBinCount = poDTChild->GetIntField( "numBins" );
-
-            if( nBinCount == nRowCount 
-                && dfMax != dfMin && nBinCount != 0 )
-                poRAT->SetLinearBinning( dfMin, 
-                                         (dfMax-dfMin) / (nBinCount-1) );
-        }
-
-        if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") 
-            && EQUAL(poDTChild->GetStringField( "binFunction.type.string" ),
-                     "BFUnique") )
-        {
-            double *padfBinValues = HFAReadBFUniqueBins( poDTChild, nRowCount );
-            
-            if( padfBinValues != NULL )
-            {
-                poRAT->CreateColumn( "BinValues", GFT_Real, GFU_MinMax );
-                for( i = 0; i < nRowCount; i++ )
-                    poRAT->SetValue( i, poRAT->GetColumnCount()-1, 
-                                     padfBinValues[i] );
-
-                CPLFree( padfBinValues );
-            }
-        }
-
-        if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
-            continue;
-
-        int nOffset = poDTChild->GetIntField( "columnDataPtr" );
-        const char * pszType = poDTChild->GetStringField( "dataType" );
-        GDALRATFieldUsage eType = GFU_Generic;
-
-        if( pszType == NULL || nOffset == 0 )
-            continue;
-        
-        if( EQUAL(poDTChild->GetName(),"Histogram") )
-            eType = GFU_Generic;
-        else if( EQUAL(poDTChild->GetName(),"Red") )
-            eType = GFU_Red;
-        else if( EQUAL(poDTChild->GetName(),"Green") )
-            eType = GFU_Green;
-        else if( EQUAL(poDTChild->GetName(),"Blue") )
-            eType = GFU_Blue;
-        else if( EQUAL(poDTChild->GetName(),"Alpha") )
-            eType = GFU_Alpha;
-        else if( EQUAL(poDTChild->GetName(),"Class_Names") )
-            eType = GFU_Name;
-            
-        if( EQUAL(pszType,"real") )
-        {
-            double *padfColData = (double*)VSIMalloc2(nRowCount, sizeof(double));
-            if (nRowCount != 0 && padfColData == NULL)
-            {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFARasterBand::ReadNamedRAT : Out of memory");
-                delete poRAT;
-                return NULL;
-            }
-
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            if ((int)VSIFReadL( padfColData, sizeof(double), nRowCount, hHFA->fp ) != nRowCount)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterBand::ReadNamedRAT : Cannot read values");
-                CPLFree(padfColData);
-                delete poRAT;
-                return NULL;
-            }
-#ifdef CPL_MSB
-            GDALSwapWords( padfColData, 8, nRowCount, 8 );
-#endif
-            poRAT->CreateColumn( poDTChild->GetName(), GFT_Real, eType );
-            for( i = 0; i < nRowCount; i++ )
-                poRAT->SetValue( i, poRAT->GetColumnCount()-1, padfColData[i]);
-
-            CPLFree( padfColData );
-        }
-        else if( EQUAL(pszType,"string") )
-        {
-            int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
-            char *pachColData = (char*)VSICalloc(nRowCount+1,nMaxNumChars);
-            if (pachColData == NULL)
-            {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFARasterBand::ReadNamedRAT : Out of memory");
-                delete poRAT;
-                return NULL;
-            }
-
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            if ((int)VSIFReadL( pachColData, nMaxNumChars, nRowCount, hHFA->fp ) != nRowCount)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterBand::ReadNamedRAT : Cannot read values");
-                CPLFree(pachColData);
-                delete poRAT;
-                return NULL;
-            }
-
-            poRAT->CreateColumn(poDTChild->GetName(),GFT_String,eType);
-            for( i = 0; i < nRowCount; i++ )
-            {
-                CPLString oRowVal;
-
-                oRowVal.assign( pachColData+nMaxNumChars*i, nMaxNumChars );
-                poRAT->SetValue( i, poRAT->GetColumnCount()-1, 
-                                 oRowVal.c_str() );
-            }
-
-            CPLFree( pachColData );
-        }
-        else if( EQUALN(pszType,"int",3) )
-        {
-            GInt32 *panColData = (GInt32*)VSIMalloc2(nRowCount, sizeof(GInt32));
-            if (nRowCount != 0 && panColData == NULL)
-            {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFARasterBand::ReadNamedRAT : Out of memory");
-                delete poRAT;
-                return NULL;
-            }
-
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            if ((int)VSIFReadL( panColData, sizeof(GInt32), nRowCount, hHFA->fp ) != nRowCount)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterBand::ReadNamedRAT : Cannot read values");
-                CPLFree(panColData);
-                delete poRAT;
-                return NULL;
-            }
-#ifdef CPL_MSB
-            GDALSwapWords( panColData, 4, nRowCount, 4 );
-#endif
-            poRAT->CreateColumn(poDTChild->GetName(),GFT_Integer,eType);
-            for( i = 0; i < nRowCount; i++ )
-                poRAT->SetValue( i, poRAT->GetColumnCount()-1, panColData[i] );
-
-            CPLFree( panColData );
-        }
-    }
-
-    return poRAT;
-}
-
-/************************************************************************/
 /*                            WriteNamedRAT()                            */
 /************************************************************************/
  
@@ -1759,7 +3101,7 @@ CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttrib
         }
         else if( poRAT->GetUsageOfCol(col) == GFU_Alpha )
         {
-            pszName = "Alpha";
+            pszName = "Opacity";
         }
         else if( poRAT->GetUsageOfCol(col) == GFU_PixelCount )
         {
@@ -1789,8 +3131,16 @@ CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttrib
 
 
         poColumn->SetIntField( "numRows", nRowCount );
+        // color cols which are integer in GDAL are written as floats in HFA
+        int bIsColorCol = FALSE;
+        if( ( poRAT->GetUsageOfCol(col) == GFU_Red ) || ( poRAT->GetUsageOfCol(col) == GFU_Green ) ||
+            ( poRAT->GetUsageOfCol(col) == GFU_Blue) || ( poRAT->GetUsageOfCol(col) == GFU_Alpha ) )
+        {
+            bIsColorCol = TRUE;
+        }
    
-        if( poRAT->GetTypeOfCol(col) == GFT_Real )
+        // write float also if a color column, or histogram
+        if( ( poRAT->GetTypeOfCol(col) == GFT_Real ) || bIsColorCol || (poRAT->GetUsageOfCol(col) == GFU_PixelCount) )
         {
             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
                                             nRowCount * sizeof(double) );
@@ -1800,7 +3150,11 @@ CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttrib
             double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
             for( int i = 0; i < nRowCount; i++)
             {
-                padfColData[i] = poRAT->GetValueAsDouble(i,col);
+                if( bIsColorCol )
+                    // stored 0..1
+                    padfColData[i] = poRAT->GetValueAsInt(i,col) / 255.0;
+                else
+                    padfColData[i] = poRAT->GetValueAsDouble(i,col);
             }
 #ifdef CPL_MSB
             GDALSwapWords( padfColData, 8, nRowCount, 8 );
@@ -2015,6 +3369,8 @@ CPLErr HFADataset::WriteProjection()
         int	i;
 
         sDatum.datumname = (char *) poGeogSRS->GetAttrValue( "GEOGCS|DATUM" );
+        if( sDatum.datumname == NULL )
+            sDatum.datumname = (char*) "";
 
         /* WKT to Imagine translation */
         for( i = 0; apszDatumMap[i] != NULL; i += 2 )
@@ -2068,6 +3424,11 @@ CPLErr HFADataset::WriteProjection()
         sPro.proSpheroid.eSquared = (a2-b2)/a2;
     }
 
+    if( sDatum.datumname == NULL )
+        sDatum.datumname = (char*) "";
+    if( sPro.proSpheroid.sphereName == NULL )
+        sPro.proSpheroid.sphereName = (char*) "";
+
 /* -------------------------------------------------------------------- */
 /*      Recognise various projections.                                  */
 /* -------------------------------------------------------------------- */
@@ -2737,6 +4098,10 @@ int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA)
   const char *pszDatum = poSRS->GetAttrValue( "DATUM" );
   int gcsNameOffset = 0;
   int datumNameOffset = 0;
+  if( pszGEOGCS == NULL )
+      pszGEOGCS = "";
+  if( pszDatum == NULL )
+      pszDatum = "";
   if(strstr(pszGEOGCS, "GCS_"))
     gcsNameOffset = strlen("GCS_");
   if(strstr(pszDatum, "D_"))
diff --git a/frmts/hfa/hfaentry.cpp b/frmts/hfa/hfaentry.cpp
index 7c59243..54bab8e 100644
--- a/frmts/hfa/hfaentry.cpp
+++ b/frmts/hfa/hfaentry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaentry.cpp 23494 2011-12-07 23:56:41Z rouault $
+ * $Id: hfaentry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAEntry class for reading and relating
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 #include "hfa_p.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: hfaentry.cpp 23494 2011-12-07 23:56:41Z rouault $");
+CPL_CVSID("$Id: hfaentry.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                              HFAEntry()                              */
diff --git a/frmts/hfa/hfafield.cpp b/frmts/hfa/hfafield.cpp
index e7912b7..5c1417e 100644
--- a/frmts/hfa/hfafield.cpp
+++ b/frmts/hfa/hfafield.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfafield.cpp 26254 2013-07-31 19:49:54Z rouault $
+ * $Id: hfafield.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAField class for managing information
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfafield.cpp 26254 2013-07-31 19:49:54Z rouault $");
+CPL_CVSID("$Id: hfafield.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define MAX_ENTRY_REPORT   16
                            
@@ -497,7 +498,12 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
     else if( chReqType == 'd' )
     {
         dfDoubleValue = *((double *) pValue);
-        nIntValue = (int) dfDoubleValue;
+        if( dfDoubleValue > INT_MAX )
+            nIntValue = INT_MAX;
+        else if( dfDoubleValue < INT_MIN )
+            nIntValue = INT_MIN;
+        else
+            nIntValue = (int) dfDoubleValue;
     }
     else if( chReqType == 'i' )
     {
@@ -1045,6 +1051,36 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
                   nIntRet = 0;
               }
           }
+          else if( nBaseItemType == EPT_u2 )
+          {
+              int nBitOffset = nIndexValue & 0x3;
+              int nByteOffset = nIndexValue >> 2;
+              int nMask = 0x3;
+
+              if (nByteOffset >= nDataSize)
+              {
+                  CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
+                  return FALSE;
+              }
+
+              nIntRet = (pabyData[nByteOffset] >> nBitOffset) & nMask;
+              dfDoubleRet = nIntRet;
+          }
+          else if( nBaseItemType == EPT_u4 )
+          {
+              int nBitOffset = nIndexValue & 0x7;
+              int nByteOffset = nIndexValue >> 3;
+              int nMask = 0x7;
+
+              if (nByteOffset >= nDataSize)
+              {
+                  CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
+                  return FALSE;
+              }
+
+              nIntRet = (pabyData[nByteOffset] >> nBitOffset) & nMask;
+              dfDoubleRet = nIntRet;
+          }
           else if( nBaseItemType == EPT_u8 )
           {
               if (nIndexValue >= nDataSize)
@@ -1147,7 +1183,12 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
               HFAStandard( 8, &dfValue );
 
               dfDoubleRet = dfValue;
-              nIntRet = (int) dfValue;
+              if( dfDoubleRet > INT_MAX )
+                  nIntRet = INT_MAX;
+              else if( dfDoubleRet < INT_MIN )
+                  nIntRet = INT_MIN;
+              else
+                  nIntRet = (int) dfDoubleRet;
           }
           else
           {
diff --git a/frmts/hfa/hfaopen.cpp b/frmts/hfa/hfaopen.cpp
index a069a72..0b2fb9a 100644
--- a/frmts/hfa/hfaopen.cpp
+++ b/frmts/hfa/hfaopen.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaopen.cpp 23624 2011-12-21 19:31:43Z rouault $
+ * $Id: hfaopen.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,7 +42,7 @@
 #include <limits.h>
 #include <vector>
 
-CPL_CVSID("$Id: hfaopen.cpp 23624 2011-12-21 19:31:43Z rouault $");
+CPL_CVSID("$Id: hfaopen.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 static const char *apszAuxMetadataItems[] = {
@@ -2741,7 +2742,7 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                     // first because the SetStringField sets the count for the object
                     // BinFunction to the length of the string
                     poEntry->MakeData( 70 );
-                    poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
+                    poEntry->SetStringField( "BinFunction.binFunctionType", "direct" );
                     
                     bCreatedHistogramParameters = TRUE;
                 }
@@ -2820,7 +2821,11 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
             poBinFunc->SetIntField( "numBins", nNumBins );
             poBinFunc->SetDoubleField( "minLimit", dMinLimit );
             poBinFunc->SetDoubleField( "maxLimit", dMaxLimit );
-            poBinFunc->SetStringField( "binFunctionType", "linear" ); // we use always a linear
+            // direct for thematic layers, linear otherwise
+            if ( EQUALN ( poNode->GetStringField("layerType"), "thematic", 8) )
+                poBinFunc->SetStringField( "binFunctionType", "direct" );
+            else
+                poBinFunc->SetStringField( "binFunctionType", "linear" );
 
             // we need a child named histogram
             HFAEntry * poHisto = poEntry->GetNamedChild( "Histogram" );
@@ -2829,9 +2834,9 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                 
             poHisto->SetIntField( "numRows", nNumBins );
             // allocate space for the bin values
-            GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*4 );
+            GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*8 );
             poHisto->SetIntField( "columnDataPtr", nOffset );
-            poHisto->SetStringField( "dataType", "integer" );
+            poHisto->SetStringField( "dataType", "real" );
             poHisto->SetIntField( "maxNumChars", 0 );
             // write out histogram data
             char * pszWork = pszBinValues;
@@ -2841,15 +2846,67 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                 if ( pszEnd != NULL )
                 {
                     *pszEnd = 0;
-                    VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET );
-                    int nValue = atoi( pszWork );
-                    HFAStandard( 4, &nValue );
+                    VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET );
+                    double nValue = atof( pszWork );
+                    HFAStandard( 8, &nValue );
 
-                    VSIFWriteL( (void *)&nValue, 1, 4, hHFA->fp );
+                    VSIFWriteL( (void *)&nValue, 1, 8, hHFA->fp );
                     pszWork = pszEnd + 1;
                 }
             }
         }
+        else if ( poEntry != NULL )
+        {
+            // In this case, there are HistogramParameters present, but we did not
+            // create them. However, we might be modifying them, in the case where 
+            // the data has changed and the histogram counts need to be updated. It could 
+            // be worse than that, but that is all we are going to cope with for now. 
+            // We are assuming that we did not change any of the other stuff, like 
+            // skip factors and so forth. The main need for this case is for programs
+            // (such as Imagine itself) which will happily modify the pixel values
+            // without re-calculating the histogram counts. 
+            int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
+            HFAEntry *poEntryDescrTbl = poNode->GetNamedChild( "Descriptor_Table" );
+            HFAEntry *poHisto = NULL;
+            if ( poEntryDescrTbl != NULL) {
+                poHisto = poEntryDescrTbl->GetNamedChild( "Histogram" );
+            }
+            if ( poHisto != NULL ) {
+                int nOffset = poHisto->GetIntField( "columnDataPtr" );
+                // write out histogram data
+                char * pszWork = pszBinValues;
+                
+                // Check whether histogram counts were written as int or double
+                bool bCountIsInt = TRUE;
+                const char *pszDataType = poHisto->GetStringField("dataType");
+                if ( EQUALN(pszDataType, "real", strlen(pszDataType)) )
+                {
+                    bCountIsInt = FALSE;
+                }
+                for ( int nBin = 0; nBin < nNumBins; ++nBin )
+                {
+                    char * pszEnd = strchr( pszWork, '|' );
+                    if ( pszEnd != NULL )
+                    {
+                        *pszEnd = 0;
+                        if ( bCountIsInt ) {
+                            // Histogram counts were written as ints, so re-write them the same way
+                            VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET );
+                            int nValue = atoi( pszWork );
+                            HFAStandard( 4, &nValue );
+                            VSIFWriteL( (void *)&nValue, 1, 4, hHFA->fp );
+                        } else {
+                            // Histogram were written as doubles, as is now the default behaviour
+                            VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET );
+                            double nValue = atof( pszWork );
+                            HFAStandard( 8, &nValue );
+                            VSIFWriteL( (void *)&nValue, 1, 8, hHFA->fp );
+                        }
+                        pszWork = pszEnd + 1;
+                    }
+                }
+            }
+        }
         free( pszBinValues );
     }
 
diff --git a/frmts/hfa/hfatest.cpp b/frmts/hfa/hfatest.cpp
index 7031841..07b28fa 100644
--- a/frmts/hfa/hfatest.cpp
+++ b/frmts/hfa/hfatest.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatest.cpp 22802 2011-07-24 14:16:58Z rouault $
+ * $Id: hfatest.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Testing mainline for HFA services - transitory.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "hfa_p.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: hfatest.cpp 22802 2011-07-24 14:16:58Z rouault $");
+CPL_CVSID("$Id: hfatest.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
diff --git a/frmts/hfa/hfatype.cpp b/frmts/hfa/hfatype.cpp
index bc3fb08..bbcd51f 100644
--- a/frmts/hfa/hfatype.cpp
+++ b/frmts/hfa/hfatype.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatype.cpp 23495 2011-12-08 00:16:33Z rouault $
+ * $Id: hfatype.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAType class, for managing one type
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Intergraph Corporation
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfatype.cpp 23495 2011-12-08 00:16:33Z rouault $");
+CPL_CVSID("$Id: hfatype.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/idrisi/IdrisiDataset.cpp b/frmts/idrisi/IdrisiDataset.cpp
index 6644183..682917f 100644
--- a/frmts/idrisi/IdrisiDataset.cpp
+++ b/frmts/idrisi/IdrisiDataset.cpp
@@ -1,12 +1,17 @@
 /*****************************************************************************
-* $Id: IdrisiDataset.cpp 25214 2012-11-06 18:54:12Z rouault $
+* $Id: IdrisiDataset.cpp 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
-* Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+* Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
+*
+* Revised by Hongmei Zhu, February, 2013
+* honzhu at clarku.edu
+* Clark Labs/Clark University
 *
 ******************************************************************************
 * Copyright( c ) 2006, Ivan Lucena
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files( the "Software" ),
@@ -37,7 +42,7 @@
 #include "gdal_rat.h"
 #include "idrisi.h"
 
-CPL_CVSID( "$Id: IdrisiDataset.cpp 25214 2012-11-06 18:54:12Z rouault $" );
+CPL_CVSID( "$Id: IdrisiDataset.cpp 27044 2014-03-16 23:41:27Z rouault $" );
 
 CPL_C_START
 void GDALRegister_IDRISI( void);
@@ -192,6 +197,174 @@ static const ReferenceTab aoUSStateTable[] = {
     {5101,    "hi"},
     {5200,    "pr"}
 };
+
+//---- The origin table for USA State Plane Systems
+struct OriginTab83 {
+    double longitude;
+	double latitude;
+	const char *spcs;
+};
+
+#define ORIGIN_COUNT    148
+
+//---- USA State plane coordinate system in IDRISI
+static const OriginTab83 SPCS83Origin[] = {
+	{85.83,   30.50,    "SPC83AL1"},
+	{87.50,   30.00,    "SPC83AL2"},
+	{176.00,  51.00,    "SPC83AK0"},
+	{142.00,  54.00,    "SPC83AK2"},
+	{146.00,  54.00,    "SPC83AK3"},
+	{150.00,  54.00,    "SPC83AK4"},
+	{154.00,  54.00,    "SPC83AK5"},
+	{158.00,  54.00,    "SPC83AK6"},
+	{162.00,  54.00,    "SPC83AK7"},
+	{166.00,  54.00,    "SPC83AK8"},
+	{170.00,  54.00,    "SPC83AK9"},
+	{110.17,  31.00,    "SPC83AZ1"},
+	{111.92,  31.00,    "SPC83AZ2"},
+	{113.75,  31.00,    "SPC83AZ3"},
+	{92.00,   34.33,    "SPC83AR1"},
+	{92.00,   32.67,    "SPC83AR2"},
+	{122.00,  39.33,    "SPC83CA1"},
+	{122.00,  37.67,    "SPC83CA2"},
+	{120.50,  36.50,    "SPC83CA3"},
+	{119.00,  35.33,    "SPC83CA4"},
+	{118.00,  33.50,    "SPC83CA5"},
+	{116.25,  32.17,    "SPC83CA6"},
+	{105.50,  39.33,    "SPC83CO1"},
+	{105.50,  37.83,    "SPC83CO2"},
+	{105.50,  36.67,    "SPC83CO3"},
+	{72.75,   40.83,    "SPC83CT1"},
+	{75.42,   38.00,    "SPC83DE1"},
+	{81.00,   24.33,    "SPC83FL1"},
+	{82.00,   24.33,    "SPC83FL2"},
+	{84.50,   29.00,    "SPC83FL3"},
+	{82.17,   30.00,    "SPC83GA1"},
+	{84.17,   30.00,    "SPC83GA2"},
+	{155.50,  18.83,    "SPC83HI1"},
+	{156.67,  20.33,    "SPC83HI2"},
+	{158.00,  21.17,    "SPC83HI3"},
+	{159.50,  21.83,    "SPC83HI4"},
+	{160.17,  21.67,    "SPC83HI5"}, 
+	{112.17,  41.67,    "SPC83ID1"}, 
+	{114.00,  41.67,    "SPC83ID2"},
+	{115.75,  41.67,    "SPC83ID3"},
+	{88.33,   36.67,    "SPC83IL1"},
+	{90.17,   36.67,    "SPC83IL1"},
+	{85.67,   37.50,    "SPC83IN1"},
+	{87.08,   37.50,    "SPC83IN2"},
+	{93.50,   41.50,    "SPC83IA1"},
+	{93.50,   40.00,    "SPC83IA1"},
+	{98.00,   38.33,    "SPC83KS1"},
+	{98.50,   36.67,    "SPC83KS2"},
+	{84.25,   37.50,    "SPC83KY1"},
+	{85.75,   36.33,    "SPC83KY2"},
+	{92.50,   30.50,    "SPC83LA1"},
+	{91.33,   28.50,    "SPC83LA2"},
+	{91.33,   25.50,    "SPC83LA3"},
+	{92.50,   30.67,    "SPC27LA1"},//NAD27 system
+	{91.33,   28.67,    "SPC27LA2"},
+	{91.33,   25.67,    "SPC27LA3"},//
+	{68.50,   43.67,    "SPC83ME1"},
+	{68.50,   43.83,    "SPC27ME1"},//NAD27
+	{70.17,   42.83,    "SPC83ME2"},
+	{77.00,   37.67,    "SPC83MD1"},//
+	{77.00,   37.83,    "SPC27MD1"},//NAD27
+        {71.50,   41.00,    "SPC83MA1"},
+        {70.50,   41.00,    "SPC83MA2"},
+	{87.00,   44.78,    "SPC83MI1"},
+	{84.37,   43.32,    "SPC83MI2"},
+	{84.37,   41.50,    "SPC83MI3"},
+	{84.33,   43.32,    "SPC27MI2"},//NAD27 L
+	{84.33,   41.50,    "SPC27MI3"},//NAD27 L
+	{83.67,   41.50,    "SPC27MI4"},//NAD27 TM
+	{85.75,   41.50,    "SPC27MI5"},//NAD27 TM
+	{88.75,   41.50,    "SPC27MI6"},//NAD27 TM
+	{93.10,   46.50,    "SPC83MN1"},
+	{94.25,   45.00,    "SPC83MN2"},
+	{94.00,   43.00,    "SPC83MN3"},
+	{88.83,   29.50,    "SPC83MS1"},
+	{90.33,   29.50,    "SPC83MS2"},
+	{88.83,   29.67,    "SPC83MS1"},//NAD27
+	{90.33,   30.50,    "SPC83MS2"},//
+	{90.50,   35.83,    "SPC83MO1"},
+	{92.50,   35.83,    "SPC83MO2"},
+	{94.50,   36.17,    "SPC83MO3"},
+	{109.50,  44.25,    "SPC83MT1"},
+	{109.50,  47.00,    "SPC27MT1"},//NAD27
+	{109.50,  45.83,    "SPC27MT2"},
+	{109.50,  44.00,    "SPC27MT3"},//
+	{100.00,  39.83,    "SPC83NE1"},
+	{115.58,  34.75,    "SPC83NV1"},
+	{116.67,  34.75,    "SPC83NV2"},
+	{118.58,  34.75,    "SPC83NV3"},
+	{71.67,   42.50,    "SPC83NH1"},
+	{74.50,   38.83,    "SPC83NJ1"},
+	{74.67,   38.83,    "SPC27NJ1"},//NAD27 
+	{104.33,  31.00,    "SPC83NM1"},
+	{106.25,  31.00,    "SPC83NM2"},
+	{107.83,  31.00,    "SPC83NM3"},
+	{74.50,   38.83,    "SPC83NY1"},
+	{76.58,   40.00,    "SPC83NY2"},
+	{78.58,   40.00,    "SPC83NY3"},
+	{74.00,   40.17,    "SPC83NY4"},
+	{74.33,   40.00,    "SPC27NY1"},//NAD27
+	{74.00,   40.50,    "SPC27NY4"},//
+	{79.00,   33.75,    "SPC83NC1"},
+	{100.50,  47.00,    "SPC83ND1"},
+	{100.50,  45.67,    "SPC83ND2"},
+	{82.50,   39.67,    "SPC83OH1"},
+	{82.50,   38.00,    "SPC83OH2"},
+	{98.00,   35.00,    "SPC83OK1"},
+	{98.00,   33.33,    "SPC83OK2"},
+	{120.50,  43.67,    "SPC83OR1"},
+	{120.50,  41.67,    "SPC83OR2"},
+	{77.75,   40.17,    "SPC83PA1"},
+	{77.75,   39.33,    "SPC83PA2"},
+	{71.50,   41.08,    "SPC83RI1"},
+	{81.00,   31.83,    "SPC83SC1"},
+	{81.00,   33.00,    "SPC27SC1"},//NAD27
+	{81.00,   31.83,    "SPC27SC2"},//NAD27
+	{100.00,  43.83,    "SPC83SD1"},
+	{100.33,  42.33,    "SPC83SD2"},
+	{86.00,   34.33,    "SPC83TN1"},
+	{86.00,   34.67,    "SPC27TN1"},//NAD27
+	{101.50,  34.00,    "SPC83TX1"},//
+	{98.50,   31.67,    "SPC83TX2"},
+	{100.33,  29.67,    "SPC83TX3"},
+	{99.00,   27.83,    "SPC83TX4"},
+	{98.50,   25.67,    "SPC83TX5"},
+	{97.50,   31.67,    "SPC27TX2"},//NAD27
+	{111.50,  40.33,    "SPC83UT1"},
+	{111.50,  38.33,    "SPC83UT2"},
+	{111.50,  36.67,    "SPC83UT3"},
+	{72.50,   42.50,    "SPC83VT1"},
+	{78.50,   37.67,    "SPC83VA1"},
+	{78.50,   36.33,    "SPC83VA2"},
+	{120.83,  47.00,    "SPC83WA1"},
+	{120.50,  45.33,    "SPC83WA2"},
+	{79.50,   38.50,    "SPC83WV1"},
+	{81.00,   37.00,    "SPC83WV2"},
+	{90.00,   45.17,    "SPC83WI1"},
+	{90.00,   43.83,    "SPC83WI2"},
+	{90.00,   42.00,    "SPC83WI3"},
+	{105.17,  40.50,    "SPC83WY1"},
+	{107.33,  40.50,    "SPC83WY2"},
+	{108.75,  40.50,    "SPC83WY3"},
+	{110.08,  40.50,    "SPC83WY4"},
+	{105.17,  40.67,    "SPC27WY1"},//NAD27
+	{105.33,  40.67,    "SPC27WY2"},
+	{108.75,  40.67,    "SPC27WY3"},
+	{110.08,  40.67,    "SPC27WY4"},//
+	{66.43,   17.83,    "SPC83PR1"}
+};
+
+//Get IDRISI State Plane name by origin
+char *GetSpcs(double dfLon, double dfLat);
+
+//change NAD from 83 to 27
+void NAD83to27( char *pszOutRef, char *pszInRef);
+
 #define US_STATE_COUNT ( sizeof( aoUSStateTable ) / sizeof( ReferenceTab ) )
 
 //----- Get the Code of a US State
@@ -275,7 +448,7 @@ private:
     char *pszProjection;
     char **papszCategories;
     char *pszUnitType;
-
+	//move GeoReference2Wkt() into header file
     CPLErr Wkt2GeoReference( const char *pszProjString,
         char **pszRefSystem, 
         char **pszRefUnit );
@@ -344,7 +517,7 @@ public:
     virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                   double dfMean, double dfStdDev ); 
     CPLErr SetMinMax( double dfMin, double dfMax );
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
     float  fMaximum;
@@ -389,16 +562,35 @@ IdrisiDataset::~IdrisiDataset()
 
     if( papszRDC != NULL )
     {
-        if( eAccess == GA_Update )
-        {
-            int i;
+		
+        int i;
 
-            for( i = 0; i < nBands; i++ )
-            {
-                IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 1 );
-                poBand->SetMinMax( poBand->fMinimum, poBand->fMaximum );
-            }
+        //int bSuccessMin = FALSE;
+        //int bSuccessMax = FALSE;
 
+        double dfMin = 0.0;
+        double dfMax = 0.0;
+        double dfMean = 0.0;
+        double dfStdDev = 0.0;
+
+        for( i = 0; i < nBands; i++ )
+        {
+            IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 1 );
+            poBand->ComputeStatistics( false, &dfMin, &dfMax, &dfMean, &dfStdDev, NULL, NULL);
+            /*
+              dfMin = poBand->GetMinimum( &bSuccessMin );
+              dfMax = poBand->GetMaximum( &bSuccessMax );
+
+              if( ! ( bSuccessMin && bSuccessMax ) )
+              {
+              poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
+              }
+            */
+            poBand->SetMinMax( dfMin, dfMax);
+        }
+		
+        if( eAccess == GA_Update )
+        {
             CSLSetNameValueSeparator( papszRDC, ": " );
             SaveAsCRLF( papszRDC, pszDocFilename );
         }
@@ -425,7 +617,7 @@ IdrisiDataset::~IdrisiDataset()
 
 GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE )
+    if(  ( poOpenInfo->fp == NULL ) || (EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE ))//modified
         return NULL;
 
     // --------------------------------------------------------------------
@@ -655,10 +847,10 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         int nLine = -1;
         for( int i = 0;( i < CSLCount( poDS->papszRDC ) ) &&( nLine == -1 ); i++ )
             if( EQUALN( poDS->papszRDC[i], rdcLEGEND_CATS, 11 ) )
-                nLine = i;
+                nLine = i;//get the line where legend cats is
         if( nLine > 0 )
         {
-            sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );
+            sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );//asign legend cats to nCode
             for( int i = 0;( i < 255 ) &&( nCount < nCatCount ); i++ )
             {
                 if( i == nCode )
@@ -734,16 +926,21 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     //      Check input options
     // -------------------------------------------------------------------- 
 
-    if( nBands != 1 ) 
+    if( nBands != 1 && nBands != 3) 
     {
-        if( !( nBands == 3 && eType == GDT_Byte ) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "Attempt to create IDRISI dataset with an illegal "
-                "number of bands(%d) or data type(%s).\n",
+		CPLError( CE_Failure, CPLE_AppDefined,
+                "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
+                " Try again by selecting a specific band if possible. \n", nBands);
+		return NULL;  
+    }
+
+	if( nBands == 3 && eType != GDT_Byte )
+    {
+		CPLError( CE_Failure, CPLE_AppDefined,
+                "Attempt to create IDRISI dataset with an unsupported combination "
+                "of the number of bands(%d) and data type(%s). \n",
                 nBands, GDALGetDataTypeName( eType ) );
-            return NULL;
-        }
+        return NULL;
     }
 
     // ---------------------------------------------------------------- 
@@ -766,13 +963,41 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     case GDT_Float32:                
         pszLDataType = rstREAL;
         break;
+	//--- process compatible data types
+	case (GDT_UInt16):
+		pszLDataType = rstINTEGER;
+		CPLError( CE_Warning, CPLE_AppDefined,
+			      "This process requires a conversion from %s to signed 16-bit %s, "
+				  "which may cause data loss.\n",
+				  GDALGetDataTypeName( eType ), rstINTEGER);
+		break;
+	case GDT_UInt32:
+		pszLDataType = rstINTEGER;
+		CPLError( CE_Warning, CPLE_AppDefined,
+			      "This process requires a conversion from %s to signed 16-bit %s, "
+				  "which may cause data loss.\n",
+				  GDALGetDataTypeName( eType ), rstINTEGER);
+		break;
+	case GDT_Int32:
+		pszLDataType = rstINTEGER;
+		CPLError( CE_Warning, CPLE_AppDefined,
+			      "This process requires a conversion from %s to signed 16-bit %s, "
+				  "which may cause data loss.\n",
+				  GDALGetDataTypeName( eType ), rstINTEGER);
+		break;
+	case GDT_Float64:
+		pszLDataType = rstREAL;
+		CPLError( CE_Warning, CPLE_AppDefined,
+			      "This process requires a conversion from %s to float 32-bit %s, "
+				  "which may cause data loss.\n",
+				  GDALGetDataTypeName( eType ), rstREAL);
+		break;
     default:
         CPLError( CE_Failure, CPLE_AppDefined,
             "Attempt to create IDRISI dataset with an illegal "
             "data type(%s).\n",
             GDALGetDataTypeName( eType ) );
         return NULL;
-
     };
 
     char **papszLRDC;
@@ -848,18 +1073,24 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     // ------------------------------------------------------------------------
     //      Check number of bands
     // ------------------------------------------------------------------------
-
-    if ( ( ( poSrcDS->GetRasterCount() == 1 ) ||
-         ( ( poSrcDS->GetRasterCount() == 3 ) &&
-         ( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() == GDT_Byte ) &&
-           ( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() == GDT_Byte ) &&
-           ( poSrcDS->GetRasterBand( 3 )->GetRasterDataType() == GDT_Byte ) ) ) ) == FALSE )
-    {
-
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Attempt to create IDRISI dataset with an illegal "
-            "number of bands(%d).\n",
-            poSrcDS->GetRasterCount() );
+	if ( !( poSrcDS->GetRasterCount() == 1 ) && !( poSrcDS->GetRasterCount() == 3 ))
+	{
+		CPLError( CE_Failure, CPLE_AppDefined,
+                "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
+                " Try again by selecting a specific band if possible.\n",
+				poSrcDS->GetRasterCount() );
+		return NULL; 
+
+	}
+    if ( ( poSrcDS->GetRasterCount() == 3 ) &&
+         ( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() != GDT_Byte ) ||
+         ( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() != GDT_Byte ) ||
+         ( poSrcDS->GetRasterBand( 3 )->GetRasterDataType() != GDT_Byte ) ) )
+    {
+		CPLError( CE_Failure, CPLE_AppDefined,
+                "Attempt to create IDRISI dataset with an unsupported "
+                "data type when there are three bands. Only BYTE allowed.\n"
+			    "Try again by selecting a specific band to convert if possible.\n");
         return NULL;
     }
 
@@ -897,8 +1128,7 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
                 eType != GDT_Float64 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                    "Attempt to create IDRISI dataset with an illegal "
-                    "data type(%s).\n",
+					"Attempt to create IDRISI dataset with an illegal data type(%s).\n",
                     GDALGetDataTypeName( eType ) );
                 return NULL;
             }
@@ -923,7 +1153,7 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
 
     if( ! ( bSuccessMin && bSuccessMax ) )
     {
-      poBand->GetStatistics( false, false, &dfMin, &dfMax, NULL, NULL );
+      poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
     }
 
     if(!( ( eType == GDT_Byte ) || 
@@ -970,30 +1200,15 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
 
     double adfGeoTransform[6];
 
-    poDS->SetProjection( poSrcDS->GetProjectionRef() );
-
-    if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
-    {
-        poDS->SetGeoTransform( adfGeoTransform );
-    }
-    else
+    if (!EQUAL(poSrcDS->GetProjectionRef(),""))
     {
-        poDS->papszRDC =
-            CSLSetNameValue( poDS->papszRDC, rdcMIN_X, CPLSPrintf( "%.1f", -0.5 ));
-        poDS->papszRDC =
-            CSLSetNameValue( poDS->papszRDC, rdcMAX_X, CPLSPrintf( "%.1f",
-            poSrcDS->GetRasterXSize() - 0.5 ) );
-        poDS->papszRDC =
-            CSLSetNameValue( poDS->papszRDC, rdcMIN_Y, CPLSPrintf( "%.1f",
-            poSrcDS->GetRasterYSize() + 0.5 ) );
-        poDS->papszRDC =
-            CSLSetNameValue( poDS->papszRDC, rdcMAX_Y, CPLSPrintf( "%.1f", 0.5 ));
-        poDS->papszRDC =
-            CSLSetNameValue( poDS->papszRDC, rdcRESOLUTION, "1" );
+        poSrcDS->GetGeoTransform(adfGeoTransform);
+        poDS->SetGeoTransform(adfGeoTransform);
+        poDS->SetProjection( poSrcDS->GetProjectionRef() );
     }
 
     // --------------------------------------------------------------------
-    //      Copy information to the raster band
+    //      Copy information to the raster band(s)
     // --------------------------------------------------------------------
 
     GDALRasterBand *poSrcBand;
@@ -1125,7 +1340,7 @@ CPLErr  IdrisiDataset::GetGeoTransform( double * padfTransform )
     if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
-
+		/*
         if( adfGeoTransform[0] == 0.0
         &&  adfGeoTransform[1] == 1.0
         &&  adfGeoTransform[2] == 0.0
@@ -1133,6 +1348,7 @@ CPLErr  IdrisiDataset::GetGeoTransform( double * padfTransform )
         &&  adfGeoTransform[4] == 0.0
         &&  adfGeoTransform[5] == 1.0 )
             return CE_Failure;
+		*/
     }
 
     return CE_None;
@@ -1404,7 +1620,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     {
         for( i = 0; i < nBlockXSize; i++ )
         {
-            float fVal = ((float*) pabyScanLine)[i];
+            float fVal = ((float*) pabyScanLine)[i]; //this is fine
             if( !bHasNoDataValue || fVal != fNoDataValue )
             {
                 if( bFirstVal )
@@ -1454,7 +1670,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
                 }
                 else
                 {
-                    if( fVal < fMinimum) fMinimum = fVal;
+                    if( fVal < fMinimum) fMinimum = fVal;//I don't change this part, keep it as it is
                     if( fVal > fMaximum) fMaximum = fVal;
                 }
             }
@@ -1516,7 +1732,7 @@ double IdrisiRasterBand::GetMaximum( int *pbSuccess )
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if (CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ) == NULL)
-        return GDALPamRasterBand::GetMinimum(pbSuccess);
+        return GDALPamRasterBand::GetMaximum(pbSuccess);
 
     double adfMaxValue[3];
     sscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf", 
@@ -1669,7 +1885,7 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
         }
     }
 
-    poGDS->papszRDC = CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );
+    poGDS->papszRDC = CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );//this is fine
 
     return CE_None;
 }
@@ -2059,7 +2275,7 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 {        
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
@@ -2079,7 +2295,7 @@ const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
         delete poDefaultRAT;
     }
 
-    poDefaultRAT = new GDALRasterAttributeTable();
+    poDefaultRAT = new GDALDefaultRasterAttributeTable();
 
     // ----------------------------------------------------------
     // Create (Value, Red, Green, Blue, Alpha, Class_Name) fields
@@ -2586,11 +2802,11 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     // -----------------------------------------------------
 
     if EQUAL( pszProjString, "" )
-    {
-        *pszRefSystem = CPLStrdup( rstPLANE );
-        *pszRefUnit   = CPLStrdup( rstMETER );
-        return CE_None;
-    }
+            {
+                *pszRefSystem = CPLStrdup( rstPLANE );
+                *pszRefUnit   = CPLStrdup( rstMETER );
+                return CE_None;
+            }
 
     OGRSpatialReference oSRS;
     oSRS.importFromWkt( (char **) &pszProjString );
@@ -2603,7 +2819,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     {
         *pszRefSystem = CPLStrdup( rstPLANE );
         *pszRefUnit   = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), 
-                        CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
+                                        CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
         return CE_None;
     }
 
@@ -2618,12 +2834,12 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         char *pszDatum    = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
         int nGCSCode = -1;
         if EQUAL( pszAuthName, "EPSG" )
-        {
-            nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
-        }
+                {
+                    nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
+                }
         if( ( nGCSCode == 4326 ) ||( 
-            ( EQUALN( pszSpheroid, "WGS", 3 ) ) &&( strstr( pszSpheroid, "84" ) ) &&
-            ( EQUALN( pszDatum, "WGS", 3 ) )    &&( strstr( pszDatum, "84" ) ) ) )
+                ( EQUALN( pszSpheroid, "WGS", 3 ) ) &&( strstr( pszSpheroid, "84" ) ) &&
+                ( EQUALN( pszDatum, "WGS", 3 ) )    &&( strstr( pszDatum, "84" ) ) ) )
         {
             *pszRefSystem = CPLStrdup( rstLATLONG );
             *pszRefUnit   = CPLStrdup( rstDEGREE );
@@ -2682,7 +2898,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         if( strlen( pszID ) > 0 )
         {
             pszPCSCode = CPLStrdup( CSVGetField( CSVFilename( "stateplane.csv" ),
-                "EPSG_PCS_CODE", pszID, CC_Integer, "ID" ) );
+                                                 "EPSG_PCS_CODE", pszID, CC_Integer, "ID" ) );
             if( strlen( pszPCSCode ) > 0 )
             {
                 int nNADYear   = 83;
@@ -2704,11 +2920,47 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                 {
                     *pszRefSystem   = CPLStrdup( CPLSPrintf( rstSPC, nNADYear, pszState, nZone ) );
                     *pszRefUnit     = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
-                                      CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
+                                                      CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
                     return CE_None;
                 }
             }
+        }//
+
+        //if EPSG code is missing, go to following steps to work with origin
+        double dfLon = 0.0;
+        double dfLat = 0.0;
+
+        const char *pszNAD83 = "83";
+        const char *pszNAD27 = "27";
+        int isOldNAD = FALSE;
+
+        const char *pszDatumValue = oSRS.GetAttrValue("DATUM",0);
+        if( (strstr(pszDatumValue, pszNAD83) == NULL) && (strstr(pszDatumValue, pszNAD27) != NULL ))
+            //strcpy(pszNAD, "27");
+            isOldNAD = TRUE;
+
+        if ( (oSRS.FindProjParm("central_meridian",NULL) != -1) && (oSRS.FindProjParm("central_meridian",NULL) != -1) )
+        {
+            dfLon = oSRS.GetProjParm("central_meridian");
+            dfLat = oSRS.GetProjParm("latitude_of_origin");
+            dfLon = (int)(fabs(dfLon) * 100 + 0.5) / 100.0;
+            dfLat = (int)(fabs(dfLat) * 100 + 0.5) / 100.0;
+            *pszRefSystem = CPLStrdup(GetSpcs(dfLon, dfLat));
         }
+		
+        if(*pszRefSystem != NULL)
+        {
+            //Convert 83 TO 27
+            if(isOldNAD)
+            {
+                char pszOutRefSystem[9];
+                NAD83to27(pszOutRefSystem, *pszRefSystem);	
+                *pszRefSystem = CPLStrdup(pszOutRefSystem);
+            }
+            *pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
+            return CE_None;
+        }
+
     }
 
 #endif // GDAL_RST_PLUGIN
@@ -2722,56 +2974,56 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         // ---------------------------------------------------------
 
         if EQUAL( pszProjName, SRS_PT_MERCATOR_1SP )
-        {
-            pszProjectionOut =  "Mercator" ;
-        }
+                {
+                    pszProjectionOut =  "Mercator" ;
+                }
         if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )         
-        {   
-            pszProjectionOut =  "Transverse Mercator" ;
-        }
+                {   
+                    pszProjectionOut =  "Transverse Mercator" ;
+                }
         else if EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP )
-        {
-            pszProjectionOut =  "Lambert Conformal Conic" ;
-        }
+                     {
+                         pszProjectionOut =  "Lambert Conformal Conic" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_EQUIRECTANGULAR )
-        {
-            pszProjectionOut =  "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
-        }
+                     {
+                         pszProjectionOut =  "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
+                     }
         else if EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA )
-        {   
-            double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
-            if( dfCenterLat == 0.0 )
-                pszProjectionOut =  "Lambert Transverse Azimuthal Equal Area" ; 
-            else if( fabs( dfCenterLat ) == 90.0 )
-                pszProjectionOut =  "Lambert Oblique Polar Azimuthal Equal Area" ;
-            else if( dfCenterLat > 0.0 )
-                pszProjectionOut =  "Lambert North Oblique Azimuthal Equal Area" ; 
-            else
-                pszProjectionOut =  "Lambert South Oblique Azimuthal Equal Area" ;
-        }
+                     {   
+                         double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
+                         if( dfCenterLat == 0.0 )
+                             pszProjectionOut =  "Lambert Transverse Azimuthal Equal Area" ; 
+                         else if( fabs( dfCenterLat ) == 90.0 )
+                             pszProjectionOut =  "Lambert Oblique Polar Azimuthal Equal Area" ;
+                         else if( dfCenterLat > 0.0 )
+                             pszProjectionOut =  "Lambert North Oblique Azimuthal Equal Area" ; 
+                         else
+                             pszProjectionOut =  "Lambert South Oblique Azimuthal Equal Area" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_POLAR_STEREOGRAPHIC )
-        {
-            if( oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL ) > 0 )
-                pszProjectionOut =  "North Polar Stereographic" ;
-            else
-                pszProjectionOut =  "South Polar Stereographic" ;
-        }
+                     {
+                         if( oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL ) > 0 )
+                             pszProjectionOut =  "North Polar Stereographic" ;
+                         else
+                             pszProjectionOut =  "South Polar Stereographic" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_STEREOGRAPHIC )
-        {
-            pszProjectionOut =  "Transverse Stereographic" ;
-        }
+                     {
+                         pszProjectionOut =  "Transverse Stereographic" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC )
-        {
-            pszProjectionOut =  "Oblique Stereographic" ;
-        }
+                     {
+                         pszProjectionOut =  "Oblique Stereographic" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_SINUSOIDAL )
-        {
-            pszProjectionOut =  "Sinusoidal" ;
-        }
+                     {
+                         pszProjectionOut =  "Sinusoidal" ;
+                     }
         else if EQUAL( pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA )
-        {
-            pszProjectionOut =  "Alber's Equal Area Conic" ;
-        }
+                     {
+                         pszProjectionOut =  "Alber's Equal Area Conic" ;
+                     }
 
         // ---------------------------------------------------------
         //  Failure, Projection system not suppotted
@@ -2842,7 +3094,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     }
 
     // ---------------------------------------------------------
-    //  Create a compaining georeference file for this dataset
+    //  Create a companion georeference file for this dataset
     // ---------------------------------------------------------
 
     char **papszRef = NULL;
@@ -2850,7 +3102,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     papszRef = CSLAddNameValue( papszRef, refPROJECTION,   pszProjectionOut );  
     papszRef = CSLAddNameValue( papszRef, refDATUM,        pszDatum );     
     papszRef = CSLAddNameValue( papszRef, refDELTA_WGS84,  CPLSPrintf( "%.3g %.3g %.3g", 
-        adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] ) );
+                                                                       adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] ) );
     papszRef = CSLAddNameValue( papszRef, refELLIPSOID,    pszEllipsoid );
     papszRef = CSLAddNameValue( papszRef, refMAJOR_SAX,    CPLSPrintf( "%.3f", dfSemiMajor ) );
     papszRef = CSLAddNameValue( papszRef, refMINOR_SAX,    CPLSPrintf( "%.3f", dfSemiMinor ) );
@@ -2911,7 +3163,7 @@ int GetStateCode( const char *pszState )
 }
 
 /************************************************************************/
-/*                            GetStateCode()                            */
+/*                            GetStateName()                            */
 /************************************************************************/
 
 const char *GetStateName( int nCode )
@@ -2928,6 +3180,46 @@ const char *GetStateName( int nCode )
     return NULL;
 }
 
+
+/************************************************************************/
+/*                            GetSpcs()                                 */
+/************************************************************************/
+
+char *GetSpcs(double dfLon, double dfLat)
+{
+    int i;
+    for( i=0; i<ORIGIN_COUNT; i++)
+    {
+        if(( dfLon == SPCS83Origin[i].longitude ) && ( dfLat == SPCS83Origin[i].latitude ))
+        {
+            return (char *)SPCS83Origin[i].spcs;
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                            NAD83to27()                               */
+/************************************************************************/
+void NAD83to27( char *pszOutRef, char *pszInRef)
+{
+    char *pOutput, *pInput;
+
+    pOutput = pszOutRef;
+    pInput = pszInRef;
+    strncpy(pOutput, pInput, 3);
+
+    pOutput = pOutput +3;
+    pInput = pInput +3;
+
+    strncpy(pOutput, "27", 2);
+    pOutput = pOutput +2;
+    pInput = pInput +2;
+    strcpy(pOutput, pInput);
+}
+
+
+
 /************************************************************************/
 /*                            GetUnitIndex()                            */
 /************************************************************************/
diff --git a/frmts/idrisi/idrisi.h b/frmts/idrisi/idrisi.h
index 5ed93f2..912f170 100644
--- a/frmts/idrisi/idrisi.h
+++ b/frmts/idrisi/idrisi.h
@@ -1,12 +1,13 @@
 /*****************************************************************************
-* $Id: idrisi.h 23040 2011-09-04 14:42:12Z rouault $
+* $Id: idrisi.h 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
-* Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+* Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
 *
 ******************************************************************************
 * Copyright( c ) 2006, Ivan Lucena
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files( the "Software" ),
diff --git a/frmts/ilwis/ilwiscoordinatesystem.cpp b/frmts/ilwis/ilwiscoordinatesystem.cpp
index 02df1d1..318aaa2 100644
--- a/frmts/ilwis/ilwiscoordinatesystem.cpp
+++ b/frmts/ilwis/ilwiscoordinatesystem.cpp
@@ -5,6 +5,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, ITC
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/ilwis/ilwisdataset.cpp b/frmts/ilwis/ilwisdataset.cpp
index 80337f0..380c610 100644
--- a/frmts/ilwis/ilwisdataset.cpp
+++ b/frmts/ilwis/ilwisdataset.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, ITC
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/ingr/IngrTypes.cpp b/frmts/ingr/IngrTypes.cpp
index 14e2763..8f45bf6 100644
--- a/frmts/ingr/IngrTypes.cpp
+++ b/frmts/ingr/IngrTypes.cpp
@@ -1,12 +1,13 @@
 /*****************************************************************************
- * $Id: IngrTypes.cpp 25809 2013-03-27 21:54:18Z rouault $
+ * $Id: IngrTypes.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types support function
- * Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/IngrTypes.h b/frmts/ingr/IngrTypes.h
index b53ba41..24b2906 100644
--- a/frmts/ingr/IngrTypes.h
+++ b/frmts/ingr/IngrTypes.h
@@ -1,12 +1,13 @@
 /*****************************************************************************
- * $Id: IngrTypes.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: IngrTypes.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types, constants and functions definition
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/IntergraphBand.cpp b/frmts/ingr/IntergraphBand.cpp
index ca53d53..415bfd3 100644
--- a/frmts/ingr/IntergraphBand.cpp
+++ b/frmts/ingr/IntergraphBand.cpp
@@ -1,12 +1,13 @@
 /*****************************************************************************
- * $Id: IntergraphBand.cpp 25785 2013-03-23 11:34:53Z rouault $
+ * $Id: IntergraphBand.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, band support
- * Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/IntergraphBand.h b/frmts/ingr/IntergraphBand.h
index 8fd973a..9439aaf 100644
--- a/frmts/ingr/IntergraphBand.h
+++ b/frmts/ingr/IntergraphBand.h
@@ -1,12 +1,13 @@
 /*****************************************************************************
-* $Id: IntergraphBand.h 25785 2013-03-23 11:34:53Z rouault $
+* $Id: IntergraphBand.h 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  Intergraph Raster Format support
 * Purpose:  Read selected types of Intergraph Raster Format
-* Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+* Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
 *
 ******************************************************************************
 * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/IntergraphDataset.cpp b/frmts/ingr/IntergraphDataset.cpp
index c471434..5235721 100644
--- a/frmts/ingr/IntergraphDataset.cpp
+++ b/frmts/ingr/IntergraphDataset.cpp
@@ -1,12 +1,13 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.cpp 25785 2013-03-23 11:34:53Z rouault $
+ * $Id: IntergraphDataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, dataset support
- * Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/IntergraphDataset.h b/frmts/ingr/IntergraphDataset.h
index 8a70ccf..29b4a89 100644
--- a/frmts/ingr/IntergraphDataset.h
+++ b/frmts/ingr/IntergraphDataset.h
@@ -1,12 +1,13 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: IntergraphDataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read selected types of Intergraph Raster Format
- * Author:   Ivan Lucena [ivan.lucena at pmldnet.com]
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/ingr/JpegHelper.cpp b/frmts/ingr/JpegHelper.cpp
index 60afe23..0dd0fc2 100644
--- a/frmts/ingr/JpegHelper.cpp
+++ b/frmts/ingr/JpegHelper.cpp
@@ -3,7 +3,7 @@
  *
  * Project:  Creates a jpeg header
  * Purpose:  Abreviated JPEG support
- * Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
diff --git a/frmts/ingr/JpegHelper.h b/frmts/ingr/JpegHelper.h
index b105659..b97f46d 100644
--- a/frmts/ingr/JpegHelper.h
+++ b/frmts/ingr/JpegHelper.h
@@ -3,10 +3,11 @@
  *
  * Project:  Project:  Creates a jpeg header
  * Purpose:  Abreviated JPEG support
- * Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+ * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
  * Copyright (c) 2007, Ivan Lucena
+ * Copyright (c) 2007, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files ( the "Software" ),
diff --git a/frmts/iris/irisdataset.cpp b/frmts/iris/irisdataset.cpp
index ad8e915..54e7c5f 100644
--- a/frmts/iris/irisdataset.cpp
+++ b/frmts/iris/irisdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: irisdataset.cpp 25348 2012-12-26 11:37:51Z rouault $
+ * $Id: irisdataset.cpp 27141 2014-04-09 09:00:05Z rouault $
  *
  * Project:  IRIS Reader
  * Purpose:  All code for IRIS format Reader
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2012, Roger Veciana <rveciana at gmail.com>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,7 @@
 #include <sstream>
 
 
-CPL_CVSID("$Id: irisdataset.cpp 25348 2012-12-26 11:37:51Z rouault $");
+CPL_CVSID("$Id: irisdataset.cpp 27141 2014-04-09 09:00:05Z rouault $");
 
 CPL_C_START
 void	GDALRegister_IRIS(void);
@@ -194,7 +195,6 @@ CPLErr IRISRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     IRISDataset *poGDS = (IRISDataset *) poDS;
 
-    //printf("hola %d %s\n",poGDS->dataTypeCode,poGDS->aszDataTypeCodes[poGDS->dataTypeCode]);
     //Every product type has it's own size. TODO: Move it like dataType
     int nDataLength = 1;
     if(poGDS->nDataTypeCode == 2){nDataLength=1;}
@@ -229,9 +229,9 @@ CPLErr IRISRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( (int)VSIFReadL( pszRecord, nBlockXSize*nDataLength, 1, poGDS->fp ) != 1 )
         return CE_Failure;
     
-    //If datatype is dbZ:
-    //See point 3.3.5 at page 3.42 of the manual
-    if(poGDS->nDataTypeCode == 2){
+    //If datatype is dbZ or dBT:
+    //See point 3.3.3 at page 3.33 of the manual
+    if(poGDS->nDataTypeCode == 2 || poGDS->nDataTypeCode == 1){
         float fVal;
         for (i=0;i<nBlockXSize;i++){
             fVal = (((float) *(pszRecord+i*nDataLength)) -64)/2.0;
@@ -239,6 +239,16 @@ CPLErr IRISRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 fVal = -9999;
             ((float *) pImage)[i] = fVal;
         }
+    //If datatype is dbZ2 or dBT2:
+    //See point 3.3.4 at page 3.33 of the manual
+    } else if(poGDS->nDataTypeCode == 8 || poGDS->nDataTypeCode == 9){
+        float fVal;
+        for (i=0;i<nBlockXSize;i++){
+            fVal = (((float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength)) - 32768)/100.0;
+            if (fVal == 327.67)
+                fVal = -9999;
+            ((float *) pImage)[i] = fVal;
+        }
     //Fliquid2 (Rain1 & Rainn products)
     //See point 3.3.11 at page 3.43 of the manual
     } else if(poGDS->nDataTypeCode == 37){
@@ -695,13 +705,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    for (int iBandNum = 1; iBandNum <= nNumBands; iBandNum++) {
-        poDS->SetBand( iBandNum, new IRISRasterBand( poDS, iBandNum ));
-        poDS->GetRasterBand(iBandNum)->SetNoDataValue(-9999);
-    }
+    
     
 /* -------------------------------------------------------------------- */
 /*      Setting the Metadata                                            */
@@ -853,7 +857,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
         //See point 3.2.2 at page 3.2 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
         float fElevation = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
-        poDS->SetMetadataItem( "CAPPI_HEIGHT",CPLString().Printf("%.1f m",fElevation));
+        poDS->SetMetadataItem( "CAPPI_BOTTOM_HEIGHT",CPLString().Printf("%.1f m",fElevation));
         float fAzimuthSmoothingForShear = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12))) / 65536;
         poDS->SetMetadataItem( "AZIMUTH_SMOOTHING_FOR_SHEAR" ,CPLString().Printf("%.1f", fAzimuthSmoothingForShear));
         unsigned int  nMaxAgeVVPCorrection = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
@@ -914,6 +918,21 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for (int iBandNum = 1; iBandNum <= nNumBands; iBandNum++) {
+        poDS->SetBand( iBandNum, new IRISRasterBand( poDS, iBandNum ));
+
+        poDS->GetRasterBand(iBandNum)->SetNoDataValue(-9999);
+        //Calculating the band height to include it in the band metadata. Only for the CAPPI product
+        if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
+            float fScaleZ = float (CPL_LSBSINT32PTR (poDS->abyHeader + 96 + 12 )) / 100;
+            float fOffset = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
+
+            poDS->GetRasterBand(iBandNum)->SetMetadataItem("height",CPLString().Printf("%.0f m",fOffset + fScaleZ*(iBandNum-1)));
+        }
+    }
+/* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
diff --git a/frmts/iso8211/8211dump.cpp b/frmts/iso8211/8211dump.cpp
index 482db22..212ab23 100644
--- a/frmts/iso8211/8211dump.cpp
+++ b/frmts/iso8211/8211dump.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: 8211dump.cpp 25826 2013-04-01 20:23:04Z rouault $
+ * $Id: 8211dump.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Dump 8211 file in verbose form - just a junk program. 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: 8211dump.cpp 25826 2013-04-01 20:23:04Z rouault $");
+CPL_CVSID("$Id: 8211dump.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 int main( int nArgc, char ** papszArgv )
diff --git a/frmts/iso8211/ddfmodule.cpp b/frmts/iso8211/ddfmodule.cpp
index 5144a54..bdc6e28 100644
--- a/frmts/iso8211/ddfmodule.cpp
+++ b/frmts/iso8211/ddfmodule.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfmodule.cpp 25841 2013-04-02 21:30:03Z rouault $
+ * $Id: ddfmodule.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFModule class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfmodule.cpp 25841 2013-04-02 21:30:03Z rouault $");
+CPL_CVSID("$Id: ddfmodule.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                             DDFModule()                              */
diff --git a/frmts/iso8211/ddfrecord.cpp b/frmts/iso8211/ddfrecord.cpp
index 1478650..d66f883 100644
--- a/frmts/iso8211/ddfrecord.cpp
+++ b/frmts/iso8211/ddfrecord.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfrecord.cpp 25841 2013-04-02 21:30:03Z rouault $
+ * $Id: ddfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFRecord class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfrecord.cpp 25841 2013-04-02 21:30:03Z rouault $");
+CPL_CVSID("$Id: ddfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const int nLeaderSize = 24;
 
diff --git a/frmts/iso8211/ddfsubfielddefn.cpp b/frmts/iso8211/ddfsubfielddefn.cpp
index 8294ed5..7f75a34 100644
--- a/frmts/iso8211/ddfsubfielddefn.cpp
+++ b/frmts/iso8211/ddfsubfielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfsubfielddefn.cpp 25697 2013-03-02 18:44:32Z rouault $
+ * $Id: ddfsubfielddefn.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFSubfieldDefn class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfsubfielddefn.cpp 25697 2013-03-02 18:44:32Z rouault $");
+CPL_CVSID("$Id: ddfsubfielddefn.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          DDFSubfieldDefn()                           */
diff --git a/frmts/jaxapalsar/jaxapalsardataset.cpp b/frmts/jaxapalsar/jaxapalsardataset.cpp
index 500dbcb..96d507e 100644
--- a/frmts/jaxapalsar/jaxapalsardataset.cpp
+++ b/frmts/jaxapalsar/jaxapalsardataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jaxapalsardataset.cpp 22636 2011-07-03 10:39:11Z rouault $
+ * $Id: jaxapalsardataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PALSAR JAXA imagery reader
  * Purpose:  Support for PALSAR L1.1/1.5 imagery and appropriate metadata from
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Philippe P. Vachon <philippe at cowpig.ca>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jaxapalsardataset.cpp 22636 2011-07-03 10:39:11Z rouault $");
+CPL_CVSID("$Id: jaxapalsardataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PALSARJaxa(void);
diff --git a/frmts/jdem/jdemdataset.cpp b/frmts/jdem/jdemdataset.cpp
index 71ba285..abe0970 100644
--- a/frmts/jdem/jdemdataset.cpp
+++ b/frmts/jdem/jdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jdemdataset.cpp 25143 2012-10-16 18:49:32Z rouault $
+ * $Id: jdemdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JDEM Reader
  * Purpose:  All code for Japanese DEM Reader
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jdemdataset.cpp 25143 2012-10-16 18:49:32Z rouault $");
+CPL_CVSID("$Id: jdemdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_JDEM(void);
diff --git a/frmts/jp2kak/frmt_jp2kak.html b/frmts/jp2kak/frmt_jp2kak.html
index 122323d..0efd505 100644
--- a/frmts/jp2kak/frmt_jp2kak.html
+++ b/frmts/jp2kak/frmt_jp2kak.html
@@ -93,7 +93,7 @@ produce better compression than lossy compression. <P>
 
 <li> <b>GMLJP2=YES/NO</b>: Indicates whether a GML box conforming to the OGC GML in JPEG2000 specification should be included in the file.  Defaults to YES.<p>
 
-<li> <b>GeoJP2=YES/NO</b>: Indicates whether a GML box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification should be included in the file.  Defaults to YES.<p>
+<li> <b>GeoJP2=YES/NO</b>: Indicates whether a UUID/GeoTIFF box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification should be included in the file.  Defaults to YES.<p>
 
 <li> <b>LAYERS=n</b>: Control the number of layers produced.  These are 
 sort of like resolution layers, but not exactly.  The default value is
diff --git a/frmts/jp2kak/jp2kak.lst b/frmts/jp2kak/jp2kak.lst
index deb4014..652e772 100644
--- a/frmts/jp2kak/jp2kak.lst
+++ b/frmts/jp2kak/jp2kak.lst
@@ -14,3 +14,8 @@ KAK_OBJ +=	\
     $(KAKDIR)/apps/make/kdu_tiff.o \
     $(KAKDIR)/apps/make/jpx.o
 
+# The following are just for Kakadu 7.0 later.
+ifneq ($(wildcard $(KAKDIR)/apps/make/ssse3_stripe_transfe?.o),)
+KAK_OBJ +=	\
+    $(KAKDIR)/apps/make/ssse3_stripe_transfer.o
+endif
diff --git a/frmts/jp2kak/jp2kakdataset.cpp b/frmts/jp2kak/jp2kakdataset.cpp
index 823f165..468df43 100644
--- a/frmts/jp2kak/jp2kakdataset.cpp
+++ b/frmts/jp2kak/jp2kakdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jp2kakdataset.cpp 25764 2013-03-18 20:29:55Z warmerdam $
+ * $Id: jp2kakdataset.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Implementation of the ISO/IEC 15444-1 standard based on Kakadu.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,7 +28,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
@@ -64,9 +65,19 @@
 #  define kdu_client void
 #endif
 
-// #define KAKADU_JPX	1
+CPL_CVSID("$Id: jp2kakdataset.cpp 27182 2014-04-14 20:03:08Z rouault $");
+
+// Generally Kakadu does not advertise its version well, so we look for a
+// clue to V6 vs V7, the main difference in api.
+#ifndef KAKADU_VERSION
+#  ifdef KDU_TARGET_CAP_SEQUENTIAL
+#    define KAKADU_VERSION 700
+#  else
+#    define KAKADU_VERSION 600
+#  endif
+#endif
 
-CPL_CVSID("$Id: jp2kakdataset.cpp 25764 2013-03-18 20:29:55Z warmerdam $");
+// #define KAKADU_JPX	1
 
 static int kakadu_initialized = FALSE;
 
@@ -88,7 +99,7 @@ static unsigned char jpc_header[] =
 /* ==================================================================== */
 /************************************************************************/
 
-class JP2KAKDataset : public GDALPamDataset
+class JP2KAKDataset : public GDALJP2AbstractDataset
 {
     friend class JP2KAKRasterBand;
 
@@ -102,19 +113,11 @@ class JP2KAKDataset : public GDALPamDataset
     bool           bPreferNPReads;
     kdu_thread_env *poThreadEnv;
 
+    int            bCached;
     int            bResilient;
     int            bFussy;
     bool           bUseYCC;
 
-    char	   *pszProjection;
-    double	   adfGeoTransform[6];
-    int            bGeoTransformValid;
-
-    int		   nGCPCount;
-    GDAL_GCP       *pasGCPList;
-
-    void           PamOverride();
-
     int         TestUseBlockIO( int, int, int, int, int, int,
                                 GDALDataType, int, int * );
     CPLErr      DirectRasterIO( GDALRWFlag, int, int, int, int,
@@ -132,12 +135,6 @@ class JP2KAKDataset : public GDALPamDataset
     
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
-    
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
 
     static void KakaduInitialize();
     static GDALDataset *Open( GDALOpenInfo * );
@@ -785,23 +782,13 @@ JP2KAKDataset::JP2KAKDataset()
 {
     poInput = NULL;
     poRawInput = NULL;
-    pszProjection = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
     family = NULL;
     jpip_client = NULL;
     poThreadEnv = NULL;
 
+    bCached = 0;
     bPreferNPReads = false;
 
-    bGeoTransformValid = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
-
     poDriver = (GDALDriver*) GDALGetDriverByName( "JP2KAK" );
 }
 
@@ -814,14 +801,6 @@ JP2KAKDataset::~JP2KAKDataset()
 {
     FlushCache();
 
-    CPLFree( pszProjection );
-    
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
-
     if( poInput != NULL )
     {
         oCodeStream.destroy();
@@ -851,70 +830,6 @@ JP2KAKDataset::~JP2KAKDataset()
     }
 }
 
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *JP2KAKDataset::GetProjectionRef()
-
-{
-    if( pszProjection && *pszProjection )
-        return( pszProjection );
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr JP2KAKDataset::GetGeoTransform( double * padfTransform )
-
-{
-    if( bGeoTransformValid )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-    
-        return CE_None;
-    }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int JP2KAKDataset::GetGCPCount()
-
-{
-    return nGCPCount;
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *JP2KAKDataset::GetGCPProjection()
-
-{
-    if( nGCPCount > 0 )
-        return pszProjection;
-    else
-        return "";
-}
-
-/************************************************************************/
-/*                               GetGCP()                               */
-/************************************************************************/
-
-const GDAL_GCP *JP2KAKDataset::GetGCPs()
-
-{
-    return pasGCPList;
-}
-
 /************************************************************************/
 /*                          IBuildOverviews()                           */
 /************************************************************************/
@@ -1051,6 +966,16 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
     int bResilient = CSLTestBoolean(
         CPLGetConfigOption( "JP2KAK_RESILIENT", "NO" ) );
 
+    /* Doesn't seem to bring any real performance gain on Linux */
+    int bBuffered = CSLTestBoolean(
+        CPLGetConfigOption( "JP2KAK_BUFFERED",
+#ifdef WIN32
+                            "YES"
+#else
+                            "NO"
+#endif
+                            ) );
+
 /* -------------------------------------------------------------------- */
 /*      Handle setting up datasource for JPIP.                          */
 /* -------------------------------------------------------------------- */
@@ -1073,7 +998,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             try
             {
                 poRawInput = new subfile_source;
-                poRawInput->open( poOpenInfo->pszFilename, bResilient );
+                poRawInput->open( poOpenInfo->pszFilename, bResilient, bBuffered );
                 poRawInput->seek( 0 );
 
                 poRawInput->read( abySubfileHeader, 16 );
@@ -1103,12 +1028,12 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poRawInput == NULL
         && !bIsJPIP
-        && (bResilient || poOpenInfo->fp == NULL) )
+        && (bBuffered || bResilient || poOpenInfo->fp == NULL) )
     {
         try
         {
             poRawInput = new subfile_source;
-            poRawInput->open( poOpenInfo->pszFilename, bResilient );
+            poRawInput->open( poOpenInfo->pszFilename, bResilient, bBuffered );
             poRawInput->seek( 0 );
         }
         catch( ... )
@@ -1207,8 +1132,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             else
                 family->open( poOpenInfo->pszFilename, true );
             jp2_src = new jp2_source;
-            jp2_src->open( family );
-            jp2_src->read_header();
+            if( !jp2_src->open( family ) ||
+                !jp2_src->read_header() )
+            {
+                CPLDebug( "JP2KAK", "Cannot read JP2 boxes" );
+                delete jp2_src;
+                delete family;
+                return NULL;
+            }
 
             poInput = jp2_src;
 
@@ -1253,6 +1184,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->oCodeStream.create( poInput );
         poDS->oCodeStream.set_persistent();
 
+        poDS->bCached = bBuffered;
         poDS->bResilient = bResilient;
         poDS->bFussy = CSLTestBoolean(
             CPLGetConfigOption( "JP2KAK_FUSSY", "NO" ) );
@@ -1424,69 +1356,9 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Look for supporting coordinate system information.              */
 /* -------------------------------------------------------------------- */
-        if( poOpenInfo->nHeaderBytes > 0 )
+        if( poOpenInfo->nHeaderBytes != 0 )
         {
-            GDALJP2Metadata oJP2Geo;
-        
-            if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
-            {
-                poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-                poDS->bGeoTransformValid = TRUE;
-                memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
-                        sizeof(double) * 6 );
-                poDS->nGCPCount = oJP2Geo.nGCPCount;
-                poDS->pasGCPList = oJP2Geo.pasGCPList;
-                oJP2Geo.pasGCPList = NULL;
-                oJP2Geo.nGCPCount = 0;
-            }
-
-            if (oJP2Geo.pszXMPMetadata)
-            {
-                char *apszMDList[2];
-                apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-                apszMDList[1] = NULL;
-                poDS->GDALPamDataset::SetMetadata(apszMDList, "xml:XMP");
-            }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have any XML boxes we would like to treat as special      */
-/*      domain metadata?                                                */
-/* -------------------------------------------------------------------- */
-            int iBox;
-
-            for( iBox = 0; 
-                 oJP2Geo.papszGMLMetadata
-                     && oJP2Geo.papszGMLMetadata[iBox] != NULL; 
-                 iBox++ )
-            {
-                char *pszName = NULL;
-                const char *pszXML = 
-                    CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox], 
-                                       &pszName );
-                CPLString osDomain;
-                char *apszMDList[2];
-
-                osDomain.Printf( "xml:%s", pszName );
-                apszMDList[0] = (char *) pszXML;
-                apszMDList[1] = NULL;
-
-                poDS->GDALPamDataset::SetMetadata( apszMDList, osDomain );
-
-                CPLFree( pszName );
-            }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have other misc metadata?                                 */
-/* -------------------------------------------------------------------- */
-            if( oJP2Geo.papszMetadata != NULL )
-            {
-                char **papszMD = CSLDuplicate(poDS->GDALPamDataset::GetMetadata());
-
-                papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
-                poDS->GDALPamDataset::SetMetadata( papszMD );
-
-                CSLDestroy( papszMD );
-            }
+            poDS->LoadJP2Metadata(poOpenInfo);
         }
 
 /* -------------------------------------------------------------------- */
@@ -1510,16 +1382,6 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->nPamFlags |= GPF_NOSAVE;
 
 /* -------------------------------------------------------------------- */
-/*      Do we have PAM information to override other geo-info?          */
-/* -------------------------------------------------------------------- */
-        poDS->PamOverride();
-
-        if( !poDS->bGeoTransformValid )
-            poDS->bGeoTransformValid = 
-                GDALReadWorldFile( poOpenInfo->pszFilename, 0, 
-                                   poDS->adfGeoTransform );
-
-/* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, osPhysicalFilename );
@@ -1553,44 +1415,6 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                            PamOverride()                             */
-/*                                                                      */
-/*      Override geolocation information from PAM if there is PAM       */
-/*      geolocation information.                                        */
-/************************************************************************/
-
-void JP2KAKDataset::PamOverride()
-
-{
-    if( strlen(GDALPamDataset::GetProjectionRef()) > 0 )
-    {
-        CPLFree( pszProjection );
-        pszProjection = CPLStrdup(GDALPamDataset::GetProjectionRef());
-    }
-
-    double adfPamGT[6];
-    if( GDALPamDataset::GetGeoTransform( adfPamGT ) == CE_None )
-    {
-        memcpy( adfGeoTransform, adfPamGT, sizeof(double) * 6 );
-        bGeoTransformValid = TRUE;
-    }
-
-    if( GDALPamDataset::GetGCPCount() > 0 )
-    {
-        if( nGCPCount > 0 )
-        {
-            GDALDeinitGCPs( nGCPCount, pasGCPList );
-            CPLFree( pasGCPList );
-        }
-
-        nGCPCount = GDALPamDataset::GetGCPCount();
-        pasGCPList = GDALDuplicateGCPs( nGCPCount, GDALPamDataset::GetGCPs() );
-        CPLFree( pszProjection );
-        pszProjection = CPLStrdup(GDALPamDataset::GetGCPProjection());
-    }
-}
-
-/************************************************************************/
 /*                           DirectRasterIO()                           */
 /************************************************************************/
 
@@ -1621,7 +1445,7 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag eRWFlag,
 
     if( bPreferNPReads )
     {
-        subfile_src.open( GetDescription(), bResilient );
+        subfile_src.open( GetDescription(), bResilient, bCached );
 
         if( family != NULL )
         {
@@ -1739,11 +1563,13 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag eRWFlag,
                     sample_offsets[i] = i * nBandSpace / 2;
                     sample_gaps[i] = nPixelSpace / 2;
                     row_gaps[i] = nLineSpace / 2;
+                    /* Introduced in r25136 with an unrelated commit message.
+                    Reverted per ticket #5328
                     if( precisions[i] == 12 )
                     {
                       CPLDebug( "JP2KAK", "16bit extend 12 bit data." );
                       precisions[i] = 16;
-                    }
+                    }*/
                 }
                 
             }
@@ -2041,6 +1867,13 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
     kdu_push_ifc  *engines = new kdu_push_ifc[num_components];
     kdu_line_buf  *lines = new kdu_line_buf[num_components];
     kdu_sample_allocator allocator;
+    
+    // Ticket #4050 patch : use a 32 bits kdu_line_buf for GDT_UInt16 reversible compression
+    // ToDo: test for GDT_UInt16?
+    bool   bUseShorts = bReversible;
+    if ((eType == GDT_UInt16)&&(bReversible))
+        bUseShorts = false;
+
     for (c=0; c < num_components; c++)
     {
         kdu_resolution res = oTile.access_component(c).access_resolution(); 
@@ -2053,9 +1886,12 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
             res.get_dims(dims);
             roi_node = poROIImage->acquire_node(c,dims);
         }
-
-        lines[c].pre_create(&allocator,nXSize,bReversible,bReversible);
-        engines[c] = kdu_analysis(res,&allocator,bReversible,1.0F,roi_node);
+#if KAKADU_VERSION >= 700
+        lines[c].pre_create(&allocator,nXSize,bReversible,bUseShorts,0,0);
+#else
+        lines[c].pre_create(&allocator,nXSize,bReversible,bUseShorts);
+#endif
+        engines[c] = kdu_analysis(res,&allocator,bUseShorts,1.0F,roi_node);
     }
 
     try
@@ -2119,11 +1955,12 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                 }
                 else if( bReversible && eType == GDT_UInt16 )
                 {
-                    kdu_sample16 *dest = lines[c].get_buf16();
+                    // Ticket #4050 patch : use a 32 bits kdu_line_buf for GDT_UInt16 reversible compression
+                    kdu_sample32 *dest = lines[c].get_buf32();
                     GUInt16 *sp = (GUInt16 *) pabyBuffer;
                 
                     for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->ival = *sp;
+                        dest->ival = (kdu_int32)(*sp)-32768;
                 }
                 else if( eType == GDT_Byte )
                 {
@@ -2166,7 +2003,11 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                         dest->fval = *sp;  /* scale it? */
                 }
 
+#if KAKADU_VERSION >= 700
+                engines[c].push(lines[c]);
+#else
                 engines[c].push(lines[c],true);
+#endif
 
                 iLinesWritten++;
 
@@ -2713,7 +2554,9 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             oJP2MD.SetGeoTransform( adfGeoTransform );
         }
 
-        
+        const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+        oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
+
         if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
             JP2KAKWriteBox( &jp2_out, oJP2MD.CreateGMLJP2(nXSize,nYSize) );
         if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
@@ -2866,7 +2709,8 @@ void GDALRegister_JP2KAK()
         
         poDriver->SetDescription( "JP2KAK" );
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG-2000 (based on Kakadu)" );
+                                   "JPEG-2000 (based on Kakadu " 
+                                   KDU_CORE_VERSION ")" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_jp2kak.html" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
diff --git a/frmts/jp2kak/subfile_source.h b/frmts/jp2kak/subfile_source.h
index 391f813..b0d78bc 100644
--- a/frmts/jp2kak/subfile_source.h
+++ b/frmts/jp2kak/subfile_source.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: subfile_source.h 23357 2011-11-07 18:34:42Z warmerdam $
+ * $Id: subfile_source.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Implements read-only virtual io on a subregion of a file.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,10 @@
 
 #include "kdu_file_io.h"
 #include "cpl_error.h"
+#include "cpl_vsi_virtual.h"
 
+#define IO_CHUNK_SIZE 65536L
+#define IO_BUFFER_SIZE 1048576L
 /************************************************************************/
 /*                            subfile_source                            */
 /************************************************************************/
@@ -45,7 +49,7 @@ class subfile_source : public kdu_compressed_source {
 
     bool operator!() { return (file == NULL); }
 
-    void open(const char *fname, int bSequential )
+    void open(const char *fname, int bSequential, int bCached )
       {
           const char *real_filename;
           close();
@@ -96,6 +100,18 @@ class subfile_source : public kdu_compressed_source {
               return;
           }
 
+          if ( bCached )
+          {
+              file = (VSILFILE*)VSICreateCachedFile( (VSIVirtualHandle*)file, IO_CHUNK_SIZE, IO_BUFFER_SIZE );
+              if( file == NULL )
+              {
+                  kdu_error e;
+                  e << "Unable to open compressed data file, \"" << 
+                      real_filename << "\"!";
+                  return;
+              }
+          }
+
           if( bSequential ) 
             capabilities = KDU_SOURCE_CAP_SEQUENTIAL;
           else
diff --git a/frmts/jpeg/frmt_jpeg.html b/frmts/jpeg/frmt_jpeg.html
index 4defd75..417e49c 100644
--- a/frmts/jpeg/frmt_jpeg.html
+++ b/frmts/jpeg/frmt_jpeg.html
@@ -51,6 +51,17 @@ and SSE2 SIMD instructions to accelerate baseline JPEG compression/decompression
 Starting with GDAL 1.9.0, XMP metadata can be extracted from the file, and will be
 stored as XML raw content in the xml:XMP metadata domain.<p>
 
+<h2>Color Profile Metadata</h2>
+
+<p>Starting with GDAL 1.11, GDAL can deal with the following color profile metadata in the COLOR_PROFILE domain:</p>
+<ul>
+<li>SOURCE_ICC_PROFILE (Base64 encoded ICC profile embedded in file.)</li>
+</ul>
+
+<p>Note that this metadata property can only be used on the original raw pixel data. If automatic conversion to RGB has been done, the color profile information cannot be used.</p>
+
+<p>This metadata tag can be used as creation options.</p>
+
 <h2>Creation Options</h2>
 
 JPEG files are created using the "JPEG" driver code.  Only Byte band types
diff --git a/frmts/jpeg/jpgdataset.cpp b/frmts/jpeg/jpgdataset.cpp
index 63d513e..b9ecda1 100644
--- a/frmts/jpeg/jpgdataset.cpp
+++ b/frmts/jpeg/jpgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpgdataset.cpp 26064 2013-06-05 09:57:06Z rouault $
+ * $Id: jpgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
@@ -49,7 +50,7 @@ typedef struct {
         GUInt32  tiff_diroff;    /* byte offset to first directory */
 } TIFFHeader;
 
-CPL_CVSID("$Id: jpgdataset.cpp 26064 2013-06-05 09:57:06Z rouault $");
+CPL_CVSID("$Id: jpgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 #ifdef LIBJPEG_12_PATH 
@@ -148,7 +149,6 @@ protected:
     GDAL_GCP *pasGCPList;
 
     VSILFILE   *fpImage;
-    int         bOwnFPImage;
     GUIntBig nSubfileOffset;
 
     int    nLoadedScanline;
@@ -156,6 +156,7 @@ protected:
 
     int    bHasReadEXIFMetadata;
     int    bHasReadXMPMetadata;
+    int    bHasReadICCMetadata;
     char   **papszMetadata;
     char   **papszSubDatasets;
     int	   bigendian;
@@ -175,6 +176,7 @@ protected:
     virtual int GetOutColorSpace() = 0;
 
     int    EXIFInit(VSILFILE *);
+    void   ReadICCProfile();
 
     int    nQLevel;
 
@@ -219,6 +221,7 @@ protected:
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
 
+    virtual char      **GetMetadataDomainList();
     virtual char  **GetMetadata( const char * pszDomain = "" );
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
@@ -254,8 +257,7 @@ class JPGDataset : public JPGDatasetCommon
 
     static GDALDataset *Open( const char* pszFilename,
                               char** papszSiblingFiles = NULL,
-                              int nScaleFactor = 1,
-                              VSILFILE* fpIn = NULL);
+                              int nScaleFactor = 1 );
     static GDALDataset* CreateCopy( const char * pszFilename,
                                     GDALDataset *poSrcDS,
                                     int bStrict, char ** papszOptions,
@@ -444,6 +446,17 @@ void JPGDatasetCommon::ReadXMPMetadata()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **JPGDatasetCommon::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:XMP", "COLOR_PROFILE", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
@@ -454,8 +467,11 @@ char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
         (pszDomain == NULL || EQUAL(pszDomain, "")))
         ReadEXIFMetadata();
     if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
-        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        pszDomain != NULL && EQUAL(pszDomain, "xml:XMP"))
         ReadXMPMetadata();
+    if (eAccess == GA_ReadOnly && !bHasReadICCMetadata &&
+        pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE"))
+        ReadICCProfile();
     return GDALPamDataset::GetMetadata(pszDomain);
 }
 
@@ -471,10 +487,168 @@ const char *JPGDatasetCommon::GetMetadataItem( const char * pszName,
         (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL && EQUALN(pszName, "EXIF_", 5))
         ReadEXIFMetadata();
+    if (eAccess == GA_ReadOnly && !bHasReadICCMetadata &&
+        pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE"))
+        ReadICCProfile();
     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
 }
 
 /************************************************************************/
+/*                        ReadICCProfile()                              */
+/*                                                                      */
+/*                 Read ICC Profile from APP2 data                      */
+/************************************************************************/
+void JPGDatasetCommon::ReadICCProfile()
+{
+    if (bHasReadICCMetadata)
+        return;
+    bHasReadICCMetadata = TRUE;
+
+    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+
+    int nTotalSize = 0;
+    int nChunkCount = -1;
+    int anChunkSize[256];
+    char *apChunk[256];
+
+    memset(anChunkSize, 0, 256 * sizeof(int));
+    memset(apChunk, 0, 256 * sizeof(char*));
+
+/* -------------------------------------------------------------------- */
+/*      Search for APP2 chunk.                                          */
+/* -------------------------------------------------------------------- */
+    GByte abyChunkHeader[18];
+    int nChunkLoc = 2;
+    bool bOk = true;
+
+    for( ; TRUE; ) 
+    {
+        if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
+            break;
+
+        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
+            break;
+
+        if( abyChunkHeader[0] != 0xFF )
+            break; // Not a valid tag
+
+        if (abyChunkHeader[1] == 0xD9)
+            break; // End of image
+
+        if ((abyChunkHeader[1] >= 0xD0) && (abyChunkHeader[1] <= 0xD8))
+        {
+            // Restart tags have no length
+            nChunkLoc += 2;
+            continue;
+        }
+
+        int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
+
+        if( abyChunkHeader[1] == 0xe2
+            && memcmp((const char *) abyChunkHeader + 4,"ICC_PROFILE\0",12) == 0 )
+        {
+            /* Get length and segment ID */
+            /* Header: */
+            /* APP2 tag: 2 bytes */
+            /* App Length: 2 bytes */
+            /* ICC_PROFILE\0 tag: 12 bytes */
+            /* Segment index: 1 bytes */
+            /* Total segments: 1 bytes */
+            int nICCChunkLength = nChunkLength - 16;
+            int nICCChunkID = abyChunkHeader[16];
+            int nICCMaxChunkID = abyChunkHeader[17];
+
+            if (nChunkCount == -1)
+                nChunkCount = nICCMaxChunkID;
+
+            /* Check that all max segment counts are the same */
+            if (nICCMaxChunkID != nChunkCount)
+            {
+                bOk = false;
+                break;
+            }
+
+            /* Check that no segment ID is larger than the total segment count */
+            if ((nICCChunkID > nChunkCount) || (nICCChunkID == 0) || (nChunkCount == 0)) 
+            {
+                bOk = false;
+                break;
+            }
+
+            /* Check if ICC segment already loaded */
+            if (apChunk[nICCChunkID-1] != NULL)
+            {
+                bOk = false;
+                break;
+            }
+
+            /* Load it */
+            apChunk[nICCChunkID-1] = (char*)VSIMalloc(nICCChunkLength);
+            anChunkSize[nICCChunkID-1] = nICCChunkLength;
+
+            if( VSIFReadL( apChunk[nICCChunkID-1], nICCChunkLength, 1, fpImage ) != 1 )
+            {
+                bOk = false;
+                break;
+            }
+        }
+
+        nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
+    }
+
+    /* Get total size and verify that there are no missing segments */
+    if (bOk)
+    {
+        for(int i = 0; i < nChunkCount; i++)
+        {
+            if (apChunk[i] == NULL)
+            {
+                /* Missing segment... abort */
+                bOk = false;
+                break;
+                
+            }
+            nTotalSize += anChunkSize[i];
+        }
+    }
+
+    /* Merge all segments together and set metadata */
+    if (bOk && nChunkCount > 0)
+    {
+        char *pBuffer = (char*)VSIMalloc(nTotalSize);
+        char *pBufferPtr = pBuffer;
+        for(int i = 0; i < nChunkCount; i++)
+        {
+            memcpy(pBufferPtr, apChunk[i], anChunkSize[i]);
+            pBufferPtr += anChunkSize[i];
+        }
+
+        /* Escape the profile */
+        char *pszBase64Profile = CPLBase64Encode(nTotalSize, (const GByte*)pBuffer);
+
+        /* Avoid setting the PAM dirty bit just for that */
+        int nOldPamFlags = nPamFlags;
+
+        /* Set ICC profile metadata */
+        SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
+
+        nPamFlags = nOldPamFlags;
+
+        VSIFree(pBuffer);
+        CPLFree(pszBase64Profile);
+    }
+
+    /* Cleanup */
+    for(int i = 0; i < nChunkCount; i++)
+    {
+        if (apChunk[i] != NULL)
+            VSIFree(apChunk[i]);
+    }
+
+    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+}
+
+/************************************************************************/
 /*                        EXIFInit()                                    */
 /*                                                                      */
 /*           Create Metadata from Information file directory APP1       */
@@ -908,7 +1082,6 @@ JPGDatasetCommon::JPGDatasetCommon()
 
 {
     fpImage = NULL;
-    bOwnFPImage = FALSE;
 
     nScaleFactor = 1;
     bHasInitInternalOverviews = FALSE;
@@ -921,6 +1094,7 @@ JPGDatasetCommon::JPGDatasetCommon()
 
     bHasReadEXIFMetadata = FALSE;
     bHasReadXMPMetadata = FALSE;
+    bHasReadICCMetadata = FALSE;
     papszMetadata   = NULL;
     papszSubDatasets= NULL;
     nExifOffset     = -1;
@@ -961,7 +1135,7 @@ JPGDatasetCommon::JPGDatasetCommon()
 JPGDatasetCommon::~JPGDatasetCommon()
 
 {
-    if( bOwnFPImage && fpImage != NULL )
+    if( fpImage != NULL )
         VSIFCloseL( fpImage );
 
     if( pabyScanline != NULL )
@@ -997,10 +1171,11 @@ int JPGDatasetCommon::CloseDependentDatasets()
         bRet = TRUE;
         for(int i = 0; i < nInternalOverviewsToFree; i++)
             delete papoInternalOverviews[i];
-        CPLFree(papoInternalOverviews);
-        papoInternalOverviews = NULL;
         nInternalOverviewsToFree = 0;
     }
+    CPLFree(papoInternalOverviews);
+    papoInternalOverviews = NULL;
+
     return bRet;
 }
 
@@ -1404,6 +1579,10 @@ void JPGDataset::Restart()
 CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
 
 {
+    CPLErr eErr = GDALPamDataset::GetGeoTransform( padfTransform );
+    if( eErr != CE_Failure )
+        return eErr;
+
     LoadWorldFileOrTab();
 
     if( bGeoTransformValid )
@@ -1413,7 +1592,7 @@ CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
         return CE_None;
     }
     else 
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+        return eErr;
 }
 
 /************************************************************************/
@@ -1423,6 +1602,10 @@ CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
 int JPGDatasetCommon::GetGCPCount()
 
 {
+    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    if( nPAMGCPCount != 0 )
+        return nPAMGCPCount;
+
     LoadWorldFileOrTab();
 
     return nGCPCount;
@@ -1435,6 +1618,10 @@ int JPGDatasetCommon::GetGCPCount()
 const char *JPGDatasetCommon::GetGCPProjection()
 
 {
+    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    if( nPAMGCPCount != 0 )
+        return GDALPamDataset::GetGCPProjection();
+
     LoadWorldFileOrTab();
 
     if( pszProjection && nGCPCount > 0 )
@@ -1450,6 +1637,10 @@ const char *JPGDatasetCommon::GetGCPProjection()
 const GDAL_GCP *JPGDatasetCommon::GetGCPs()
 
 {
+    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    if( nPAMGCPCount != 0 )
+        return GDALPamDataset::GetGCPs();
+
     LoadWorldFileOrTab();
 
     return pasGCPList;
@@ -1627,7 +1818,7 @@ GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 
 GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles,
-                               int nScaleFactor, VSILFILE* fpIn )
+                               int nScaleFactor )
 
 {
 /* -------------------------------------------------------------------- */
@@ -1702,20 +1893,15 @@ GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles
 /* -------------------------------------------------------------------- */
     VSILFILE* fpImage;
 
-    if( fpIn == NULL )
-    {
-        fpImage = VSIFOpenL( real_filename, "rb" );
+    fpImage = VSIFOpenL( real_filename, "rb" );
 
-        if( fpImage == NULL )
-        {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                    "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
-                    real_filename );
-            return NULL;
-        }
+    if( fpImage == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
+                real_filename );
+        return NULL;
     }
-    else
-        fpImage = fpIn;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -1725,7 +1911,6 @@ GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles
     poDS = new JPGDataset();
     poDS->nQLevel = nQLevel;
     poDS->fpImage = fpImage;
-    poDS->bOwnFPImage = (fpIn == NULL);
 
 /* -------------------------------------------------------------------- */
 /*      Move to the start of jpeg data.                                 */
@@ -1851,14 +2036,15 @@ GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles
             poDS->eGDALColorSpace = JCS_RGB;
             poDS->nBands = 3;
             poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
+
+            /* libjpeg does the translation from YCrCbK -> CMYK internally */
+            /* and we'll do the translation to RGB in IReadBlock() */
+            poDS->sDInfo.out_color_space = JCS_CMYK;
         }
         else
         {
             poDS->nBands = 4;
         }
-        /* libjpeg does the translation from YCrCbK -> CMYK internally */
-        /* and we'll do the translation to RGB in IReadBlock() */
-        poDS->sDInfo.out_color_space = JCS_CMYK;
     }
     else
     {
@@ -1900,6 +2086,15 @@ GDALDataset *JPGDataset::Open( const char* pszFilename, char** papszSiblingFiles
 /*      Open (external) overviews.                                      */
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, real_filename, papszSiblingFiles );
+
+        /* In the case of a file downloaded through the HTTP driver, this one */
+        /* will unlink the temporary /vsimem file just after GDALOpen(), so */
+        /* later VSIFOpenL() when reading internal overviews would fail. */
+        /* Initialize them now */
+        if( strncmp(real_filename, "/vsimem/http_", strlen("/vsimem/http_")) == 0 )
+        {
+            poDS->InitInternalOverviews();
+        }
     }
     else
         poDS->nPamFlags |= GPF_NOSAVE;
@@ -2167,6 +2362,55 @@ void JPGDataset::ErrorExit(j_common_ptr cinfo)
     longjmp(*setjmp_buffer, 1);
 }
 
+/************************************************************************/
+/*                           JPGAddICCProfile()                         */
+/*                                                                      */
+/*      This function adds an ICC profile to a JPEG file.               */
+/************************************************************************/
+
+static void JPGAddICCProfile( struct jpeg_compress_struct *pInfo, const char *pszICCProfile )
+{
+    if( pszICCProfile == NULL )
+        return;
+
+    /* Write out each segment of the ICC profile */
+    char *pEmbedBuffer = CPLStrdup(pszICCProfile);
+    GInt32 nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+    char *pEmbedPtr = pEmbedBuffer;
+    char const * const paHeader = "ICC_PROFILE";
+    int nSegments = (nEmbedLen + 65518) / 65519;
+    int nSegmentID = 1;
+
+    while( nEmbedLen != 0)
+    {
+        /* 65535 - 16 bytes for header = 65519 */
+        int nChunkLen = (nEmbedLen > 65519)?65519:nEmbedLen;
+        nEmbedLen -= nChunkLen;
+
+        /* write marker and length. */
+        jpeg_write_m_header(pInfo, JPEG_APP0 + 2,
+			        (unsigned int) (nChunkLen + 14));
+
+        /* Write identifier */
+        for(int i = 0; i < 12; i++)
+            jpeg_write_m_byte(pInfo, paHeader[i]);
+
+        /* Write ID and max ID */
+        jpeg_write_m_byte(pInfo, nSegmentID);
+        jpeg_write_m_byte(pInfo, nSegments);
+
+        /* Write ICC Profile */
+        for(int i = 0; i < nChunkLen; i++)
+            jpeg_write_m_byte(pInfo, pEmbedPtr[i]);
+
+        nSegmentID++;
+
+        pEmbedPtr += nChunkLen;
+    }
+
+    CPLFree(pEmbedBuffer);        
+}
+
 #if !defined(JPGDataset)
 
 /************************************************************************/
@@ -2530,6 +2774,16 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     jpeg_start_compress( &sCInfo, TRUE );
 
 /* -------------------------------------------------------------------- */
+/*      Save ICC profile if available                                   */
+/* -------------------------------------------------------------------- */
+    const char *pszICCProfile = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
+    if (pszICCProfile == NULL)
+        pszICCProfile = poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE", "COLOR_PROFILE" );
+
+    if (pszICCProfile != NULL)
+        JPGAddICCProfile( &sCInfo, pszICCProfile );
+
+/* -------------------------------------------------------------------- */
 /*      Does the source have a mask?  If so, we will append it to the   */
 /*      jpeg file after the imagery.                                    */
 /* -------------------------------------------------------------------- */
@@ -2649,16 +2903,19 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     /* If outputing to stdout, we can't reopen it, so we'll return */
     /* a fake dataset to make the caller happy */
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    JPGDataset *poDS = (JPGDataset*) Open( pszFilename );
-    CPLPopErrorHandler();
-    if( poDS )
+    if( CSLTestBoolean(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
     {
-        poDS->CloneInfo( poSrcDS, nCloneFlags );
-        return poDS;
-    }
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        JPGDataset *poDS = (JPGDataset*) Open( pszFilename );
+        CPLPopErrorHandler();
+        if( poDS )
+        {
+            poDS->CloneInfo( poSrcDS, nCloneFlags );
+            return poDS;
+        }
 
-    CPLErrorReset();
+        CPLErrorReset();
+    }
 
     JPGDataset* poJPG_DS = new JPGDataset();
     poJPG_DS->nRasterXSize = nXSize;
@@ -2714,6 +2971,7 @@ void GDALRegister_JPEG()
 "       <Value>RGB1</Value>"
 "   </Option>"
 #endif
+"   <Option name='SOURCE_ICC_PROFILE' type='string'/>\n"
 "</CreationOptionList>\n" );
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
diff --git a/frmts/jpeg/jpgdataset_12.cpp b/frmts/jpeg/jpgdataset_12.cpp
index 7d78800..da8ec78 100644
--- a/frmts/jpeg/jpgdataset_12.cpp
+++ b/frmts/jpeg/jpgdataset_12.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: jpgdataset_12.cpp 25458 2013-01-05 20:32:43Z rouault $
+ * $Id: jpgdataset_12.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2009, Even Rouault
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/jpeg/libjpeg/README b/frmts/jpeg/libjpeg/README
index 86cc206..065dbcf 100644
--- a/frmts/jpeg/libjpeg/README
+++ b/frmts/jpeg/libjpeg/README
@@ -1,3 +1,13 @@
+GDAL specific
+-------------
+
+The patch http://src.chromium.org/viewvc/chrome/trunk/src/third_party/libjpeg/jdmarker.c?view=patch&r1=228354&r2=228353&pathrev=228354
+for CVE-2013-6629 has been applied on top of libjpeg 6b.
+See https://bugzilla.redhat.com/show_bug.cgi?id=1031734
+
+End of GDAL specific
+--------------------
+
 The Independent JPEG Group's JPEG software
 ==========================================
 
diff --git a/frmts/jpeg/libjpeg/jdmarker.c b/frmts/jpeg/libjpeg/jdmarker.c
index f4cca8c..c9325af 100644
--- a/frmts/jpeg/libjpeg/jdmarker.c
+++ b/frmts/jpeg/libjpeg/jdmarker.c
@@ -342,6 +342,12 @@ get_sos (j_decompress_ptr cinfo)
     
     TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
 	     compptr->dc_tbl_no, compptr->ac_tbl_no);
+
+    /* This CSi (cc) should differ from the previous CSi */
+    for (ci = 0; ci < i; ci++) {
+      if (cinfo->cur_comp_info[ci] == compptr)
+        ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+    }
   }
 
   /* Collect the additional scan parameters Ss, Se, Ah/Al. */
diff --git a/frmts/jpeg/vsidataio.h b/frmts/jpeg/vsidataio.h
index d457c06..57a87f3 100644
--- a/frmts/jpeg/vsidataio.h
+++ b/frmts/jpeg/vsidataio.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsidataio.h 24269 2012-04-20 20:52:55Z rouault $
+ * $Id: vsidataio.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement JPEG read/write io indirection through VSI.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.cpp b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
index 0d76130..e1c017c 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.cpp
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000_vsil_io.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: jpeg2000_vsil_io.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Return a stream for a VSIL file
@@ -15,6 +15,7 @@
  *   British Columbia.
  * Copyright (c) 2001-2003 Michael David Adams.
  * All rights reserved.
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  */
 
 /* __START_OF_JASPER_LICENSE__
@@ -76,7 +77,7 @@
 #include "jpeg2000_vsil_io.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /*
  * File descriptor file object.
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.h b/frmts/jpeg2000/jpeg2000_vsil_io.h
index 678ac7d..7a560e2 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.h
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: jpeg2000_vsil_io.h 17567 2009-08-23 14:38:13Z rouault $
+ * $Id: jpeg2000_vsil_io.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Return a stream for a VSIL file
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/jpeg2000/jpeg2000dataset.cpp b/frmts/jpeg2000/jpeg2000dataset.cpp
index 0d6a498..cccb82e 100644
--- a/frmts/jpeg2000/jpeg2000dataset.cpp
+++ b/frmts/jpeg2000/jpeg2000dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000dataset.cpp 25662 2013-02-22 12:04:24Z rouault $
+ * $Id: jpeg2000dataset.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,14 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "cpl_string.h"
+#include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
+#include "cpl_string.h"
 
 #include <jasper/jasper.h>
 #include "jpeg2000_vsil_io.h"
 
-CPL_CVSID("$Id: jpeg2000dataset.cpp 25662 2013-02-22 12:04:24Z rouault $");
+CPL_CVSID("$Id: jpeg2000dataset.cpp 27182 2014-04-14 20:03:08Z rouault $");
 
 CPL_C_START
 void    GDALRegister_JPEG2000(void);
@@ -167,7 +168,7 @@ int jp2_encode_uuid(jas_image_t *image, jas_stream_t *out,
 /* ==================================================================== */
 /************************************************************************/
 
-class JPEG2000Dataset : public GDALPamDataset
+class JPEG2000Dataset : public GDALJP2AbstractDataset
 {
     friend class JPEG2000RasterBand;
 
@@ -175,12 +176,6 @@ class JPEG2000Dataset : public GDALPamDataset
     jas_image_t *psImage;
     int         iFormat;
 
-    char        *pszProjection;
-    int         bGeoTransformValid;
-    double      adfGeoTransform[6];
-    int         nGCPCount;
-    GDAL_GCP    *pasGCPList;
-
     int         bAlreadyDecoded;
     int         DecodeImage();
 
@@ -190,12 +185,6 @@ class JPEG2000Dataset : public GDALPamDataset
     
     static int           Identify( GDALOpenInfo * );
     static GDALDataset  *Open( GDALOpenInfo * );
-
-    CPLErr              GetGeoTransform( double* );
-    virtual const char  *GetProjectionRef(void);
-    virtual int         GetGCPCount();
-    virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
 };
 
 /************************************************************************/
@@ -410,16 +399,6 @@ JPEG2000Dataset::JPEG2000Dataset()
     psStream = NULL;
     psImage = NULL;
     nBands = 0;
-    pszProjection = CPLStrdup("");
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    bGeoTransformValid = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
     bAlreadyDecoded = FALSE;
     
     poDriver = (GDALDriver *)GDALGetDriverByName("JPEG2000");
@@ -438,14 +417,6 @@ JPEG2000Dataset::~JPEG2000Dataset()
         jas_stream_close( psStream );
     if ( psImage )
         jas_image_destroy( psImage );
-
-    if ( pszProjection )
-        CPLFree( pszProjection );
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
 }
 
 /************************************************************************/
@@ -535,65 +506,6 @@ int JPEG2000Dataset::DecodeImage()
     return TRUE;
 }
 
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *JPEG2000Dataset::GetProjectionRef()
-
-{
-    return( pszProjection );
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr JPEG2000Dataset::GetGeoTransform( double * padfTransform )
-{
-    if( bGeoTransformValid )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
-        return CE_None;
-    }
-    else
-        return CE_Failure;
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int JPEG2000Dataset::GetGCPCount()
-
-{
-    return nGCPCount;
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *JPEG2000Dataset::GetGCPProjection()
-
-{
-    if( nGCPCount > 0 )
-        return pszProjection;
-    else
-        return "";
-}
-
-/************************************************************************/
-/*                               GetGCP()                               */
-/************************************************************************/
-
-const GDAL_GCP *JPEG2000Dataset::GetGCPs()
-
-{
-    return pasGCPList;
-}
-
 static void JPEG2000Init()
 {
     static int bHasInit = FALSE;
@@ -831,45 +743,7 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     if ( pabSignedness )
         CPLFree( pabSignedness );
 
-/* -------------------------------------------------------------------- */
-/*      Check for georeferencing information.                           */
-/* -------------------------------------------------------------------- */
-    GDALJP2Metadata oJP2Geo;
-    
-    if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
-    {
-        if ( poDS->pszProjection )
-            CPLFree( poDS->pszProjection );
-        poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-        poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
-        memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
-                sizeof(double) * 6 );
-        poDS->nGCPCount = oJP2Geo.nGCPCount;
-        poDS->pasGCPList =
-            GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
-    }
-
-    if (oJP2Geo.pszXMPMetadata)
-    {
-        char *apszMDList[2];
-        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-        apszMDList[1] = NULL;
-        poDS->SetMetadata(apszMDList, "xml:XMP");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
-/* -------------------------------------------------------------------- */
-    if( !poDS->bGeoTransformValid )
-    {
-        poDS->bGeoTransformValid |=
-            GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
-                                poDS->adfGeoTransform,
-                                poOpenInfo->papszSiblingFiles, NULL )
-            || GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
-                                   poDS->adfGeoTransform,
-                                   poOpenInfo->papszSiblingFiles, NULL );
-    }
+    poDS->LoadJP2Metadata(poOpenInfo);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -1197,6 +1071,9 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 oJP2Geo.SetGeoTransform( adfGeoTransform );
             }
 
+            const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+            oJP2Geo.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
+
             GDALJP2Box *poBox = oJP2Geo.CreateJP2GeoTIFF();
             jp2_box_t  *box = jp2_box_create( JP2_BOX_UUID );
             memcpy( box->data.uuid.uuid, poBox->GetUUID(), 16 );
diff --git a/frmts/jpegls/jpeglsdataset.cpp b/frmts/jpegls/jpeglsdataset.cpp
index 428e703..6a4c6fe 100644
--- a/frmts/jpegls/jpeglsdataset.cpp
+++ b/frmts/jpegls/jpeglsdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: jpeglsdataset.cpp 21192 2010-12-04 10:49:56Z rouault $
+ * $Id: jpeglsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  JPEGLS driver based on CharLS library
  * Purpose:  JPEGLS driver based on CharLS library
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@ extern "C" void GDALRegister_JPEGLS();
 
 /* g++ -Wall -g fmrts/jpegls/jpeglsdataset.cpp -shared -fPIC -o gdal_JPEGLS.so -Iport -Igcore -L. -lgdal -I/home/even/charls-1.0 -L/home/even/charls-1.0/build -lCharLS */
 
-CPL_CVSID("$Id: jpeglsdataset.cpp 21192 2010-12-04 10:49:56Z rouault $");
+CPL_CVSID("$Id: jpeglsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/jpipkak/GNUmakefile b/frmts/jpipkak/GNUmakefile
index b028429..8fe0d83 100644
--- a/frmts/jpipkak/GNUmakefile
+++ b/frmts/jpipkak/GNUmakefile
@@ -27,6 +27,7 @@ kdu_cache.cpp:	  $(KAKDIR)/apps/caching_sources/kdu_cache.cpp
 clean:
 	rm -f *.o $(O_OBJ)
 	rm -f $(INSTOBJ)
+	rm -f kdu_cache.cpp
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
index 5f17844..d9b69a7 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, SPADAC Inc. <harsh.govind at spadac.com>
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -183,7 +184,13 @@ void GenerateTiles(std::string filename,
     delete [] pafScanline;
     delete [] hadnoData;
 
-    GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, NULL, NULL, NULL);
+    CPLString osOpenAfterCopy = CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "");
+    CPLSetThreadLocalConfigOption("GDAL_OPEN_AFTER_COPY", "NO");
+    /* to prevent CreateCopy() from calling QuietDelete() */
+    char** papszOptions = CSLAddNameValue(NULL, "QUIET_DELETE_ON_CREATE_COPY", "NO");
+    GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, papszOptions, NULL, NULL);
+    CSLDestroy(papszOptions);
+    CPLSetThreadLocalConfigOption("GDAL_OPEN_AFTER_COPY", osOpenAfterCopy.size() ? osOpenAfterCopy.c_str() : NULL);
 
     GDALClose(poTmpDataset);
     if (outDs)
@@ -201,7 +208,9 @@ int  GenerateRootKml(const char* filename,
                      double south, 
                      double east, 
                      double west, 
-                     int tilesize)
+                     int tilesize,
+                     const char* pszOverlayName,
+                     const char* pszOverlayDescription)
 {
     VSILFILE* fp = VSIFOpenL(filename, "wb");
     if (fp == NULL)
@@ -213,36 +222,53 @@ int  GenerateRootKml(const char* filename,
     int minlodpixels = tilesize/2;
 
     const char* tmpfilename = CPLGetBasename(kmlfilename);
+    if( pszOverlayName == NULL )
+        pszOverlayName = tmpfilename;
+
     // If we haven't writen any features yet, output the layer's schema
-    VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
+    VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+    VSIFPrintfL(fp, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
     VSIFPrintfL(fp, "\t<Document>\n");
-    VSIFPrintfL(fp, "\t\t<name>%s</name>\n", tmpfilename);
-    VSIFPrintfL(fp, "\t\t<description></description>\n");
-    VSIFPrintfL(fp, "\t\t<Style>\n");
+    char* pszEncoded = CPLEscapeString(pszOverlayName, -1, CPLES_XML);
+    VSIFPrintfL(fp, "\t\t<name>%s</name>\n", pszEncoded);
+    CPLFree(pszEncoded);
+    if( pszOverlayDescription == NULL )
+    {
+        VSIFPrintfL(fp, "\t\t<description></description>\n");
+    }
+    else
+    {
+        pszEncoded = CPLEscapeString(pszOverlayDescription, -1, CPLES_XML);
+        VSIFPrintfL(fp, "\t\t<description>%s</description>\n", pszEncoded);
+        CPLFree(pszEncoded);
+    }
+    VSIFPrintfL(fp, "\t\t<styleUrl>#hideChildrenStyle</styleUrl>\n");
+    VSIFPrintfL(fp, "\t\t<Style id=\"hideChildrenStyle\">\n");
     VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
     VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
     VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
     VSIFPrintfL(fp, "\t\t</Style>\n");
-    VSIFPrintfL(fp, "\t\t<Region>\n \t\t<LatLonAltBox>\n");
+    /*VSIFPrintfL(fp, "\t\t<Region>\n");
+    VSIFPrintfL(fp, "\t\t\t<LatLonAltBox>\n");
     VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", north);
     VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", south);
     VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", east);
     VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", west);
     VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
-    VSIFPrintfL(fp, "\t\t</Region>\n");
+    VSIFPrintfL(fp, "\t\t</Region>\n");*/
     VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
     VSIFPrintfL(fp, "\t\t\t<open>1</open>\n");
     VSIFPrintfL(fp, "\t\t\t<Region>\n");
-    VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
-    VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minlodpixels);
-    VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
-    VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
     VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
     VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", north);
     VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", south);
     VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", east);
     VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", west);
     VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
+    VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
+    VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minlodpixels);
+    VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
+    VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
     VSIFPrintfL(fp, "\t\t\t</Region>\n");
     VSIFPrintfL(fp, "\t\t\t<Link>\n");
     VSIFPrintfL(fp, "\t\t\t\t<href>0/0/0.kml</href>\n");
@@ -268,7 +294,9 @@ int  GenerateChildKml(std::string filename,
                       int ysize, int maxzoom, 
                       OGRCoordinateTransformation * poTransform,
                       std::string fileExt,
-                      bool fixAntiMeridian)
+                      bool fixAntiMeridian,
+                      const char* pszAltitude,
+                      const char* pszAltitudeMode)
 {
     double tnorth = south + zoomypixel *((iy + 1)*dysize);
     double tsouth = south + zoomypixel *(iy*dysize);
@@ -344,25 +372,27 @@ int  GenerateChildKml(std::string filename,
         return FALSE;
     }
 
-    VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
+    VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+    VSIFPrintfL(fp, "<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
     VSIFPrintfL(fp, "\t<Document>\n");
     VSIFPrintfL(fp, "\t\t<name>%d/%d/%d.kml</name>\n", zoom, ix, iy);
-    VSIFPrintfL(fp, "\t\t<Style>\n");
+    VSIFPrintfL(fp, "\t\t<styleUrl>#hideChildrenStyle</styleUrl>\n");
+    VSIFPrintfL(fp, "\t\t<Style id=\"hideChildrenStyle\">\n");
     VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
     VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
     VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
     VSIFPrintfL(fp, "\t\t</Style>\n");
     VSIFPrintfL(fp, "\t\t<Region>\n");
-    VSIFPrintfL(fp, "\t\t\t<Lod>\n");
-    VSIFPrintfL(fp, "\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minLodPixels);
-    VSIFPrintfL(fp, "\t\t\t\t<maxLodPixels>%d</maxLodPixels>\n", maxLodPix);
-    VSIFPrintfL(fp, "\t\t\t</Lod>\n");
     VSIFPrintfL(fp, "\t\t\t<LatLonAltBox>\n");
     VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", tnorth);
     VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", tsouth);
     VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", teast);
     VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", twest);
     VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
+    VSIFPrintfL(fp, "\t\t\t<Lod>\n");
+    VSIFPrintfL(fp, "\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minLodPixels);
+    VSIFPrintfL(fp, "\t\t\t\t<maxLodPixels>%d</maxLodPixels>\n", maxLodPix);
+    VSIFPrintfL(fp, "\t\t\t</Lod>\n");
     VSIFPrintfL(fp, "\t\t</Region>\n");
     VSIFPrintfL(fp, "\t\t<GroundOverlay>\n");
     VSIFPrintfL(fp, "\t\t\t<drawOrder>%d</drawOrder>\n", zoom);
@@ -370,6 +400,23 @@ int  GenerateChildKml(std::string filename,
     VSIFPrintfL(fp, "\t\t\t\t<href>%d%s</href>\n", iy, fileExt.c_str());
     VSIFPrintfL(fp, "\t\t\t</Icon>\n");
 
+    if( pszAltitude != NULL )
+    {
+        VSIFPrintfL(fp, "\t\t\t<altitude>%s</altitude>\n", pszAltitude);
+    }
+    if( pszAltitudeMode != NULL &&
+        (strcmp(pszAltitudeMode, "clampToGround") == 0 ||
+         strcmp(pszAltitudeMode, "absolute") == 0) )
+    {
+        VSIFPrintfL(fp, "\t\t\t<altitudeMode>%s</altitudeMode>\n", pszAltitudeMode);
+    }
+    else if( pszAltitudeMode != NULL &&
+        (strcmp(pszAltitudeMode, "relativeToSeaFloor") == 0 ||
+         strcmp(pszAltitudeMode, "clampToSeaFloor") == 0) )
+    {
+        VSIFPrintfL(fp, "\t\t\t<gx:altitudeMode>%s</gx:altitudeMode>\n", pszAltitudeMode);
+    }
+
     /* When possible, use <LatLonBox>. I've noticed otherwise that */
     /* if using <gx:LatLonQuad> with extents of the size of a country or */
     /* continent, the overlay is really bad placed in GoogleEarth */
@@ -422,16 +469,16 @@ int  GenerateChildKml(std::string filename,
             VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
             VSIFPrintfL(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cy, fileExt.c_str());
             VSIFPrintfL(fp, "\t\t\t<Region>\n");
-            VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
-            VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
-            VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
-            VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
             VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
             VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
             VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
             VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
             VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
             VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
+            VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
+            VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
+            VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
+            VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
             VSIFPrintfL(fp, "\t\t\t</Region>\n");
             VSIFPrintfL(fp, "\t\t\t<Link>\n");
             VSIFPrintfL(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cy);
@@ -450,139 +497,6 @@ int  GenerateChildKml(std::string filename,
 }
 
 /************************************************************************/
-/*                           zipWithMinizip()                           */
-/************************************************************************/
-bool zipWithMinizip(std::vector<std::string> srcFiles, std::string srcDirectory, std::string targetFile)
-{
-    void  *zipfile = CPLCreateZip(targetFile.c_str(), NULL);
-    if (!zipfile)
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Unable to open target zip file.." );
-        return false;
-    }
-
-    std::vector <std::string>::iterator v1_Iter;
-    for(v1_Iter = srcFiles.begin(); v1_Iter != srcFiles.end(); v1_Iter++)
-    {
-        std::string fileRead = *v1_Iter;
-
-        // Find relative path and open new file with zip file
-        std::string relativeFileReadPath = fileRead;
-        int remNumChars = srcDirectory.size();
-        if(remNumChars > 0)
-        {
-            int f = fileRead.find(srcDirectory);
-            if( f >= 0 )
-            {
-                relativeFileReadPath.erase(f, remNumChars + 1); // 1 added for backslash at the end
-            }      
-        }
-
-        std::basic_string<char>::iterator iter1;
-        for (iter1 = relativeFileReadPath.begin(); iter1 != relativeFileReadPath.end(); iter1++)
-        {
-            int f = relativeFileReadPath.find("\\");
-            if (f >= 0)
-            {
-                relativeFileReadPath.replace(f, 1, "/");
-            }
-            else
-            {
-                break;
-            }
-        }
-        if (CPLCreateFileInZip(zipfile, relativeFileReadPath.c_str(), NULL) != CE_None)
-        {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Unable to create file within the zip file.." );
-            return false;
-        }
-
-        // Read source file and write to zip file
-        VSILFILE* fp = VSIFOpenL(fileRead.c_str(), "rb");
-        if (fp == NULL)
-        {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Could not open source file.." );
-            return false;
-        }
-
-        // Read file in buffer
-        std::string fileData;
-        const unsigned int bufSize = 1024;
-        char buf[bufSize];
-        int nRead;
-        while((nRead = VSIFReadL(buf, 1, bufSize, fp)) != 0)
-        {
-            if ( CPLWriteFileInZip(zipfile, buf, nRead) != CE_None )
-            {
-                CPLError( CE_Failure, CPLE_FileIO,
-                        "Could not write to file within zip file.." );
-                CPLCloseFileInZip(zipfile);
-                CPLCloseZip(zipfile);
-                VSIFCloseL(fp);
-                return false;
-            }
-        }
-
-        VSIFCloseL(fp);
-
-        // Close one src file zipped completely
-        if ( CPLCloseFileInZip(zipfile) != CE_None )
-        {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Could not close file written within zip file.." );
-            CPLCloseZip(zipfile);
-            return false;
-        }
-    }
-
-    CPLCloseZip(zipfile);
-
-    return true;
-}
-
-/************************************************************************/
-/*                   KMLSuperOverlayRecursiveUnlink()                   */
-/************************************************************************/
-
-static void KMLSuperOverlayRecursiveUnlink( const char *pszName )
-
-{
-    char **papszFileList;
-    int i;
-
-    papszFileList = CPLReadDir( pszName );
-
-    for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
-    {
-        VSIStatBufL  sStatBuf;
-
-        if( EQUAL(papszFileList[i],".") || EQUAL(papszFileList[i],"..") )
-            continue;
-
-        CPLString osFullFilename =
-                 CPLFormFilename( pszName, papszFileList[i], NULL );
-
-        VSIStatL( osFullFilename, &sStatBuf );
-
-        if( VSI_ISREG( sStatBuf.st_mode ) )
-        {
-            VSIUnlink( osFullFilename );
-        }
-        else if( VSI_ISDIR( sStatBuf.st_mode ) )
-        {
-            KMLSuperOverlayRecursiveUnlink( osFullFilename );
-        }
-    }
-
-    CSLDestroy( papszFileList );
-
-    VSIRmdir( pszName );
-}
-
-/************************************************************************/
 /*                           CreateCopy()                               */
 /************************************************************************/
 
@@ -597,6 +511,9 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
                                         int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData)
 {
     bool isKmz = false;
+    
+    if( pfnProgress == NULL )
+        pfnProgress = GDALDummyProgress;
 
     int bands = poSrcDS->GetRasterCount();
     if (bands != 1 && bands != 3 && bands != 4)
@@ -634,13 +551,15 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
     CPLFree(output_dir);
     output_dir = NULL;
 
+    VSILFILE* zipHandle = NULL;
     if (isKmz)
     {
-        outDir = CPLFormFilename(outDir, CPLSPrintf("kmlsuperoverlaytmp_%p", pszFilename) , NULL);
-        if (VSIMkdir(outDir, 0755) != 0)
+        outDir = "/vsizip/";
+        outDir += pszFilename;
+        zipHandle = VSIFOpenL(outDir, "wb");
+        if( zipHandle == NULL )
         {
-            CPLError( CE_Failure, CPLE_None,
-                    "Cannot create %s", outDir.c_str() );
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s", pszFilename);
             return NULL;
         }
     }
@@ -661,8 +580,11 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
     {
         CPLError( CE_Failure, CPLE_None,
                   "Image export driver was not found.." );
-        if (isKmz)
-            KMLSuperOverlayRecursiveUnlink(outDir);
+        if( zipHandle != NULL )
+        {
+            VSIFCloseL(zipHandle);
+            VSIUnlink(pszFilename);
+        }
         return NULL;
     }
 
@@ -756,26 +678,84 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
     std::string tmpFileName; 
     std::vector<std::string> fileVector;
     int nRet;
+
+    const char* pszOverlayName = CSLFetchNameValue(papszOptions, "NAME");
+    const char* pszOverlayDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+
     if (isKmz)
     {
-        tmpFileName = CPLFormFilename(outDir, "tmp.kml", NULL);
-        nRet = GenerateRootKml(tmpFileName.c_str(), pszFilename, north, south, east, west, (int)tilexsize);
+        tmpFileName = CPLFormFilename(outDir, "doc.kml", NULL);
+        nRet = GenerateRootKml(tmpFileName.c_str(), pszFilename,
+                               north, south, east, west, (int)tilexsize,
+                               pszOverlayName, pszOverlayDescription);
         fileVector.push_back(tmpFileName);
     }
     else
     {
-        nRet = GenerateRootKml(pszFilename, pszFilename, north, south, east, west, (int)tilexsize);
+        nRet = GenerateRootKml(pszFilename, pszFilename,
+                               north, south, east, west, (int)tilexsize,
+                               pszOverlayName, pszOverlayDescription);
     }
     
     if (nRet == FALSE)
     {
         OGRCoordinateTransformation::DestroyCT( poTransform );
-        if (isKmz)
-            KMLSuperOverlayRecursiveUnlink(outDir);
+        if( zipHandle != NULL )
+        {
+            VSIFCloseL(zipHandle);
+            VSIUnlink(pszFilename);
+        }
         return NULL;
     }
 
-    for (int zoom = maxzoom; zoom >= 0; --zoom)
+    const char* pszAltitude = CSLFetchNameValue(papszOptions, "ALTITUDE");
+    const char* pszAltitudeMode = CSLFetchNameValue(papszOptions, "ALTITUDEMODE");
+    if( pszAltitudeMode != NULL )
+    {
+        if( strcmp(pszAltitudeMode, "clampToGround") == 0 )
+        {
+            pszAltitudeMode = NULL;
+            pszAltitude = NULL;
+        }
+        else if( strcmp(pszAltitudeMode, "absolute") == 0 )
+        {
+            if( pszAltitude == NULL )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "Using ALTITUDE=0 as default value");
+                pszAltitude = "0";
+            }
+        }
+        else if( strcmp(pszAltitudeMode, "relativeToSeaFloor") == 0 )
+        {
+            /* nothing to do */
+        }
+        else if( strcmp(pszAltitudeMode, "clampToSeaFloor") == 0 )
+        {
+            pszAltitude = NULL;
+        }
+        else
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "Ignoring unhandled value of ALTITUDEMODE");
+            pszAltitudeMode = NULL;
+            pszAltitude = NULL;
+        }
+    }
+
+    int zoom;
+    int nTotalTiles = 0;
+    int nTileCount = 0;
+
+    for (zoom = maxzoom; zoom >= 0; --zoom)
+    {
+        int rmaxxsize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tilexsize);
+        int rmaxysize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tileysize);
+
+        int xloop = (int)xsize/rmaxxsize;
+        int yloop = (int)ysize/rmaxysize;
+        nTotalTiles += xloop * yloop;
+    }
+
+    for (zoom = maxzoom; zoom >= 0; --zoom)
     {
         int rmaxxsize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tilexsize);
         int rmaxysize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tileysize);
@@ -785,35 +765,37 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
 
         xloop = xloop>0 ? xloop : 1;
         yloop = yloop>0 ? yloop : 1;
+        
+        std::stringstream zoomStr;
+        zoomStr << zoom;
+
+        std::string zoomDir = outDir;
+        zoomDir+= "/" + zoomStr.str();
+        VSIMkdir(zoomDir.c_str(), 0775);
+
         for (int ix = 0; ix < xloop; ix++)
         {
             int rxsize = (int)(rmaxxsize);
             int rx = (int)(ix * rmaxxsize);
+            int dxsize = (int)(rxsize/rmaxxsize * tilexsize);
+
+            std::stringstream ixStr;
+            ixStr << ix;
+
+            zoomDir = outDir;
+            zoomDir+= "/" + zoomStr.str();
+            zoomDir+= "/" + ixStr.str();
+            VSIMkdir(zoomDir.c_str(), 0775);
 
             for (int iy = 0; iy < yloop; iy++)
             {
                 int rysize = (int)(rmaxysize);
                 int ry = (int)(ysize - (iy * rmaxysize)) - rysize;
-
-                int dxsize = (int)(rxsize/rmaxxsize * tilexsize);
                 int dysize = (int)(rysize/rmaxysize * tileysize);
 
-                std::stringstream zoomStr;
-                std::stringstream ixStr;
                 std::stringstream iyStr;
-
-                zoomStr << zoom;
-                ixStr << ix;
                 iyStr << iy;
 
-                std::string zoomDir = outDir;
-                zoomDir+= "/" + zoomStr.str();
-                VSIMkdir(zoomDir.c_str(), 0775);
-        
-
-                zoomDir = zoomDir + "/" + ixStr.str();
-                VSIMkdir(zoomDir.c_str(), 0775);
-
                 std::string fileExt = ".jpg";
                 if (isJpegDriver == false)
                 {
@@ -847,31 +829,22 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename, GDALDataset *p
                 }
 
                 GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix, 
-                                 dxsize, dysize, tmpSouth, adfGeoTransform[0], xsize, ysize, maxzoom, poTransform, fileExt, fixAntiMeridian);
+                                 dxsize, dysize, tmpSouth, adfGeoTransform[0],
+                                 xsize, ysize, maxzoom, poTransform, fileExt, fixAntiMeridian,
+                                 pszAltitude, pszAltitudeMode);
+
+                nTileCount ++;
+                pfnProgress(1.0 * nTileCount / nTotalTiles, "", pProgressData);
             }
         }
     }
 
     OGRCoordinateTransformation::DestroyCT( poTransform );
     poTransform = NULL;
-    
-    if (isKmz)
-    {
-        std::string outputfile = pszFilename;
-        bool zipDone = true;
-        if (zipWithMinizip(fileVector, outDir, outputfile) == false)
-        {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Unable to do zip.." );
-            zipDone = false;
-        }
 
-        KMLSuperOverlayRecursiveUnlink(outDir);
-
-        if (zipDone == false)
-        {
-            return NULL;
-        }
+    if( zipHandle != NULL )
+    {
+        VSIFCloseL(zipHandle);
     }
 
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
@@ -1028,7 +1001,7 @@ KmlSuperOverlayRasterBand::KmlSuperOverlayRasterBand(KmlSuperOverlayReadDataset*
 }
 
 /************************************************************************/
-/*                       ~KmlSuperOverlayRasterBand()                   */
+/*                               IReadBlock()                           */
 /************************************************************************/
 
 CPLErr KmlSuperOverlayRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pData )
@@ -1571,7 +1544,7 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(GDALOpenInfo * poOpenInfo)
 /*                         KmlSuperOverlayLoadIcon()                    */
 /************************************************************************/
 
-#define BUFFER_SIZE 1000000
+#define BUFFER_SIZE 20000000
 
 static
 GDALDataset* KmlSuperOverlayLoadIcon(const char* pszBaseFilename, const char* pszIcon)
@@ -1598,7 +1571,12 @@ GDALDataset* KmlSuperOverlayLoadIcon(const char* pszBaseFilename, const char* ps
     {
         return NULL;
     }
-    GByte* pabyBuffer = (GByte*) CPLMalloc(BUFFER_SIZE);
+    GByte* pabyBuffer = (GByte*) VSIMalloc(BUFFER_SIZE);
+    if( pabyBuffer == NULL )
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
     int nRead = (int)VSIFReadL(pabyBuffer, 1, BUFFER_SIZE, fp);
     VSIFCloseL(fp);
     if( nRead == BUFFER_SIZE )
@@ -1693,6 +1671,554 @@ static void KmlSuperOverlayComputeDepth(CPLString osFilename,
 }
 
 /************************************************************************/
+/*                    KmlSingleDocRasterDataset                         */
+/************************************************************************/
+
+class KmlSingleDocRasterRasterBand;
+
+struct KmlSingleDocRasterTilesDesc
+{
+    int nMaxJ_i;     /* i index at which a tile with max j is realized */
+    int nMaxJ_j;     /* j index at which a tile with max j is realized */
+    int nMaxI_i;     /* i index at which a tile with max i is realized */
+    int nMaxI_j;     /* j index at which a tile with max i is realized */
+    char szExtJ[4];  /* extension of tile at which max j is realized */
+    char szExtI[4];  /* extension of tile at which max i is realized */
+};
+
+class KmlSingleDocRasterDataset: public GDALDataset
+{
+        friend class KmlSingleDocRasterRasterBand;
+        CPLString osDirname;
+        CPLString osNominalExt;
+        GDALDataset* poCurTileDS;
+        double adfGlobalExtents[4];
+        double adfGeoTransform[6];
+        std::vector<KmlSingleDocRasterDataset*> apoOverviews;
+        std::vector<KmlSingleDocRasterTilesDesc> aosDescs;
+        int nLevel;
+        int nTileSize;
+        int bHasBuiltOverviews;
+        int bLockOtherBands;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
+    public:
+                KmlSingleDocRasterDataset();
+                ~KmlSingleDocRasterDataset();
+
+        virtual CPLErr GetGeoTransform( double * padfGeoTransform )
+        {
+            memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
+            return CE_None;
+        }
+
+        virtual const char *GetProjectionRef() { return SRS_WKT_WGS84; }
+
+        void BuildOverviews();
+
+        static GDALDataset* Open(const char* pszFilename,
+                                 const CPLString& osFilename,
+                                 CPLXMLNode* psNode);
+};
+
+/************************************************************************/
+/*                    KmlSingleDocRasterRasterBand                      */
+/************************************************************************/
+
+class KmlSingleDocRasterRasterBand: public GDALRasterBand
+{
+    public:
+        KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDS,
+                                     int nBand);
+
+        virtual CPLErr IReadBlock( int, int, void * );
+        virtual GDALColorInterp GetColorInterpretation();
+
+        virtual int GetOverviewCount();
+        virtual GDALRasterBand *GetOverview(int);
+};
+
+/************************************************************************/
+/*                        KmlSingleDocRasterDataset()                   */
+/************************************************************************/
+
+KmlSingleDocRasterDataset::KmlSingleDocRasterDataset()
+{
+    poCurTileDS = NULL;
+    nLevel = 0;
+    nTileSize = 0;
+    bHasBuiltOverviews = FALSE;
+    bLockOtherBands = FALSE;
+}
+
+/************************************************************************/
+/*                       ~KmlSingleDocRasterDataset()                   */
+/************************************************************************/
+
+KmlSingleDocRasterDataset::~KmlSingleDocRasterDataset()
+{
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                         CloseDependentDatasets()                     */
+/************************************************************************/
+
+int KmlSingleDocRasterDataset::CloseDependentDatasets()
+{
+    int bRet = FALSE;
+
+    if( poCurTileDS != NULL )
+    {
+        bRet = TRUE;
+        GDALClose((GDALDatasetH) poCurTileDS);
+        poCurTileDS = NULL;
+    }
+    if( apoOverviews.size() > 0 )
+    {
+        bRet = TRUE;
+        for(size_t i = 0; i < apoOverviews.size(); i++)
+            delete apoOverviews[i];
+        apoOverviews.resize(0);
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                     KmlSingleDocGetDimensions()                      */
+/************************************************************************/
+
+static int KmlSingleDocGetDimensions(const CPLString& osDirname,
+                                     const KmlSingleDocRasterTilesDesc& oDesc,
+                                     int nLevel,
+                                     int nTileSize,
+                                     int& nXSize,
+                                     int& nYSize,
+                                     int& nBands,
+                                     int& bHasCT)
+{
+    const char* pszImageFilename = CPLFormFilename( osDirname,
+            CPLSPrintf("kml_image_L%d_%d_%d", nLevel,
+                    oDesc.nMaxJ_j,
+                    oDesc.nMaxJ_i),
+                    oDesc.szExtJ );
+    GDALDataset* poImageDS = (GDALDataset*) GDALOpen(pszImageFilename, GA_ReadOnly);
+    if( poImageDS == NULL )
+    {
+        return FALSE;
+    }
+    int nRightXSize;
+    int nBottomYSize = poImageDS->GetRasterYSize();
+    nBands = poImageDS->GetRasterCount();
+    bHasCT = (nBands == 1 && poImageDS->GetRasterBand(1)->GetColorTable() != NULL);
+    if( oDesc.nMaxJ_j == oDesc.nMaxI_j &&
+        oDesc.nMaxJ_i == oDesc.nMaxI_i)
+    {
+        nRightXSize = poImageDS->GetRasterXSize();
+    }
+    else
+    {
+        GDALClose( (GDALDatasetH) poImageDS) ;
+        pszImageFilename = CPLFormFilename( osDirname,
+            CPLSPrintf("kml_image_L%d_%d_%d", nLevel,
+                    oDesc.nMaxI_j,
+                    oDesc.nMaxI_i),
+                    oDesc.szExtI );
+        poImageDS = (GDALDataset*) GDALOpen(pszImageFilename, GA_ReadOnly);
+        if( poImageDS == NULL )
+        {
+            return FALSE;
+        }
+        nRightXSize = poImageDS->GetRasterXSize();
+    }
+    GDALClose( (GDALDatasetH) poImageDS) ;
+
+    nXSize = nRightXSize + oDesc.nMaxI_i * nTileSize;
+    nYSize = nBottomYSize + oDesc.nMaxJ_j * nTileSize;
+    return (nXSize > 0 && nYSize > 0);
+}
+
+/************************************************************************/
+/*                           BuildOverviews()                           */
+/************************************************************************/
+
+void KmlSingleDocRasterDataset::BuildOverviews()
+{
+    if( bHasBuiltOverviews )
+        return;
+    bHasBuiltOverviews = TRUE;
+
+    for(int k = 2; k <= (int)aosDescs.size(); k++)
+    {
+        const KmlSingleDocRasterTilesDesc& oDesc = aosDescs[aosDescs.size()-k];
+        int nXSize = 0, nYSize = 0, nTileBands = 0, bHasCT = FALSE;
+        if( !KmlSingleDocGetDimensions(osDirname, oDesc, (int)aosDescs.size() - k  + 1,
+                                       nTileSize,
+                                       nXSize, nYSize, nTileBands, bHasCT) )
+        {
+            break;
+        }
+
+        KmlSingleDocRasterDataset* poOvrDS = new KmlSingleDocRasterDataset();
+        poOvrDS->nRasterXSize = nXSize;
+        poOvrDS->nRasterYSize = nYSize;
+        poOvrDS->nLevel = (int)aosDescs.size() - k +  1;
+        poOvrDS->nTileSize = nTileSize;
+        poOvrDS->osDirname = osDirname;
+        poOvrDS->osNominalExt = oDesc.szExtI;
+        poOvrDS->adfGeoTransform[0] = adfGlobalExtents[0];
+        poOvrDS->adfGeoTransform[1] = (adfGlobalExtents[2] - adfGlobalExtents[0]) / poOvrDS->nRasterXSize;
+        poOvrDS->adfGeoTransform[2] = 0.0;
+        poOvrDS->adfGeoTransform[3] = adfGlobalExtents[3];
+        poOvrDS->adfGeoTransform[4] = 0.0;
+        poOvrDS->adfGeoTransform[5] = -(adfGlobalExtents[3] - adfGlobalExtents[1]) / poOvrDS->nRasterXSize;
+        for(int iBand = 1; iBand <= nBands; iBand ++ )
+            poOvrDS->SetBand(iBand, new KmlSingleDocRasterRasterBand(poOvrDS, iBand));
+        poOvrDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+
+        apoOverviews.push_back(poOvrDS);
+    }
+}
+
+/************************************************************************/
+/*                      KmlSingleDocRasterRasterBand()                  */
+/************************************************************************/
+
+KmlSingleDocRasterRasterBand::KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDS,
+                                                           int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    nBlockXSize = poDS->nTileSize;
+    nBlockYSize = poDS->nTileSize;
+    eDataType = GDT_Byte;
+}
+
+/************************************************************************/
+/*                               IReadBlock()                           */
+/************************************************************************/
+
+CPLErr KmlSingleDocRasterRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                                 void * pImage )
+{
+    KmlSingleDocRasterDataset* poGDS = (KmlSingleDocRasterDataset*) poDS;
+    const char* pszImageFilename = CPLFormFilename( poGDS->osDirname,
+        CPLSPrintf("kml_image_L%d_%d_%d", poGDS->nLevel, nBlockYOff, nBlockXOff), poGDS->osNominalExt );
+    if( poGDS->poCurTileDS == NULL || 
+        strcmp(CPLGetFilename(poGDS->poCurTileDS->GetDescription()),
+               CPLGetFilename(pszImageFilename)) != 0 )
+    {
+        if( poGDS->poCurTileDS != NULL ) GDALClose((GDALDatasetH) poGDS->poCurTileDS);
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        poGDS->poCurTileDS = (GDALDataset*) GDALOpen(pszImageFilename, GA_ReadOnly);
+        CPLPopErrorHandler();
+    }
+    GDALDataset* poImageDS = poGDS->poCurTileDS;
+    if( poImageDS == NULL )
+    {
+        memset( pImage, 0, nBlockXSize * nBlockYSize );
+        return CE_None;
+    }
+    int nXSize = poImageDS->GetRasterXSize();
+    int nYSize = poImageDS->GetRasterYSize();
+
+    int nReqXSize = nBlockXSize;
+    if( nBlockXOff * nBlockXSize + nReqXSize > nRasterXSize )
+        nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
+    int nReqYSize = nBlockYSize;
+    if( nBlockYOff * nBlockYSize + nReqYSize > nRasterYSize )
+        nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
+
+    if( nXSize != nReqXSize || nYSize != nReqYSize )
+    {
+        CPLDebug("KMLSUPEROVERLAY", "Tile %s, dimensions %dx%d, expected %dx%d",
+                 pszImageFilename, nXSize, nYSize, nReqXSize, nReqYSize);
+        return CE_Failure;
+    }
+
+    CPLErr eErr = CE_Failure;
+    if( poImageDS->GetRasterCount() == 1 )
+    {
+        GDALColorTable* poColorTable = poImageDS->GetRasterBand(1)->GetColorTable();
+        if( nBand == 4 && poColorTable == NULL )
+        {
+            /* Add fake alpha band */
+            memset( pImage, 255, nBlockXSize * nBlockYSize );
+            eErr = CE_None;
+        }
+        else
+        {
+            eErr = poImageDS->GetRasterBand(1)->RasterIO(GF_Read,
+                                                    0, 0, nXSize, nYSize,
+                                                    pImage,
+                                                    nXSize, nYSize,
+                                                    GDT_Byte, 1, nBlockXSize);
+
+            /* Expand color table */
+            if( eErr == CE_None && poColorTable != NULL )
+            {
+                int j, i;
+                for(j = 0; j < nReqYSize; j++ )
+                {
+                    for(i = 0; i < nReqXSize; i++ )
+                    {
+                        GByte nVal = ((GByte*) pImage)[j * nBlockXSize + i];
+                        const GDALColorEntry * poEntry = poColorTable->GetColorEntry(nVal);
+                        if( poEntry != NULL )
+                        {
+                            if( nBand == 1 )
+                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c1;
+                            else if( nBand == 2 )
+                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c2;
+                            else if( nBand == 3 )
+                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c3;
+                            else
+                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c4;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else if( nBand <= poImageDS->GetRasterCount() )
+    {
+        eErr = poImageDS->GetRasterBand(nBand)->RasterIO(GF_Read,
+                                                0, 0, nXSize, nYSize,
+                                                pImage,
+                                                nXSize, nYSize,
+                                                GDT_Byte, 1, nBlockXSize);
+    }
+    else if( nBand == 4 && poImageDS->GetRasterCount() == 3 )
+    {
+        /* Add fake alpha band */
+        memset( pImage, 255, nBlockXSize * nBlockYSize );
+        eErr = CE_None;
+    }
+
+    /* Cache other bands */
+    if( !poGDS->bLockOtherBands )
+    {
+        poGDS->bLockOtherBands = TRUE;
+        for(int iBand = 1; iBand <= poGDS->nBands; iBand ++ )
+        {
+            if( iBand != nBand )
+            {
+                KmlSingleDocRasterRasterBand* poOtherBand =
+                    (KmlSingleDocRasterRasterBand*)poGDS->GetRasterBand(iBand);
+                GDALRasterBlock* poBlock = poOtherBand->
+                                    GetLockedBlockRef(nBlockXOff, nBlockYOff);
+                if( poBlock == NULL )
+                    continue;
+                poBlock->DropLock();
+            }
+        }
+        poGDS->bLockOtherBands = FALSE;
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          GetColorInterpretation()                    */
+/************************************************************************/
+
+GDALColorInterp  KmlSingleDocRasterRasterBand::GetColorInterpretation()
+{
+    return (GDALColorInterp)(GCI_RedBand + nBand - 1);
+}
+
+/************************************************************************/
+/*                          GetOverviewCount()                          */
+/************************************************************************/
+
+int KmlSingleDocRasterRasterBand::GetOverviewCount()
+{
+    KmlSingleDocRasterDataset* poGDS = (KmlSingleDocRasterDataset*) poDS;
+    poGDS->BuildOverviews();
+
+    return (int)poGDS->apoOverviews.size();
+}
+
+/************************************************************************/
+/*                           GetOverview()                              */
+/************************************************************************/
+
+GDALRasterBand *KmlSingleDocRasterRasterBand::GetOverview(int iOvr)
+{
+    KmlSingleDocRasterDataset* poGDS = (KmlSingleDocRasterDataset*) poDS;
+    poGDS->BuildOverviews();
+
+    if( iOvr < 0 || iOvr >= (int)poGDS->apoOverviews.size() )
+        return NULL;
+
+    return poGDS->apoOverviews[iOvr]->GetRasterBand(nBand);
+}
+
+/************************************************************************/
+/*                       KmlSingleDocCollectTiles()                     */
+/************************************************************************/
+
+static void KmlSingleDocCollectTiles(CPLXMLNode* psNode,
+                                     std::vector<KmlSingleDocRasterTilesDesc>& aosDescs,
+                                     CPLString& osURLBase)
+{
+    if( strcmp(psNode->pszValue, "href") == 0 )
+    {
+        int level, j, i;
+        char szExt[4];
+        const char* pszHref = CPLGetXMLValue(psNode, "", "");
+        if( strncmp(pszHref, "http", 4) == 0 )
+        {
+            osURLBase = CPLGetPath(pszHref);
+        }
+        if( sscanf(CPLGetFilename(pszHref), "kml_image_L%d_%d_%d.%3s",
+                   &level, &j, &i, szExt) == 4 )
+        {
+            if( level > (int)aosDescs.size() )
+            {
+                KmlSingleDocRasterTilesDesc sDesc;
+                while( level > (int)aosDescs.size() + 1 )
+                {
+                    sDesc.nMaxJ_i = -1;
+                    sDesc.nMaxJ_j = -1;
+                    sDesc.nMaxI_i = -1;
+                    sDesc.nMaxI_j = -1;
+                    strcpy(sDesc.szExtI, "");
+                    strcpy(sDesc.szExtJ, "");
+                    aosDescs.push_back(sDesc);
+                }
+
+                sDesc.nMaxJ_j = j;
+                sDesc.nMaxJ_i = i;
+                strcpy(sDesc.szExtJ, szExt);
+                sDesc.nMaxI_j = j;
+                sDesc.nMaxI_i = i;
+                strcpy(sDesc.szExtI, szExt);
+                aosDescs.push_back(sDesc);
+            }
+            else
+            {
+                /* 2010_USACE_JALBTCX_Louisiana_Mississippi_Lidar.kmz has not a lower-right tile */
+                /* so the right most tile and the bottom most tile might be different */
+                if( (j > aosDescs[level-1].nMaxJ_j) ||
+                    (j == aosDescs[level-1].nMaxJ_j &&
+                     i > aosDescs[level-1].nMaxJ_i) )
+                {
+                    aosDescs[level-1].nMaxJ_j = j;
+                    aosDescs[level-1].nMaxJ_i = i;
+                    strcpy(aosDescs[level-1].szExtJ, szExt);
+                }
+                if( i > aosDescs[level-1].nMaxI_i ||
+                   (i == aosDescs[level-1].nMaxI_i &&
+                    j > aosDescs[level-1].nMaxI_j) )
+                {
+                    aosDescs[level-1].nMaxI_j = j;
+                    aosDescs[level-1].nMaxI_i = i;
+                    strcpy(aosDescs[level-1].szExtI, szExt);
+                }
+            }
+        }
+    }
+    else
+    {
+        CPLXMLNode* psIter = psNode->psChild;
+        while(psIter != NULL)
+        {
+            if( psIter->eType == CXT_Element )
+                KmlSingleDocCollectTiles(psIter, aosDescs, osURLBase);
+            psIter = psIter->psNext;
+        }
+    }
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+/* Read raster with a structure like http://opentopo.sdsc.edu/files/Haiti/NGA_Haiti_LiDAR2.kmz */
+/* i.e. made of a doc.kml that list all tiles at all overview levels */
+/* The tile name pattern is "kml_image_L{level}_{j}_{i}.{png|jpg}" */
+GDALDataset* KmlSingleDocRasterDataset::Open(const char* pszFilename,
+                                             const CPLString& osFilename,
+                                             CPLXMLNode* psRoot)
+{
+    CPLXMLNode* psRootFolder = CPLGetXMLNode(psRoot, "=kml.Document.Folder");
+    if( psRootFolder == NULL )
+        return NULL;
+    const char* pszRootFolderName =
+        CPLGetXMLValue(psRootFolder, "name", "");
+    if( strcmp(pszRootFolderName, "kml_image_L1_0_0") != 0 )
+        return NULL;
+
+    double adfGlobalExtents[4];
+    CPLXMLNode* psRegion = CPLGetXMLNode(psRootFolder, "Region");
+    if( psRegion == NULL )
+        return NULL;
+    if( !KmlSuperOverlayGetBoundingBox(psRegion, adfGlobalExtents) )
+        return NULL;
+
+    std::vector<KmlSingleDocRasterTilesDesc> aosDescs;
+    CPLString osDirname = CPLGetPath(osFilename);
+    KmlSingleDocCollectTiles(psRootFolder, aosDescs, osDirname);
+    if( aosDescs.size() == 0 )
+        return NULL;
+    int k;
+    for(k = 0; k < (int)aosDescs.size(); k++)
+    {
+        if( aosDescs[k].nMaxJ_i < 0 )
+            return NULL;
+    }
+
+    const char* pszImageFilename = CPLFormFilename( osDirname,
+            CPLSPrintf("kml_image_L%d_%d_%d", (int)aosDescs.size(), 0, 0), aosDescs[aosDescs.size()-1].szExtI);
+    GDALDataset* poImageDS = (GDALDataset*) GDALOpen(pszImageFilename, GA_ReadOnly);
+    if( poImageDS == NULL )
+    {
+        return NULL;
+    }
+    int nTileSize = poImageDS->GetRasterXSize();
+    if( nTileSize != poImageDS->GetRasterYSize() )
+    {
+        nTileSize = 1024;
+    }
+    GDALClose( (GDALDatasetH) poImageDS) ;
+
+    const KmlSingleDocRasterTilesDesc& oDesc = aosDescs[aosDescs.size()-1];
+    int nXSize = 0, nYSize = 0, nBands = 0, bHasCT = FALSE;
+    if( !KmlSingleDocGetDimensions(osDirname, oDesc, (int)aosDescs.size(), nTileSize,
+                                   nXSize, nYSize, nBands, bHasCT) )
+    {
+        return NULL;
+    }
+
+    KmlSingleDocRasterDataset* poDS = new KmlSingleDocRasterDataset();
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+    poDS->nLevel = (int)aosDescs.size();
+    poDS->nTileSize = nTileSize;
+    poDS->osDirname = osDirname;
+    poDS->osNominalExt = oDesc.szExtI;
+    memcpy(poDS->adfGlobalExtents, adfGlobalExtents, 4 * sizeof(double));
+    poDS->adfGeoTransform[0] = adfGlobalExtents[0];
+    poDS->adfGeoTransform[1] = (adfGlobalExtents[2] - adfGlobalExtents[0]) / poDS->nRasterXSize;
+    poDS->adfGeoTransform[2] = 0.0;
+    poDS->adfGeoTransform[3] = adfGlobalExtents[3];
+    poDS->adfGeoTransform[4] = 0.0;
+    poDS->adfGeoTransform[5] = -(adfGlobalExtents[3] - adfGlobalExtents[1]) / poDS->nRasterYSize;
+    if( nBands == 1 && bHasCT ) nBands = 4;
+    for(int iBand = 1; iBand <= nBands; iBand ++ )
+        poDS->SetBand(iBand, new KmlSingleDocRasterRasterBand(poDS, iBand));
+    poDS->SetDescription(pszFilename);
+    poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+    poDS->aosDescs = aosDescs;
+
+    return poDS;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -1750,8 +2276,11 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
     if( !KmlSuperOverlayFindRegionStart(psNode, &psRegion,
                                         &psDocument, &psGroundOverlay, &psLink) )
     {
+        GDALDataset* psDS = KmlSingleDocRasterDataset::Open(pszFilename,
+                                                            osFilename,
+                                                            psNode);
         CPLDestroyXMLNode(psNode);
-        return NULL;
+        return psDS;
     }
 
     if( psLink != NULL )
@@ -1773,12 +2302,42 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
             osSubFilename += pszHref;
             osSubFilename = KMLRemoveSlash(osSubFilename);
         }
+
+        CPLString osOverlayName, osOverlayDescription;
+        psDocument = CPLGetXMLNode(psNode, "=kml.Document");
+        if( psDocument )
+        {
+            const char* pszOverlayName = CPLGetXMLValue(psDocument, "name", NULL);
+            if( pszOverlayName != NULL &&
+                strcmp(pszOverlayName, CPLGetBasename(pszFilename)) != 0 )
+            {
+                osOverlayName = pszOverlayName;
+            }
+            const char* pszOverlayDescription = CPLGetXMLValue(psDocument, "description", NULL);
+            if( pszOverlayDescription != NULL )
+            {
+                osOverlayDescription = pszOverlayDescription;
+            }
+        }
+
         CPLDestroyXMLNode(psNode);
 
         // FIXME
         GDALDataset* poDS = Open(osSubFilename, poParent, nRec + 1);
         if( poDS != NULL )
+        {
             poDS->SetDescription(pszFilename);
+
+            if( osOverlayName.size() )
+            {
+                poDS->SetMetadataItem( "NAME", osOverlayName);
+            }
+            if( osOverlayDescription.size() )
+            {
+                poDS->SetMetadataItem( "DESCRIPTION", osOverlayDescription);
+            }
+        }
+
         return poDS;
     }
 
@@ -1895,7 +2454,16 @@ void GDALRegister_KMLSUPEROVERLAY()
 
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
-"   <Option name='FORMAT' type='string-select' default='JPEG' description='Force of the tiles'>"
+"   <Option name='NAME' type='string' description='Overlay name'/>"
+"   <Option name='DESCRIPTION' type='string' description='Overlay description'/>"
+"   <Option name='ALTITUDE' type='float' description='Distance above the earth surface, in meters, interpreted according to the altitude mode'/>"
+"   <Option name='ALTITUDEMODE' type='string-select' default='clampToGround' description='Specifies hows the altitude is interpreted'>"
+"       <Value>clampToGround</Value>"
+"       <Value>absolute</Value>"
+"       <Value>relativeToSeaFloor</Value>"
+"       <Value>clampToSeaFloor</Value>"
+"   </Option>"
+"   <Option name='FORMAT' type='string-select' default='JPEG' description='Format of the tiles'>"
 "       <Value>PNG</Value>"
 "       <Value>JPEG</Value>"
 "   </Option>"
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
index f54e5e0..48b1ef3 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, SPADAC Inc. <harsh.govind at spadac.com>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/l1b/frmt_l1b.html b/frmts/l1b/frmt_l1b.html
index d9aaf86..ae201db 100644
--- a/frmts/l1b/frmt_l1b.html
+++ b/frmts/l1b/frmt_l1b.html
@@ -16,25 +16,42 @@ correctly.
 
 <h2>Georeference</h2>
 
+<p>
 Note, that GDAL simple affine georeference model completely unsuitable for
 the NOAA data. So you should not rely on it. It is recommended to use the
 thin plate spline warper (tps). Automatic image rectification can be done with
 ground control points (GCPs) from the input file.
-
+</p>
+<p>
 NOAA stores 51 GCPs per scanline both in the LAC and GAC datasets. In fact
 you may get less than 51 GCPs, especially at end of scanlines. Another approach
 to rectification is manual selection of the GCPs using external source of
 georeference information.
-<br>
+</p>
+<p>
+Before GDAL 1.10.2, a maximum of 11 x 20 GCPs were reported. This might be
+unsuitable for correct warping. Starting with GDAL 1.10.2, a much higher density
+will be reported, unless the L1B_HIGH_GCP_DENSITY configuration option is set
+to NO.
+</p>
+<p>
 Precision of the GCPs determination depends from the satellite type. In the
 NOAA-9 -- NOAA-14 datasets geographic coordinates of the GCPs stored in
 integer values as a 128th of a degree. So we can't determine positions more
 precise than 1/128=0.0078125 of degree (~28"). In NOAA-15 -- NOAA-17 datasets
 we have much more precise positions, they are stored as 10000th of degree.
-<br>
+</p>
+<p>
+Starting with GDAL 1.11, the GCPs will also be reported as a
+<a href="http://trac.osgeo.org/gdal/wiki/rfc4_geolocate">geolocation array</a>,
+with Lagrangian interpolation of the 51 GCPs per scanline to the number of pixels
+per scanline width.
+</p>
+<p>
 Image will be always returned with most northern scanline located at the top of
 image. If you want determine actual direction of the satellite moving you
 should look at <b>LOCATION</b> metadata record.
+</p>
 
 <h2>Data</h2>
 
@@ -74,9 +91,37 @@ millisecond of day).<p>
 <li> <b>LOCATION</b>: AVHRR Earth location indication. Will be <b>Ascending</b>
 when satellite moves from low latitudes to high latitudes and <b>Descending</b>
 in other case.<p>
-
 </ul>
 
+Starting with GDAL 1.11, most metadata records can be written to a .CSV file when
+the L1B_FETCH_METADATA configuration file is set to YES. By default, the filename
+will be called "[l1b_dataset_name]_metadata.csv", and located in the
+same directory as the L1B dataset. By defining the L1B_METADATA_DIRECTORY configuration
+option, it is possible to create that file in another directory.
+The documentation to interpret those metadata is <a href="http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/podug/html/c3/sec3-1.htm">
+PODUG 3.1</a> for NOAA <=14 and <a href="http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/c8/sec83133-1.htm">
+KLM 8.3.1.3.3.1</a> for NOAA >=15.
+<p>
+
+<h2>Subdatasets</h2>
+
+(Starting with GDAL 1.11)<p>
+
+NOAA <=14 datasets advertize a L1B_SOLAR_ZENITH_ANGLES:"l1b_dataset_name"
+subdataset that contains a maximum of 51 solar zenith angles for each scanline (
+beginning at sample 5 with a step of 8 samples for GAC data, beginning at sample
+25 with a step of 40 samples for HRPT/LAC/FRAC data).<p>
+
+NOAA >=15 datasets advertize a L1B_ANGLES:"l1b_dataset_name"
+subdataset that contains 3 bands (solar zenith angles, satellite zenith angles
+and relative azimuth angles) with 51 values for each scanline (
+beginning at sample 5 with a step of 8 samples for GAC data, beginning at sample
+25 with a step of 40 samples for HRPT/LAC/FRAC data).<p>
+
+NOAA >=15 datasets advertize a L1B_CLOUDS:"l1b_dataset_name"
+subdataset that contains a band of same dimensions as bands of the main L1B
+dataset. The values of each pixel are 0 = unknown; 1 = clear; 2 = cloudy; 3 = partly cloudy.<p>
+
 <h2>See Also:</h2>
 
 <ul>
diff --git a/frmts/l1b/l1bdataset.cpp b/frmts/l1b/l1bdataset.cpp
index 2fec08e..52a7c6b 100644
--- a/frmts/l1b/l1bdataset.cpp
+++ b/frmts/l1b/l1bdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: l1bdataset.cpp 25940 2013-04-20 14:23:19Z rouault $
+ * $Id: l1bdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NOAA Polar Orbiter Level 1b Dataset Reader (AVHRR)
  * Purpose:  Can read NOAA-9(F)-NOAA-17(M) AVHRR datasets
@@ -9,6 +9,11 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * ----------------------------------------------------------------------------
+ * Lagrange interpolation suitable for NOAA level 1B file formats.
+ * Submitted by Andrew Brooks <arb at sat.dundee.ac.uk>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,20 +37,20 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: l1bdataset.cpp 25940 2013-04-20 14:23:19Z rouault $");
+CPL_CVSID("$Id: l1bdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_L1B(void);
 CPL_C_END
 
-enum {                  // File formats
+typedef enum {                  // File formats
     L1B_NONE,           // Not a L1B format
     L1B_NOAA9,          // NOAA-9/14
     L1B_NOAA15,         // NOAA-15/METOP-2
     L1B_NOAA15_NOHDR    // NOAA-15/METOP-2 without ARS header
-};
+} L1BFileFormat;
 
-enum {          // Spacecrafts:
+typedef enum {          // Spacecrafts:
     TIROSN,     // TIROS-N
     // NOAA are given a letter before launch and a number after launch
     NOAA6,      // NOAA-6(A)
@@ -67,22 +72,22 @@ enum {          // Spacecrafts:
     METOP2,     // METOP-A(2)
     METOP1,     // METOP-B(1)
     METOP3,     // METOP-C(3)
-};
+} L1BSpaceCraftdID;
 
-enum {          // Product types
+typedef enum {          // Product types
     HRPT,
     LAC,
     GAC,
     FRAC
-};
+} L1BProductType;
 
-enum {          // Data format
+typedef enum {          // Data format
     PACKED10BIT,
     UNPACKED8BIT,
     UNPACKED16BIT
-};
+} L1BDataFormat;
 
-enum {          // Receiving stations names:
+typedef enum {          // Receiving stations names:
     DU,         // Dundee, Scotland, UK
     GC,         // Fairbanks, Alaska, USA (formerly Gilmore Creek)
     HO,         // Honolulu, Hawaii, USA
@@ -92,20 +97,20 @@ enum {          // Receiving stations names:
     WI,         // Wallops Island, Virginia, USA
     SV,         // Svalbard, Norway
     UNKNOWN_STATION
-};
+} L1BReceivingStation;
 
-enum {          // Data processing centers:
+typedef enum {          // Data processing centers:
     CMS,        // Centre de Meteorologie Spatiale - Lannion, France
     DSS,        // Dundee Satellite Receiving Station - Dundee, Scotland, UK
     NSS,        // NOAA/NESDIS - Suitland, Maryland, USA
     UKM,        // United Kingdom Meteorological Office - Bracknell, England, UK
     UNKNOWN_CENTER
-};
+} L1BProcessingCenter;
 
-enum {          // AVHRR Earth location indication
+typedef enum {          // AVHRR Earth location indication
     ASCEND,
     DESCEND
-};
+} L1BAscendOrDescend;
 
 /************************************************************************/
 /*                      AVHRR band widths                               */
@@ -160,6 +165,8 @@ static const char *apszBandDesc[] =
 #define L1B_NOAA15_HDR_REC_STAT_OFF 116 // Instrument status offset
 #define L1B_NOAA15_HDR_REC_SRC_OFF  154 // Receiving station name offset
 
+/* This only apply if L1B_HIGH_GCP_DENSITY is explicitely set to NO */
+/* otherwise we will report more GCPs */
 #define DESIRED_GCPS_PER_LINE 11
 #define DESIRED_LINES_OF_GCPS 20
 
@@ -193,6 +200,9 @@ class TimeCode {
     {
         lMillisecond = millisecond;
     }
+    long GetYear() { return lYear; }
+    long GetDay() { return lDay; }
+    long GetMillisecond() { return lMillisecond; }
     char* PrintTime()
     {
         snprintf(pszString, L1B_TIMECODE_LENGTH,
@@ -208,29 +218,47 @@ class TimeCode {
 /*                              L1BDataset                              */
 /* ==================================================================== */
 /************************************************************************/
+class L1BGeolocDataset;
+class L1BGeolocRasterBand;
+class L1BSolarZenithAnglesDataset;
+class L1BSolarZenithAnglesRasterBand;
+class L1BNOAA15AnglesDataset;
+class L1BNOAA15AnglesRasterBand;
+class L1BCloudsDataset;
+class L1BCloudsRasterBand;
 
 class L1BDataset : public GDALPamDataset
 {
     friend class L1BRasterBand;
+    friend class L1BGeolocDataset;
+    friend class L1BGeolocRasterBand;
+    friend class L1BSolarZenithAnglesDataset;
+    friend class L1BSolarZenithAnglesRasterBand;
+    friend class L1BNOAA15AnglesDataset;
+    friend class L1BNOAA15AnglesRasterBand;
+    friend class L1BCloudsDataset;
+    friend class L1BCloudsRasterBand;
 
     //char        pszRevolution[6]; // Five-digit number identifying spacecraft revolution
-    int         eSource;        // Source of data (receiving station name)
-    int         eProcCenter;    // Data processing center
+    L1BReceivingStation       eSource;        // Source of data (receiving station name)
+    L1BProcessingCenter       eProcCenter;    // Data processing center
     TimeCode    sStartTime;
     TimeCode    sStopTime;
 
+    int         bHighGCPDensityStrategy;
     GDAL_GCP    *pasGCPList;
     int         nGCPCount;
     int         iGCPOffset;
     int         iGCPCodeOffset;
+    int         iCLAVRStart;
     int         nGCPsPerLine;
     int         eLocationIndicator, iGCPStart, iGCPStep;
 
-    int         eL1BFormat;
+    L1BFileFormat eL1BFormat;
     int         nBufferSize;
-    int         eSpacecraftID;
-    int         eProductType;   // LAC, GAC, HRPT, FRAC
-    int         iDataFormat;    // 10-bit packed or 16-bit unpacked
+    L1BSpaceCraftdID eSpacecraftID;
+    L1BProductType   eProductType;   // LAC, GAC, HRPT, FRAC
+    L1BDataFormat    iDataFormat;    // 10-bit packed or 16-bit unpacked
     int         nRecordDataStart;
     int         nRecordDataEnd;
     int         nDataStartOffset;
@@ -246,16 +274,22 @@ class L1BDataset : public GDALPamDataset
     int         bGuessDataFormat;
 
     void        ProcessRecordHeaders();
-    void        FetchGCPs( GDAL_GCP *, GByte *, int );
-    void        FetchNOAA9TimeCode(TimeCode *, GByte *, int *);
-    void        FetchNOAA15TimeCode(TimeCode *, GUInt16 *, int *);
-    CPLErr      ProcessDatasetHeader();
+    int         FetchGCPs( GDAL_GCP *, GByte *, int );
+    void        FetchNOAA9TimeCode(TimeCode *, const GByte *, int *);
+    void        FetchNOAA15TimeCode(TimeCode *, const GUInt16 *, int *);
+    void        FetchTimeCode( TimeCode *psTime, const void *pRecordHeader,
+                               int *peLocationIndicator );
+    CPLErr      ProcessDatasetHeader(const char* pszFilename);
     int         ComputeFileOffsets();
     
-    static int  DetectFormat( GDALOpenInfo *poOpenInfo );
+    void        FetchMetadata();
+    void        FetchMetadataNOAA15();
+    
+    static L1BFileFormat  DetectFormat( const char* pszFilename,
+                              const GByte* pabyHeader, int nHeaderBytes );
 
   public:
-                L1BDataset( int );
+                L1BDataset( L1BFileFormat );
                 ~L1BDataset();
     
     virtual int GetGCPCount();
@@ -409,18 +443,36 @@ CPLErr L1BRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                           L1BDataset()                               */
 /************************************************************************/
 
-L1BDataset::L1BDataset( int eL1BFormat )
+L1BDataset::L1BDataset( L1BFileFormat eL1BFormat )
 
 {
-    this->eL1BFormat = eL1BFormat;
-    fp = NULL;
-    nGCPCount = 0;
+    eSource = UNKNOWN_STATION;
+    eProcCenter = UNKNOWN_CENTER;
+    // sStartTime
+    // sStopTime
+    bHighGCPDensityStrategy = CSLTestBoolean(CPLGetConfigOption("L1B_HIGH_GCP_DENSITY", "TRUE"));
     pasGCPList = NULL;
-    pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",7043]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",6322]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4322]]" );
-    nBands = 0;
+    nGCPCount = 0;
+    iGCPOffset = 0;
+    iGCPCodeOffset = 0;
+    iCLAVRStart = 0;
+    nGCPsPerLine = 0;
     eLocationIndicator = DESCEND; // XXX: should be initialised
-    iChannelsMask = 0;
+    iGCPStart = 0;
+    iGCPStep = 0;
+    this->eL1BFormat = eL1BFormat;
+    nBufferSize = 0;
+    eSpacecraftID = TIROSN;
+    eProductType = HRPT;
+    iDataFormat = PACKED10BIT;
+    nRecordDataStart = 0;
+    nRecordDataEnd = 0;
+    nDataStartOffset = 0;
+    nRecordSize = 0;
     iInstrumentStatus = 0;
+    iChannelsMask = 0;
+    pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",7043]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",6322]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4322]]" );
+    fp = NULL;
     bFetchGeolocation = FALSE;
     bGuessDataFormat = FALSE;
 }
@@ -481,7 +533,8 @@ const GDAL_GCP *L1BDataset::GetGCPs()
 /*      Fetch timecode from the record header (NOAA9-NOAA14 version)    */
 /************************************************************************/
 
-void L1BDataset::FetchNOAA9TimeCode( TimeCode *psTime, GByte *piRecordHeader,
+void L1BDataset::FetchNOAA9TimeCode( TimeCode *psTime,
+                                     const GByte *piRecordHeader,
                                      int *peLocationIndicator )
 {
     GUInt32 lTemp;
@@ -507,45 +560,52 @@ void L1BDataset::FetchNOAA9TimeCode( TimeCode *psTime, GByte *piRecordHeader,
 /************************************************************************/
 
 void L1BDataset::FetchNOAA15TimeCode( TimeCode *psTime,
-                                      GUInt16 *piRecordHeader,
+                                      const GUInt16 *piRecordHeader,
                                       int *peLocationIndicator )
 {
-#ifdef CPL_LSB
     GUInt16 iTemp;
     GUInt32 lTemp;
 
     iTemp = piRecordHeader[1];
-    psTime->SetYear(CPL_SWAP16(iTemp));
+    psTime->SetYear(CPL_MSBWORD16(iTemp));
     iTemp = piRecordHeader[2];
-    psTime->SetDay(CPL_SWAP16(iTemp));
-    lTemp = (GUInt32)CPL_SWAP16(piRecordHeader[4]) << 16 |
-        (GUInt32)CPL_SWAP16(piRecordHeader[5]);
+    psTime->SetDay(CPL_MSBWORD16(iTemp));
+    lTemp = (GUInt32)CPL_MSBWORD16(piRecordHeader[4]) << 16 |
+        (GUInt32)CPL_MSBWORD16(piRecordHeader[5]);
     psTime->SetMillisecond(lTemp);
     if ( peLocationIndicator )
     {
         // FIXME: hemisphere
         *peLocationIndicator =
-            ((CPL_SWAP16(piRecordHeader[6]) & 0x8000) == 0) ? ASCEND : DESCEND;
+            ((CPL_MSBWORD16(piRecordHeader[6]) & 0x8000) == 0) ? ASCEND : DESCEND;
     }
-#else
-    psTime->SetYear(piRecordHeader[1]);
-    psTime->SetDay(piRecordHeader[2]);
-    psTime->SetMillisecond( (GUInt32)piRecordHeader[4] << 16
-                            | (GUInt32)piRecordHeader[5] );
-    if ( peLocationIndicator )
+}
+/************************************************************************/
+/*                          FetchTimeCode()                             */
+/************************************************************************/
+
+void L1BDataset::FetchTimeCode( TimeCode *psTime,
+                                const void *pRecordHeader,
+                                int *peLocationIndicator )
+{
+    if (eSpacecraftID <= NOAA14)
     {
-        *peLocationIndicator =
-            ((piRecordHeader[6] & 0x8000) == 0) ? ASCEND : DESCEND;
+        FetchNOAA9TimeCode( psTime, (const GByte *) pRecordHeader,
+                            peLocationIndicator );
+    }
+    else
+    {
+        FetchNOAA15TimeCode( psTime, (const GUInt16 *) pRecordHeader,
+                             peLocationIndicator );
     }
-#endif
 }
 
 /************************************************************************/
 /*      Fetch GCPs from the individual scanlines                        */
 /************************************************************************/
 
-void L1BDataset::FetchGCPs( GDAL_GCP *pasGCPList,
-                            GByte *pabyRecordHeader, int iLine )
+int L1BDataset::FetchGCPs( GDAL_GCP *pasGCPListRow,
+                           GByte *pabyRecordHeader, int iLine )
 {
     // LAC and HRPT GCPs are tied to the center of pixel,
     // GAC ones are slightly displaced.
@@ -570,6 +630,7 @@ void L1BDataset::FetchGCPs( GDAL_GCP *pasGCPList,
 
     pabyRecordHeader += iGCPOffset;
 
+    int nGCPCountRow = 0;
     while ( nGCPs-- )
     {
         if ( eSpacecraftID <= NOAA14 )
@@ -579,8 +640,8 @@ void L1BDataset::FetchGCPs( GDAL_GCP *pasGCPList,
             GInt16  nRawX = CPL_MSBWORD16( *(GInt16*)pabyRecordHeader );
             pabyRecordHeader += sizeof(GInt16);
 
-            pasGCPList[nGCPCount].dfGCPY = nRawY / L1B_NOAA9_GCP_SCALE;
-            pasGCPList[nGCPCount].dfGCPX = nRawX / L1B_NOAA9_GCP_SCALE;
+            pasGCPListRow[nGCPCountRow].dfGCPY = nRawY / L1B_NOAA9_GCP_SCALE;
+            pasGCPListRow[nGCPCountRow].dfGCPX = nRawX / L1B_NOAA9_GCP_SCALE;
         }
         else
         {
@@ -589,24 +650,25 @@ void L1BDataset::FetchGCPs( GDAL_GCP *pasGCPList,
             GInt32  nRawX = CPL_MSBWORD32( *(GInt32*)pabyRecordHeader );
             pabyRecordHeader += sizeof(GInt32);
 
-            pasGCPList[nGCPCount].dfGCPY = nRawY / L1B_NOAA15_GCP_SCALE;
-            pasGCPList[nGCPCount].dfGCPX = nRawX / L1B_NOAA15_GCP_SCALE;
+            pasGCPListRow[nGCPCountRow].dfGCPY = nRawY / L1B_NOAA15_GCP_SCALE;
+            pasGCPListRow[nGCPCountRow].dfGCPX = nRawX / L1B_NOAA15_GCP_SCALE;
         }
 
-        if ( pasGCPList[nGCPCount].dfGCPX < -180
-             || pasGCPList[nGCPCount].dfGCPX > 180
-             || pasGCPList[nGCPCount].dfGCPY < -90
-             || pasGCPList[nGCPCount].dfGCPY > 90 )
+        if ( pasGCPListRow[nGCPCountRow].dfGCPX < -180
+             || pasGCPListRow[nGCPCountRow].dfGCPX > 180
+             || pasGCPListRow[nGCPCountRow].dfGCPY < -90
+             || pasGCPListRow[nGCPCountRow].dfGCPY > 90 )
             continue;
 
-        pasGCPList[nGCPCount].dfGCPZ = 0.0;
-        pasGCPList[nGCPCount].dfGCPPixel = dfPixel;
+        pasGCPListRow[nGCPCountRow].dfGCPZ = 0.0;
+        pasGCPListRow[nGCPCountRow].dfGCPPixel = dfPixel;
         dfPixel += (eLocationIndicator == DESCEND) ? iGCPStep : -iGCPStep;
-        pasGCPList[nGCPCount].dfGCPLine =
+        pasGCPListRow[nGCPCountRow].dfGCPLine =
             (double)( (eLocationIndicator == DESCEND) ?
                 iLine : nRasterYSize - iLine - 1 ) + 0.5;
-        nGCPCount++;
+        nGCPCountRow++;
     }
+    return nGCPCountRow;
 }
 
 /************************************************************************/
@@ -620,34 +682,49 @@ void L1BDataset::ProcessRecordHeaders()
     VSIFSeekL(fp, nDataStartOffset, SEEK_SET);
     VSIFReadL(pRecordHeader, 1, nRecordDataStart, fp);
 
-    if (eSpacecraftID <= NOAA14)
-    {
-        FetchNOAA9TimeCode( &sStartTime, (GByte *) pRecordHeader,
-                            &eLocationIndicator );
-    }
-    else
-    {
-        FetchNOAA15TimeCode( &sStartTime, (GUInt16 *) pRecordHeader,
-                             &eLocationIndicator );
-    }
+    FetchTimeCode( &sStartTime, pRecordHeader, &eLocationIndicator );
 
     VSIFSeekL( fp, nDataStartOffset + (nRasterYSize - 1) * nRecordSize,
               SEEK_SET);
     VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp );
 
-    if (eSpacecraftID <= NOAA14)
-        FetchNOAA9TimeCode( &sStopTime, (GByte *) pRecordHeader, NULL );
-    else
-        FetchNOAA15TimeCode( &sStopTime, (GUInt16 *) pRecordHeader, NULL );
+    FetchTimeCode( &sStopTime, pRecordHeader, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Pick a skip factor so that we will get roughly 20 lines         */
 /*      worth of GCPs.  That should give respectible coverage on all    */
 /*      but the longest swaths.                                         */
 /* -------------------------------------------------------------------- */
-    int nTargetLines = DESIRED_LINES_OF_GCPS;
-    int nLineSkip = nRasterYSize / ( nTargetLines - 1 );
-    
+    int nTargetLines;
+    double dfLineStep;
+
+    if( bHighGCPDensityStrategy )
+    {
+        if (nRasterYSize < nGCPsPerLine)
+        {
+            nTargetLines = nRasterYSize;
+        }
+        else
+        {
+            int nColStep;
+            nColStep = nRasterXSize / nGCPsPerLine;
+            if (nRasterYSize >= nRasterXSize)
+            {
+                dfLineStep = nColStep;
+            }
+            else
+            {
+                dfLineStep = nRasterYSize / nGCPsPerLine;
+            }
+            nTargetLines = nRasterYSize / dfLineStep;
+        }
+    }
+    else
+    {
+        nTargetLines = MIN(DESIRED_LINES_OF_GCPS, nRasterYSize);
+    }
+    dfLineStep = 1.0 * (nRasterYSize - 1) / ( nTargetLines - 1 );
+
 /* -------------------------------------------------------------------- */
 /*      Initialize the GCP list.                                        */
 /* -------------------------------------------------------------------- */
@@ -667,49 +744,62 @@ void L1BDataset::ProcessRecordHeaders()
 /*      leaves a bigger than expected gap.                              */
 /* -------------------------------------------------------------------- */
     int iStep;
+    int iPrevLine = -1;
 
     for( iStep = 0; iStep < nTargetLines; iStep++ )
     {
-        int nOrigGCPs = nGCPCount;
         int iLine;
 
         if( iStep == nTargetLines - 1 )
-            iLine = nRasterXSize - 1;
+            iLine = nRasterYSize - 1;
         else
-            iLine = nLineSkip * iStep;
+            iLine = (int)(dfLineStep * iStep);
+        if( iLine == iPrevLine )
+            continue;
+        iPrevLine = iLine;
 
         VSIFSeekL( fp, nDataStartOffset + iLine * nRecordSize, SEEK_SET );
         VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp );
 
-        FetchGCPs( pasGCPList, (GByte *)pRecordHeader, iLine );
+        int nGCPsOnThisLine = FetchGCPs( pasGCPList + nGCPCount, (GByte *)pRecordHeader, iLine );
 
+        if( !bHighGCPDensityStrategy )
+        {
 /* -------------------------------------------------------------------- */
 /*      We don't really want too many GCPs per line.  Downsample to     */
 /*      11 per line.                                                    */
 /* -------------------------------------------------------------------- */
-        int iGCP;
-        int nGCPsOnThisLine = nGCPCount - nOrigGCPs;
-        int nDesiredGCPsPerLine = MIN(DESIRED_GCPS_PER_LINE,nGCPsOnThisLine);
-        int nGCPStep = ( nDesiredGCPsPerLine > 1 ) ?
-            ( nGCPsOnThisLine - 1 ) / ( nDesiredGCPsPerLine-1 ) : 1;
-        int iSrcGCP = nOrigGCPs;
-        int iDstGCP = nOrigGCPs;
-
-        if( nGCPStep == 0 )
-            nGCPStep = 1;
-
-        for( iGCP = 0; iGCP < nDesiredGCPsPerLine; iGCP++ )
-        {
-            iSrcGCP += iGCP * nGCPStep;
-            iDstGCP += iGCP;
 
-            pasGCPList[iDstGCP].dfGCPX = pasGCPList[iSrcGCP].dfGCPX;
-            pasGCPList[iDstGCP].dfGCPY = pasGCPList[iSrcGCP].dfGCPY;
-            pasGCPList[iDstGCP].dfGCPPixel = pasGCPList[iSrcGCP].dfGCPPixel;
-            pasGCPList[iDstGCP].dfGCPLine = pasGCPList[iSrcGCP].dfGCPLine;
-        }
+            int iGCP;
+            int nDesiredGCPsPerLine = MIN(DESIRED_GCPS_PER_LINE,nGCPsOnThisLine);
+            int nGCPStep = ( nDesiredGCPsPerLine > 1 ) ?
+                ( nGCPsOnThisLine - 1 ) / ( nDesiredGCPsPerLine-1 ) : 1;
+            int iSrcGCP = nGCPCount;
+            int iDstGCP = nGCPCount;
+
+            if( nGCPStep == 0 )
+                nGCPStep = 1;
+
+            for( iGCP = 0; iGCP < nDesiredGCPsPerLine; iGCP++ )
+            {
+                if( iGCP == nDesiredGCPsPerLine - 1 )
+                    iSrcGCP = nGCPCount + nGCPsOnThisLine - 1;
+                else
+                    iSrcGCP += nGCPStep;
+                iDstGCP ++;
+
+                pasGCPList[iDstGCP].dfGCPX = pasGCPList[iSrcGCP].dfGCPX;
+                pasGCPList[iDstGCP].dfGCPY = pasGCPList[iSrcGCP].dfGCPY;
+                pasGCPList[iDstGCP].dfGCPPixel = pasGCPList[iSrcGCP].dfGCPPixel;
+                pasGCPList[iDstGCP].dfGCPLine = pasGCPList[iSrcGCP].dfGCPLine;
+            }
 
-        nGCPCount = nOrigGCPs + nDesiredGCPsPerLine;
+            nGCPCount += nDesiredGCPsPerLine;
+        }
+        else
+        {
+            nGCPCount += nGCPsOnThisLine;
+        }
     }
 
     if( nGCPCount < nTargetLines * nGCPsPerLine )
@@ -743,6 +833,358 @@ void L1BDataset::ProcessRecordHeaders()
 }
 
 /************************************************************************/
+/*                           FetchMetadata()                            */
+/************************************************************************/
+
+void L1BDataset::FetchMetadata()
+{
+    if( eL1BFormat != L1B_NOAA9 )
+    {
+        FetchMetadataNOAA15();
+        return;
+    }
+
+    const char* pszDir = CPLGetConfigOption("L1B_METADATA_DIRECTORY", NULL);
+    if( pszDir == NULL )
+    {
+        pszDir = CPLGetPath(GetDescription());
+        if( pszDir[0] == '\0' )
+            pszDir = ".";
+    }
+    CPLString osMetadataFile(CPLSPrintf("%s/%s_metadata.csv", pszDir, CPLGetFilename(GetDescription())));
+    VSILFILE* fpCSV = VSIFOpenL(osMetadataFile, "wb");
+    if( fpCSV == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create metadata file : %s",
+                 osMetadataFile.c_str());
+        return;
+    }
+
+    VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,");
+    VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,DATA_JITTER,INSUFFICIENT_DATA_FOR_CAL,NO_EARTH_LOCATION,DESCEND,P_N_STATUS,");
+    VSIFPrintfL(fpCSV, "BIT_SYNC_STATUS,SYNC_ERROR,FRAME_SYNC_ERROR,FLYWHEELING,BIT_SLIPPAGE,C3_SBBC,C4_SBBC,C5_SBBC,");
+    VSIFPrintfL(fpCSV, "TIP_PARITY_FRAME_1,TIP_PARITY_FRAME_2,TIP_PARITY_FRAME_3,TIP_PARITY_FRAME_4,TIP_PARITY_FRAME_5,");
+    VSIFPrintfL(fpCSV, "SYNC_ERRORS,");
+    VSIFPrintfL(fpCSV, "CAL_SLOPE_C1,CAL_INTERCEPT_C1,CAL_SLOPE_C2,CAL_INTERCEPT_C2,CAL_SLOPE_C3,CAL_INTERCEPT_C3,CAL_SLOPE_C4,CAL_INTERCEPT_C4,CAL_SLOPE_C5,CAL_INTERCEPT_C5,");
+    VSIFPrintfL(fpCSV, "NUM_SOLZENANGLES_EARTHLOCPNTS");
+    VSIFPrintfL(fpCSV, "\n");
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(nRecordDataStart);
+
+    for( int nBlockYOff = 0; nBlockYOff < nRasterYSize; nBlockYOff ++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+        int iDataOffset = (eLocationIndicator == DESCEND) ?
+            nDataStartOffset + nBlockYOff * nRecordSize :
+            nDataStartOffset +
+                (nRasterYSize - nBlockYOff - 1) * nRecordSize;
+        VSIFSeekL( fp, iDataOffset, SEEK_SET );
+
+        VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp );
+
+        GUInt16 nScanlineNumber;
+        memcpy(&nScanlineNumber, pabyRecordHeader, 2);
+        CPL_MSBPTR16(&nScanlineNumber);
+
+        TimeCode timeCode;
+        FetchTimeCode( &timeCode, pabyRecordHeader, NULL );
+
+        VSIFPrintfL(fpCSV,
+                    "%d,%d,%d,%d,%d,",
+                    nScanlineNumber,
+                    nBlockYOff,
+                    (int)timeCode.GetYear(),
+                    (int)timeCode.GetDay(),
+                    (int)timeCode.GetMillisecond());
+        VSIFPrintfL(fpCSV,
+                    "%d,%d,%d,%d,%d,%d,%d,%d,",
+                    (pabyRecordHeader[8] >> 7) & 1,
+                    (pabyRecordHeader[8] >> 6) & 1,
+                    (pabyRecordHeader[8] >> 5) & 1,
+                    (pabyRecordHeader[8] >> 4) & 1,
+                    (pabyRecordHeader[8] >> 3) & 1,
+                    (pabyRecordHeader[8] >> 2) & 1,
+                    (pabyRecordHeader[8] >> 1) & 1,
+                    (pabyRecordHeader[8] >> 0) & 1);
+        VSIFPrintfL(fpCSV,
+                    "%d,%d,%d,%d,%d,%d,%d,%d,",
+                    (pabyRecordHeader[9] >> 7) & 1,
+                    (pabyRecordHeader[9] >> 6) & 1,
+                    (pabyRecordHeader[9] >> 5) & 1,
+                    (pabyRecordHeader[9] >> 4) & 1,
+                    (pabyRecordHeader[9] >> 3) & 1,
+                    (pabyRecordHeader[9] >> 2) & 1,
+                    (pabyRecordHeader[9] >> 1) & 1,
+                    (pabyRecordHeader[9] >> 0) & 1);
+        VSIFPrintfL(fpCSV,
+                    "%d,%d,%d,%d,%d,",
+                    (pabyRecordHeader[10] >> 7) & 1,
+                    (pabyRecordHeader[10] >> 6) & 1,
+                    (pabyRecordHeader[10] >> 5) & 1,
+                    (pabyRecordHeader[10] >> 4) & 1,
+                    (pabyRecordHeader[10] >> 3) & 1);
+        VSIFPrintfL(fpCSV, "%d,", pabyRecordHeader[11] >> 2);
+        GInt32 i32;
+        for(int i=0;i<10;i++)
+        {
+            memcpy(&i32, pabyRecordHeader + 12 + 4 *i, 4);
+            CPL_MSBPTR32(&i32);
+            /* Scales : http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/podug/html/c3/sec3-3.htm */
+            if( (i % 2) == 0 )
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 30.0));
+            else
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 22.0));
+        }
+        VSIFPrintfL(fpCSV, "%d", pabyRecordHeader[52]);
+        VSIFPrintfL(fpCSV, "\n");
+    }
+
+    CPLFree(pabyRecordHeader);
+    VSIFCloseL(fpCSV);
+}
+
+/************************************************************************/
+/*                         FetchMetadataNOAA15()                        */
+/************************************************************************/
+
+void L1BDataset::FetchMetadataNOAA15()
+{
+    int i,j;
+    const char* pszDir = CPLGetConfigOption("L1B_METADATA_DIRECTORY", NULL);
+    if( pszDir == NULL )
+    {
+        pszDir = CPLGetPath(GetDescription());
+        if( pszDir[0] == '\0' )
+            pszDir = ".";
+    }
+    CPLString osMetadataFile(CPLSPrintf("%s/%s_metadata.csv", pszDir, CPLGetFilename(GetDescription())));
+    VSILFILE* fpCSV = VSIFOpenL(osMetadataFile, "wb");
+    if( fpCSV == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create metadata file : %s",
+                 osMetadataFile.c_str());
+        return;
+    }
+
+    VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,SAT_CLOCK_DRIF_DELTA,SOUTHBOUND,SCANTIME_CORRECTED,C3_SELECT,");
+    VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,INSUFFICIENT_DATA_FOR_CAL,"
+                       "NO_EARTH_LOCATION,FIRST_GOOD_TIME_AFTER_CLOCK_UPDATE,"
+                       "INSTRUMENT_STATUS_CHANGED,SYNC_LOCK_DROPPED,"
+                       "FRAME_SYNC_ERROR,FRAME_SYNC_DROPPED_LOCK,FLYWHEELING,"
+                       "BIT_SLIPPAGE,TIP_PARITY_ERROR,REFLECTED_SUNLIGHT_C3B,"
+                       "REFLECTED_SUNLIGHT_C4,REFLECTED_SUNLIGHT_C5,RESYNC,P_N_STATUS,");
+    VSIFPrintfL(fpCSV, "BAD_TIME_CAN_BE_INFERRED,BAD_TIME_CANNOT_BE_INFERRED,"
+                       "TIME_DISCONTINUITY,REPEAT_SCAN_TIME,");
+    VSIFPrintfL(fpCSV, "UNCALIBRATED_BAD_TIME,CALIBRATED_FEWER_SCANLINES,"
+                       "UNCALIBRATED_BAD_PRT,CALIBRATED_MARGINAL_PRT,"
+                       "UNCALIBRATED_CHANNELS,");
+    VSIFPrintfL(fpCSV, "NO_EARTH_LOC_BAD_TIME,EARTH_LOC_QUESTIONABLE_TIME,"
+                       "EARTH_LOC_QUESTIONABLE,EARTH_LOC_VERY_QUESTIONABLE,");
+    VSIFPrintfL(fpCSV, "C3B_UNCALIBRATED,C3B_QUESTIONABLE,C3B_ALL_BLACKBODY,"
+                       "C3B_ALL_SPACEVIEW,C3B_MARGINAL_BLACKBODY,C3B_MARGINAL_SPACEVIEW,");
+    VSIFPrintfL(fpCSV, "C4_UNCALIBRATED,C4_QUESTIONABLE,C4_ALL_BLACKBODY,"
+                       "C4_ALL_SPACEVIEW,C4_MARGINAL_BLACKBODY,C4_MARGINAL_SPACEVIEW,");
+    VSIFPrintfL(fpCSV, "C5_UNCALIBRATED,C5_QUESTIONABLE,C5_ALL_BLACKBODY,"
+                       "C5_ALL_SPACEVIEW,C5_MARGINAL_BLACKBODY,C5_MARGINAL_SPACEVIEW,");
+    VSIFPrintfL(fpCSV, "BIT_ERRORS,");
+    for(i=0;i<3;i++)
+    {
+        const char* pszChannel = (i==0) ? "C1" : (i==1) ? "C2" : "C3A";
+        for(j=0;j<3;j++)
+        {
+            const char* pszType = (j==0) ? "OP": (j==1) ? "TEST": "PRELAUNCH";
+            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_1,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_1,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_2,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_2,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERSECTION,", pszType, pszChannel);
+        }
+    }
+    for(i=0;i<3;i++)
+    {
+        const char* pszChannel = (i==0) ? "C3B" : (i==1) ? "C4" : "C5";
+        for(j=0;j<2;j++)
+        {
+            const char* pszType = (j==0) ? "OP": "TEST";
+            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_1,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_2,", pszType, pszChannel);
+            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_3,", pszType, pszChannel);
+        }
+    }
+    VSIFPrintfL(fpCSV, "EARTH_LOC_CORR_TIP_EULER,EARTH_LOC_IND,"
+                       "SPACECRAFT_ATT_CTRL,ATT_SMODE,ATT_PASSIVE_WHEEL_TEST,"
+                       "TIME_TIP_EULER,TIP_EULER_ROLL,TIP_EULER_PITCH,TIP_EULER_YAW,"
+                       "SPACECRAFT_ALT");
+    VSIFPrintfL(fpCSV, "\n");
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(nRecordDataStart);
+    GInt16 i16;
+    GUInt16 n16;
+    GInt32 i32;
+    GUInt32 n32;
+
+    for( int nBlockYOff = 0; nBlockYOff < nRasterYSize; nBlockYOff ++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+        int iDataOffset = (eLocationIndicator == DESCEND) ?
+            nDataStartOffset + nBlockYOff * nRecordSize :
+            nDataStartOffset +
+                (nRasterYSize - nBlockYOff - 1) * nRecordSize;
+        VSIFSeekL( fp, iDataOffset, SEEK_SET );
+
+        VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp );
+
+        GUInt16 nScanlineNumber;
+        memcpy(&nScanlineNumber, pabyRecordHeader, 2);
+        CPL_MSBPTR16(&nScanlineNumber);
+
+        TimeCode timeCode;
+        FetchTimeCode( &timeCode, pabyRecordHeader, NULL );
+
+        /* Clock drift delta */
+        memcpy(&i16, pabyRecordHeader + 6, 2);
+        CPL_MSBPTR16(&i16);
+
+        VSIFPrintfL(fpCSV,
+                    "%d,%d,%d,%d,%d,%d,%d,%d,%d,",
+                    nScanlineNumber,
+                    nBlockYOff,
+                    (int)timeCode.GetYear(),
+                    (int)timeCode.GetDay(),
+                    (int)timeCode.GetMillisecond(),
+                    i16,
+                    (pabyRecordHeader[12] >> 7) & 1,
+                    (pabyRecordHeader[12] >> 6) & 1,
+                    (pabyRecordHeader[12] >> 0) & 3);
+
+        memcpy(&n32, pabyRecordHeader + 24, 4);
+        CPL_MSBPTR32(&n32);
+        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
+                    (n32 >> 31) & 1,
+                    (n32 >> 30) & 1,
+                    (n32 >> 29) & 1,
+                    (n32 >> 28) & 1,
+                    (n32 >> 27) & 1,
+                    (n32 >> 26) & 1,
+                    (n32 >> 25) & 1,
+                    (n32 >> 24) & 1,
+                    (n32 >> 23) & 1,
+                    (n32 >> 22) & 1,
+                    (n32 >> 21) & 1,
+                    (n32 >> 20) & 1,
+                    (n32 >> 8) & 1,
+                    (n32 >> 6) & 3,
+                    (n32 >> 4) & 3,
+                    (n32 >> 2) & 3,
+                    (n32 >> 1) & 1,
+                    (n32 >> 0) & 1);
+
+        memcpy(&n32, pabyRecordHeader + 28, 4);
+        CPL_MSBPTR32(&n32);
+        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
+                    (n32 >> 23) & 1,
+                    (n32 >> 22) & 1,
+                    (n32 >> 21) & 1,
+                    (n32 >> 20) & 1,
+                    (n32 >> 15) & 1,
+                    (n32 >> 14) & 1,
+                    (n32 >> 13) & 1,
+                    (n32 >> 12) & 1,
+                    (n32 >> 11) & 1,
+                    (n32 >> 7) & 1,
+                    (n32 >> 6) & 1,
+                    (n32 >> 5) & 1,
+                    (n32 >> 4) & 1);
+
+        for(i=0;i<3;i++)
+        {
+            memcpy(&n16, pabyRecordHeader + 32 + 2 * i, 2);
+            CPL_MSBPTR16(&n16);
+            VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,",
+                    (n32 >> 7) & 1,
+                    (n32 >> 6) & 1,
+                    (n32 >> 5) & 1,
+                    (n32 >> 4) & 1,
+                    (n32 >> 2) & 1,
+                    (n32 >> 1) & 1);
+        }
+
+        /* Bit errors */
+        memcpy(&n16, pabyRecordHeader + 38, 2);
+        CPL_MSBPTR16(&n16);
+        VSIFPrintfL(fpCSV, "%d,", n16);
+
+        int nOffset = 48;
+        for(i=0;i<3;i++)
+        {
+            for(j=0;j<3;j++)
+            {
+                memcpy(&i32, pabyRecordHeader + nOffset, 4);
+                CPL_MSBPTR32(&i32);
+                nOffset += 4;
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0));
+                memcpy(&i32, pabyRecordHeader + nOffset, 4);
+                CPL_MSBPTR32(&i32);
+                nOffset += 4;
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+                memcpy(&i32, pabyRecordHeader + nOffset, 4);
+                CPL_MSBPTR32(&i32);
+                nOffset += 4;
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0));
+                memcpy(&i32, pabyRecordHeader + nOffset, 4);
+                CPL_MSBPTR32(&i32);
+                nOffset += 4;
+                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+                memcpy(&i32, pabyRecordHeader + nOffset, 4);
+                CPL_MSBPTR32(&i32);
+                nOffset += 4;
+                VSIFPrintfL(fpCSV, "%d,", i32);
+            }
+        }
+        for(i=0;i<18;i++)
+        {
+            memcpy(&i32, pabyRecordHeader + nOffset, 4);
+            CPL_MSBPTR32(&i32);
+            nOffset += 4;
+            VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+        }
+
+        memcpy(&n32, pabyRecordHeader + 312, 4);
+        CPL_MSBPTR32(&n32);
+        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,",
+                    (n32 >> 16) & 1,
+                    (n32 >> 12) & 15,
+                    (n32 >> 8) & 15,
+                    (n32 >> 4) & 15,
+                    (n32 >> 0) & 15);
+
+        memcpy(&n32, pabyRecordHeader + 316, 4);
+        CPL_MSBPTR32(&n32);
+        VSIFPrintfL(fpCSV,"%d,",n32);
+
+        for(i=0;i<3;i++)
+        {
+            memcpy(&i16, pabyRecordHeader + 320 + 2 * i, 2);
+            CPL_MSBPTR16(&i16);
+            VSIFPrintfL(fpCSV,"%f,",i16 / pow(10.0,3.0));
+        }
+
+        memcpy(&n16, pabyRecordHeader + 326, 2);
+        CPL_MSBPTR16(&n16);
+        VSIFPrintfL(fpCSV,"%f",n16 / pow(10.0,1.0));
+
+        VSIFPrintfL(fpCSV, "\n");
+    }
+
+    CPLFree(pabyRecordHeader);
+    VSIFCloseL(fpCSV);
+}
+
+/************************************************************************/
 /*                           EBCDICToASCII                              */
 /************************************************************************/
 
@@ -770,7 +1212,7 @@ static const GByte EBCDICToASCII[] =
 /*                      ProcessDatasetHeader()                          */
 /************************************************************************/
 
-CPLErr L1BDataset::ProcessDatasetHeader()
+CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
 {
     char    szDatasetName[L1B_DATASET_NAME_SIZE + 1];
 
@@ -806,18 +1248,22 @@ CPLErr L1BDataset::ProcessDatasetHeader()
                 L1B_DATASET_NAME_SIZE );
         szDatasetName[L1B_DATASET_NAME_SIZE] = '\0';
 
+        // Deal with a few NOAA <= 9 datasets with no dataset name in TBM header
+        if( memcmp(szDatasetName,
+                    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", L1B_DATASET_NAME_SIZE) == 0 &&
+            strlen(pszFilename) == L1B_DATASET_NAME_SIZE )
+        {
+            strcpy(szDatasetName, pszFilename);
+        }
+
         // Determine processing center where the dataset was created
-        if ( EQUALN((const char *)abyTBMHeader
-                    + L1B_NOAA9_HDR_NAME_OFF, "CMS", 3) )
+        if ( EQUALN(szDatasetName, "CMS", 3) )
              eProcCenter = CMS;
-        else if ( EQUALN((const char *)abyTBMHeader
-                         + L1B_NOAA9_HDR_NAME_OFF, "DSS", 3) )
+        else if ( EQUALN(szDatasetName, "DSS", 3) )
              eProcCenter = DSS;
-        else if ( EQUALN((const char *)abyTBMHeader
-                         + L1B_NOAA9_HDR_NAME_OFF, "NSS", 3) )
+        else if ( EQUALN(szDatasetName, "NSS", 3) )
              eProcCenter = NSS;
-        else if ( EQUALN((const char *)abyTBMHeader
-                         + L1B_NOAA9_HDR_NAME_OFF, "UKM", 3) )
+        else if ( EQUALN(szDatasetName, "UKM", 3) )
              eProcCenter = UKM;
         else
              eProcCenter = UNKNOWN_CENTER;
@@ -882,14 +1328,6 @@ CPLErr L1BDataset::ProcessDatasetHeader()
         // Determine the spacecraft name
         switch ( abyRecHeader[L1B_NOAA9_HDR_REC_ID_OFF] )
         {
-            /* FIXME: use time code to determine TIROS-N, because the SatID
-             * identical to NOAA-11
-             * case 1:
-                eSpacecraftID = TIROSN;
-                break;
-            case 2:
-                eSpacecraftID = NOAA6;
-                break;*/
             case 4:
                 eSpacecraftID = NOAA7;
                 break;
@@ -903,14 +1341,28 @@ CPLErr L1BDataset::ProcessDatasetHeader()
                 eSpacecraftID = NOAA10;
                 break;
             case 1:
-                eSpacecraftID = NOAA11;
+            {
+                /* We could also use the time code to determine TIROS-N */
+                if( strlen(pszFilename) == L1B_DATASET_NAME_SIZE &&
+                    strncmp(pszFilename + 8, ".TN.", 4) == 0 )
+                    eSpacecraftID = TIROSN;
+                else
+                    eSpacecraftID = NOAA11;
                 break;
+            }
             case 5:
                 eSpacecraftID = NOAA12;
                 break;
             case 2:
-                eSpacecraftID = NOAA13;
+            {
+                /* We could also use the time code to determine NOAA6 */
+                if( strlen(pszFilename) == L1B_DATASET_NAME_SIZE &&
+                    strncmp(pszFilename + 8, ".NA.", 4) == 0 )
+                    eSpacecraftID = NOAA6;
+                else
+                    eSpacecraftID = NOAA13;
                 break;
+            }
             case 3:
                 eSpacecraftID = NOAA14;
                 break;
@@ -1306,6 +1758,11 @@ CPLErr L1BDataset::ProcessDatasetHeader()
 
 int L1BDataset::ComputeFileOffsets()
 {
+    CPLDebug("L1B", "Data format = %s",
+             (iDataFormat == PACKED10BIT) ? "Packed 10 bit" :
+             (iDataFormat == UNPACKED16BIT) ? "Unpacked 16 bit" :
+                                              "Unpacked 8 bit");
+
     switch( eProductType )
     {
         case HRPT:
@@ -1313,7 +1770,7 @@ int L1BDataset::ComputeFileOffsets()
         case FRAC:
             nRasterXSize = 2048;
             nBufferSize = 20484;
-            iGCPStart = 25;
+            iGCPStart = 25 - 1; /* http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/c2/sec2-4.htm */
             iGCPStep = 40;
             nGCPsPerLine = 51;
             if ( eL1BFormat == L1B_NOAA9 )
@@ -1388,56 +1845,67 @@ int L1BDataset::ComputeFileOffsets()
                 {
                     nRecordSize = 15872;
                     nRecordDataEnd = 14920;
+                    iCLAVRStart = 14984;
                 }
                 else if (iDataFormat == UNPACKED16BIT)
-                {
+                { /* Table 8.3.1.3.3.1-3 */
                     switch(nBands)
                     {
                         case 1:
                         nRecordSize = 6144;
                         nRecordDataEnd = 5360;
+                        iCLAVRStart = 5368 + 56; /* guessed but not verified */
                         break;
                         case 2:
                         nRecordSize = 10240;
                         nRecordDataEnd = 9456;
+                        iCLAVRStart = 9464 + 56; /* guessed but not verified */
                         break;
                         case 3:
                         nRecordSize = 14336;
                         nRecordDataEnd = 13552;
+                        iCLAVRStart = 13560 + 56; /* guessed but not verified */
                         break;
                         case 4:
                         nRecordSize = 18432;
                         nRecordDataEnd = 17648;
+                        iCLAVRStart = 17656 + 56; /* guessed but not verified */
                         break;
                         case 5:
                         nRecordSize = 22528;
                         nRecordDataEnd = 21744;
+                        iCLAVRStart = 21752 + 56;
                         break;
                     }
                 }
                 else // UNPACKED8BIT
-                {
+                { /* Table 8.3.1.3.3.1-2 */
                     switch(nBands)
                     {
                         case 1:
                         nRecordSize = 4096;
                         nRecordDataEnd = 3312;
+                        iCLAVRStart = 3320 + 56; /* guessed but not verified */
                         break;
                         case 2:
                         nRecordSize = 6144;
                         nRecordDataEnd = 5360;
+                        iCLAVRStart = 5368 + 56; /* guessed but not verified */
                         break;
                         case 3:
                         nRecordSize = 8192;
                         nRecordDataEnd = 7408;
+                        iCLAVRStart = 7416 + 56; /* guessed but not verified */
                         break;
                         case 4:
                         nRecordSize = 10240;
                         nRecordDataEnd = 9456;
+                        iCLAVRStart = 9464 + 56; /* guessed but not verified */
                         break;
                         case 5:
                         nRecordSize = 12288;
                         nRecordDataEnd = 11504;
+                        iCLAVRStart = 11512 + 56; /* guessed but not verified */
                         break;
                     }
                 }
@@ -1454,7 +1922,7 @@ int L1BDataset::ComputeFileOffsets()
         case GAC:
             nRasterXSize = 409;
             nBufferSize = 4092;
-            iGCPStart = 5; // FIXME: depends of scan direction
+            iGCPStart = 5 - 1; // FIXME: depends of scan direction
             iGCPStep = 8;
             nGCPsPerLine = 51;
             if (  eL1BFormat == L1B_NOAA9 )
@@ -1527,56 +1995,67 @@ int L1BDataset::ComputeFileOffsets()
                 {
                     nRecordSize = 4608;
                     nRecordDataEnd = 3992;
+                    iCLAVRStart = 4056;
                 }
                 else if (iDataFormat == UNPACKED16BIT)
-                {
+                { /* Table 8.3.1.4.3.1-3 */
                     switch(nBands)
                     {
                         case 1:
                         nRecordSize = 2360;
                         nRecordDataEnd = 2082;
+                        iCLAVRStart = 2088 + 56; /* guessed but not verified */
                         break;
                         case 2:
                         nRecordSize = 3176;
                         nRecordDataEnd = 2900;
+                        iCLAVRStart = 2904 + 56; /* guessed but not verified */
                         break;
                         case 3:
                         nRecordSize = 3992;
                         nRecordDataEnd = 3718;
+                        iCLAVRStart = 3720 + 56; /* guessed but not verified */
                         break;
                         case 4:
                         nRecordSize = 4816;
                         nRecordDataEnd = 4536;
+                        iCLAVRStart = 4544 + 56; /* guessed but not verified */
                         break;
                         case 5:
                         nRecordSize = 5632;
                         nRecordDataEnd = 5354;
+                        iCLAVRStart = 5360 + 56;
                         break;
                     }
                 }
                 else // UNPACKED8BIT
-                {
+                { /* Table 8.3.1.4.3.1-2 but record length is wrong in the table ! */
                     switch(nBands)
                     {
                         case 1:
                         nRecordSize = 1952;
                         nRecordDataEnd = 1673;
+                        iCLAVRStart = 1680 + 56; /* guessed but not verified */
                         break;
                         case 2:
                         nRecordSize = 2360;
                         nRecordDataEnd = 2082;
+                        iCLAVRStart = 2088 + 56; /* guessed but not verified */
                         break;
                         case 3:
                         nRecordSize = 2768;
                         nRecordDataEnd = 2491;
+                        iCLAVRStart = 2496 + 56; /* guessed but not verified */
                         break;
                         case 4:
                         nRecordSize = 3176;
                         nRecordDataEnd = 2900;
+                        iCLAVRStart = 2904 + 56; /* guessed but not verified */
                         break;
                         case 5:
                         nRecordSize = 3584;
                         nRecordDataEnd = 3309;
+                        iCLAVRStart = 3312 + 56; /* guessed but not verified */
                         break;
                     }
                 }
@@ -1597,127 +2076,969 @@ int L1BDataset::ComputeFileOffsets()
 }
 
 /************************************************************************/
-/*                           DetectFormat()                             */
+/*                       L1BGeolocDataset                               */
 /************************************************************************/
 
-int L1BDataset::DetectFormat( GDALOpenInfo *poOpenInfo )
+class L1BGeolocDataset : public GDALDataset
+{
+    friend class L1BGeolocRasterBand;
+
+    L1BDataset* poL1BDS;
+    int bInterpolGeolocationDS;
 
+    public:
+                L1BGeolocDataset(L1BDataset* poMainDS,
+                                 int bInterpolGeolocationDS);
+       virtual ~L1BGeolocDataset();
+
+       static GDALDataset* CreateGeolocationDS(L1BDataset* poL1BDS,
+                                               int bInterpolGeolocationDS);
+};
+
+/************************************************************************/
+/*                       L1BGeolocRasterBand                            */
+/************************************************************************/
+
+class L1BGeolocRasterBand: public GDALRasterBand
 {
-    GByte* pabyHeader = poOpenInfo->pabyHeader;
-    if (pabyHeader == NULL || poOpenInfo->nHeaderBytes < L1B_NOAA9_HEADER_SIZE)
-        return L1B_NONE;
+    public:
+            L1BGeolocRasterBand(L1BGeolocDataset* poDS, int nBand);
 
-    // We will try the NOAA-15 and later formats first
-    if ( poOpenInfo->nHeaderBytes > L1B_NOAA15_HEADER_SIZE + 61
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 25) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 30) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 33) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 40) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 46) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 52) == '.'
-         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 61) == '.' )
-        return L1B_NOAA15;
+            virtual CPLErr IReadBlock(int, int, void*);
+            virtual double GetNoDataValue( int *pbSuccess = NULL );
+};
 
-    // Next try the NOAA-9/14 formats
-    if ( *(pabyHeader + 8 + 25) == '.'
-         && *(pabyHeader + 8 + 30) == '.'
-         && *(pabyHeader + 8 + 33) == '.'
-         && *(pabyHeader + 8 + 40) == '.'
-         && *(pabyHeader + 8 + 46) == '.'
-         && *(pabyHeader + 8 + 52) == '.'
-         && *(pabyHeader + 8 + 61) == '.' )
-        return L1B_NOAA9;
+/************************************************************************/
+/*                        L1BGeolocDataset()                            */
+/************************************************************************/
 
-    // Next try the NOAA-9/14 formats with dataset name in EBCDIC
-    if ( *(pabyHeader + 8 + 25) == 'K'
-         && *(pabyHeader + 8 + 30) == 'K'
-         && *(pabyHeader + 8 + 33) == 'K'
-         && *(pabyHeader + 8 + 40) == 'K'
-         && *(pabyHeader + 8 + 46) == 'K'
-         && *(pabyHeader + 8 + 52) == 'K'
-         && *(pabyHeader + 8 + 61) == 'K' )
-        return L1B_NOAA9;
+L1BGeolocDataset::L1BGeolocDataset(L1BDataset* poL1BDS,
+                                   int bInterpolGeolocationDS)
+{
+    this->poL1BDS = poL1BDS;
+    this->bInterpolGeolocationDS = bInterpolGeolocationDS;
+    if( bInterpolGeolocationDS )
+        nRasterXSize = poL1BDS->nRasterXSize;
+    else
+        nRasterXSize = poL1BDS->nGCPsPerLine;
+    nRasterYSize = poL1BDS->nRasterYSize;
+}
 
-    // Finally try the AAPP formats 
-    if ( *(pabyHeader + 25) == '.'
-         && *(pabyHeader + 30) == '.'
-         && *(pabyHeader + 33) == '.'
-         && *(pabyHeader + 40) == '.'
-         && *(pabyHeader + 46) == '.'
-         && *(pabyHeader + 52) == '.'
-         && *(pabyHeader + 61) == '.' )
-        return L1B_NOAA15_NOHDR;
+/************************************************************************/
+/*                       ~L1BGeolocDataset()                            */
+/************************************************************************/
 
-    return L1B_NONE;
+L1BGeolocDataset::~L1BGeolocDataset()
+{
+    delete poL1BDS;
 }
 
 /************************************************************************/
-/*                              Identify()                              */
+/*                        L1BGeolocRasterBand()                         */
 /************************************************************************/
 
-int L1BDataset::Identify( GDALOpenInfo *poOpenInfo )
+L1BGeolocRasterBand::L1BGeolocRasterBand(L1BGeolocDataset* poDS, int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    nRasterXSize = poDS->nRasterXSize;
+    nRasterYSize = poDS->nRasterYSize;
+    eDataType = GDT_Float64;
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = 1;
+    if( nBand == 1 )
+        SetDescription("GEOLOC X");
+    else
+        SetDescription("GEOLOC Y");
+}
+
+/************************************************************************/
+/*                         LagrangeInterpol()                           */
+/************************************************************************/
 
+/* ----------------------------------------------------------------------------
+ * Perform a Lagrangian interpolation through the given x,y coordinates
+ * and return the interpolated y value for the given x value.
+ * The array size and thus the polynomial order is defined by numpt.
+ * Input: x[] and y[] are of size numpt,
+ *  x0 is the x value for which we calculate the corresponding y
+ * Returns: y value calculated for given x0.
+ */
+static double LagrangeInterpol(const double x[],
+                               const double y[], double x0, int numpt)
 {
-    if ( DetectFormat(poOpenInfo) == L1B_NONE )
-        return FALSE;
+    int i, j;
+    double L;
+    double y0 = 0;
 
-    return TRUE;
+    for (i=0; i<numpt; i++)
+    {
+        L = 1.0;
+        for (j=0; j<numpt; j++)
+        {
+            if (i == j)
+                continue;
+            L = L * (x0 - x[j]) / (x[i] - x[j]);
+        }
+        y0 = y0 + L * y[i];
+    }
+    return(y0);
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                         L1BInterpol()                                */
 /************************************************************************/
 
-GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
-
+/* ----------------------------------------------------------------------------
+ * Interpolate an array of size numPoints where the only values set on input are
+ * at knownFirst, and intervals of knownStep thereafter.
+ * On return all the rest from 0..numPoints-1 will be filled in.
+ * Uses the LagrangeInterpol() function to do the interpolation; 5-point for the
+ * beginning and end of the array and 4-point for the rest.
+ * To use this function for NOAA level 1B data extract the 51 latitude values
+ * into their appropriate places in the vals array then call L1BInterpol to
+ * calculate the rest of the values.  Do similarly for longitudes, solar zenith
+ * angles, and any others which are present in the file.
+ * Reference:
+ *  http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/c2/sec2-4.htm
+ */
+
+#define MIDDLE_INTERP_ORDER 4
+#define END_INTERP_ORDER  5  /* Ensure this is an odd number, 5 is suitable.*/
+
+/* Convert number of known point to its index in full array */
+#define IDX(N) ((N)*knownStep+knownFirst)
+
+static void
+L1BInterpol(double vals[],
+            int numKnown,   /* Number of known points (typically 51) */
+            int knownFirst, /* Index in full array of first known point (24) */
+            int knownStep,  /* Interval to next and subsequent known points (40) */
+            int numPoints   /* Number of points in whole array (2048) */ )
 {
-    int     eL1BFormat = DetectFormat( poOpenInfo );
-    if ( eL1BFormat == L1B_NONE )
-        return NULL;
-        
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->eAccess == GA_Update )
+    int i, j;
+    double x[END_INTERP_ORDER];
+    double y[END_INTERP_ORDER];
+
+    /* First extrapolate first 24 points */
+    for (i=0; i<END_INTERP_ORDER; i++)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The L1B driver does not support update access to existing"
-                  " datasets.\n" );
-        return NULL;
+        x[i] = IDX(i);
+        y[i] = vals[IDX(i)];
+    }
+    for (i=0; i<knownFirst; i++)
+    {
+        vals[i] = LagrangeInterpol(x, y, i, END_INTERP_ORDER);
+    }
+
+    /* Next extrapolate last 23 points */
+    for (i=0; i<END_INTERP_ORDER; i++)
+    {
+        x[i] = IDX(numKnown-END_INTERP_ORDER+i);
+        y[i] = vals[IDX(numKnown-END_INTERP_ORDER+i)];
+    }
+    for (i=IDX(numKnown-1); i<numPoints; i++)
+    {
+        vals[i] = LagrangeInterpol(x, y, i, END_INTERP_ORDER);
+    }
+
+    /* Interpolate all intermediate points using two before and two after */
+    for (i=knownFirst; i<IDX(numKnown-1); i++)
+    {
+        double x[MIDDLE_INTERP_ORDER];
+        double y[MIDDLE_INTERP_ORDER];
+        int startpt;
+
+        /* Find a suitable set of two known points before and two after */
+        startpt = (i/knownStep)-MIDDLE_INTERP_ORDER/2;
+        if (startpt<0)
+            startpt=0;
+        if (startpt+MIDDLE_INTERP_ORDER-1 >= numKnown)
+            startpt = numKnown-MIDDLE_INTERP_ORDER;
+        for (j=0; j<MIDDLE_INTERP_ORDER; j++)
+        {
+            x[j] = IDX(startpt+j);
+            y[j] = vals[IDX(startpt+j)];
+        }
+        vals[i] = LagrangeInterpol(x, y, i, MIDDLE_INTERP_ORDER);
+    }
+}
+
+/************************************************************************/
+/*                         IReadBlock()                                 */
+/************************************************************************/
+
+CPLErr L1BGeolocRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pData)
+{
+    L1BGeolocDataset* poGDS = (L1BGeolocDataset*)poDS;
+    L1BDataset* poL1BDS = poGDS->poL1BDS;
+    GDAL_GCP* pasGCPList = (GDAL_GCP *)CPLCalloc( poL1BDS->nGCPsPerLine,
+                                        sizeof(GDAL_GCP) );
+    GDALInitGCPs( poL1BDS->nGCPsPerLine, pasGCPList );
+
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(poL1BDS->nRecordSize);
+
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+    int iDataOffset = (poL1BDS->eLocationIndicator == DESCEND) ?
+        poL1BDS->nDataStartOffset + nBlockYOff * poL1BDS->nRecordSize :
+        poL1BDS->nDataStartOffset +
+            (nRasterYSize - nBlockYOff - 1) * poL1BDS->nRecordSize;
+    VSIFSeekL( poL1BDS->fp, iDataOffset, SEEK_SET );
+
+    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordDataStart, poL1BDS->fp );
+
+    /* Fetch the GCPs for the row */
+    int nGotGCPs = poL1BDS->FetchGCPs(pasGCPList, pabyRecordHeader, nBlockYOff );
+    double* padfData = (double*)pData;
+    int i;
+    if( poGDS->bInterpolGeolocationDS )
+    {
+        /* Fill the known position */
+        for(i=0;i<nGotGCPs;i++)
+        {
+            double dfVal = (nBand == 1) ? pasGCPList[i].dfGCPX : pasGCPList[i].dfGCPY;
+            padfData[poL1BDS->iGCPStart + i * poL1BDS->iGCPStep] = dfVal;
+        }
+
+        if( nGotGCPs == poL1BDS->nGCPsPerLine )
+        {
+            /* And do Lagangian interpolation to fill the holes */
+            L1BInterpol(padfData, poL1BDS->nGCPsPerLine,
+                        poL1BDS->iGCPStart, poL1BDS->iGCPStep, nRasterXSize);
+        }
+        else
+        {
+            int iFirstNonValid = 0;
+            if( nGotGCPs > 5 )
+                iFirstNonValid = poL1BDS->iGCPStart + nGotGCPs * poL1BDS->iGCPStep + poL1BDS->iGCPStep / 2;
+            for(i=iFirstNonValid; i<nRasterXSize; i++)
+            {
+                padfData[i] = GetNoDataValue(NULL);
+            }
+            if( iFirstNonValid > 0 )
+            {
+                L1BInterpol(padfData, poL1BDS->nGCPsPerLine,
+                            poL1BDS->iGCPStart, poL1BDS->iGCPStep, iFirstNonValid);
+            }
+        }
+    }
+    else
+    {
+        for(i=0;i<nGotGCPs;i++)
+        {
+            padfData[i] = (nBand == 1) ? pasGCPList[i].dfGCPX : pasGCPList[i].dfGCPY;
+        }
+        for(i=nGotGCPs;i<nRasterXSize;i++)
+            padfData[i] = GetNoDataValue(NULL);
+    }
+
+    if( poL1BDS->eLocationIndicator == ASCEND )
+    {
+        for(i=0;i<nRasterXSize/2;i++)
+        {
+            double dfTmp = padfData[i];
+            padfData[i] = padfData[nRasterXSize-1-i];
+            padfData[nRasterXSize-1-i] = dfTmp;
+        }
+    }
+
+    CPLFree(pabyRecordHeader);
+    GDALDeinitGCPs( poL1BDS->nGCPsPerLine, pasGCPList );
+    CPLFree(pasGCPList);
+    
+    return CE_None;
+}
+
+/************************************************************************/
+/*                        GetNoDataValue()                              */
+/************************************************************************/
+
+double L1BGeolocRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = TRUE;
+    return -200.0;
+}
+
+/************************************************************************/
+/*                      CreateGeolocationDS()                           */
+/************************************************************************/
+
+GDALDataset* L1BGeolocDataset::CreateGeolocationDS(L1BDataset* poL1BDS,
+                                             int bInterpolGeolocationDS)
+{
+    L1BGeolocDataset* poGeolocDS = new L1BGeolocDataset(poL1BDS, bInterpolGeolocationDS);
+    for(int i=1;i<=2;i++)
+    {
+        poGeolocDS->SetBand(i, new L1BGeolocRasterBand(poGeolocDS, i));
+    }
+    return poGeolocDS;
+}
+
+/************************************************************************/
+/*                    L1BSolarZenithAnglesDataset                       */
+/************************************************************************/
+
+class L1BSolarZenithAnglesDataset : public GDALDataset
+{
+    friend class L1BSolarZenithAnglesRasterBand;
+
+    L1BDataset* poL1BDS;
+
+    public:
+                L1BSolarZenithAnglesDataset(L1BDataset* poMainDS);
+       virtual ~L1BSolarZenithAnglesDataset();
+
+       static GDALDataset* CreateSolarZenithAnglesDS(L1BDataset* poL1BDS);
+};
+
+/************************************************************************/
+/*                  L1BSolarZenithAnglesRasterBand                      */
+/************************************************************************/
+
+class L1BSolarZenithAnglesRasterBand: public GDALRasterBand
+{
+    public:
+            L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDS, int nBand);
+
+            virtual CPLErr IReadBlock(int, int, void*);
+            virtual double GetNoDataValue( int *pbSuccess = NULL );
+};
+
+/************************************************************************/
+/*                  L1BSolarZenithAnglesDataset()                       */
+/************************************************************************/
+
+L1BSolarZenithAnglesDataset::L1BSolarZenithAnglesDataset(L1BDataset* poL1BDS)
+{
+    this->poL1BDS = poL1BDS;
+    nRasterXSize = 51;
+    nRasterYSize = poL1BDS->nRasterYSize;
+}
+
+/************************************************************************/
+/*                  ~L1BSolarZenithAnglesDataset()                      */
+/************************************************************************/
+
+L1BSolarZenithAnglesDataset::~L1BSolarZenithAnglesDataset()
+{
+    delete poL1BDS;
+}
+
+/************************************************************************/
+/*                  L1BSolarZenithAnglesRasterBand()                    */
+/************************************************************************/
+
+L1BSolarZenithAnglesRasterBand::L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDS, int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    nRasterXSize = poDS->nRasterXSize;
+    nRasterYSize = poDS->nRasterYSize;
+    eDataType = GDT_Float32;
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = 1;
+}
+
+/************************************************************************/
+/*                         IReadBlock()                                 */
+/************************************************************************/
+
+CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pData)
+{
+    L1BSolarZenithAnglesDataset* poGDS = (L1BSolarZenithAnglesDataset*)poDS;
+    L1BDataset* poL1BDS = poGDS->poL1BDS;
+    int i;
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(poL1BDS->nRecordSize);
+
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+    int iDataOffset = (poL1BDS->eLocationIndicator == DESCEND) ?
+        poL1BDS->nDataStartOffset + nBlockYOff * poL1BDS->nRecordSize :
+        poL1BDS->nDataStartOffset +
+            (nRasterYSize - nBlockYOff - 1) * poL1BDS->nRecordSize;
+    VSIFSeekL( poL1BDS->fp, iDataOffset, SEEK_SET );
+
+    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+
+    int nValidValues = MIN(nRasterXSize, pabyRecordHeader[poL1BDS->iGCPCodeOffset]);
+    float* pafData = (float*)pData;
+
+    int bHasFractional = ( poL1BDS->nRecordDataEnd + 20 <= poL1BDS->nRecordSize );
+
+#ifdef notdef
+    if( bHasFractional )
+    {
+        for(i=0;i<20;i++)
+        {
+            GByte val = pabyRecordHeader[poL1BDS->nRecordDataEnd + i];
+            for(int j=0;j<8;j++)
+                fprintf(stderr, "%c", ((val >> (7 -j)) & 1) ? '1' : '0');
+            fprintf(stderr, " ");
+        }
+        fprintf(stderr, "\n");
+    }
+#endif
+
+    for(i=0;i<nValidValues;i++)
+    {
+        pafData[i] = pabyRecordHeader[poL1BDS->iGCPCodeOffset + 1 + i] / 2.0;
+
+        if( bHasFractional )
+        {
+            /* Cf http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/podug/html/l/app-l.htm#notl-2 */
+            /* This is not very clear on if bits must be counted from MSB or LSB */
+            /* but when testing on n12gac10bit.l1b, it appears that the 3 bits for i=0 are the 3 MSB bits */
+            int nAddBitStart = i * 3;
+            int nFractional;
+
+#if 1
+            if( (nAddBitStart % 8) + 3 <= 8 )
+            {
+                nFractional = (pabyRecordHeader[poL1BDS->nRecordDataEnd + (nAddBitStart / 8)] >> (8 - ((nAddBitStart % 8)+3))) & 0x7;
+            }
+            else
+            {
+                nFractional = (((pabyRecordHeader[poL1BDS->nRecordDataEnd + (nAddBitStart / 8)] << 8) |
+                                pabyRecordHeader[poL1BDS->nRecordDataEnd + (nAddBitStart / 8) + 1]) >> (16 - ((nAddBitStart % 8)+3))) & 0x7;
+            }
+#else
+            nFractional = (pabyRecordHeader[poL1BDS->nRecordDataEnd + (nAddBitStart / 8)] >> (nAddBitStart % 8)) & 0x7;
+            if( (nAddBitStart % 8) + 3 > 8 )
+                nFractional |= (pabyRecordHeader[poL1BDS->nRecordDataEnd + (nAddBitStart / 8) + 1] & ((1 << (((nAddBitStart % 8) + 3 - 8))) - 1)) << (3 - ((((nAddBitStart % 8) + 3 - 8))));*/
+#endif
+            if( nFractional > 4 )
+            {
+                CPLDebug("L1B", "For nBlockYOff=%d, i=%d, wrong fractional value : %d",
+                         nBlockYOff, i, nFractional);
+            }
+
+            pafData[i] += nFractional / 10.0;
+        }
+    }
+
+    for(;i<nRasterXSize;i++)
+        pafData[i] = GetNoDataValue(NULL);
+
+    if( poL1BDS->eLocationIndicator == ASCEND )
+    {
+        for(i=0;i<nRasterXSize/2;i++)
+        {
+            double fTmp = pafData[i];
+            pafData[i] = pafData[nRasterXSize-1-i];
+            pafData[nRasterXSize-1-i] = fTmp;
+        }
+    }
+
+    CPLFree(pabyRecordHeader);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                        GetNoDataValue()                              */
+/************************************************************************/
+
+double L1BSolarZenithAnglesRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = TRUE;
+    return -200.0;
+}
+
+/************************************************************************/
+/*                      CreateSolarZenithAnglesDS()                     */
+/************************************************************************/
+
+GDALDataset* L1BSolarZenithAnglesDataset::CreateSolarZenithAnglesDS(L1BDataset* poL1BDS)
+{
+    L1BSolarZenithAnglesDataset* poGeolocDS = new L1BSolarZenithAnglesDataset(poL1BDS);
+    for(int i=1;i<=1;i++)
+    {
+        poGeolocDS->SetBand(i, new L1BSolarZenithAnglesRasterBand(poGeolocDS, i));
+    }
+    return poGeolocDS;
+}
+
+
+/************************************************************************/
+/*                     L1BNOAA15AnglesDataset                           */
+/************************************************************************/
+
+class L1BNOAA15AnglesDataset : public GDALDataset
+{
+    friend class L1BNOAA15AnglesRasterBand;
+
+    L1BDataset* poL1BDS;
+
+    public:
+                L1BNOAA15AnglesDataset(L1BDataset* poMainDS);
+       virtual ~L1BNOAA15AnglesDataset();
+
+       static GDALDataset* CreateAnglesDS(L1BDataset* poL1BDS);
+};
+
+/************************************************************************/
+/*                     L1BNOAA15AnglesRasterBand                        */
+/************************************************************************/
+
+class L1BNOAA15AnglesRasterBand: public GDALRasterBand
+{
+    public:
+            L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDS, int nBand);
+
+            virtual CPLErr IReadBlock(int, int, void*);
+};
+
+/************************************************************************/
+/*                       L1BNOAA15AnglesDataset()                       */
+/************************************************************************/
+
+L1BNOAA15AnglesDataset::L1BNOAA15AnglesDataset(L1BDataset* poL1BDS)
+{
+    this->poL1BDS = poL1BDS;
+    nRasterXSize = 51;
+    nRasterYSize = poL1BDS->nRasterYSize;
+}
+
+/************************************************************************/
+/*                     ~L1BNOAA15AnglesDataset()                        */
+/************************************************************************/
+
+L1BNOAA15AnglesDataset::~L1BNOAA15AnglesDataset()
+{
+    delete poL1BDS;
+}
+
+/************************************************************************/
+/*                      L1BNOAA15AnglesRasterBand()                     */
+/************************************************************************/
+
+L1BNOAA15AnglesRasterBand::L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDS, int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    nRasterXSize = poDS->nRasterXSize;
+    nRasterYSize = poDS->nRasterYSize;
+    eDataType = GDT_Float32;
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = 1;
+    if( nBand == 1 )
+        SetDescription("Solar zenith angles");
+    else if( nBand == 2 )
+        SetDescription("Satellite zenith angles");
+    else
+        SetDescription("Relative azimuth angles");
+}
+
+/************************************************************************/
+/*                         IReadBlock()                                 */
+/************************************************************************/
+
+CPLErr L1BNOAA15AnglesRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pData)
+{
+    L1BNOAA15AnglesDataset* poGDS = (L1BNOAA15AnglesDataset*)poDS;
+    L1BDataset* poL1BDS = poGDS->poL1BDS;
+    int i;
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(poL1BDS->nRecordSize);
+
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+    int iDataOffset = (poL1BDS->eLocationIndicator == DESCEND) ?
+        poL1BDS->nDataStartOffset + nBlockYOff * poL1BDS->nRecordSize :
+        poL1BDS->nDataStartOffset +
+            (nRasterYSize - nBlockYOff - 1) * poL1BDS->nRecordSize;
+    VSIFSeekL( poL1BDS->fp, iDataOffset, SEEK_SET );
+
+    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+
+    float* pafData = (float*)pData;
+
+    for(i=0;i<nRasterXSize;i++)
+    {
+        GInt16 i16;
+        memcpy(&i16, pabyRecordHeader + 328 + 6 * i + 2 * (nBand - 1), 2);
+        CPL_MSBPTR16(&i16);
+        pafData[i] = i16 / 100.0;
+    }
+
+    if( poL1BDS->eLocationIndicator == ASCEND )
+    {
+        for(i=0;i<nRasterXSize/2;i++)
+        {
+            double fTmp = pafData[i];
+            pafData[i] = pafData[nRasterXSize-1-i];
+            pafData[nRasterXSize-1-i] = fTmp;
+        }
+    }
+
+    CPLFree(pabyRecordHeader);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            CreateAnglesDS()                          */
+/************************************************************************/
+
+GDALDataset* L1BNOAA15AnglesDataset::CreateAnglesDS(L1BDataset* poL1BDS)
+{
+    L1BNOAA15AnglesDataset* poGeolocDS = new L1BNOAA15AnglesDataset(poL1BDS);
+    for(int i=1;i<=3;i++)
+    {
+        poGeolocDS->SetBand(i, new L1BNOAA15AnglesRasterBand(poGeolocDS, i));
+    }
+    return poGeolocDS;
+}
+
+/************************************************************************/
+/*                          L1BCloudsDataset                            */
+/************************************************************************/
+
+class L1BCloudsDataset : public GDALDataset
+{
+    friend class L1BCloudsRasterBand;
+
+    L1BDataset* poL1BDS;
+
+    public:
+                L1BCloudsDataset(L1BDataset* poMainDS);
+       virtual ~L1BCloudsDataset();
+
+       static GDALDataset* CreateCloudsDS(L1BDataset* poL1BDS);
+};
+
+/************************************************************************/
+/*                        L1BCloudsRasterBand                           */
+/************************************************************************/
+
+class L1BCloudsRasterBand: public GDALRasterBand
+{
+    public:
+            L1BCloudsRasterBand(L1BCloudsDataset* poDS, int nBand);
+
+            virtual CPLErr IReadBlock(int, int, void*);
+};
+
+/************************************************************************/
+/*                         L1BCloudsDataset()                           */
+/************************************************************************/
+
+L1BCloudsDataset::L1BCloudsDataset(L1BDataset* poL1BDS)
+{
+    this->poL1BDS = poL1BDS;
+    nRasterXSize = poL1BDS->nRasterXSize;
+    nRasterYSize = poL1BDS->nRasterYSize;
+}
+
+/************************************************************************/
+/*                        ~L1BCloudsDataset()                           */
+/************************************************************************/
+
+L1BCloudsDataset::~L1BCloudsDataset()
+{
+    delete poL1BDS;
+}
+
+/************************************************************************/
+/*                         L1BCloudsRasterBand()                        */
+/************************************************************************/
+
+L1BCloudsRasterBand::L1BCloudsRasterBand(L1BCloudsDataset* poDS, int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    nRasterXSize = poDS->nRasterXSize;
+    nRasterYSize = poDS->nRasterYSize;
+    eDataType = GDT_Byte;
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = 1;
+}
+
+/************************************************************************/
+/*                         IReadBlock()                                 */
+/************************************************************************/
+
+CPLErr L1BCloudsRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pData)
+{
+    L1BCloudsDataset* poGDS = (L1BCloudsDataset*)poDS;
+    L1BDataset* poL1BDS = poGDS->poL1BDS;
+    int i;
+
+    GByte* pabyRecordHeader = (GByte*)CPLMalloc(poL1BDS->nRecordSize);
+
+/* -------------------------------------------------------------------- */
+/*      Seek to data.                                                   */
+/* -------------------------------------------------------------------- */
+    int iDataOffset = (poL1BDS->eLocationIndicator == DESCEND) ?
+        poL1BDS->nDataStartOffset + nBlockYOff * poL1BDS->nRecordSize :
+        poL1BDS->nDataStartOffset +
+            (nRasterYSize - nBlockYOff - 1) * poL1BDS->nRecordSize;
+    VSIFSeekL( poL1BDS->fp, iDataOffset, SEEK_SET );
+
+    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+
+    GByte* pabyData = (GByte*)pData;
+
+    for(i=0;i<nRasterXSize;i++)
+    {
+        pabyData[i] = ((pabyRecordHeader[poL1BDS->iCLAVRStart + (i / 4)] >> (8 - ((i%4)*2+2))) & 0x3);
+    }
+
+    if( poL1BDS->eLocationIndicator == ASCEND )
+    {
+        for(i=0;i<nRasterXSize/2;i++)
+        {
+            GByte byTmp = pabyData[i];
+            pabyData[i] = pabyData[nRasterXSize-1-i];
+            pabyData[nRasterXSize-1-i] = byTmp;
+        }
+    }
+
+    CPLFree(pabyRecordHeader);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      CreateCloudsDS()                     */
+/************************************************************************/
+
+GDALDataset* L1BCloudsDataset::CreateCloudsDS(L1BDataset* poL1BDS)
+{
+    L1BCloudsDataset* poGeolocDS = new L1BCloudsDataset(poL1BDS);
+    for(int i=1;i<=1;i++)
+    {
+        poGeolocDS->SetBand(i, new L1BCloudsRasterBand(poGeolocDS, i));
+    }
+    return poGeolocDS;
+}
+
+
+/************************************************************************/
+/*                           DetectFormat()                             */
+/************************************************************************/
+
+L1BFileFormat L1BDataset::DetectFormat( const char* pszFilename,
+                              const GByte* pabyHeader, int nHeaderBytes )
+
+{
+    if (pabyHeader == NULL || nHeaderBytes < L1B_NOAA9_HEADER_SIZE)
+        return L1B_NONE;
+
+    // We will try the NOAA-15 and later formats first
+    if ( nHeaderBytes > L1B_NOAA15_HEADER_SIZE + 61
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 25) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 30) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 33) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 40) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 46) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 52) == '.'
+         && *(pabyHeader + L1B_NOAA15_HEADER_SIZE + 61) == '.' )
+        return L1B_NOAA15;
+
+    // Next try the NOAA-9/14 formats
+    if ( *(pabyHeader + 8 + 25) == '.'
+         && *(pabyHeader + 8 + 30) == '.'
+         && *(pabyHeader + 8 + 33) == '.'
+         && *(pabyHeader + 8 + 40) == '.'
+         && *(pabyHeader + 8 + 46) == '.'
+         && *(pabyHeader + 8 + 52) == '.'
+         && *(pabyHeader + 8 + 61) == '.' )
+        return L1B_NOAA9;
+
+    // Next try the NOAA-9/14 formats with dataset name in EBCDIC
+    if ( *(pabyHeader + 8 + 25) == 'K'
+         && *(pabyHeader + 8 + 30) == 'K'
+         && *(pabyHeader + 8 + 33) == 'K'
+         && *(pabyHeader + 8 + 40) == 'K'
+         && *(pabyHeader + 8 + 46) == 'K'
+         && *(pabyHeader + 8 + 52) == 'K'
+         && *(pabyHeader + 8 + 61) == 'K' )
+        return L1B_NOAA9;
+
+    // Finally try the AAPP formats 
+    if ( *(pabyHeader + 25) == '.'
+         && *(pabyHeader + 30) == '.'
+         && *(pabyHeader + 33) == '.'
+         && *(pabyHeader + 40) == '.'
+         && *(pabyHeader + 46) == '.'
+         && *(pabyHeader + 52) == '.'
+         && *(pabyHeader + 61) == '.' )
+        return L1B_NOAA15_NOHDR;
+
+    // A few NOAA <= 9 datasets with no dataset name in TBM header
+    if( strlen(pszFilename) == L1B_DATASET_NAME_SIZE &&
+        pszFilename[3] == '.' &&
+        pszFilename[8] == '.' &&
+        pszFilename[11] == '.' &&
+        pszFilename[18] == '.' &&
+        pszFilename[24] == '.' &&
+        pszFilename[30] == '.' &&
+        pszFilename[39] == '.' &&
+        memcmp(pabyHeader + 30, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", L1B_DATASET_NAME_SIZE) == 0 &&
+        (pabyHeader[75] == '+' || pabyHeader[75] == '-') &&
+        (pabyHeader[78] == '+' || pabyHeader[78] == '-') &&
+        (pabyHeader[81] == '+' || pabyHeader[81] == '-') &&
+        (pabyHeader[85] == '+' || pabyHeader[85] == '-') )
+        return L1B_NOAA9;
+
+    return L1B_NONE;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int L1BDataset::Identify( GDALOpenInfo *poOpenInfo )
+
+{
+    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) )
+        return TRUE;
+    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:") ) )
+        return TRUE;
+    if ( EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") ) )
+        return TRUE;
+    if ( EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") ) )
+        return TRUE;
+    if ( EQUALN( poOpenInfo->pszFilename, "L1B_CLOUDS:", strlen("L1B_CLOUDS:") ) )
+        return TRUE;
+
+    if ( DetectFormat(CPLGetFilename(poOpenInfo->pszFilename),
+                      poOpenInfo->pabyHeader,
+                      poOpenInfo->nHeaderBytes) == L1B_NONE )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    GDALDataset* poOutDS;
+    VSILFILE* fp = NULL;
+    CPLString osFilename = poOpenInfo->pszFilename;
+    int bAskGeolocationDS = FALSE;
+    int bInterpolGeolocationDS = FALSE;
+    int bAskSolarZenithAnglesDS = FALSE;
+    int bAskAnglesDS = FALSE;
+    int bAskCloudsDS = FALSE;
+    L1BFileFormat eL1BFormat;
+
+    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) ||
+         EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:") ) ||
+         EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") )||
+         EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") )||
+         EQUALN( poOpenInfo->pszFilename, "L1B_CLOUDS:", strlen("L1B_CLOUDS:") ) )
+    {
+        GByte abyHeader[1024];
+        const char* pszFilename;
+        if( EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:")) )
+        {
+            bAskGeolocationDS = TRUE;
+            bInterpolGeolocationDS = TRUE;
+            pszFilename = poOpenInfo->pszFilename + strlen("L1BGCPS_INTERPOL:");
+        }
+        else if (EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) )
+        {
+            bAskGeolocationDS = TRUE;
+            pszFilename = poOpenInfo->pszFilename + strlen("L1BGCPS:");
+        }
+        else if (EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") ) )
+        {
+            bAskSolarZenithAnglesDS = TRUE;
+            pszFilename = poOpenInfo->pszFilename + strlen("L1B_SOLAR_ZENITH_ANGLES:");
+        }
+        else if (EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") ) )
+        {
+            bAskAnglesDS = TRUE;
+            pszFilename = poOpenInfo->pszFilename + strlen("L1B_ANGLES:");
+        }
+        else
+        {
+            bAskCloudsDS = TRUE;
+            pszFilename = poOpenInfo->pszFilename + strlen("L1B_CLOUDS:");
+        }
+        if( pszFilename[0] == '"' )
+            pszFilename ++;
+        osFilename = pszFilename;
+        if( osFilename.size() > 0 && osFilename[osFilename.size()-1] == '"' )
+            osFilename.resize(osFilename.size()-1);
+        fp = VSIFOpenL( osFilename, "rb" );
+        if ( !fp )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Can't open file \"%s\".", osFilename.c_str() );
+            return NULL;
+        }
+        VSIFReadL( abyHeader, 1, sizeof(abyHeader)-1, fp);
+        abyHeader[sizeof(abyHeader)-1] = '\0';
+        eL1BFormat = DetectFormat( CPLGetFilename(osFilename),
+                                   abyHeader, sizeof(abyHeader) );
+    }
+    else
+        eL1BFormat = DetectFormat( CPLGetFilename(osFilename),
+                                   poOpenInfo->pabyHeader,
+                                   poOpenInfo->nHeaderBytes );
+
+    if ( eL1BFormat == L1B_NONE )
+    {
+        if( fp != NULL )
+            VSIFCloseL(fp);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Confirm the requested access is supported.                      */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported, 
+                  "The L1B driver does not support update access to existing"
+                  " datasets.\n" );
+        if( fp != NULL )
+            VSIFCloseL(fp);
+        return NULL;
     }
-    
-#if 0
-    Geolocation
-    if ( EQUAL( poOpenInfo->pszFilename, "L1BGCPS:" ) )
-        bFetchGeolocation = TRUE;
-#endif
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
     L1BDataset  *poDS;
     VSIStatBufL  sStat;
-    const char  *pszFilename = poOpenInfo->pszFilename;
 
     poDS = new L1BDataset( eL1BFormat );
 
-    poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+    if( fp == NULL )
+        fp = VSIFOpenL( osFilename, "rb" );
+    poDS->fp = fp;
     if ( !poDS->fp )
     {
-        CPLDebug( "L1B", "Can't open file \"%s\".", poOpenInfo->pszFilename );
+        CPLDebug( "L1B", "Can't open file \"%s\".", osFilename.c_str() );
         goto bad;
     }
     
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    if ( poDS->ProcessDatasetHeader() != CE_None )
+    if ( poDS->ProcessDatasetHeader(CPLGetFilename(osFilename)) != CE_None )
     {
         CPLDebug( "L1B", "Error reading L1B record header." );
         goto bad;
     }
 
-    VSIStatL(pszFilename, &sStat);
+    VSIStatL(osFilename, &sStat);
 
     if ( poDS->bGuessDataFormat )
     {
@@ -1731,7 +3052,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 
         for(j=0;j<3;j++)
         {
-            poDS->iDataFormat = PACKED10BIT + j;
+            poDS->iDataFormat = (L1BDataFormat) (PACKED10BIT + j);
             if (!poDS->ComputeFileOffsets())
                 goto bad;
 
@@ -1748,9 +3069,8 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 VSIFSeekL(poDS->fp, poDS->nDataStartOffset + i * poDS->nRecordSize, SEEK_SET);
                 VSIFReadL(&nScanlineNumber, 1, 2, poDS->fp);
-#ifdef CPL_LSB
-                CPL_SWAP16PTR( &nScanlineNumber );
-#endif
+                CPL_MSBPTR16( &nScanlineNumber );
+
                 if (i == 1)
                 {
                     nDiffLine = nScanlineNumber - nLastScanlineNumber;
@@ -1793,6 +3113,115 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         (sStat.st_size - poDS->nDataStartOffset) / poDS->nRecordSize;
 
 /* -------------------------------------------------------------------- */
+/*      Deal with GCPs                                                  */
+/* -------------------------------------------------------------------- */
+    poDS->ProcessRecordHeaders();
+
+    if( bAskGeolocationDS )
+    {
+        return L1BGeolocDataset::CreateGeolocationDS(poDS, bInterpolGeolocationDS);
+    }
+    else if( bAskSolarZenithAnglesDS )
+    {
+        if( eL1BFormat == L1B_NOAA9 )
+            return L1BSolarZenithAnglesDataset::CreateSolarZenithAnglesDS(poDS);
+        else
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+    else if( bAskAnglesDS )
+    {
+        if( eL1BFormat != L1B_NOAA9 )
+            return L1BNOAA15AnglesDataset::CreateAnglesDS(poDS);
+        else
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+    else if( bAskCloudsDS )
+    {
+        if( poDS->iCLAVRStart > 0 )
+            poOutDS = L1BCloudsDataset::CreateCloudsDS(poDS);
+        else
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+    else
+    {
+        poOutDS = poDS;
+    }
+
+    {
+        CPLString  osTMP;
+        int bInterpol = CSLTestBoolean(CPLGetConfigOption("L1B_INTERPOL_GCPS", "TRUE"));
+
+        poOutDS->SetMetadataItem( "SRS", poDS->pszGCPProjection, "GEOLOCATION" ); /* unused by gdalgeoloc.cpp */
+
+        if( bInterpol )
+            osTMP.Printf( "L1BGCPS_INTERPOL:\"%s\"", osFilename.c_str() );
+        else
+            osTMP.Printf( "L1BGCPS:\"%s\"", osFilename.c_str() );
+        poOutDS->SetMetadataItem( "X_DATASET", osTMP, "GEOLOCATION" );
+        poOutDS->SetMetadataItem( "X_BAND", "1" , "GEOLOCATION" );
+        poOutDS->SetMetadataItem( "Y_DATASET", osTMP, "GEOLOCATION" );
+        poOutDS->SetMetadataItem( "Y_BAND", "2" , "GEOLOCATION" );
+
+        if( bInterpol )
+        {
+            poOutDS->SetMetadataItem( "PIXEL_OFFSET", "0", "GEOLOCATION" );
+            poOutDS->SetMetadataItem( "PIXEL_STEP", "1", "GEOLOCATION" );
+        }
+        else
+        {
+            osTMP.Printf( "%d", poDS->iGCPStart);
+            poOutDS->SetMetadataItem( "PIXEL_OFFSET", osTMP, "GEOLOCATION" );
+            osTMP.Printf( "%d", poDS->iGCPStep);
+            poOutDS->SetMetadataItem( "PIXEL_STEP", osTMP, "GEOLOCATION" );
+        }
+
+        poOutDS->SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
+        poOutDS->SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
+    }
+    
+    if( poOutDS != poDS )
+        return poOutDS;
+
+    if( eL1BFormat == L1B_NOAA9 )
+    {
+        char** papszSubdatasets = NULL;
+        papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_1_NAME",
+                                        CPLSPrintf("L1B_SOLAR_ZENITH_ANGLES:\"%s\"", osFilename.c_str()));
+        papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_1_DESC",
+                                        "Solar zenith angles");
+        poDS->SetMetadata(papszSubdatasets, "SUBDATASETS");
+        CSLDestroy(papszSubdatasets);
+    }
+    else
+    {
+        char** papszSubdatasets = NULL;
+        papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_1_NAME",
+                                        CPLSPrintf("L1B_ANGLES:\"%s\"", osFilename.c_str()));
+        papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_1_DESC",
+                                        "Solar zenith angles, satellite zenith angles and relative azimuth angles");
+
+        if( poDS->iCLAVRStart > 0 )
+        {
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_2_NAME",
+                                            CPLSPrintf("L1B_CLOUDS:\"%s\"", osFilename.c_str()));
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets, "SUBDATASET_2_DESC",
+                                            "Clouds from AVHRR (CLAVR)");
+        }
+
+        poDS->SetMetadata(papszSubdatasets, "SUBDATASETS");
+        CSLDestroy(papszSubdatasets);
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     int iBand, i;
@@ -1852,37 +3281,6 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Do we have GCPs?                                                */
-/* -------------------------------------------------------------------- */
-    if ( 1/*EQUALN((const char *)pabyTBMHeader + 96, "Y", 1)*/ )
-    {
-        poDS->ProcessRecordHeaders();
-
-#if 0
-    Geolocation
-        CPLString  osTMP;
-
-        poDS->SetMetadataItem( "SRS", poDS->pszGCPProjection, "GEOLOCATION" );
-        
-        osTMP.Printf( "L1BGCPS:\"%s\"", pszFilename );
-        poDS->SetMetadataItem( "X_DATASET", osTMP, "GEOLOCATION" );
-        poDS->SetMetadataItem( "X_BAND", "1" , "GEOLOCATION" );
-        poDS->SetMetadataItem( "Y_DATASET", osTMP, "GEOLOCATION" );
-        poDS->SetMetadataItem( "Y_BAND", "2" , "GEOLOCATION" );
-
-        osTMP.Printf( "%d", (poDS->eLocationIndicator == DESCEND) ?
-            poDS->iGCPStart : (poDS->nRasterXSize - poDS->iGCPStart) );
-        poDS->SetMetadataItem( "PIXEL_OFFSET", osTMP, "GEOLOCATION" );
-        osTMP.Printf( "%d", (poDS->eLocationIndicator == DESCEND) ?
-                      poDS->iGCPStep : -poDS->iGCPStep );
-        poDS->SetMetadataItem( "PIXEL_STEP", osTMP, "GEOLOCATION" );
-
-        poDS->SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
-        poDS->SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
-#endif
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
@@ -1893,6 +3291,14 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
 
+/* -------------------------------------------------------------------- */
+/*      Fetch metadata in CSV file                                      */
+/* -------------------------------------------------------------------- */
+    if( CSLTestBoolean(CPLGetConfigOption("L1B_FETCH_METADATA", "NO")) )
+    {
+        poDS->FetchMetadata();
+    }
+
     return( poDS );
 
 bad:
@@ -1920,6 +3326,7 @@ void GDALRegister_L1B()
                                    "frmt_l1b.html" );
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 
         poDriver->pfnOpen = L1BDataset::Open;
         poDriver->pfnIdentify = L1BDataset::Identify;
diff --git a/frmts/leveller/levellerdataset.cpp b/frmts/leveller/levellerdataset.cpp
index f349485..332851b 100644
--- a/frmts/leveller/levellerdataset.cpp
+++ b/frmts/leveller/levellerdataset.cpp
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005-2007 Daylon Graphics Ltd.
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: levellerdataset.cpp 25572 2013-01-27 00:46:10Z rouault $");
+CPL_CVSID("$Id: levellerdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_Leveller(void);
diff --git a/frmts/map/mapdataset.cpp b/frmts/map/mapdataset.cpp
index dab13cc..6c2bfa0 100644
--- a/frmts/map/mapdataset.cpp
+++ b/frmts/map/mapdataset.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2012, Jean-Claude Repetto
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: mapdataset.cpp 25369 2012-12-27 19:06:27Z rouault $");
+CPL_CVSID("$Id: mapdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/mbtiles/GNUmakefile b/frmts/mbtiles/GNUmakefile
index c30caeb..72bf33b 100644
--- a/frmts/mbtiles/GNUmakefile
+++ b/frmts/mbtiles/GNUmakefile
@@ -7,7 +7,7 @@ ifeq ($(LIBZ_SETTING),internal)
   XTRA_OPT :=   $(XTRA_OPT) -I../zlib
 endif
 
-CPPFLAGS	:=	$(XTRA_OPT) $(GDAL_INCLUDE) $(CPPFLAGS) -I../../ogr -I../../ogr/ogrsf_frmts/geojson
+CPPFLAGS	:=	$(JSON_INCLUDE) $(XTRA_OPT) $(GDAL_INCLUDE) $(CPPFLAGS) -I../../ogr
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/mbtiles/makefile.vc b/frmts/mbtiles/makefile.vc
index 2ef130d..3687c75 100644
--- a/frmts/mbtiles/makefile.vc
+++ b/frmts/mbtiles/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ	=	mbtilesdataset.obj
 
-EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/geojson -I../zlib
+EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I../zlib
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/mbtiles/mbtilesdataset.cpp b/frmts/mbtiles/mbtilesdataset.cpp
index 0e6dd71..71aa928 100644
--- a/frmts/mbtiles/mbtilesdataset.cpp
+++ b/frmts/mbtiles/mbtilesdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: mbtilesdataset.cpp 23737 2012-01-09 19:26:10Z rouault $
+ * $Id: mbtilesdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL MBTiles driver
  * Purpose:  Implement GDAL MBTiles support using OGR SQLite driver
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,13 +33,13 @@
 #include "cpl_vsil_curl_priv.h"
 
 #include "zlib.h"
-#include "jsonc/json.h"
+#include "json.h"
 
 #include <math.h>
 
 extern "C" void GDALRegister_MBTiles();
 
-CPL_CVSID("$Id: mbtilesdataset.cpp 23737 2012-01-09 19:26:10Z rouault $");
+CPL_CVSID("$Id: mbtilesdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const char * const apszAllowedDrivers[] = {"JPEG", "PNG", NULL};
 
@@ -63,6 +63,8 @@ class MBTilesDataset : public GDALPamDataset
 
     virtual CPLErr GetGeoTransform(double* padfGeoTransform);
     virtual const char* GetProjectionRef();
+    
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -126,6 +128,7 @@ class MBTilesBand: public GDALPamRasterBand
 
     virtual CPLErr          IReadBlock( int, int, void * );
 
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
 };
@@ -728,6 +731,15 @@ end:
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **MBTilesBand::GetMetadataDomainList()
+{
+    return CSLAddString(GDALPamRasterBand::GetMetadataDomainList(), "LocationInfo");
+}
+
+/************************************************************************/
 /*                         GetMetadataItem()                            */
 /************************************************************************/
 
@@ -1060,6 +1072,17 @@ const char* MBTilesDataset::GetProjectionRef()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **MBTilesDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -1462,6 +1485,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS, int nMinLevel, int nMaxLevel,
     OGRFeatureH hFeat;
     const char* pszSQL;
     VSILFILE* fpCURLOGR = NULL;
+    int bFirstSelect = TRUE;
 
     int nBands = -1;
 
@@ -1503,6 +1527,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS, int nMinLevel, int nMaxLevel,
         /* Install a spy on the file connexion that will intercept */
         /* PNG or JPEG headers, to interrupt their downloading */
         /* once the header is found. Speeds up dataset opening. */
+        CPLErrorReset();
         VSICurlInstallReadCbk(fpCURLOGR, MBTilesCurlReadCbk, &nBands, TRUE);
 
         CPLErrorReset();
@@ -1545,21 +1570,29 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS, int nMinLevel, int nMaxLevel,
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     }
 
-    if (hSQLLyr == NULL)
+    while( TRUE )
     {
-        pszSQL = CPLSPrintf("SELECT tile_data FROM tiles WHERE "
-                            "zoom_level = %d LIMIT 1", nMaxLevel);
-        CPLDebug("MBTILES", "%s", pszSQL);
-        hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
-        if (hSQLLyr == NULL)
-            return -1;
-    }
+        if (hSQLLyr == NULL && bFirstSelect)
+        {
+            bFirstSelect = FALSE;
+            pszSQL = CPLSPrintf("SELECT tile_data FROM tiles WHERE "
+                                "zoom_level = %d LIMIT 1", nMaxLevel);
+            CPLDebug("MBTILES", "%s", pszSQL);
+            hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
+            if (hSQLLyr == NULL)
+                return -1;
+        }
 
-    hFeat = OGR_L_GetNextFeature(hSQLLyr);
-    if (hFeat == NULL)
-    {
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-        return -1;
+        hFeat = OGR_L_GetNextFeature(hSQLLyr);
+        if (hFeat == NULL)
+        {
+            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+            hSQLLyr = NULL;
+            if( !bFirstSelect )
+                return -1;
+        }
+        else
+            break;
     }
 
     CPLString osMemFileName;
diff --git a/frmts/mem/memdataset.cpp b/frmts/mem/memdataset.cpp
index dfdb02d..3bddd39 100644
--- a/frmts/mem/memdataset.cpp
+++ b/frmts/mem/memdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.cpp 25873 2013-04-07 11:06:58Z rouault $
+ * $Id: memdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Memory Array Translator
  * Purpose:  Complete implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "memdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: memdataset.cpp 25873 2013-04-07 11:06:58Z rouault $");
+CPL_CVSID("$Id: memdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        MEMCreateRasterBand()                         */
@@ -874,34 +875,44 @@ GDALDataset *MEMDataset::Create( const char * pszFilename,
     int         nWordSize = GDALGetDataTypeSize(eType) / 8;
     int         bAllocOK = TRUE;
 
+    GUIntBig nGlobalBigSize = (GUIntBig)nWordSize * nBands * nXSize * nYSize;
+    size_t nGlobalSize = (size_t)nGlobalBigSize;
+#if SIZEOF_VOIDP == 4
+    if( (GUIntBig)nGlobalSize != nGlobalBigSize )
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+                  "Cannot allocate " CPL_FRMT_GUIB " bytes on this platform.",
+                  nGlobalBigSize );
+        return NULL;
+    }
+#endif
+
     if( bPixelInterleaved )
     {
         apbyBandData.push_back( 
-            (GByte *) VSIMalloc3( nWordSize * nBands, nXSize, nYSize ) );
+            (GByte *) VSICalloc( 1, nGlobalSize ) );
 
         if( apbyBandData[0] == NULL )
             bAllocOK = FALSE;
         else
-    {
-            memset(apbyBandData[0], 0, ((size_t)nWordSize) * nBands * nXSize * nYSize);
+        {
             for( iBand = 1; iBand < nBands; iBand++ )
                 apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize );
         }
     }
-        else
+    else
+    {
+        for( iBand = 0; iBand < nBands; iBand++ )
         {
-            for( iBand = 0; iBand < nBands; iBand++ )
-            {
             apbyBandData.push_back( 
-                (GByte *) VSIMalloc3( nWordSize, nXSize, nYSize ) );
+                (GByte *) VSICalloc( 1, ((size_t)nWordSize) * nXSize * nYSize ) );
             if( apbyBandData[iBand] == NULL )
             {
                 bAllocOK = FALSE;
                 break;
             }
-            memset(apbyBandData[iBand], 0, ((size_t)nWordSize) * nXSize * nYSize);
         }
-            }
+    }
 
     if( !bAllocOK )
     {
@@ -910,10 +921,10 @@ GDALDataset *MEMDataset::Create( const char * pszFilename,
             if( apbyBandData[iBand] )
                 VSIFree( apbyBandData[iBand] );
         }
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "Unable to create band arrays ... out of memory." );
-            return NULL;
-        }
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+                    "Unable to create band arrays ... out of memory." );
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create the new GTiffDataset object.                             */
diff --git a/frmts/mrsid/mrsiddataset.cpp b/frmts/mrsid/mrsiddataset.cpp
index e22e1d6..2d0e4e4 100644
--- a/frmts/mrsid/mrsiddataset.cpp
+++ b/frmts/mrsid/mrsiddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mrsiddataset.cpp 25659 2013-02-19 22:51:46Z warmerdam $
+ * $Id: mrsiddataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Read/write LizardTech's MrSID file format - Version 4+ SDK.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #define NO_DELETE
 
-#include "gdal_pam.h"
+#include "gdaljp2abstractdataset.h"
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 #include "gdaljp2metadata.h"
@@ -38,7 +39,7 @@
 #include <geo_normalize.h>
 #include <geovalues.h>
 
-CPL_CVSID("$Id: mrsiddataset.cpp 25659 2013-02-19 22:51:46Z warmerdam $");
+CPL_CVSID("$Id: mrsiddataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 double GTIFAngleToDD( double dfAngle, int nUOMAngle );
@@ -208,7 +209,7 @@ private:
 /* ==================================================================== */
 /************************************************************************/
 
-class MrSIDDataset : public GDALPamDataset
+class MrSIDDataset : public GDALJP2AbstractDataset
 {
     friend class MrSIDRasterBand;
 
@@ -241,9 +242,6 @@ class MrSIDDataset : public GDALPamDataset
 
     double              dfCurrentMag;
 
-    int                 bHasGeoTransform;
-    double              adfGeoTransform[6];
-    char                *pszProjection;
     GTIFDefn            *psDefn;
 
     MrSIDDataset       *poParentDS;
@@ -275,8 +273,6 @@ class MrSIDDataset : public GDALPamDataset
                 ~MrSIDDataset();
 
     static GDALDataset  *Open( GDALOpenInfo * poOpenInfo, int bIsJP2 );
-    virtual CPLErr      GetGeoTransform( double * padfTransform );
-    const char          *GetProjectionRef();
 
     virtual char      **GetFileList();
 
@@ -569,7 +565,7 @@ CPLErr MrSIDRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                && nBlockYOff >= 0
                && pImage != NULL );
 
-#if DEBUG
+#ifdef DEBUG
     CPLDebug( "MrSID", "IWriteBlock(): nBlockXOff=%d, nBlockYOff=%d",
               nBlockXOff, nBlockYOff );
 #endif
@@ -752,14 +748,6 @@ MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
     nPrevBlockXOff = 0;
     nPrevBlockYOff = 0;
     
-    pszProjection = CPLStrdup( "" );
-    bHasGeoTransform = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
     psDefn = NULL;
     
     dfCurrentMag = 1.0;
@@ -802,8 +790,6 @@ MrSIDDataset::~MrSIDDataset()
     // points to another member, don't delete
     poStream = NULL;
 
-    if ( pszProjection )
-        CPLFree( pszProjection );
     if ( psDefn )
         delete psDefn;
     CloseDependentDatasets();
@@ -1046,39 +1032,6 @@ CPLErr MrSIDDataset::IBuildOverviews( const char *, int, int *,
 }
 
 /************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr MrSIDDataset::GetGeoTransform( double * padfTransform )
-{
-    if( (strlen(GDALPamDataset::GetProjectionRef()) > 0 &&
-         GDALPamDataset::GetGeoTransform( padfTransform ) == CE_None )
-        || !bHasGeoTransform )
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
-    else
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-        return( CE_None );
-    }
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *MrSIDDataset::GetProjectionRef()
-{
-    const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
-
-    if( strlen(pszProjection) > 0 && strlen(pszPamPrj) == 0 )
-        return pszProjection;
-    else
-        return pszPamPrj;
-}
-
-/************************************************************************/
 /*                        SerializeMetadataRec()                        */
 /************************************************************************/
 
@@ -1302,11 +1255,11 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
         
         adfGeoTransform[0] = adfGeoTransform[0] - adfGeoTransform[1] / 2;
         adfGeoTransform[3] = adfGeoTransform[3] - adfGeoTransform[5] / 2;
-        bHasGeoTransform = TRUE;
+        bGeoTransformValid = TRUE;
     }
     else if( iZoom == 0 )
     {
-        bHasGeoTransform = 
+        bGeoTransformValid = 
             GDALReadWorldFile( GetDescription(), NULL,
                                adfGeoTransform )
             || GDALReadWorldFile( GetDescription(), ".wld",
@@ -1698,26 +1651,7 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
 
     if (bIsJP2)
     {
-        GDALJP2Metadata oJP2Geo;
-        if ( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
-        {
-            /*poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-            poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
-            memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform,
-                    sizeof(double) * 6 );
-            poDS->nGCPCount = oJP2Geo.nGCPCount;
-            poDS->pasGCPList = oJP2Geo.pasGCPList;
-            oJP2Geo.pasGCPList = NULL;
-            oJP2Geo.nGCPCount = 0;*/
-        }
-
-        if (oJP2Geo.pszXMPMetadata)
-        {
-            char *apszMDList[2];
-            apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-            apszMDList[1] = NULL;
-            poDS->SetMetadata(apszMDList, "xml:XMP");
-        }
+        poDS->LoadJP2Metadata(poOpenInfo);
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/frmts/mrsid/mrsidstream.cpp b/frmts/mrsid/mrsidstream.cpp
index 536a4fe..2915d59 100644
--- a/frmts/mrsid/mrsidstream.cpp
+++ b/frmts/mrsid/mrsidstream.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mrsidstream.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: mrsidstream.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Input/output stream wrapper for usage with LizardTech's
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_error.h"
 #include "mrsidstream.h"
 
-CPL_CVSID("$Id: mrsidstream.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: mrsidstream.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 LT_USE_NAMESPACE(LizardTech)
 
diff --git a/frmts/mrsid/nmake.opt b/frmts/mrsid/nmake.opt
index 7d3adcb..8b11ac5 100644
--- a/frmts/mrsid/nmake.opt
+++ b/frmts/mrsid/nmake.opt
@@ -438,6 +438,8 @@ MRSID_INCLUDE =    -I"$(MRSID_LIDAR_DIR)\include" $(MRSID_INCLUDE)
 !ERROR Cannot link dynamically against the MrSID Raster ESDK.  Try linking statically by setting MRSID_RDLLBUILD to NO.
 !ELSE IF EXIST("$(MRSID_RASTER_DIR)\lib\lti_dsdk.dll")
 MRSID_LIB =        "$(MRSID_RASTER_DIR)\lib\lti_dsdk.lib" $(MRSID_LIB)
+!ELSE IF EXIST("$(MRSID_RASTER_DIR)\lib\lti_dsdk_9.0.dll")
+MRSID_LIB =        "$(MRSID_RASTER_DIR)\lib\lti_dsdk.lib" $(MRSID_LIB)
 !ELSE IF EXIST("$(MRSID_RASTER_DIR)\lib\$(MRSID_CONFIG)\lti_dsdk_dll.dll")
 MRSID_LIB =        "$(MRSID_RASTER_DIR)\lib\$(MRSID_CONFIG)\lti_dsdk_dll.lib" $(MRSID_LIB)
 !ELSE IF EXIST("$(MRSID_RASTER_DIR)\lib\Release_md\lti_dsdk_dll.dll")
@@ -519,6 +521,8 @@ MRSID_LIB =        $(MRSID_LIB) advapi32.lib user32.lib
 # Find and validate the specific DLL and add it to MRSID_LIB
 !IF EXIST("$(MRSID_LIDAR_DIR)\lib\lti_lidar_dsdk.dll")
 MRSID_LIB =        "$(MRSID_LIDAR_DIR)\lib\lti_lidar_dsdk.lib" $(MRSID_LIB)
+!ELSE IF EXIST("$(MRSID_LIDAR_DIR)\lib\lti_lidar_dsdk_1.1.dll")
+MRSID_LIB =        "$(MRSID_LIDAR_DIR)\lib\lti_lidar_dsdk.lib" $(MRSID_LIB)
 !ELSE IF $(MRSID_LVER)0 < 1110
 !ERROR Cannot link dynamically against this version of the MrSID Lidar SDK ($(MRSID_LVER)).  Try linking statically by setting MRSID_LDLLBUILD to NO.
 !ELSE
diff --git a/frmts/msg/msgdataset.cpp b/frmts/msg/msgdataset.cpp
index 17831b4..6125b6a 100644
--- a/frmts/msg/msgdataset.cpp
+++ b/frmts/msg/msgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: msgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  MSG Driver
  * Purpose:  GDALDataset driver for MSG translator for read support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, ITC
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/msgn/msgndataset.cpp b/frmts/msgn/msgndataset.cpp
index 445363b..f059a21 100644
--- a/frmts/msgn/msgndataset.cpp
+++ b/frmts/msgn/msgndataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgndataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: msgndataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  All code for EUMETSAT Archive format reader
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frans van den Bergh <fvdbergh at csir.co.za>
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "msg_reader_core.h"
 using namespace msg_native_format;
 
-CPL_CVSID("$Id: msgndataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: msgndataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void   GDALRegister_MSGN(void);
diff --git a/frmts/netcdf/gmtdataset.cpp b/frmts/netcdf/gmtdataset.cpp
index decca3a..b92a9a2 100644
--- a/frmts/netcdf/gmtdataset.cpp
+++ b/frmts/netcdf/gmtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmtdataset.cpp 25593 2013-02-02 13:03:03Z rouault $
+ * $Id: gmtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library for GMT Grids.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "netcdf.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gmtdataset.cpp 25593 2013-02-02 13:03:03Z rouault $");
+CPL_CVSID("$Id: gmtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern void *hNCMutex; /* shared with netcdf. See netcdfdataset.cpp */
 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 56783f5..da5550f 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.cpp 26111 2013-06-27 21:25:29Z etourigny $
+ * $Id: netcdfdataset.cpp 27050 2014-03-18 00:09:03Z kyle $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -7,6 +7,8 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2010, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +33,7 @@
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: netcdfdataset.cpp 26111 2013-06-27 21:25:29Z etourigny $");
+CPL_CVSID("$Id: netcdfdataset.cpp 27050 2014-03-18 00:09:03Z kyle $");
 
 #include <map> //for NCDFWriteProjAttribs()
 
@@ -1541,7 +1543,7 @@ netCDFDataset::~netCDFDataset()
     if( pszCFCoordinates )
         CPLFree( pszCFCoordinates );
 
-    if( cdfid ) {
+    if( cdfid > 0 ) {
 #ifdef NCDF_DEBUG
         CPLDebug( "GDAL_netCDF", "calling nc_close( %d )", cdfid );
 #endif
@@ -1577,6 +1579,17 @@ int netCDFDataset::SetDefineMode( int bNewDefineMode )
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **netCDFDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 char **netCDFDataset::GetMetadata( const char *pszDomain )
@@ -4247,7 +4260,8 @@ int netCDFDataset::IdentifyFormat( GDALOpenInfo * poOpenInfo, bool bCheckExt = T
         if ( bCheckExt ) { /* Check by default */
             const char* pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
             if ( ! ( EQUAL( pszExtension, "nc")  || EQUAL( pszExtension, "cdf") 
-                     || EQUAL( pszExtension, "nc2") || EQUAL( pszExtension, "nc4") ) )
+                     || EQUAL( pszExtension, "nc2") || EQUAL( pszExtension, "nc4")
+					 || EQUAL( pszExtension, "nc3") || EQUAL( pszExtension, "grd") ) )
                 return NCDF_FORMAT_HDF5;
         }
 #endif
@@ -4344,13 +4358,18 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     char         szExtraDimDef[NC_MAX_NAME];
     nc_type      nType=NC_NAT;
 
+#ifdef NCDF_DEBUG
     CPLDebug( "GDAL_netCDF", "\n=====\nOpen(), filename=[%s]", poOpenInfo->pszFilename );
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Does this appear to be a netcdf file?                           */
 /* -------------------------------------------------------------------- */
     if( ! EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) ) {
         nTmpFormat = IdentifyFormat( poOpenInfo );
+#ifdef NCDF_DEBUG
+    CPLDebug( "GDAL_netCDF", "identified format %d", nTmpFormat );
+#endif
         /* Note: not calling Identify() directly, because we want the file type */
         /* Only support NCDF_FORMAT* formats */
         if( ! ( NCDF_FORMAT_NC  == nTmpFormat ||
@@ -4438,14 +4457,21 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
+#ifdef NCDF_DEBUG
     CPLDebug( "GDAL_netCDF", "calling nc_open( %s )", poDS->osFilename.c_str() );
+#endif
     if( nc_open( poDS->osFilename, NC_NOWRITE, &cdfid ) != NC_NOERR ) {
+#ifdef NCDF_DEBUG
+        CPLDebug( "GDAL_netCDF", "error opening" );
+#endif
         CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
+#ifdef NCDF_DEBUG
     CPLDebug( "GDAL_netCDF", "got cdfid=%d\n", cdfid );
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Is this a real netCDF file?                                     */
@@ -4923,8 +4949,6 @@ void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
     char       szTemp[ NCDF_MAX_STR_LEN ];
     int        nItems;
 
-    CPLDebug( "GDAL_netCDF", "CopyMetadata()" );
-
     /* Remove the following band meta but set them later from band data */
     const char *papszIgnoreBand[] = { CF_ADD_OFFSET, CF_SCALE_FACTOR, 
                                       "valid_range", "_Unsigned", 
@@ -4946,10 +4970,6 @@ void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
         papszFieldData = CSLTokenizeString2 (pszField, "=", 
                                              CSLT_HONOURSTRINGS );
         if( papszFieldData[1] != NULL ) {
-#ifdef NCDF_DEBUG
-            CPLDebug( "GDAL_netCDF", "copy metadata [%s]=[%s]", 
-                      papszFieldData[ 0 ], papszFieldData[ 1 ] );
-#endif
 
 #ifdef NCDF_DEBUG
             CPLDebug( "GDAL_netCDF", "copy metadata [%s]=[%s]", 
diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h
index 5ddbfe7..a22c9e7 100644
--- a/frmts/netcdf/netcdfdataset.h
+++ b/frmts/netcdf/netcdfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.h 26007 2013-05-16 15:03:22Z etourigny $
+ * $Id: netcdfdataset.h 26612 2013-11-14 17:35:56Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -28,7 +28,7 @@
  ****************************************************************************/
 
 #ifndef _NETCDFDATASET_H_INCLUDED_
-#define _NETCDFATASET_H_INCLUDED_
+#define _NETCDFDATASET_H_INCLUDED_
 
 #include <float.h>
 #include "gdal_pam.h"
@@ -743,6 +743,7 @@ class netCDFDataset : public GDALPamDataset
     const char * GetProjectionRef();
     CPLErr 	SetProjection (const char *);
 
+    virtual char      **GetMetadataDomainList();
     char ** GetMetadata( const char * );
 
     int GetCDFID() { return cdfid; }
diff --git a/frmts/ngsgeoid/ngsgeoiddataset.cpp b/frmts/ngsgeoid/ngsgeoiddataset.cpp
index ec5c5f1..ef1e53d 100644
--- a/frmts/ngsgeoid/ngsgeoiddataset.cpp
+++ b/frmts/ngsgeoid/ngsgeoiddataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ngsgeoiddataset.cpp 23334 2011-11-05 22:40:46Z rouault $
+ * $Id: ngsgeoiddataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NGSGEOID driver
  * Purpose:  GDALDataset driver for NGSGEOID dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "gdal_pam.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ngsgeoiddataset.cpp 23334 2011-11-05 22:40:46Z rouault $");
+CPL_CVSID("$Id: ngsgeoiddataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_NGSGEOID(void);
diff --git a/frmts/nitf/ecrgtocdataset.cpp b/frmts/nitf/ecrgtocdataset.cpp
index c1397e3..3b7f455 100644
--- a/frmts/nitf/ecrgtocdataset.cpp
+++ b/frmts/nitf/ecrgtocdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ecrgtocdataset.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: ecrgtocdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ECRG TOC read Translator
  * Purpose:  Implementation of ECRGTOCDataset and ECRGTOCSubDataset.
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +35,7 @@
 #include "cpl_minixml.h"
 #include <vector>
 
-CPL_CVSID("$Id: ecrgtocdataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: ecrgtocdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /** Overview of used classes :
    - ECRGTOCDataset : lists the different subdatasets, listed in the .xml,
diff --git a/frmts/nitf/frmt_nitf.html b/frmts/nitf/frmt_nitf.html
index 64ed726..495146b 100644
--- a/frmts/nitf/frmt_nitf.html
+++ b/frmts/nitf/frmt_nitf.html
@@ -69,12 +69,18 @@ creation options can be used. See the <a href="frmt_jpeg.html">JPEG driver
 documentation</a>. Starting with GDAL 1.7.0, multi-block images can be written.
 <li>M3 is a variation of C3. The only difference is that a block map is written,
 which allow for fast seeking to any block. (Starting with GDAL 1.7.0.)
-<li>C8 means JPEG2000 compression (one block) and is available for both
-CreateCopy() and Create() methods. JPEG2000 compression is only available
-if the JP2ECW driver is available. The TARGET and PROFILE JP2ECW-specific
-creation options can be used. See the <a href="frmt_jp2ecw.html">JP2ECW driver
-documentation</a>. Starting with GDAL 1.7.0, if JP2ECW driver is not available,
-Jasper JPEG2000 driver can be used in the CreateCopy() case.
+<li>C8 means JPEG2000 compression (one block) and is available for 
+CreateCopy() and/or Create() methods. JPEG2000 compression is only available
+if the JP2ECW, JP2KAK or Jasper driver is available :
+<ul>
+<li> JP2ECW : The TARGET and PROFILE JP2ECW-specific creation options can be used.
+Both CreateCopy() and/or Create() methods are available.
+See the <a href="frmt_jp2ecw.html">JP2ECW driver documentation</a>.
+<li> JP2KAK : The general JP2KAK-specific creation options can be used (QUALITY, BLOCKXSIZE, BLOCKYSIZE, GMLPJ2, GeoJP2, LAYERS, ROI).
+Only CreateCopy() method is available.
+See the <a href="frmt_jp2kak.html">JP2KAK driver documentation</a>.
+<li>Starting with GDAL 1.7.0, if JP2ECW and JP2KAK drivers are not available, Jasper JPEG2000 driver can be used in the CreateCopy() case.
+</ul>
 </ul>
 </li>
 <p>
diff --git a/frmts/nitf/nitfaridpcm.cpp b/frmts/nitf/nitfaridpcm.cpp
index 3291546..78aacb5 100644
--- a/frmts/nitf/nitfaridpcm.cpp
+++ b/frmts/nitf/nitfaridpcm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfaridpcm.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: nitfaridpcm.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  ARIDPCM reading code.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007, Frank Warmerdam 
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "nitflib.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: nitfaridpcm.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: nitfaridpcm.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const int neighbourhood_size_75[4] = { 23, 47, 74, 173 };
 static const int bits_per_level_by_busycode_75[4/*busy code*/][4/*level*/] = { 
diff --git a/frmts/nitf/nitfbilevel.cpp b/frmts/nitf/nitfbilevel.cpp
index 5495e74..ea879e5 100644
--- a/frmts/nitf/nitfbilevel.cpp
+++ b/frmts/nitf/nitfbilevel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfbilevel.cpp 16416 2009-02-25 21:13:08Z rouault $
+ * $Id: nitfbilevel.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module implement BILEVEL (C1) compressed image reading.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007, Frank Warmerdam
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,7 +40,7 @@ CPL_C_END
 
 TIFF* VSI_TIFFOpen(const char* name, const char* mode);
 
-CPL_CVSID("$Id: nitfbilevel.cpp 16416 2009-02-25 21:13:08Z rouault $");
+CPL_CVSID("$Id: nitfbilevel.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       NITFUncompressBILEVEL()                        */
diff --git a/frmts/nitf/nitfdataset.cpp b/frmts/nitf/nitfdataset.cpp
index 71707fe..b1ef961 100644
--- a/frmts/nitf/nitfdataset.cpp
+++ b/frmts/nitf/nitfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdataset.cpp 25666 2013-02-22 17:59:01Z rouault $
+ * $Id: nitfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFDataset and driver related implementations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
@@ -34,7 +35,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: nitfdataset.cpp 25666 2013-02-22 17:59:01Z rouault $");
+CPL_CVSID("$Id: nitfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void NITFPatchImageLength( const char *pszFilename,
                                   GUIntBig nImageOffset, 
@@ -2939,6 +2940,19 @@ void NITFDataset::InitializeTREMetadata()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **NITFDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "NITF_METADATA", "NITF_DES", "NITF_DES_METADATA",
+                                   "NITF_FILE_HEADER_TRES", "NITF_IMAGE_SEGMENT_TRES",
+                                   "CGM", "TEXT", "TRE", "xml:TRE", "OVERVIEWS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -3681,13 +3695,13 @@ static const char *GDALToNITFDataType( GDALDataType eType )
 }
 
 /************************************************************************/
-/*                           NITFJP2Options()                           */
+/*                          NITFJP2ECWOptions()                         */
 /*                                                                      */
 /*      Prepare JP2-in-NITF creation options based in part of the       */
 /*      NITF creation options.                                          */
 /************************************************************************/
 
-static char **NITFJP2Options( char **papszOptions )
+static char **NITFJP2ECWOptions( char **papszOptions )
 
 {
     int i;
@@ -3709,6 +3723,39 @@ static char **NITFJP2Options( char **papszOptions )
 
     return papszJP2Options;
 }
+/************************************************************************/
+/*                           NITFJP2KAKOptions()                        */
+/*                                                                      */
+/*      Prepare JP2-in-NITF creation options based in part of the       */
+/*      NITF creation options.                                          */
+/************************************************************************/
+
+static char **NITFJP2KAKOptions( char **papszOptions )
+
+{
+    int i;
+    char** papszKAKOptions = NULL;
+    
+    for( i = 0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
+    {
+       if(      EQUALN(papszOptions[i],"QUALITY=", 8) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"BLOCKXSIZE=", 11) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"BLOCKYSIZE=", 11) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"GMLPJ2=", 7) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"GeoJP2=", 7) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"LAYERS=", 7) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+       else if (EQUALN(papszOptions[i],"ROI=", 4) )
+          papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
+    }
+
+    return papszKAKOptions;
+}
 
 
 
@@ -3815,7 +3862,7 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
     if( pszIC != NULL && EQUAL(pszIC,"C8") )
     {
         int bHasCreate = FALSE;
-
+       
         poJ2KDriver = GetGDALDriverManager()->GetDriverByName( "JP2ECW" );
         if( poJ2KDriver != NULL )
             bHasCreate = poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATE, 
@@ -3825,7 +3872,7 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
             CPLError( CE_Failure, CPLE_AppDefined, 
                       "Unable to create JPEG2000 encoded NITF files.  The\n"
                       "JP2ECW driver is unavailable, or missing Create support." );
-            return NULL;
+           return NULL;
         }
     }
 
@@ -3894,7 +3941,7 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 
         NITFClose( psFile );
 
-        char** papszJP2Options = NITFJP2Options(papszOptions);
+        char** papszJP2Options = NITFJP2ECWOptions(papszOptions);
         poWritableJ2KDataset = 
             poJ2KDriver->Create( osDSName, nXSize, nYSize, nBands, eType, 
                                  papszJP2Options );
@@ -3974,15 +4021,15 @@ NITFDataset::NITFCreateCopy(
             if( poJ2KDriver == NULL || 
                 poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATECOPY, NULL ) == NULL )
             {
-                /* Try with Jasper as an alternate driver */
+                /* Try with  JP2KAK as an alternate driver */
                 poJ2KDriver = 
-                    GetGDALDriverManager()->GetDriverByName( "JPEG2000" );
+                    GetGDALDriverManager()->GetDriverByName(  "JP2KAK" );
             }
             if( poJ2KDriver == NULL )
             {
-                /* Try with JP2KAK as an alternate driver */
+                /* Try with Jasper as an alternate driver */
                 poJ2KDriver = 
-                    GetGDALDriverManager()->GetDriverByName( "JP2KAK" );
+                    GetGDALDriverManager()->GetDriverByName( "JPEG2000" );
             }
             if( poJ2KDriver == NULL )
             {
@@ -4361,13 +4408,23 @@ NITFDataset::NITFCreateCopy(
                              
         if (EQUAL(poJ2KDriver->GetDescription(), "JP2ECW"))
         {
-            char** papszJP2Options = NITFJP2Options(papszOptions);
+            char** papszJP2Options = NITFJP2ECWOptions(papszOptions);
             poJ2KDataset = 
                 poJ2KDriver->CreateCopy( osDSName, poSrcDS, FALSE,
                                          papszJP2Options,
                                          pfnProgress, pProgressData );
             CSLDestroy(papszJP2Options);
         }
+        else if (EQUAL(poJ2KDriver->GetDescription(), "JP2KAK"))
+        {
+           char** papszKAKOptions = NITFJP2KAKOptions(papszOptions);
+            poJ2KDataset = 
+                poJ2KDriver->CreateCopy( osDSName, poSrcDS, FALSE,
+                                         papszKAKOptions,
+                                         pfnProgress, pProgressData );
+            CSLDestroy(papszKAKOptions);
+            
+        }
         else
         {
             /* Jasper case */
diff --git a/frmts/nitf/nitfdataset.h b/frmts/nitf/nitfdataset.h
index eabaeaf..09b6414 100644
--- a/frmts/nitf/nitfdataset.h
+++ b/frmts/nitf/nitfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdataset.h 25194 2012-10-30 22:33:21Z rouault $
+ * $Id: nitfdataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand declarations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
@@ -148,6 +149,7 @@ class NITFDataset : public GDALPamDataset
     virtual const GDAL_GCP *GetGCPs();
     virtual char **GetFileList(void);
 
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
diff --git a/frmts/nitf/nitfdes.c b/frmts/nitf/nitfdes.c
index a3fe9a2..5d22098 100644
--- a/frmts/nitf/nitfdes.c
+++ b/frmts/nitf/nitfdes.c
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: nitfdes.c 24916 2012-09-05 21:30:41Z hobu $
+ * $Id: nitfdes.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of DE segments.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfdes.c 24916 2012-09-05 21:30:41Z hobu $");
+CPL_CVSID("$Id: nitfdes.c 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          NITFDESAccess()                             */
diff --git a/frmts/nitf/nitfdump.c b/frmts/nitf/nitfdump.c
index e4d68dd..08472c2 100644
--- a/frmts/nitf/nitfdump.c
+++ b/frmts/nitf/nitfdump.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdump.c 21182 2010-11-30 16:49:59Z rouault $
+ * $Id: nitfdump.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Simple test mainline to dump info about NITF file. 
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "ogr_api.h"
 #endif
 
-CPL_CVSID("$Id: nitfdump.c 21182 2010-11-30 16:49:59Z rouault $");
+CPL_CVSID("$Id: nitfdump.c 27044 2014-03-16 23:41:27Z rouault $");
 
 static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static void DumpMetadata( const char *, const char *, char ** );
diff --git a/frmts/nitf/nitffile.c b/frmts/nitf/nitffile.c
index e199c8e..79a5ed9 100644
--- a/frmts/nitf/nitffile.c
+++ b/frmts/nitf/nitffile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitffile.c 25541 2013-01-21 21:26:40Z rouault $
+ * $Id: nitffile.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for opening NITF file, populating NITFFile
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitffile.c 25541 2013-01-21 21:26:40Z rouault $");
+CPL_CVSID("$Id: nitffile.c 27044 2014-03-16 23:41:27Z rouault $");
 
 static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
                             int *pnOffset,
@@ -1704,46 +1705,14 @@ double NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( double dfLat )
 /*                        NITFGetSeriesInfo()                           */
 /************************************************************************/
 
+/* From http://trac.osgeo.org/gdal/attachment/ticket/5353/MIL-STD-2411_1_CHG-3.pdf */
 static const NITFSeries nitfSeries[] =
 {
-    { "GN", "GNC", "1:5M", "Global Navigation Chart", "CADRG"},
-    { "JN", "JNC", "1:2M", "Jet Navigation Chart", "CADRG"},
-    { "OH", "VHRC", "1:1M", "VFR Helicopter Route Chart", "CADRG"},
-    { "ON", "ONC", "1:1M", "Operational Navigation Chart", "CADRG"},
-    { "OW", "WAC", "1:1M", "High Flying Chart - Host Nation", "CADRG"},
-    { "TP", "TPC", "1:500K", "Tactical Pilotage Chart", "CADRG"},
-    { "LF", "LFC-FR (Day)", "1:500K", "Low Flying Chart (Day) - Host Nation", "CADRG"},
-    { "L1", "LFC-1", "1:500K", "Low Flying Chart (TBD #1)", "CADRG"},
-    { "L2", "LFC-2", "1:500K", "Low Flying Chart (TBD #2)", "CADRG"},
-    { "L3", "LFC-3", "1:500K", "Low Flying Chart (TBD #3)", "CADRG"},
-    { "L4", "LFC-4", "1:500K", "Low Flying Chart (TBD #4)", "CADRG"},
-    { "L5", "LFC-5", "1:500K", "Low Flying Chart (TBD #5)", "CADRG"},
-    { "LN", "LN (Night)", "1:500K", "Low Flying Chart (Night) - Host Nation", "CADRG"},
-    { "JG", "JOG", "1:250K", "Joint Operation Graphic", "CADRG"},
-    { "JA", "JOG-A", "1:250K", "Joint Operation Graphic - Air", "CADRG"},
-    { "JR", "JOG-R", "1:250K", "Joint Operation Graphic - Radar", "CADRG"},
-    { "JO", "OPG", "1:250K", "Operational Planning Graphic", "CADRG"},
-    { "VT", "VTAC", "1:250K", "VFR Terminal Area Chart", "CADRG"},
-    { "F1", "TFC-1", "1:250K", "Transit Flying Chart (TBD #1)", "CADRG"},
-    { "F2", "TFC-2", "1:250K", "Transit Flying Chart (TBD #2)", "CADRG"},
-    { "F3", "TFC-3", "1:250K", "Transit Flying Chart (TBD #3)", "CADRG"},
-    { "F4", "TFC-4", "1:250K", "Transit Flying Chart (TBD #4)", "CADRG"},
-    { "F5", "TFC-5", "1:250K", "Transit Flying Chart (TBD #5)", "CADRG"},
-    { "TF", "TFC", "1:250K", "Transit Flying Chart (UK)", "CADRG"}, /* Not mentionned in 24111CN1.pdf paragraph 5.1.4 */
+    { "A1", "CM", "1:10K", "Combat Charts (1:10K)", "CADRG"},
+    { "A2", "CM", "1:25K", "Combat Charts (1:25K)", "CADRG"},
+    { "A3", "CM", "1:50K", "Combat Charts (1:50K)", "CADRG"},
+    { "A4", "CM", "1:100K", "Combat Charts (1:100K)", "CADRG"},
     { "AT", "ATC", "1:200K", "Series 200 Air Target Chart", "CADRG"},
-    { "VH", "HRC", "1:125K", "Helicopter Route Chart", "CADRG"},
-    { "TN", "TFC (Night)", "1:250K", "Transit Flying Charget (Night) - Host Nation", "CADRG"},
-    { "TR", "TLM 200", "1:200K", "Topographic Line Map 1:200,000 scale", "CADRG"},
-    { "TC", "TLM 100", "1:100K", "Topographic Line Map 1:100,000 scale", "CADRG"},
-    { "RV", "Riverine", "1:50K", "Riverine Map 1:50,000 scale", "CADRG"},
-    { "TL", "TLM 50", "1:50K", "Topographic Line Map 1:50,000 scale", "CADRG"},
-    { "UL", "TLM 50 - Other", "1:50K", "Topographic Line Map (other 1:50,000 scale)", "CADRG"},
-    { "TT", "TLM 25", "1:25K", "Topographic Line Map 1:25,000 scale", "CADRG"},
-    { "TQ", "TLM 24", "1:24K", "Topographic Line Map 1:24,000 scale", "CADRG"},
-    { "HA", "HA", "Various", "Harbor and Approach Charts", "CADRG"},
-    { "CO", "CO", "Various", "Coastal Charts", "CADRG"},
-    { "OA", "OPAREA", "Various", "Naval Range Operation Area Chart", "CADRG"},
-    { "CG", "CG", "Various", "City Graphics", "CADRG"},
     { "C1", "CG", "1:10000", "City Graphics", "CADRG"},
     { "C2", "CG", "1:10560", "City Graphics", "CADRG"},
     { "C3", "CG", "1:11000", "City Graphics", "CADRG"},
@@ -1759,36 +1728,168 @@ static const NITFSeries nitfSeries[] =
     { "CD", "CG", "1:16666", "City Graphics", "CADRG"},
     { "CE", "CG", "1:17000", "City Graphics", "CADRG"},
     { "CF", "CG", "1:17500", "City Graphics", "CADRG"},
+    { "CG", "CG", "Various", "City Graphics", "CADRG"},
     { "CH", "CG", "1:18000", "City Graphics", "CADRG"},
     { "CJ", "CG", "1:20000", "City Graphics", "CADRG"},
     { "CK", "CG", "1:21000", "City Graphics", "CADRG"},
     { "CL", "CG", "1:21120", "City Graphics", "CADRG"},
+    { "CM", "CM", "Various", "Combat Charts", "CADRG"},
     { "CN", "CG", "1:22000", "City Graphics", "CADRG"},
+    { "CO", "CO", "Various", "Coastal Charts", "CADRG"},
     { "CP", "CG", "1:23000", "City Graphics", "CADRG"},
     { "CQ", "CG", "1:25000", "City Graphics", "CADRG"},
     { "CR", "CG", "1:26000", "City Graphics", "CADRG"},
     { "CS", "CG", "1:35000", "City Graphics", "CADRG"},
     { "CT", "CG", "1:36000", "City Graphics", "CADRG"},
-    { "CM", "CM", "Various", "Combat Charts", "CADRG"},
-    { "A1", "CM", "1:10K", "Combat Charts (1:10K)", "CADRG"},
-    { "A2", "CM", "1:25K", "Combat Charts (1:25K)", "CADRG"},
-    { "A3", "CM", "1:50K", "Combat Charts (1:50K)", "CADRG"},
-    { "A4", "CM", "1:100K", "Combat Charts (1:100K)", "CADRG"},
-    { "MI", "MIM", "1:50K", "Military Installation Maps", "CADRG"},
-    { "M1", "MIM", "Various", "Military Installation Maps (TBD #1)", "CADRG"},
-    { "M2", "MIM", "Various", "Military Installation Maps (TBD #2)", "CADRG"},
-    { "VN", "VNC", "1:500K", "Visual Navigation Charts", "CADRG"},
-    { "MM", "", "Various", "(Miscellaneous Maps & Charts)", "CADRG"},
-    
+    { "D1", "", "100m", "Elevation Data from DTED level 1", "CDTED"},
+    { "D2", "", "30m", "Elevation Data from DTED level 2", "CDTED"},
+    { "EG", "NARC", "1:11,000,000", "North Atlantic Route Chart", "CADRG"},
+    { "ES", "SEC", "1:500K", "VFR Sectional", "CADRG"},
+    { "ET", "SEC", "1:250K", "VFR Sectional Inserts", "CADRG"},
+    { "F1", "TFC-1", "1:250K", "Transit Flying Chart (TBD #1)", "CADRG"},
+    { "F2", "TFC-2", "1:250K", "Transit Flying Chart (TBD #2)", "CADRG"},
+    { "F3", "TFC-3", "1:250K", "Transit Flying Chart (TBD #3)", "CADRG"},
+    { "F4", "TFC-4", "1:250K", "Transit Flying Chart (TBD #4)", "CADRG"},
+    { "F5", "TFC-5", "1:250K", "Transit Flying Chart (TBD #5)", "CADRG"},
+    { "GN", "GNC", "1:5M", "Global Navigation Chart", "CADRG"},
+    { "HA", "HA", "Various", "Harbor and Approach Charts", "CADRG"},
     { "I1", "", "10m", "Imagery, 10 meter resolution", "CIB"},
     { "I2", "", "5m", "Imagery, 5 meter resolution", "CIB"},
     { "I3", "", "2m", "Imagery, 2 meter resolution", "CIB"},
     { "I4", "", "1m", "Imagery, 1 meter resolution", "CIB"},
     { "I5", "", ".5m", "Imagery, .5 (half) meter resolution", "CIB"},
     { "IV", "", "Various > 10m", "Imagery, greater than 10 meter resolution", "CIB"},
-    
-    { "D1", "", "100m", "Elevation Data from DTED level 1", "CDTED"},
-    { "D2", "", "30m", "Elevation Data from DTED level 2", "CDTED"},
+    { "JA", "JOG-A", "1:250K", "Joint Operation Graphic - Air", "CADRG"},
+    { "JG", "JOG", "1:250K", "Joint Operation Graphic", "CADRG"},
+    { "JN", "JNC", "1:2M", "Jet Navigation Chart", "CADRG"},
+    { "JO", "OPG", "1:250K", "Operational Planning Graphic", "CADRG"},
+    { "JR", "JOG-R", "1:250K", "Joint Operation Graphic - Radar", "CADRG"},
+    { "K1", "ICM", "1:8K", "Image City Maps", "CADRG"},
+    { "K2", "ICM", "1:10K", "Image City Maps", "CADRG"},
+    { "K3", "ICM", "1:10560", "Image City Maps", "CADRG"},
+    { "K7", "ICM", "1:12500", "Image City Maps", "CADRG"},
+    { "K8", "ICM", "1:12800", "Image City Maps", "CADRG"},
+    { "KB", "ICM", "1:15K", "Image City Maps", "CADRG"},
+    { "KE", "ICM", "1:16666", "Image City Maps", "CADRG"},
+    { "KM", "ICM", "1:21120", "Image City Maps", "CADRG"},
+    { "KR", "ICM", "1:25K", "Image City Maps", "CADRG"},
+    { "KS", "ICM", "1:26K", "Image City Maps", "CADRG"},
+    { "KU", "ICM", "1:36K", "Image City Maps", "CADRG"},
+    { "L1", "LFC-1", "1:500K", "Low Flying Chart (TBD #1)", "CADRG"},
+    { "L2", "LFC-2", "1:500K", "Low Flying Chart (TBD #2)", "CADRG"},
+    { "L3", "LFC-3", "1:500K", "Low Flying Chart (TBD #3)", "CADRG"},
+    { "L4", "LFC-4", "1:500K", "Low Flying Chart (TBD #4)", "CADRG"},
+    { "L5", "LFC-5", "1:500K", "Low Flying Chart (TBD #5)", "CADRG"},
+    { "LF", "LFC-FR (Day)", "1:500K", "Low Flying Chart (Day) - Host Nation", "CADRG"},
+    { "LN", "LN (Night)", "1:500K", "Low Flying Chart (Night) - Host Nation", "CADRG"},
+    { "M1", "MIM", "Various", "Military Installation Maps (TBD #1)", "CADRG"},
+    { "M2", "MIM", "Various", "Military Installation Maps (TBD #2)", "CADRG"},
+    { "MH", "MIM", "1:25K", "Military Installation Maps", "CADRG"},
+    { "MI", "MIM", "1:50K", "Military Installation Maps", "CADRG"},
+    { "MJ", "MIM", "1:100K", "Military Installation Maps", "CADRG"},
+    { "MM", "", "Various", "(Miscellaneous Maps & Charts)", "CADRG"},
+    { "OA", "OPAREA", "Various", "Naval Range Operation Area Chart", "CADRG"},
+    { "OH", "VHRC", "1:1M", "VFR Helicopter Route Chart", "CADRG"},
+    { "ON", "ONC", "1:1M", "Operational Navigation Chart", "CADRG"},
+    { "OW", "WAC", "1:1M", "High Flying Chart - Host Nation", "CADRG"},
+    { "P1", "", "1:25K", "Special Military Map - Overlay", "CADRG"},
+    { "P2", "", "1:25K", "Special Military Purpose", "CADRG"},
+    { "P3", "", "1:25K", "Special Military Purpose", "CADRG"},
+    { "P4", "", "1:25K", "Special Military Purpose", "CADRG"},
+    { "P5", "", "1:50K", "Special Military Map - Overlay", "CADRG"},
+    { "P6", "", "1:50K", "Special Military Purpose", "CADRG"},
+    { "P7", "", "1:50K", "Special Military Purpose", "CADRG"},
+    { "P8", "", "1:50K", "Special Military Purpose", "CADRG"},
+    { "P9", "", "1:100K", "Special Military Map - Overlay", "CADRG"},
+    { "PA", "", "1:100K", "Special Military Purpose", "CADRG"},
+    { "PB", "", "1:100K", "Special Military Purpose", "CADRG"},
+    { "PC", "", "1:100K", "Special Military Purpose", "CADRG"},
+    { "PD", "", "1:250K", "Special Military Map - Overlay", "CADRG"},
+    { "PE", "", "1:250K", "Special Military Purpose", "CADRG"},
+    { "PF", "", "1:250K", "Special Military Purpose", "CADRG"},
+    { "PG", "", "1:250K", "Special Military Purpose", "CADRG"},
+    { "PH", "", "1:500K", "Special Military Map - Overlay", "CADRG"},
+    { "PI", "", "1:500K", "Special Military Purpose", "CADRG"},
+    { "PJ", "", "1:500K", "Special Military Purpose", "CADRG"},
+    { "PK", "", "1:500K", "Special Military Purpose", "CADRG"},
+    { "PL", "", "1:1M", "Special Military Map - Overlay", "CADRG"},
+    { "PM", "", "1:1M", "Special Military Purpose", "CADRG"},
+    { "PN", "", "1:1M", "Special Military Purpose", "CADRG"},
+    { "PO", "", "1:1M", "Special Military Purpose", "CADRG"},
+    { "PP", "", "1:2M", "Special Military Map - Overlay", "CADRG"},
+    { "PQ", "", "1:2M", "Special Military Purpose", "CADRG"},
+    { "PR", "", "1:2M", "Special Military Purpose", "CADRG"},
+    { "PS", "", "1:5M", "Special Military Map - Overlay", "CADRG"},
+    { "PT", "", "1:5M", "Special Military Purpose", "CADRG"},
+    { "PU", "", "1:5M", "Special Military Purpose", "CADRG"},
+    { "PV", "", "1:5M", "Special Military Purpose", "CADRG"},
+    { "R1", "", "1:50K", "Range Charts", "CADRG"},
+    { "R2", "", "1:100K", "Range Charts", "CADRG"},
+    { "R3", "", "1:250K", "Range Charts", "CADRG"},
+    { "R4", "", "1:500K", "Range Charts", "CADRG"},
+    { "R5", "", "1:1M", "Range Charts", "CADRG"},
+    { "RC", "RGS-100", "1:100K", "Russian General Staff Maps", "CADRG"},
+    { "RL", "RGS-50", "1:50K", "Russian General Staff Maps", "CADRG"},
+    { "RR", "RGS-200", "1:200K", "Russian General Staff Maps", "CADRG"},
+    { "RV", "Riverine", "1:50K", "Riverine Map 1:50,000 scale", "CADRG"},
+    { "TC", "TLM 100", "1:100K", "Topographic Line Map 1:100,000 scale", "CADRG"},
+    { "TF", "TFC (Day)", "1:250K", "Transit Flying Chart (Day)", "CADRG"},
+    { "TL", "TLM50", "1:50K", "Topographic Line Map", "CADRG"},
+    { "TN", "TFC (Night)", "1:250K", "Transit Flying Chart (Night) - Host Nation", "CADRG"},
+    { "TP", "TPC", "1:500K", "Tactical Pilotage Chart", "CADRG"},
+    { "TQ", "TLM24", "1:24K", "Topographic Line Map 1:24,000 scale", "CADRG"},
+    { "TR", "TLM200", "1:200K", "Topographic Line Map 1:200,000 scale", "CADRG"},
+    { "TT", "TLM25", "1:25K", "Topographic Line Map 1:25,000 scale", "CADRG"},
+    { "UL", "TLM50 - Other", "1:50K", "Topographic Line Map (other 1:50,000 scale)", "CADRG"},
+    { "V1", "Inset HRC", "1:50", "Helicopter Route Chart Inset", "CADRG"},
+    { "V2", "Inset HRC", "1:62500", "Helicopter Route Chart Inset", "CADRG"},
+    { "V3", "Inset HRC", "1:90K", "Helicopter Route Chart Inset", "CADRG"},
+    { "V4", "Inset HRC", "1:250K", "Helicopter Route Chart Inset", "CADRG"},
+    { "VH", "HRC", "1:125K", "Helicopter Route Chart", "CADRG"},
+    { "VN", "VNC", "1:500K", "Visual Navigation Charts", "CADRG"},
+    { "VT", "VTAC", "1:250K", "VFR Terminal Area Chart", "CADRG"},
+    { "WA", "", "1:250K", "IFR Enroute Low", "CADRG"},
+    { "WB", "", "1:500K", "IFR Enroute Low", "CADRG"},
+    { "WC", "", "1:750K", "IFR Enroute Low", "CADRG"},
+    { "WD", "", "1:1M", "IFR Enroute Low", "CADRG"},
+    { "WE", "", "1:1.5M", "IFR Enroute Low", "CADRG"},
+    { "WF", "", "1:2M", "IFR Enroute Low", "CADRG"},
+    { "WG", "", "1:2.5M", "IFR Enroute Low", "CADRG"},
+    { "WH", "", "1:3M", "IFR Enroute Low", "CADRG"},
+    { "WI", "", "1:3.5M", "IFR Enroute Low", "CADRG"},
+    { "WK", "", "1:4M", "IFR Enroute Low", "CADRG"},
+    { "XD", "", "1:1M", "IFR Enroute High", "CADRG"},
+    { "XE", "", "1:1.5M", "IFR Enroute High", "CADRG"},
+    { "XF", "", "1:2M", "IFR Enroute High", "CADRG"},
+    { "XG", "", "1:2.5M", "IFR Enroute High", "CADRG"},
+    { "XH", "", "1:3M", "IFR Enroute High", "CADRG"},
+    { "XI", "", "1:3.5M", "IFR Enroute High", "CADRG"},
+    { "XJ", "", "1:4M", "IFR Enroute High", "CADRG"},
+    { "XK", "", "1:4.5M", "IFR Enroute High", "CADRG"},
+    { "Y9", "", "1:16.5M", "IFR Enroute Area", "CADRG"},
+    { "YA", "", "1:250K", "IFR Enroute Area", "CADRG"},
+    { "YB", "", "1:500K", "IFR Enroute Area", "CADRG"},
+    { "YC", "", "1:750K", "IFR Enroute Area", "CADRG"},
+    { "YD", "", "1:1M", "IFR Enroute Area", "CADRG"},
+    { "YE", "", "1:1.5M", "IFR Enroute Area", "CADRG"},
+    { "YF", "", "1:2M", "IFR Enroute Area", "CADRG"},
+    { "YI", "", "1:3.5M", "IFR Enroute Area", "CADRG"},
+    { "YJ", "", "1:4M", "IFR Enroute Area", "CADRG"},
+    { "YZ", "", "1:12M", "IFR Enroute Area", "CADRG"},
+    { "ZA", "", "1:250K", "IFR Enroute High/Low", "CADRG"},
+    { "ZB", "", "1:500K", "IFR Enroute High/Low", "CADRG"},
+    { "ZC", "", "1:750K", "IFR Enroute High/Low", "CADRG"},
+    { "ZD", "", "1:1M", "IFR Enroute High/Low", "CADRG"},
+    { "ZE", "", "1:1.5M", "IFR Enroute High/Low", "CADRG"},
+    { "ZF", "", "1:2M", "IFR Enroute High/Low", "CADRG"},
+    { "ZG", "", "1:2.5M", "IFR Enroute High/Low", "CADRG"},
+    { "ZH", "", "1:3M", "IFR Enroute High/Low", "CADRG"},
+    { "ZI", "", "1:3.5M", "IFR Enroute High/Low", "CADRG"},
+    { "ZJ", "", "1:4M", "IFR Enroute High/Low", "CADRG"},
+    { "ZK", "", "1:4.5M", "IFR Enroute High/Low", "CADRG"},
+    { "ZT", "", "1:9M", "IFR Enroute High/Low", "CADRG"},
+    { "ZV", "", "1:10M", "IFR Enroute High/Low", "CADRG"},
+    { "ZZ", "", "1:12M", "IFR Enroute High/Low", "CADRG"}
 };
 
 /* See 24111CN1.pdf paragraph 5.1.4 */
diff --git a/frmts/nitf/nitfimage.c b/frmts/nitf/nitfimage.c
index 3c50d55..c903e4e 100644
--- a/frmts/nitf/nitfimage.c
+++ b/frmts/nitf/nitfimage.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfimage.c 26189 2013-07-20 07:43:42Z rouault $
+ * $Id: nitfimage.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of most NITFImage 
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfimage.c 26189 2013-07-20 07:43:42Z rouault $");
+CPL_CVSID("$Id: nitfimage.c 27044 2014-03-16 23:41:27Z rouault $");
 
 static int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static char *NITFTrimWhite( char * );
diff --git a/frmts/nitf/nitflib.h b/frmts/nitf/nitflib.h
index 469e7cc..8b4e6d1 100644
--- a/frmts/nitf/nitflib.h
+++ b/frmts/nitf/nitflib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitflib.h 22843 2011-07-31 23:22:42Z rouault $
+ * $Id: nitflib.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Main GDAL independent include file for NITF support.  
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/nitf/nitfrasterband.cpp b/frmts/nitf/nitfrasterband.cpp
index a0a858d..8b8c53f 100644
--- a/frmts/nitf/nitfrasterband.cpp
+++ b/frmts/nitf/nitfrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfrasterband.cpp 25784 2013-03-23 11:13:42Z rouault $
+ * $Id: nitfrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFRasterBand (and related proxy band) implementations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
@@ -34,7 +35,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: nitfrasterband.cpp 25784 2013-03-23 11:13:42Z rouault $");
+CPL_CVSID("$Id: nitfrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       NITFMakeColorTable()                           */
diff --git a/frmts/nitf/nitfwritejpeg.cpp b/frmts/nitf/nitfwritejpeg.cpp
index ae90c06..473c4e5 100644
--- a/frmts/nitf/nitfwritejpeg.cpp
+++ b/frmts/nitf/nitfwritejpeg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfwritejpeg.cpp 21951 2011-03-12 22:02:07Z warmerdam $
+ * $Id: nitfwritejpeg.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand implementation on top of "nitflib".
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
diff --git a/frmts/nitf/rpftocdataset.cpp b/frmts/nitf/rpftocdataset.cpp
index 63aa36c..83078e7 100644
--- a/frmts/nitf/rpftocdataset.cpp
+++ b/frmts/nitf/rpftocdataset.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,7 +42,7 @@
 #define GEOTRSFRM_ROTATION_PARAM2      4
 #define GEOTRSFRM_NS_RES               5
 
-CPL_CVSID("$Id: rpftocdataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: rpftocdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /** Overview of used classes :
@@ -822,7 +822,7 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
                             if( bHasNoDataValue && iC == (int)noDataValue )
                                 continue;
 
-                            const GDALColorEntry* entry = poCT->GetColorEntry(i);
+                            const GDALColorEntry* entry = poCT->GetColorEntry(iC);
                             if( entry->c1 != 0 || entry->c2 != 0 || entry->c3 != 0)
                             {
                                 bAllBlack = FALSE;
diff --git a/frmts/nitf/rpftocfile.cpp b/frmts/nitf/rpftocfile.cpp
index 98a3edb..464d2f6 100644
--- a/frmts/nitf/rpftocfile.cpp
+++ b/frmts/nitf/rpftocfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rpftocfile.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rpftocfile.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Module responsible for opening a RPF TOC file, populating RPFToc
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  **********************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,7 +49,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rpftocfile.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: rpftocfile.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        RPFTOCTrim()                                    */
diff --git a/frmts/nitf/rpftoclib.h b/frmts/nitf/rpftoclib.h
index 1faafea..2478de0 100644
--- a/frmts/nitf/rpftoclib.h
+++ b/frmts/nitf/rpftoclib.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: rpftoclib.h 21951 2011-03-12 22:02:07Z warmerdam $
+ * $Id: rpftoclib.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Main GDAL independent include file for RPF TOC support.  
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  **********************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/northwood/grcdataset.cpp b/frmts/northwood/grcdataset.cpp
index be07968..eabb552 100644
--- a/frmts/northwood/grcdataset.cpp
+++ b/frmts/northwood/grcdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grcdataset.cpp 24355 2012-05-01 10:52:54Z rouault $
+ * $Id: grcdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRC Reader
  * Purpose:  GDAL driver for Northwood Classified Format
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Waypoint Information Technology
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/northwood/grddataset.cpp b/frmts/northwood/grddataset.cpp
index e9c8dff..806ec51 100644
--- a/frmts/northwood/grddataset.cpp
+++ b/frmts/northwood/grddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grddataset.cpp 24355 2012-05-01 10:52:54Z rouault $
+ * $Id: grddataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRD Reader
  * Purpose:  GDAL driver for Northwood Grid Format
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Waypoint Information Technology
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/northwood/northwood.cpp b/frmts/northwood/northwood.cpp
index 6fd6756..0ba2989 100644
--- a/frmts/northwood/northwood.cpp
+++ b/frmts/northwood/northwood.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.cpp 24120 2012-03-15 19:41:49Z warmerdam $
+ * $Id: northwood.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Format basic implementation
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Waypoint Information Technology
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/northwood/northwood.h b/frmts/northwood/northwood.h
index 8ef16cb..5f415f7 100644
--- a/frmts/northwood/northwood.h
+++ b/frmts/northwood/northwood.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.h 21898 2011-03-06 14:27:52Z rouault $
+ * $Id: northwood.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Technologies Grid format declarations
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Waypoint Information Technology
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/ogdi/ogdidataset.cpp b/frmts/ogdi/ogdidataset.cpp
index 33975c1..61744a0 100644
--- a/frmts/ogdi/ogdidataset.cpp
+++ b/frmts/ogdi/ogdidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogdidataset.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: ogdidataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     ogdidataset.cpp
  * Project:  OGDI Bridge
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogdidataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: ogdidataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_OGDI(void);
@@ -80,6 +81,7 @@ class CPL_DLL OGDIDataset : public GDALDataset
 
     virtual void *GetInternalHandle( const char * );
 
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char * pszDomain = "" );
 };
 
@@ -533,6 +535,17 @@ OGDIDataset::~OGDIDataset()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **OGDIDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/frmts/openjpeg/openjpegdataset.cpp b/frmts/openjpeg/openjpegdataset.cpp
index 3e6adc9..1a3a119 100644
--- a/frmts/openjpeg/openjpegdataset.cpp
+++ b/frmts/openjpeg/openjpegdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: openjpegdataset.cpp 25877 2013-04-07 19:02:32Z rouault $
+ * $Id: openjpegdataset.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  JPEG2000 driver based on OpenJPEG library
  * Purpose:  JPEG2000 driver based on OpenJPEG library
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,13 +33,13 @@
 #include <openjpeg-2.0/openjpeg.h>
 #include <vector>
 
-#include "gdal_pam.h"
+#include "gdaljp2abstractdataset.h"
 #include "cpl_string.h"
 #include "gdaljp2metadata.h"
 #include "cpl_multiproc.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: openjpegdataset.cpp 25877 2013-04-07 19:02:32Z rouault $");
+CPL_CVSID("$Id: openjpegdataset.cpp 27182 2014-04-14 20:03:08Z rouault $");
 
 /************************************************************************/
 /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
@@ -56,6 +56,13 @@ static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, void *unused)
 
 static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, void *unused)
 {
+    if( strcmp(pszMsg, "Empty SOT marker detected: Psot=12.\n") == 0 )
+    {
+        static int bWarningEmitted = FALSE;
+        if( bWarningEmitted )
+            return;
+        bWarningEmitted = TRUE;
+    }
     if( strcmp(pszMsg, "JP2 box which are after the codestream will not be read by this function.\n") != 0 )
         CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
 }
@@ -143,18 +150,12 @@ static OPJ_OFF_T JP2OpenJPEGDataset_Skip(OPJ_OFF_T nBytes, void * pUserData)
 
 class JP2OpenJPEGRasterBand;
 
-class JP2OpenJPEGDataset : public GDALPamDataset
+class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
 {
     friend class JP2OpenJPEGRasterBand;
 
     VSILFILE   *fp; /* Large FILE API */
 
-    char        *pszProjection;
-    int         bGeoTransformValid;
-    double      adfGeoTransform[6];
-    int         nGCPCount;
-    GDAL_GCP    *pasGCPList;
-
     OPJ_CODEC_FORMAT eCodecFormat;
     OPJ_COLOR_SPACE eColorSpace;
 
@@ -183,11 +184,6 @@ class JP2OpenJPEGDataset : public GDALPamDataset
                                            int bStrict, char ** papszOptions, 
                                            GDALProgressFunc pfnProgress,
                                            void * pProgressData );
-    CPLErr              GetGeoTransform( double* );
-    virtual const char  *GetProjectionRef(void);
-    virtual int         GetGCPCount();
-    virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -835,16 +831,6 @@ JP2OpenJPEGDataset::JP2OpenJPEGDataset()
 {
     fp = NULL;
     nBands = 0;
-    pszProjection = CPLStrdup("");
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    bGeoTransformValid = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
     eCodecFormat = OPJ_CODEC_UNKNOWN;
     eColorSpace = OPJ_CLRSPC_UNKNOWN;
     bIs420 = FALSE;
@@ -865,13 +851,6 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
 {
     FlushCache();
 
-    if ( pszProjection )
-        CPLFree( pszProjection );
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
     if( fp != NULL )
         VSIFCloseL( fp );
 
@@ -896,74 +875,6 @@ int JP2OpenJPEGDataset::CloseDependentDatasets()
     return bRet;
 }
 
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *JP2OpenJPEGDataset::GetProjectionRef()
-
-{
-    if ( pszProjection && pszProjection[0] != 0 )
-        return( pszProjection );
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
-{
-    if( bGeoTransformValid )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
-        return CE_None;
-    }
-    else
-        return GDALPamDataset::GetGeoTransform(padfTransform);
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int JP2OpenJPEGDataset::GetGCPCount()
-
-{
-    if( nGCPCount > 0 )
-        return nGCPCount;
-    else
-        return GDALPamDataset::GetGCPCount();
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *JP2OpenJPEGDataset::GetGCPProjection()
-
-{
-    if( nGCPCount > 0 )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
-}
-
-/************************************************************************/
-/*                               GetGCP()                               */
-/************************************************************************/
-
-const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
-
-{
-    if( nGCPCount > 0 )
-        return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
-}
-
 /************************************************************************/
 /*                            Identify()                                */
 /************************************************************************/
@@ -1286,58 +1197,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for georeferencing information.                           */
-/* -------------------------------------------------------------------- */
-    GDALJP2Metadata oJP2Geo;
-
-    if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
-    {
-        if ( poDS->pszProjection )
-            CPLFree( poDS->pszProjection );
-        poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-        poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
-        memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
-                sizeof(double) * 6 );
-        poDS->nGCPCount = oJP2Geo.nGCPCount;
-        poDS->pasGCPList =
-            GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
-    }
-
-    if (oJP2Geo.pszXMPMetadata)
-    {
-        char *apszMDList[2];
-        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-        apszMDList[1] = NULL;
-        poDS->SetMetadata(apszMDList, "xml:XMP");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have other misc metadata?                                 */
-/* -------------------------------------------------------------------- */
-    if( oJP2Geo.papszMetadata != NULL )
-    {
-        char **papszMD = CSLDuplicate(poDS->GDALPamDataset::GetMetadata());
-
-        papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
-        poDS->GDALPamDataset::SetMetadata( papszMD );
-
-        CSLDestroy( papszMD );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
-/* -------------------------------------------------------------------- */
-    if( !poDS->bGeoTransformValid )
-    {
-        poDS->bGeoTransformValid |=
-            GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
-                                poDS->adfGeoTransform,
-                                poOpenInfo->papszSiblingFiles, NULL )
-            || GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
-                                   poDS->adfGeoTransform,
-                                   poOpenInfo->papszSiblingFiles, NULL );
-    }
+    poDS->LoadJP2Metadata(poOpenInfo);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -1362,6 +1222,9 @@ void JP2OpenJPEGDataset::WriteBox(VSILFILE* fp, GDALJP2Box* poBox)
     GUInt32   nLBox;
     GUInt32   nTBox;
 
+    if( poBox == NULL )
+        return;
+
     nLBox = (int) poBox->GetDataLength() + 8;
     nLBox = CPL_MSBWORD32( nLBox );
 
@@ -1681,22 +1544,42 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     GDALJP2Metadata oJP2MD;
 
     int bWriteExtraBoxes = FALSE;
+    int bHasGeoreferencing = FALSE;
+    int bGeoreferencingCompatOfGMLJP2 = FALSE;
     if( eCodecFormat == OPJ_CODEC_JP2 &&
         (CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) ||
          CSLFetchBoolean( papszOptions, "GeoJP2", TRUE )) )
     {
-        const char* pszWKT = poSrcDS->GetProjectionRef();
-        if( pszWKT != NULL && pszWKT[0] != '\0' )
+        if( poSrcDS->GetGCPCount() > 0 )
         {
             bWriteExtraBoxes = TRUE;
-            oJP2MD.SetProjection( pszWKT );
+            bHasGeoreferencing = TRUE;
+            oJP2MD.SetGCPs( poSrcDS->GetGCPCount(),
+                            poSrcDS->GetGCPs() );
+            oJP2MD.SetProjection( poSrcDS->GetGCPProjection() );
         }
-        double adfGeoTransform[6];
-        if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
+        else
         {
-            bWriteExtraBoxes = TRUE;
-            oJP2MD.SetGeoTransform( adfGeoTransform );
+            const char* pszWKT = poSrcDS->GetProjectionRef();
+            if( pszWKT != NULL && pszWKT[0] != '\0' )
+            {
+                bGeoreferencingCompatOfGMLJP2 = TRUE;
+                bHasGeoreferencing = TRUE;
+                bWriteExtraBoxes = TRUE;
+                oJP2MD.SetProjection( pszWKT );
+            }
+            double adfGeoTransform[6];
+            if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
+            {
+                bGeoreferencingCompatOfGMLJP2 = TRUE;
+                bHasGeoreferencing = TRUE;
+                bWriteExtraBoxes = TRUE;
+                oJP2MD.SetGeoTransform( adfGeoTransform );
+            }
         }
+
+        const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+        oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
     }
 
 #define PIXELS_PER_INCH 2
@@ -1810,13 +1693,15 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             delete poRes;
         }
 
-        if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
+        if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) &&
+            bGeoreferencingCompatOfGMLJP2 )
         {
             GDALJP2Box* poBox = oJP2MD.CreateGMLJP2(nXSize,nYSize);
             WriteBox(fp, poBox);
             delete poBox;
         }
-        if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
+        if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) &&
+            bHasGeoreferencing )
         {
             GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
             WriteBox(fp, poBox);
diff --git a/frmts/ozi/ozidataset.cpp b/frmts/ozi/ozidataset.cpp
index 2e9c20c..f2cb46a 100644
--- a/frmts/ozi/ozidataset.cpp
+++ b/frmts/ozi/ozidataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ozidataset.cpp 25310 2012-12-15 12:26:10Z rouault $
+ * $Id: ozidataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:   OZF2 and OZFx3 binary files driver
  * Purpose:  GDALDataset driver for OZF2 and OZFx3 binary files.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 
 /* g++ -fPIC -g -Wall frmts/ozi/ozidataset.cpp -shared -o gdal_OZI.so -Iport -Igcore -Iogr -L. -lgdal  */
 
-CPL_CVSID("$Id: ozidataset.cpp 25310 2012-12-15 12:26:10Z rouault $");
+CPL_CVSID("$Id: ozidataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_OZI(void);
diff --git a/frmts/pcidsk/GNUmakefile b/frmts/pcidsk/GNUmakefile
index cccdf32..ea255d3 100644
--- a/frmts/pcidsk/GNUmakefile
+++ b/frmts/pcidsk/GNUmakefile
@@ -5,6 +5,10 @@ ifeq ($(JPEG_SETTING),internal)
 JPEG_INCLUDE	=	-I../jpeg/libjpeg
 endif
 
+ifneq ($(JPEG_SETTING),no)
+JPEG_FLAGS = -DHAVE_LIBJPEG
+endif
+
 ifeq ($(PCIDSK_SETTING),old)
 OBJ	=	pcidskdataset.o pcidsktiledrasterband.o
 CPPFLAGS	:=	$(GDAL_INCLUDE) -I../raw $(CPPFLAGS)
@@ -12,7 +16,7 @@ $(O_OBJ):	../raw/rawdataset.h gdal_pcidsk.h
 else
 OBJ	=	pcidskdataset2.o vsi_pcidsk_io.o gdal_edb.o $(SDKOBJ)
 ifeq ($(PCIDSK_SETTING),internal)
-CPPFLAGS	:=	-DHAVE_LIBJPEG $(JPEG_INCLUDE) -DPCIDSK_INTERNAL \
+CPPFLAGS	:=	$(JPEG_FLAGS) $(JPEG_INCLUDE) -DPCIDSK_INTERNAL \
 	-Isdk $(GDAL_INCLUDE) $(CPPFLAGS)
 
 SDKOBJ 	=	\
diff --git a/frmts/pcidsk/pcidskdataset.cpp b/frmts/pcidsk/pcidskdataset.cpp
index 9ac084c..f028ff3 100644
--- a/frmts/pcidsk/pcidskdataset.cpp
+++ b/frmts/pcidsk/pcidskdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcidskdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: pcidskdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_pcidsk.h"
 
-CPL_CVSID("$Id: pcidskdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: pcidskdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_PCIDSK(void);
diff --git a/frmts/pcidsk/pcidskdataset2.cpp b/frmts/pcidsk/pcidskdataset2.cpp
index 67f5ed7..a33ba70 100644
--- a/frmts/pcidsk/pcidskdataset2.cpp
+++ b/frmts/pcidsk/pcidskdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcidskdataset2.cpp 24941 2012-09-18 22:31:13Z rouault $
+ * $Id: pcidskdataset2.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: pcidskdataset2.cpp 24941 2012-09-18 22:31:13Z rouault $");
+CPL_CVSID("$Id: pcidskdataset2.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 using namespace PCIDSK;
 
@@ -76,6 +77,7 @@ class PCIDSK2Dataset : public GDALPamDataset
     const char         *GetProjectionRef();
     CPLErr              SetProjection( const char * );
 
+    virtual char      **GetMetadataDomainList();
     CPLErr              SetMetadata( char **, const char * );
     char              **GetMetadata( const char* );
     CPLErr              SetMetadataItem(const char*,const char*,const char*);
@@ -130,6 +132,7 @@ class PCIDSK2Band : public GDALPamRasterBand
 
     virtual void        SetDescription( const char * );
 
+    virtual char      **GetMetadataDomainList();
     CPLErr              SetMetadata( char **, const char * );
     char              **GetMetadata( const char* );
     CPLErr              SetMetadataItem(const char*,const char*,const char*);
@@ -781,6 +784,17 @@ CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **PCIDSK2Band::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamRasterBand::GetMetadataDomainList(),
+                                   TRUE,
+                                   "", NULL);
+}
+
+/************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
@@ -1183,6 +1197,17 @@ CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **PCIDSK2Dataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "", NULL);
+}
+
+/************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
diff --git a/frmts/pcidsk/vsi_pcidsk_io.cpp b/frmts/pcidsk/vsi_pcidsk_io.cpp
index 5b02d5f..45a88a4 100644
--- a/frmts/pcidsk/vsi_pcidsk_io.cpp
+++ b/frmts/pcidsk/vsi_pcidsk_io.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsi_pcidsk_io.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: vsi_pcidsk_io.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  PCIDSK SDK compatiable io interface built on VSI.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "pcidsk.h"
 
-CPL_CVSID("$Id: vsi_pcidsk_io.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: vsi_pcidsk_io.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 using namespace PCIDSK;
 
diff --git a/frmts/pdf/frmt_pdf.html b/frmts/pdf/frmt_pdf.html
index 2379971..606a6db 100644
--- a/frmts/pdf/frmt_pdf.html
+++ b/frmts/pdf/frmt_pdf.html
@@ -18,7 +18,7 @@ also optionally be drawn on top of the raster layer (see OGR_* creation options
 GDAL must be compiled with libpoppler support (GPL-licensed), and libpoppler itself must have been configured with
 --enable-xpdf-headers so that the xpdf C++ headers are available. Note: the poppler C++ API isn't
 stable, so the driver compilation may fail with too old or too recent poppler versions.
-Successfully tested versions are poppler >= 0.12.X and <= 0.22.0.
+Successfully tested versions are poppler >= 0.12.X and <= 0.24.0.
 <p>
 Starting with GDAL 1.9.0, as an alternative, the PDF driver can be compiled against libpodofo (LGPL-licensed)
 to avoid the libpoppler dependency. This is sufficient to get the georeferencing information. However, for
@@ -66,8 +66,7 @@ Defaults to 3.</li>
 The layer names can be obtained by querying the LAYERS metadata domain. When this option is specified,
 layers not explicitely listed will be turned off.</li>
 <li><i>GDAL_PDF_LAYERS_OFF</i> = list of layers (comma separated) to turn OFF. The layer names can be obtained by
-querying the LAYERS metadata domain. When this option is specified, layers not explicitely listed will be turned
-off.</li>
+querying the LAYERS metadata domain.</li>
 </ul>
 
 <h2>LAYERS Metadata domain</h2>
@@ -132,7 +131,9 @@ Set the compression to use for raster data. DEFLATE is the default.</p></li>
 Set the compression to use for stream objects. DEFLATE is the default.</p></li>
 
 <li><p><b>DPI=value</b>:
-Set the DPI to use. Default to 72.</p></li>
+Set the DPI to use. Default to 72. May be automatically adjusted to higher value
+so that page dimension does not exceed the 14400 maximum value (in user units)
+allowed by Acrobat.</p></li>
 
 <li><p><b>PREDICTOR=[1/2]</b>:
 Only for DEFLATE compression. Might be set to 2 to use horizontal predictor that can make files smaller (but not always!).
diff --git a/frmts/pdf/pdfcreatecopy.cpp b/frmts/pdf/pdfcreatecopy.cpp
index 0de4f9e..85bba5e 100644
--- a/frmts/pdf/pdfcreatecopy.cpp
+++ b/frmts/pdf/pdfcreatecopy.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.cpp 25613 2013-02-07 19:33:31Z rouault $
+ * $Id: pdfcreatecopy.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,6 +31,7 @@
 /* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
 #define CPL_GBOOL_DEFINED
 
+#include "pdfdataset.h"
 #include "pdfcreatecopy.h"
 
 #include "cpl_vsi_virtual.h"
@@ -46,7 +47,10 @@
 #define M_PI       3.14159265358979323846
 #endif
 
-CPL_CVSID("$Id: pdfcreatecopy.cpp 25613 2013-02-07 19:33:31Z rouault $");
+/* Cf PDF reference v1.7, Appendix C, page 993 */
+#define MAXIMUM_SIZE_IN_UNITS   14400
+
+CPL_CVSID("$Id: pdfcreatecopy.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define PIXEL_TO_GEO_X(x,y) adfGeoTransform[0] + x * adfGeoTransform[1] + y * adfGeoTransform[2]
 #define PIXEL_TO_GEO_Y(x,y) adfGeoTransform[3] + x * adfGeoTransform[4] + y * adfGeoTransform[5]
@@ -299,9 +303,9 @@ void GDALPDFWriter::UpdateProj(GDALDataset* poSrcDS,
 
     const char* pszGEO_ENCODING = CPLGetConfigOption("GDAL_PDF_GEO_ENCODING", "ISO32000");
     if (EQUAL(pszGEO_ENCODING, "ISO32000") || EQUAL(pszGEO_ENCODING, "BOTH"))
-        nViewportId = WriteSRS_ISO32000(poSrcDS, dfDPI / 72.0, NULL, &sMargins, TRUE);
+        nViewportId = WriteSRS_ISO32000(poSrcDS, dfDPI * USER_UNIT_IN_INCH, NULL, &sMargins, TRUE);
     if (EQUAL(pszGEO_ENCODING, "OGC_BP") || EQUAL(pszGEO_ENCODING, "BOTH"))
-        nLGIDictId = WriteSRS_OGC_BP(poSrcDS, dfDPI / 72.0, NULL, &sMargins);
+        nLGIDictId = WriteSRS_OGC_BP(poSrcDS, dfDPI * USER_UNIT_IN_INCH, NULL, &sMargins);
 
 #ifdef invalidate_xref_entry
     GDALPDFObject* poVP = poPageDict->Get("VP");
@@ -1514,7 +1518,7 @@ int GDALPDFWriter::StartPage(GDALDataset* poClippingDS,
     int  nHeight = poClippingDS->GetRasterYSize();
     int  nBands = poClippingDS->GetRasterCount();
 
-    double dfUserUnit = dfDPI / 72.0;
+    double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
     double dfWidthInUserUnit = nWidth / dfUserUnit + psMargins->nLeft + psMargins->nRight;
     double dfHeightInUserUnit = nHeight / dfUserUnit + psMargins->nBottom + psMargins->nTop;
 
@@ -1657,7 +1661,7 @@ int GDALPDFWriter::WriteImagery(GDALDataset* poDS,
 {
     int  nWidth = poDS->GetRasterXSize();
     int  nHeight = poDS->GetRasterYSize();
-    double dfUserUnit = oPageContext.dfDPI / 72.0;
+    double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
 
     GDALPDFRasterDesc oRasterDesc;
 
@@ -1735,7 +1739,7 @@ int GDALPDFWriter::WriteClippedImagery(
                                 GDALProgressFunc pfnProgress,
                                 void * pProgressData)
 {
-    double dfUserUnit = oPageContext.dfDPI / 72.0;
+    double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
 
     GDALPDFRasterDesc oRasterDesc;
 
@@ -2159,7 +2163,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
 {
     GDALDataset* poClippingDS = oPageContext.poClippingDS;
     int  nHeight = poClippingDS->GetRasterYSize();
-    double dfUserUnit = oPageContext.dfDPI / 72.0;
+    double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
     double adfGeoTransform[6];
     poClippingDS->GetGeoTransform(adfGeoTransform);
 
@@ -2774,7 +2778,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
             GDALDataset* poClippingDS = oPageContext.poClippingDS;
             int  nWidth = poClippingDS->GetRasterXSize();
             int  nHeight = poClippingDS->GetRasterYSize();
-            double dfUserUnit = oPageContext.dfDPI / 72.0;
+            double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
             double dfWidthInUserUnit = nWidth / dfUserUnit + oPageContext.sMargins.nLeft + oPageContext.sMargins.nRight;
             double dfHeightInUserUnit = nHeight / dfUserUnit + oPageContext.sMargins.nBottom + oPageContext.sMargins.nTop;
 
@@ -2987,7 +2991,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
             GDALAllRegister();
 
         char** papszExtraImagesTokens = CSLTokenizeString2(pszExtraImages, ",", 0);
-        double dfUserUnit = oPageContext.dfDPI / 72.0;
+        double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
         int nCount = CSLCount(papszExtraImagesTokens);
         for(int i=0;i+4<=nCount; /* */)
         {
@@ -4361,10 +4365,6 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
 
     const char* pszXMP = CSLFetchNameValue(papszOptions, "XMP");
 
-    double dfDPI = atof(CSLFetchNameValueDef(papszOptions, "DPI", "72"));
-    if (dfDPI < 72.0)
-        dfDPI = 72.0;
-
     const char* pszPredictor = CSLFetchNameValue(papszOptions, "PREDICTOR");
     int nPredictor = 1;
     if (pszPredictor)
@@ -4411,6 +4411,57 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     const char* pszBottomMargin = CSLFetchNameValue(papszOptions, "BOTTOM_MARGIN");
     if (pszBottomMargin) sMargins.nBottom = atoi(pszBottomMargin);
 
+    const char* pszDPI = CSLFetchNameValue(papszOptions, "DPI");
+    double dfDPI = DEFAULT_DPI;
+    if( pszDPI != NULL )
+        dfDPI = CPLAtof(pszDPI);
+
+    double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
+    double dfWidthInUserUnit = nWidth / dfUserUnit + sMargins.nLeft + sMargins.nRight;
+    double dfHeightInUserUnit = nHeight / dfUserUnit + sMargins.nBottom + sMargins.nTop;
+    if( dfWidthInUserUnit > MAXIMUM_SIZE_IN_UNITS ||
+        dfHeightInUserUnit > MAXIMUM_SIZE_IN_UNITS )
+    {
+        if( pszDPI == NULL )
+        {
+            if( sMargins.nLeft + sMargins.nRight >= MAXIMUM_SIZE_IN_UNITS ||
+                sMargins.nBottom + sMargins.nTop >= MAXIMUM_SIZE_IN_UNITS )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Margins too big compared to maximum page dimension (%d) "
+                         "in user units allowed by Acrobat",
+                         MAXIMUM_SIZE_IN_UNITS);
+            }
+            else
+            {
+                if( dfWidthInUserUnit >= dfHeightInUserUnit )
+                {
+                    dfDPI = (int)(0.5 + (double)nWidth / (MAXIMUM_SIZE_IN_UNITS -
+                            (sMargins.nLeft + sMargins.nRight)) / USER_UNIT_IN_INCH);
+                }
+                else
+                {
+                    dfDPI = (int)(0.5 + (double)nHeight / (MAXIMUM_SIZE_IN_UNITS -
+                            (sMargins.nBottom + sMargins.nTop)) / USER_UNIT_IN_INCH);
+                }
+                CPLDebug("PDF", "Adjusting DPI to %d so that page dimension in "
+                        "user units remain in what is accepted by Acrobat", (int)dfDPI);
+            }
+        }
+        else
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "The page dimension in user units is %d x %d whereas the "
+                     "maximum allowed by Acrobat is %d x %d",
+                     (int)(dfWidthInUserUnit + 0.5),
+                     (int)(dfHeightInUserUnit + 0.5),
+                     MAXIMUM_SIZE_IN_UNITS, MAXIMUM_SIZE_IN_UNITS);
+        }
+    }
+
+    if (dfDPI < DEFAULT_DPI)
+        dfDPI = DEFAULT_DPI;
+
     const char* pszClippingExtent = CSLFetchNameValue(papszOptions, "CLIPPING_EXTENT");
     int bUseClippingExtent = FALSE;
     double adfClippingExtent[4] = { 0.0, 0.0, 0.0, 0.0 };
@@ -4677,7 +4728,7 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     else
     {
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
-        return (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+        return GDALPDFOpen(pszFilename, GA_ReadOnly);
 #else
         return new GDALFakePDFDataset();
 #endif
diff --git a/frmts/pdf/pdfcreatecopy.h b/frmts/pdf/pdfcreatecopy.h
index bb461aa..4bc0e17 100644
--- a/frmts/pdf/pdfcreatecopy.h
+++ b/frmts/pdf/pdfcreatecopy.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.h 25613 2013-02-07 19:33:31Z rouault $
+ * $Id: pdfcreatecopy.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/pdf/pdfdataset.cpp b/frmts/pdf/pdfdataset.cpp
index 199358e..8db8999 100644
--- a/frmts/pdf/pdfdataset.cpp
+++ b/frmts/pdf/pdfdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfdataset.cpp 26332 2013-08-15 15:25:30Z rouault $
+ * $Id: pdfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -51,11 +51,11 @@
 #include <set>
 #include <map>
 
-#define DEFAULT_DPI 150.0
+#define GDAL_DEFAULT_DPI 150.0
 
 /* g++ -fPIC -g -Wall frmts/pdf/pdfdataset.cpp -shared -o gdal_PDF.so -Iport -Igcore -Iogr -L. -lgdal -lpoppler -I/usr/include/poppler */
 
-CPL_CVSID("$Id: pdfdataset.cpp 26332 2013-08-15 15:25:30Z rouault $");
+CPL_CVSID("$Id: pdfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_PDF(void);
@@ -610,6 +610,7 @@ class PDFDataset : public GDALPamDataset
     virtual CPLErr      SetProjection(const char* pszWKTIn);
     virtual CPLErr      SetGeoTransform(double* padfGeoTransform);
 
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr      SetMetadata( char ** papszMetadata,
                                      const char * pszDomain = "" );
@@ -1329,7 +1330,7 @@ PDFDataset::PDFDataset()
 #endif
     poImageObj = NULL;
     pszWKT = NULL;
-    dfDPI = DEFAULT_DPI;
+    dfDPI = GDAL_DEFAULT_DPI;
     dfMaxArea = 0;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
@@ -1719,7 +1720,7 @@ int GDALPDFParseStreamContent(const char* pszContent,
     double adfVals[6];
     CPLString osCurrentImage;
 
-    double dfDPI = 72.0;
+    double dfDPI = DEFAULT_DPI;
     *pbDPISet = FALSE;
 
     while((ch = *pszContent) != '\0')
@@ -1821,8 +1822,8 @@ int GDALPDFParseStreamContent(const char* pszContent,
                                 double dfHeight = Get(poHeight);
                                 double dfScaleX = adfVals[0];
                                 double dfScaleY = adfVals[3];
-                                double dfDPI_X = ROUND_TO_INT_IF_CLOSE(dfWidth / dfScaleX * 72, 1e-3);
-                                double dfDPI_Y = ROUND_TO_INT_IF_CLOSE(dfHeight / dfScaleY * 72, 1e-3);
+                                double dfDPI_X = ROUND_TO_INT_IF_CLOSE(dfWidth / dfScaleX * DEFAULT_DPI, 1e-3);
+                                double dfDPI_Y = ROUND_TO_INT_IF_CLOSE(dfHeight / dfScaleY * DEFAULT_DPI, 1e-3);
                                 //CPLDebug("PDF", "Image %s, width = %.16g, height = %.16g, scaleX = %.16g, scaleY = %.16g --> DPI_X = %.16g, DPI_Y = %.16g",
                                 //                osCurrentImage.c_str(), dfWidth, dfHeight, dfScaleX, dfScaleY, dfDPI_X, dfDPI_Y);
                                 if (dfDPI_X > dfDPI) dfDPI = dfDPI_X;
@@ -1862,16 +1863,17 @@ int PDFDataset::CheckTiledRaster()
 {
     size_t i;
     int nBlockXSize = 0, nBlockYSize = 0;
+    const double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
 
     /* First pass : check that all tiles have same DPI, */
     /* are contained entirely in the raster size, */
     /* and determine the block size */
     for(i=0; i<asTiles.size(); i++)
     {
-        double dfDrawWidth = asTiles[i].adfCM[0] * dfDPI / 72.0;
-        double dfDrawHeight = asTiles[i].adfCM[3] * dfDPI / 72.0;
-        double dfX = asTiles[i].adfCM[4] * dfDPI / 72.0;
-        double dfY = asTiles[i].adfCM[5] * dfDPI / 72.0;
+        double dfDrawWidth = asTiles[i].adfCM[0] * dfUserUnit;
+        double dfDrawHeight = asTiles[i].adfCM[3] * dfUserUnit;
+        double dfX = asTiles[i].adfCM[4] * dfUserUnit;
+        double dfY = asTiles[i].adfCM[5] * dfUserUnit;
         int nX = (int)(dfX+0.1);
         int nY = (int)(dfY+0.1);
         int nWidth = (int)(asTiles[i].dfWidth + 1e-8);
@@ -1934,8 +1936,8 @@ int PDFDataset::CheckTiledRaster()
     /* Second pass to determine that all tiles are properly aligned on block size */
     for(i=0; i<asTiles.size(); i++)
     {
-        double dfX = asTiles[i].adfCM[4] * dfDPI / 72.0;
-        double dfY = asTiles[i].adfCM[5] * dfDPI / 72.0;
+        double dfX = asTiles[i].adfCM[4] * dfUserUnit;
+        double dfY = asTiles[i].adfCM[5] * dfUserUnit;
         int nX = (int)(dfX+0.1);
         int nY = (int)(dfY+0.1);
         int nWidth = (int)(asTiles[i].dfWidth + 1e-8);
@@ -1966,8 +1968,8 @@ int PDFDataset::CheckTiledRaster()
     aiTiles.resize(nXBlocks * nYBlocks, -1);
     for(i=0; i<asTiles.size(); i++)
     {
-        double dfX = asTiles[i].adfCM[4] * dfDPI / 72.0;
-        double dfY = asTiles[i].adfCM[5] * dfDPI / 72.0;
+        double dfX = asTiles[i].adfCM[4] * dfUserUnit;
+        double dfY = asTiles[i].adfCM[5] * dfUserUnit;
         int nHeight = (int)(asTiles[i].dfHeight + 1e-8);
         int nX = (int)(dfX+0.1);
         int nY = nRasterYSize - ((int)(dfY+0.1) + nHeight);
@@ -2215,7 +2217,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
               (poUserUnit->GetType() == PDFObjectType_Int ||
                poUserUnit->GetType() == PDFObjectType_Real) )
         {
-            dfDPI = ROUND_TO_INT_IF_CLOSE(Get(poUserUnit) * 72.0);
+            dfDPI = ROUND_TO_INT_IF_CLOSE(Get(poUserUnit) * DEFAULT_DPI);
             CPLDebug("PDF", "Found UserUnit in Page --> DPI = %.16g", dfDPI);
             SetMetadataItem("DPI", CPLSPrintf("%.16g", dfDPI));
         }
@@ -2225,7 +2227,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "Invalid value for GDAL_PDF_DPI. Using default value instead");
-        dfDPI = DEFAULT_DPI;
+        dfDPI = GDAL_DEFAULT_DPI;
     }
 }
 
@@ -3131,7 +3133,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 #endif
 
-    double dfUserUnit = poDS->dfDPI / 72.0;
+    double dfUserUnit = poDS->dfDPI * USER_UNIT_IN_INCH;
     poDS->nRasterXSize = (int) floor((dfX2 - dfX1) * dfUserUnit+0.5);
     poDS->nRasterYSize = (int) floor((dfY2 - dfY1) * dfUserUnit+0.5);
 
@@ -4975,6 +4977,17 @@ CPLErr PDFDataset::SetGeoTransform(double* padfGeoTransform)
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **PDFDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:XMP", "LAYERS_WITH_REF", "EMBEDDED_METADATA", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 
@@ -5200,7 +5213,6 @@ void GDALRegister_PDF()
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pdf" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                    "Byte" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 #ifdef HAVE_POPPLER
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
         poDriver->SetMetadataItem( "HAVE_POPPLER", "YES" );
@@ -5270,6 +5282,7 @@ void GDALRegister_PDF()
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
         poDriver->pfnOpen = PDFDataset::Open;
         poDriver->pfnIdentify = PDFDataset::Identify;
+        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 #endif
 
         poDriver->pfnCreateCopy = GDALPDFCreateCopy;
diff --git a/frmts/pdf/pdfdataset.h b/frmts/pdf/pdfdataset.h
index b32e42c..1518f70 100644
--- a/frmts/pdf/pdfdataset.h
+++ b/frmts/pdf/pdfdataset.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfdataset.h 24143 2012-03-19 21:40:42Z rouault $
+ * $Id: pdfdataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/pdf/pdfio.cpp b/frmts/pdf/pdfio.cpp
index 988ee83..94acd10 100644
--- a/frmts/pdf/pdfio.cpp
+++ b/frmts/pdf/pdfio.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: pdfio.cpp 25573 2013-01-27 11:09:45Z rouault $");
+CPL_CVSID("$Id: pdfio.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         VSIPDFFileStream()                           */
diff --git a/frmts/pdf/pdfio.h b/frmts/pdf/pdfio.h
index 33b2c40..ebedc57 100644
--- a/frmts/pdf/pdfio.h
+++ b/frmts/pdf/pdfio.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfio.h 25562 2013-01-26 18:36:03Z rouault $
+ * $Id: pdfio.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/pdf/pdfobject.cpp b/frmts/pdf/pdfobject.cpp
index 3b5c6e9..4a52a82 100644
--- a/frmts/pdf/pdfobject.cpp
+++ b/frmts/pdf/pdfobject.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfobject.cpp 25683 2013-02-25 14:51:41Z rouault $
+ * $Id: pdfobject.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include <vector>
 #include "pdfobject.h"
 
-CPL_CVSID("$Id: pdfobject.cpp 25683 2013-02-25 14:51:41Z rouault $");
+CPL_CVSID("$Id: pdfobject.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        ROUND_TO_INT_IF_CLOSE()                       */
diff --git a/frmts/pdf/pdfobject.h b/frmts/pdf/pdfobject.h
index 7891ac1..a1efe83 100644
--- a/frmts/pdf/pdfobject.h
+++ b/frmts/pdf/pdfobject.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: pdfobject.h 25536 2013-01-20 14:04:39Z rouault $
+ * $Id: pdfobject.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,6 +34,9 @@
 #include <map>
 #include <vector>
 
+#define DEFAULT_DPI         (72.0)
+#define USER_UNIT_IN_INCH   (1.0 / DEFAULT_DPI)
+
 #ifdef HAVE_POPPLER
 
 /* begin of poppler xpdf includes */
diff --git a/frmts/pds/isis2dataset.cpp b/frmts/pds/isis2dataset.cpp
index ff9b0b5..25a0ffc 100644
--- a/frmts/pds/isis2dataset.cpp
+++ b/frmts/pds/isis2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: isis2dataset.cpp 23371 2011-11-13 14:24:00Z rouault $
+ * $Id: isis2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ISIS Version 2 Driver
  * Purpose:  Implementation of ISIS2Dataset
@@ -14,6 +14,7 @@
  * diminish Trent and Roberts contribution. 
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,7 +50,7 @@
 #include "cpl_string.h" 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: isis2dataset.cpp 23371 2011-11-13 14:24:00Z rouault $");
+CPL_CVSID("$Id: isis2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_ISIS2(void);
diff --git a/frmts/pds/isis3dataset.cpp b/frmts/pds/isis3dataset.cpp
index 6a54027..0caef85 100644
--- a/frmts/pds/isis3dataset.cpp
+++ b/frmts/pds/isis3dataset.cpp
@@ -12,6 +12,7 @@
  * Trents contribution. 
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/pds/nasakeywordhandler.cpp b/frmts/pds/nasakeywordhandler.cpp
index 2df6ca7..baf1a07 100644
--- a/frmts/pds/nasakeywordhandler.cpp
+++ b/frmts/pds/nasakeywordhandler.cpp
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/pds/pdsdataset.cpp b/frmts/pds/pdsdataset.cpp
index d345262..89a166a 100644
--- a/frmts/pds/pdsdataset.cpp
+++ b/frmts/pds/pdsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdsdataset.cpp 25984 2013-05-05 12:20:31Z rouault $
+ * $Id: pdsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDS Driver; Planetary Data System Format
  * Purpose:  Implementation of PDSDataset
@@ -12,6 +12,7 @@
  * diminish Trent and Roberts contribution. 
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -46,7 +47,7 @@
 #include "cpl_string.h" 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: pdsdataset.cpp 25984 2013-05-05 12:20:31Z rouault $");
+CPL_CVSID("$Id: pdsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PDS(void);
diff --git a/frmts/pgchip/pgchipdataset.cpp b/frmts/pgchip/pgchipdataset.cpp
index 7da1f64..69c0b84 100644
--- a/frmts/pgchip/pgchipdataset.cpp
+++ b/frmts/pgchip/pgchipdataset.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Benjamin Simon, noumayoss at gmail.com
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/png/pngdataset.cpp b/frmts/png/pngdataset.cpp
index 72a6257..67e3a82 100644
--- a/frmts/png/pngdataset.cpp
+++ b/frmts/png/pngdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pngdataset.cpp 25571 2013-01-27 00:28:04Z rouault $
+ * $Id: pngdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PNG Driver
  * Purpose:  Implement GDAL PNG Support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,7 +50,7 @@
 #include "cpl_string.h"
 #include <setjmp.h>
 
-CPL_CVSID("$Id: pngdataset.cpp 25571 2013-01-27 00:28:04Z rouault $");
+CPL_CVSID("$Id: pngdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PNG(void);
@@ -123,6 +124,9 @@ class PNGDataset : public GDALPamDataset
     void        LoadWorldFile();
     CPLString   osWldFilename;
 
+    int         bHasReadICCMetadata;
+    void        LoadICCProfile();
+
   public:
                  PNGDataset();
                  ~PNGDataset();
@@ -140,7 +144,11 @@ class PNGDataset : public GDALPamDataset
     virtual CPLErr GetGeoTransform( double * );
     virtual void FlushCache( void );
 
+    virtual char      **GetMetadataDomainList();
+
     virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = NULL );
 
     // semi-private.
     jmp_buf     sSetJmpContext;
@@ -433,6 +441,7 @@ PNGDataset::PNGDataset()
 
     bHasTriedLoadWorldFile = FALSE;
     bHasReadXMPMetadata = FALSE;
+    bHasReadICCMetadata = FALSE;
 }
 
 /************************************************************************/
@@ -823,6 +832,106 @@ void PNGDataset::CollectXMPMetadata()
 }
 
 /************************************************************************/
+/*                           LoadICCProfile()                           */
+/************************************************************************/
+
+void PNGDataset::LoadICCProfile()
+{
+    if (hPNG == NULL || bHasReadICCMetadata)
+        return;
+    bHasReadICCMetadata = TRUE;
+
+    png_charp pszProfileName;
+    png_uint_32 nProfileLength;
+#if (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR > 4) || PNG_LIBPNG_VER_MAJOR > 1
+    png_bytep pProfileData;
+#else
+    png_charp pProfileData;
+#endif
+    int nCompressionType;
+    int nsRGBIntent;
+    double dfGamma;
+    bool bGammaAvailable = false;
+
+    /* Avoid setting the PAM dirty bit just for that */
+    int nOldPamFlags = nPamFlags;
+
+    if (png_get_iCCP(hPNG, psPNGInfo, &pszProfileName,
+       &nCompressionType, &pProfileData, &nProfileLength) != 0)
+    {
+        /* Escape the profile */
+        char *pszBase64Profile = CPLBase64Encode(nProfileLength, (const GByte*)pProfileData);
+
+        /* Set ICC profile metadata */
+        SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
+        SetMetadataItem( "SOURCE_ICC_PROFILE_NAME", pszProfileName, "COLOR_PROFILE" );
+
+        nPamFlags = nOldPamFlags;
+
+        CPLFree(pszBase64Profile);
+
+        return;
+    }
+
+    if (png_get_sRGB(hPNG, psPNGInfo, &nsRGBIntent) != 0)
+    {
+        SetMetadataItem( "SOURCE_ICC_PROFILE_NAME", "sRGB", "COLOR_PROFILE" );
+
+        nPamFlags = nOldPamFlags;
+
+        return;
+    }
+
+    if (png_get_valid(hPNG, psPNGInfo, PNG_INFO_gAMA))
+    {
+        bGammaAvailable = true;
+
+        png_get_gAMA(hPNG,psPNGInfo, &dfGamma);
+
+        SetMetadataItem( "PNG_GAMMA", 
+            CPLString().Printf( "%.9f", dfGamma ) , "COLOR_PROFILE" );
+    }
+
+    // Check if both cHRM and gAMA available
+    if (bGammaAvailable && png_get_valid(hPNG, psPNGInfo, PNG_INFO_cHRM))
+    {
+        double dfaWhitepoint[2];
+        double dfaCHR[6];
+
+        png_get_cHRM(hPNG, psPNGInfo,
+                    &dfaWhitepoint[0], &dfaWhitepoint[1],
+                    &dfaCHR[0], &dfaCHR[1],
+                    &dfaCHR[2], &dfaCHR[3],
+                    &dfaCHR[4], &dfaCHR[5]);
+
+        // Set all the colorimetric metadata.
+        SetMetadataItem( "SOURCE_PRIMARIES_RED", 
+            CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[0], dfaCHR[1] ) , "COLOR_PROFILE" );
+        SetMetadataItem( "SOURCE_PRIMARIES_GREEN", 
+            CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[2], dfaCHR[3] ) , "COLOR_PROFILE" );
+        SetMetadataItem( "SOURCE_PRIMARIES_BLUE", 
+            CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[4], dfaCHR[5] ) , "COLOR_PROFILE" );
+
+        SetMetadataItem( "SOURCE_WHITEPOINT", 
+            CPLString().Printf( "%.9f, %.9f, 1.0", dfaWhitepoint[0], dfaWhitepoint[1] ) , "COLOR_PROFILE" );
+
+    }
+
+    nPamFlags = nOldPamFlags;
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **PNGDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:XMP", "COLOR_PROFILE", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 
@@ -831,12 +940,27 @@ char  **PNGDataset::GetMetadata( const char * pszDomain )
     if (fpImage == NULL)
         return NULL;
     if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
-        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        pszDomain != NULL && EQUAL(pszDomain, "xml:XMP"))
         CollectXMPMetadata();
+    if (eAccess == GA_ReadOnly && !bHasReadICCMetadata &&
+        pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE"))
+        LoadICCProfile();
     return GDALPamDataset::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
+/*                       GetMetadataItem()                              */
+/************************************************************************/
+const char *PNGDataset::GetMetadataItem( const char * pszName,
+                                         const char * pszDomain )
+{
+    if (eAccess == GA_ReadOnly && !bHasReadICCMetadata &&
+        pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE"))
+        LoadICCProfile();
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
@@ -897,7 +1021,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
                                          NULL, NULL );
     if (poDS->hPNG == NULL)
     {
-#if LIBPNG_VER_MINOR >= 2 || LIBPNG_VER_MAJOR > 1
+#if (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 2) || PNG_LIBPNG_VER_MAJOR > 1
         int version = png_access_version_number();
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "The PNG driver failed to access libpng with version '%s',"
@@ -1340,6 +1464,136 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     
 /* -------------------------------------------------------------------- */
+/*      Copy colour profile data                                        */
+/* -------------------------------------------------------------------- */
+    const char *pszICCProfile = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
+    const char *pszICCProfileName = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE_NAME");
+    if (pszICCProfileName == NULL)
+        pszICCProfileName = poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE_NAME", "COLOR_PROFILE" );
+
+    if (pszICCProfile == NULL)
+        pszICCProfile = poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE", "COLOR_PROFILE" );
+
+    if ((pszICCProfileName != NULL) && EQUAL(pszICCProfileName, "sRGB"))
+    {
+        pszICCProfile = NULL;
+
+        png_set_sRGB(hPNG, psPNGInfo, PNG_sRGB_INTENT_PERCEPTUAL);
+    }
+
+    if (pszICCProfile != NULL)
+    {
+        char *pEmbedBuffer = CPLStrdup(pszICCProfile);
+        png_uint_32 nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+        const char* pszLocalICCProfileName = (pszICCProfileName!=NULL)?pszICCProfileName:"ICC Profile";
+
+        png_set_iCCP(hPNG, psPNGInfo,
+#if (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR > 4) || PNG_LIBPNG_VER_MAJOR > 1
+            pszLocalICCProfileName,
+#else
+            (png_charp)pszLocalICCProfileName,
+#endif
+            0,
+#if (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR > 4) || PNG_LIBPNG_VER_MAJOR > 1
+            (png_const_bytep)pEmbedBuffer,
+#else
+            (png_charp)pEmbedBuffer,
+#endif
+            nEmbedLen);
+
+        CPLFree(pEmbedBuffer);
+    }
+    else if ((pszICCProfileName == NULL) || !EQUAL(pszICCProfileName, "sRGB"))
+    {
+        // Output gamma, primaries and whitepoint
+        const char *pszGamma = CSLFetchNameValue(papszOptions, "PNG_GAMMA");
+        if (pszGamma == NULL)
+            pszGamma = poSrcDS->GetMetadataItem( "PNG_GAMMA", "COLOR_PROFILE" );
+
+        if (pszGamma != NULL)
+        {
+            double dfGamma = atof(pszGamma);
+            png_set_gAMA(hPNG, psPNGInfo, dfGamma);
+        }
+
+        const char *pszPrimariesRed = CSLFetchNameValue(papszOptions, "SOURCE_PRIMARIES_RED");
+        if (pszPrimariesRed == NULL)
+            pszPrimariesRed = poSrcDS->GetMetadataItem( "SOURCE_PRIMARIES_RED", "COLOR_PROFILE" );
+        const char *pszPrimariesGreen = CSLFetchNameValue(papszOptions, "SOURCE_PRIMARIES_GREEN");
+        if (pszPrimariesGreen == NULL)
+            pszPrimariesGreen = poSrcDS->GetMetadataItem( "SOURCE_PRIMARIES_GREEN", "COLOR_PROFILE" );
+        const char *pszPrimariesBlue = CSLFetchNameValue(papszOptions, "SOURCE_PRIMARIES_BLUE");
+        if (pszPrimariesBlue == NULL)
+            pszPrimariesBlue = poSrcDS->GetMetadataItem( "SOURCE_PRIMARIES_BLUE", "COLOR_PROFILE" );
+        const char *pszWhitepoint = CSLFetchNameValue(papszOptions, "SOURCE_WHITEPOINT");
+        if (pszWhitepoint == NULL)
+            pszWhitepoint = poSrcDS->GetMetadataItem( "SOURCE_WHITEPOINT", "COLOR_PROFILE" );
+
+        if ((pszPrimariesRed != NULL) && (pszPrimariesGreen != NULL) && (pszPrimariesBlue != NULL) &&
+            (pszWhitepoint != NULL))
+        {
+            bool bOk = true;
+            double faColour[8];
+            char** apapszTokenList[4];
+
+            apapszTokenList[0] = CSLTokenizeString2( pszWhitepoint, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            apapszTokenList[1] = CSLTokenizeString2( pszPrimariesRed, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            apapszTokenList[2] = CSLTokenizeString2( pszPrimariesGreen, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            apapszTokenList[3] = CSLTokenizeString2( pszPrimariesBlue, ",", 
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+
+            if ((CSLCount( apapszTokenList[0] ) == 3) &&
+                (CSLCount( apapszTokenList[1] ) == 3) &&
+                (CSLCount( apapszTokenList[2] ) == 3) &&
+                (CSLCount( apapszTokenList[3] ) == 3))
+            {
+                for( int i = 0; i < 4; i++ )
+                {
+                    for( int j = 0; j < 3; j++ )
+                    {
+                        double v = atof(apapszTokenList[i][j]);
+
+                        if (j == 2)
+                        {
+                            /* Last term of xyY colour must be 1.0 */
+                            if (v != 1.0)
+                            {
+                                bOk = false;
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            faColour[i*2 + j] = v;
+                        }
+                    }
+                    if (!bOk)
+                        break;
+                }
+
+                if (bOk)
+                {
+                    png_set_cHRM(hPNG, psPNGInfo, 
+                        faColour[0], faColour[1], 
+                        faColour[2], faColour[3], 
+                        faColour[4], faColour[5], 
+                        faColour[6], faColour[7]);
+
+                }
+            }
+
+            CSLDestroy( apapszTokenList[0] );
+            CSLDestroy( apapszTokenList[1] );
+            CSLDestroy( apapszTokenList[2] );
+            CSLDestroy( apapszTokenList[3] );
+        }
+
+    }
+    
+/* -------------------------------------------------------------------- */
 /*      Write palette if there is one.  Technically, I think it is      */
 /*      possible to write 16bit palettes for PNG, but we will omit      */
 /*      this for now.                                                   */
@@ -1467,20 +1721,23 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxilary pam information.         */
 /* -------------------------------------------------------------------- */
-    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
 
     /* If outputing to stdout, we can't reopen it, so we'll return */
     /* a fake dataset to make the caller happy */
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    PNGDataset *poDS = (PNGDataset*) PNGDataset::Open( &oOpenInfo );
-    CPLPopErrorHandler();
-    if( poDS )
+    if( CSLTestBoolean(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
     {
-        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
-        return poDS;
-    }
+        GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
 
-    CPLErrorReset();
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        PNGDataset *poDS = (PNGDataset*) PNGDataset::Open( &oOpenInfo );
+        CPLPopErrorHandler();
+        if( poDS )
+        {
+            poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+            return poDS;
+        }
+        CPLErrorReset();
+    }
 
     PNGDataset* poPNG_DS = new PNGDataset();
     poPNG_DS->nRasterXSize = nXSize;
@@ -1591,7 +1848,14 @@ void GDALRegister_PNG()
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
 "<CreationOptionList>\n"
 "   <Option name='WORLDFILE' type='boolean' description='Create world file'/>\n"
-"   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>"
+"   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>\n"
+"   <Option name='SOURCE_ICC_PROFILE' type='string' description='ICC Profile'/>\n"
+"   <Option name='SOURCE_ICC_PROFILE_NAME' type='string' descriptor='ICC Profile name'/>\n"
+"   <Option name='SOURCE_PRIMARIES_RED' type='string' description='x,y,1.0 (xyY) red chromaticity'/>\n"
+"   <Option name='SOURCE_PRIMARIES_GREEN' type='string' description='x,y,1.0 (xyY) green chromaticity'/>\n"
+"   <Option name='SOURCE_PRIMARIES_BLUE' type='string' description='x,y,1.0 (xyY) blue chromaticity'/>\n"
+"   <Option name='SOURCE_WHITEPOINT' type='string' description='x,y,1.0 (xyY) whitepoint'/>\n"
+"   <Option name='PNG_GAMMA' type='string' description='Gamma'/>\n"
 "</CreationOptionList>\n" );
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
diff --git a/frmts/postgisraster/GNUmakefile b/frmts/postgisraster/GNUmakefile
index 5dace85..02ebd7c 100644
--- a/frmts/postgisraster/GNUmakefile
+++ b/frmts/postgisraster/GNUmakefile
@@ -4,7 +4,7 @@
 
 include ../../GDALmake.opt
 
-OBJ	=	postgisrasterdriver.o postgisrasterdataset.o postgisrasterrasterband.o
+OBJ	=	postgisrasterdriver.o postgisrasterdataset.o postgisrasterrasterband.o postgisrastertiledataset.o postgisrastertilerasterband.o postgisrastertools.o
 
 
 CPPFLAGS	:= -I ../mem -I ../vrt $(XTRA_OPT) $(PG_INC) $(GDAL_INCLUDE) $(CPPFLAGS)
diff --git a/frmts/postgisraster/makefile.vc b/frmts/postgisraster/makefile.vc
index e279186..4f3c63f 100644
--- a/frmts/postgisraster/makefile.vc
+++ b/frmts/postgisraster/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	postgisrasterdataset.obj postgisrasterrasterband.obj postgisrasterdriver.obj
+OBJ	=	postgisrasterdataset.obj postgisrasterrasterband.obj postgisrasterdriver.obj postgisrastertiledataset.obj postgisrastertilerasterband.obj postgisrastertools.obj
 
 EXTRAFLAGS = -I ../mem -I ../vrt -I$(PG_INC_DIR)
 
diff --git a/frmts/postgisraster/postgisraster.h b/frmts/postgisraster/postgisraster.h
index b384185..7557d84 100644
--- a/frmts/postgisraster/postgisraster.h
+++ b/frmts/postgisraster/postgisraster.h
@@ -1,72 +1,80 @@
-/******************************************************************************
+/***********************************************************************
  * File :    postgisraster.h
  * Project:  PostGIS Raster driver
  * Purpose:  Main header file for PostGIS Raster Driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ * 							jorgearevalo at libregis.org
+ * 
+ * Author:	 David Zwarg, dzwarg at azavea.com
  *
  * Last changes: $Id: $
  *
- ******************************************************************************
- * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo at deimos-space.com
+ ***********************************************************************
+ * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
+ * Copyright (c) 2013, Even Rouault
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the 
+ * "Software"),to deal in the Software without restriction, including 
+ * without limitation the rights to use, copy, modify, merge, publish, 
+ * distribute, sublicense, and/or sell copies of the Software, and to 
+ * permit persons to whom the Software is furnished to do so, subject to 
+ * the following conditions:
  *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************/
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ **********************************************************************/
+
+#ifndef POSTGISRASTER_H_INCLUDED
+#define POSTGISRASTER_H_INCLUDED
+
 #include "gdal_priv.h"
 #include "libpq-fe.h"
+#include "vrtdataset.h"
+#include "cpl_quad_tree.h"
 #include <float.h>
-//#include "liblwgeom.h"
+#include <map>
 
-// General defines
+//#define DEBUG_VERBOSE
+//#define DEBUG_QUERY
 
-#define DEFAULT_HOST            "localhost"
-#define DEFAULT_PORT            "5432"
-#define DEFAULT_SCHEMA          "public"
-#define DEFAULT_COLUMN          "rast"
-#define DEFAULT_USER            "postgres"
-#define DEFAULT_PASSWORD        "postgres"
+#if defined(DEBUG_VERBOSE) && !defined(DEBUG_QUERY)
+#define DEBUG_QUERY
+#endif
+
+/**
+ * The block size for the cache will be the minimum between the tile
+ * size from sources and this value. So, please keep it at 2048 or
+ * lower
+ **/
+#define MAX_BLOCK_SIZE	2048
 
-#define DEFAULT_BLOCK_X_SIZE    256
-#define DEFAULT_BLOCK_Y_SIZE    256
 
+#define NO_VALID_RES "-1234.56"
 
+/**
+ * To move over the data return by queries
+ **/
 #define POSTGIS_RASTER_VERSION         (GUInt16)0
 #define RASTER_HEADER_SIZE              61
 #define RASTER_BAND_HEADER_FIXED_SIZE   1
 
 #define BAND_SIZE(nodatasize, datasize) \
-        (RASTER_BAND_HEADER_FIXED_SIZE + nodatasize + datasize)
+        (RASTER_BAND_HEADER_FIXED_SIZE + (nodatasize) + (datasize))
 
 #define GET_BAND_DATA(raster, nband, nodatasize, datasize) \
-    (raster + RASTER_HEADER_SIZE + nband * BAND_SIZE(nodatasize, datasize) - datasize)
-
-#define FLT_NEQ(x, y) (fabs(x - y) > FLT_EPSILON)
-#define FLT_EQ(x, y) (fabs(x - y) <= FLT_EPSILON)
-
-
-/* Working modes */
-#define NO_MODE -999
-#define ONE_RASTER_PER_ROW 1
-#define ONE_RASTER_PER_TABLE 2
-#define BROWSE_SCHEMA 3
-#define BROWSE_DATABASE 4
+    ((raster) + RASTER_HEADER_SIZE + (nband) * BAND_SIZE(nodatasize, datasize) - (datasize))
+    
 
-/* Easily working with georef arrays (taken from gdalbuiltvrt.cpp) */
 #define GEOTRSFRM_TOPLEFT_X            0
 #define GEOTRSFRM_WE_RES               1
 #define GEOTRSFRM_ROTATION_PARAM1      2
@@ -74,123 +82,319 @@
 #define GEOTRSFRM_ROTATION_PARAM2      4
 #define GEOTRSFRM_NS_RES               5
 
-/* Taken from gdalbuiltvrt.cpp */
+// Number of results return by ST_Metadata PostGIS function
+#define ELEMENTS_OF_METADATA_RECORD 10
+
+// Positions of elements of ST_Metadata PostGIS function
+#define POS_UPPERLEFTX	    0
+#define POS_UPPERLEFTY      1
+#define POS_WIDTH           2
+#define POS_HEIGHT          3
+#define POS_SCALEX          4
+#define POS_SCALEY          5
+#define POS_SKEWX           6
+#define POS_SKEWY           7
+#define POS_SRID            8
+#define POS_NBANDS          9
+
+// Number of results return by ST_BandMetadata PostGIS function
+#define ELEMENTS_OF_BAND_METADATA_RECORD 4
+
+// Positions of elements of ST_BandMetadata PostGIS function
+#define POS_PIXELTYPE       0
+#define POS_NODATAVALUE     1
+#define POS_ISOUTDB         2
+#define POS_PATH            3
+
 typedef enum
 {
     LOWEST_RESOLUTION,
     HIGHEST_RESOLUTION,
     AVERAGE_RESOLUTION,
-    USER_RESOLUTION
+    USER_RESOLUTION,
+    AVERAGE_APPROX_RESOLUTION
 } ResolutionStrategy;
 
+
 /**
- * OPTIMIZATION:
- * To construct the mosaic of tiles, we should check the pixel size of all tiles, 
- * in order to determine the dataset's pixel size. This can be really heavy. So, 
- * we define this number as the number of tiles that will be taken into account to
- * do it. If set to 0, all the tiles are taken
- **/ 
-#define MAX_TILES   3 
+ * The driver can work in these modes:
+ * - NO_MODE: Error case
+ * - ONE_RASTER_PER_ROW: Each row of the requested table is considered
+ * 	 	as a separated raster object. This is the default mode, if
+ * 		database and table name are provided, and no mode is specified.
+ * - ONE_RASTER_PER_TABLE: All the rows of the requested table are
+ * 		considered as tiles of a bigger raster coverage (the whole
+ * 		table). If database and table name are specified and mode = 2
+ * 		is present in the connection string, this is the selected mode.
+ * - BROWSE_SCHEMA: If no table name is speficied, just database and
+ * 		schema names, the driver will yell of the schema's raster tables
+ * 		as possible datasets.
+ * - BROWSE_DATABASE: If no table name is specified, just database name,
+ * 		the driver will yell of the database's raster tables as possible 
+ * 		datasets.
+ **/
+typedef enum
+{
+	NO_MODE,
+	ONE_RASTER_PER_ROW,
+	ONE_RASTER_PER_TABLE,
+	BROWSE_SCHEMA,
+	BROWSE_DATABASE
+} WorkingMode;
+
+/**
+ * Important metadata of a PostGIS Raster band
+ **/
+typedef struct {
+    GDALDataType eDataType;
+    int nBitsDepth;
+    GBool bSignedByte;
+    GBool bHasNoDataValue;
+    GBool bIsOffline;
+    char * path;
+    double dfNoDataValue;
+} BandMetadata;
+
+typedef struct {
+	char * pszSchema;
+	char * pszTable;
+	char * pszColumn;
+	int nFactor;
+} PROverview;
+
+
+// Some tools definitions
+char * ReplaceQuotes(const char *, int);
+char * ReplaceSingleQuotes(const char *, int);
+char ** ParseConnectionString(const char *);
+GBool TranslateDataType(const char *, GDALDataType *, int *, GBool *);
+        
 
 class PostGISRasterRasterBand;
+class PostGISRasterTileDataset;
 
-/*****************************************************************************
- * PostGISRasterDriver: extends GDALDriver to support PostGIS Raster connect.
- *****************************************************************************/
+/***********************************************************************
+ * PostGISRasterDriver: extends GDALDriver to support PostGIS Raster 
+ * connect.
+ **********************************************************************/
 class PostGISRasterDriver : public GDALDriver {
-    friend class PostGISRasterDataset;
 
 private:
-    PGconn** papoConnection;
-    int nRefCount;
+    void* hMutex;
+    std::map<CPLString, PGconn*> oMapConnection;
 public:
     PostGISRasterDriver();
     virtual ~PostGISRasterDriver();
-    PGconn* GetConnection(const char *, const char *, const char *,
-            const char *, const char *);
+    PGconn* GetConnection(const char* pszConnectionString,
+        const char * pszDbnameIn, const char * pszHostIn, const char * pszPortIn, const char * pszUserIn);
 };
 
-/******************************************************************************
- * PostGISRasterDataset: extends GDALDataset to support PostGIS Raster datasets
- *****************************************************************************/
-class PostGISRasterDataset : public GDALDataset {
+
+/***********************************************************************
+ * PostGISRasterDataset: extends VRTDataset to support PostGIS Raster 
+ * datasets
+ **********************************************************************/
+class PostGISRasterDataset : public VRTDataset {
     friend class PostGISRasterRasterBand;
+    friend class PostGISRasterTileRasterBand;
 private:
-    char* pszOriginalConnectionString;
     char** papszSubdatasets;
     double adfGeoTransform[6];
     int nSrid;
+    int nOverviewFactor;
+    int nBandsToCreate;
     PGconn* poConn;
     GBool bRegularBlocking;
-    GBool bAllTilesSnapToSameGrid;  // TODO: future use?
-    GBool bRegisteredInRasterColumns;// TODO: future use?
+    GBool bAllTilesSnapToSameGrid;
+    GBool bCheckAllTiles;
     char* pszSchema;
     char* pszTable;
     char* pszColumn;
     char* pszWhere;
+    char * pszPrimaryKeyName;
+    GBool  bIsFastPK;
+    int bHasTriedFetchingPrimaryKeyName;
     char* pszProjection;
     ResolutionStrategy resolutionStrategy;
-    int nMode;
+    WorkingMode nMode;
     int nTiles;
     double xmin, ymin, xmax, ymax;
-    GBool bBlocksCached;// TODO: future use?
+    PostGISRasterTileDataset ** papoSourcesHolders;
+    CPLQuadTree * hQuadTree;
+
+    GBool bHasBuiltOverviews;
+    int nOverviewCount;
+    PostGISRasterDataset* poParentDS;
+    PostGISRasterDataset** papoOverviewDS;
+    
+    std::map<CPLString, PostGISRasterTileDataset*> oMapPKIDToRTDS;
+
+    GBool bAssumeMultiBandReadPattern;
+    int nNextExpectedBand;
+    int nXOffPrev;
+    int nYOffPrev;
+    int nXSizePrev;
+    int nYSizePrev;
+
+    GBool bHasTriedHasSpatialIndex;
+    GBool bHasSpatialIndex;
+    
+    GBool bBuildQuadTreeDynamically;
+
+    GBool bTilesSameDimension;
+    int nTileWidth;
+    int nTileHeight;
+
+    GBool ConstructOneDatasetFromTiles(PGresult *);
+    GBool YieldSubdatasets(PGresult *, const char *);
     GBool SetRasterProperties(const char *);
-    GBool BrowseDatabase(const char *, char *);
-    GBool SetOverviewCount();
-    GBool GetRasterMetadata(char *, double, double, double *, double *, int *, int *);
+    GBool BrowseDatabase(const char *, const char *);
+    GBool AddComplexSource(PostGISRasterTileDataset* poRTDS);
+    GBool GetDstWin(PostGISRasterTileDataset *, int *, int *, int *, 
+		int *);
+    BandMetadata * GetBandsMetadata(int *);
+    PROverview * GetOverviewTables(int *);
+    
+    PostGISRasterTileDataset* BuildRasterTileDataset(const char* pszMetadata,
+                                                     const char* pszPKID,
+                                                     int nBandsFetched,
+                                                     BandMetadata * poBandMetaData);
+    void UpdateGlobalResolutionWithTileResolution(double tilePixelSizeX,
+                                                  double tilePixelSizeY);
+    void BuildOverviews();
+    void BuildBands(BandMetadata * poBandMetaData, int nBandsFetched);
+
+    PostGISRasterTileDataset * GetMatchingSourceRef(const char * pszPKID) { return oMapPKIDToRTDS[pszPKID]; }
+    PostGISRasterTileDataset * GetMatchingSourceRef(double dfUpperLeftX, double dfUpperLeftY);
+
+  protected:
+    virtual int         CloseDependentDatasets();
 
 public:
-    PostGISRasterDataset(ResolutionStrategy inResolutionStrategy = AVERAGE_RESOLUTION);
+    PostGISRasterDataset();
     virtual ~PostGISRasterDataset();
     static GDALDataset* Open(GDALOpenInfo *);
+    static int Identify(GDALOpenInfo *);
     static GDALDataset* CreateCopy(const char *, GDALDataset *, 
         int, char **, GDALProgressFunc, void *);
     static GBool InsertRaster(PGconn *, PostGISRasterDataset *, 
         const char *, const char *, const char *);
     static CPLErr Delete(const char*);
+    virtual char      **GetMetadataDomainList();
     char ** GetMetadata(const char *);
     const char* GetProjectionRef();
     CPLErr SetProjection(const char*);
     CPLErr SetGeoTransform(double *);
     CPLErr GetGeoTransform(double *);
+    char **GetFileList();
+
+    int    GetOverviewCount();
+    PostGISRasterDataset* GetOverviewDS(int iOvr);
+
+    const char * GetPrimaryKeyRef();
+    GBool HasSpatialIndex();
+    GBool LoadSources(int nXOff, int nYOff, int nXSize, int nYSize, int nBand);
+    GBool PolygonFromCoords(int nXOff, int nYOff, int nXEndOff, 
+        int nYEndOff,double adfProjWin[8]);
+    void CacheTile(const char* pszMetadata, const char* pszRaster, const char *pszPKID, int nBand, int bAllBandCaching);
 };
 
-/******************************************************************************
- * PostGISRasterRasterBand: extends GDALRasterBand to support PostGIS Raster bands
- ******************************************************************************/
-class PostGISRasterRasterBand : public GDALRasterBand {
+/***********************************************************************
+ * PostGISRasterRasterBand: extends VRTSourcedRasterBand to support 
+ * PostGIS Raster bands
+ **********************************************************************/
+class PostGISRasterTileRasterBand;
+ 
+class PostGISRasterRasterBand : public VRTSourcedRasterBand {
     friend class PostGISRasterDataset;
-private:
-    GBool bHasNoDataValue;
-    double dfNoDataValue;
-    int nOverviewFactor;
+protected:
     GBool bIsOffline;
-    int nOverviewCount; 
-    char* pszSchema;
-    char* pszTable;
-    char* pszColumn;
-    PostGISRasterRasterBand ** papoOverviews;
-    GDALDataType TranslateDataType(const char *);
-    GDALColorInterp eBandInterp;
+    const char* pszSchema;
+    const char* pszTable;
+    const char* pszColumn;
+
+#ifdef notdef
+    GBool GetBandMetadata(GDALDataType *, GBool *, double *);
+    void NullBlock(void *);
+#endif
 
+    void                      NullBuffer(void* pData,
+                                         int nBufXSize,
+                                         int nBufYSize,
+                                         GDALDataType eBufType, 
+                                         int nPixelSpace,
+                                         int nLineSpace);
 public:
 
-    PostGISRasterRasterBand(PostGISRasterDataset *poDS, int nBand, GDALDataType hDataType,
-            GBool bHasNoDataValue, double dfNodata, GBool bSignedByte, int nBitDepth, int nFactor,
-            int nBlockXSize, int nBlockYSize, GBool bIsOffline = false, char * inPszSchema = NULL,
-            char * inPszTable = NULL, char * inPszColumn = NULL);
+    PostGISRasterRasterBand(PostGISRasterDataset *, int ,
+		GDALDataType, GBool, double, GBool);
 
     virtual ~PostGISRasterRasterBand();
 
     virtual double GetNoDataValue(int *pbSuccess = NULL);
     virtual CPLErr SetNoDataValue(double);
-    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int, GDALDataType, 
-        int, int);
+    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, 
+		int, int, GDALDataType, int, int);
+#ifdef notdef
     virtual CPLErr IReadBlock(int, int, void *);
-    int GetBand();
-    GDALDataset* GetDataset();
+#endif
     virtual int GetOverviewCount();
     virtual GDALRasterBand * GetOverview(int);
     virtual GDALColorInterp GetColorInterpretation();
+
+    virtual double GetMinimum( int *pbSuccess );
+    virtual double GetMaximum( int *pbSuccess );
+    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax );
+};
+
+
+
+/***********************************************************************
+ * PostGISRasterTileDataset: it holds just a raster tile
+ **********************************************************************/
+class PostGISRasterTileRasterBand;
+
+class PostGISRasterTileDataset : public GDALDataset {
+	friend class PostGISRasterDataset;
+	friend class PostGISRasterRasterBand;
+	friend class PostGISRasterTileRasterBand;
+private:
+    PostGISRasterDataset* poRDS;
+    char * pszPKID;
+    double adfGeoTransform[6];
+
+public:
+	PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
+                             int nXSize, 
+                             int nYSize);
+	~PostGISRasterTileDataset();
+    CPLErr GetGeoTransform(double *);
+    void   GetExtent(double* pdfMinX, double* pdfMinY, double* pdfMaxX, double* pdfMaxY);
+    const char* GetPKID() const { return pszPKID; }
+};
+
+/***********************************************************************
+ * PostGISRasterTileRasterBand: it holds a raster tile band, that will 
+ * be used as a source for PostGISRasterRasterBand
+ **********************************************************************/
+class PostGISRasterTileRasterBand : public GDALRasterBand {
+	friend class PostGISRasterRasterBand;
+    friend class PostGISRasterDataset;
+private:
+    GBool bIsOffline;
+
+    GBool IsCached();
+    
+    VRTSource* poSource;
+	
+	
+public:
+	PostGISRasterTileRasterBand(
+        PostGISRasterTileDataset * poRTDS, int nBand,
+        GDALDataType eDataType,
+        GBool bIsOffline = false);
+	~PostGISRasterTileRasterBand();
+	virtual CPLErr IReadBlock(int, int, void *);
 };
 
+#endif // POSTGISRASTER_H_INCLUDED
diff --git a/frmts/postgisraster/postgisrasterdataset.cpp b/frmts/postgisraster/postgisrasterdataset.cpp
index da3ad3f..696984f 100644
--- a/frmts/postgisraster/postgisrasterdataset.cpp
+++ b/frmts/postgisraster/postgisrasterdataset.cpp
@@ -1,99 +1,214 @@
-/*************************************************************************
+/***********************************************************************
  * File :    postgisrasterdataset.cpp
  * Project:  PostGIS Raster driver
  * Purpose:  GDAL Dataset implementation for PostGIS Raster driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ *                          jorgearevalo at libregis.org
+ * 
+ * Author:	 David Zwarg, dzwarg at azavea.com
  *
- * Last changes:
- * $Id:$
+ * Last changes: $Id: $
  *
- ************************************************************************
- * Copyright (c) 2009 - 2011, Jorge Arevalo, jorge.arevalo at deimos-space.com
+ ***********************************************************************
+ * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ************************************************************************/
-
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ **********************************************************************/
 #include "postgisraster.h"
-#include <stdlib.h>
-#include "gdal.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "gdal_priv.h"
 #include <math.h>
-#include "cpl_error.h"
-#include "ogr_core.h"
-
-#ifdef OGR_ENABLED
-#include "ogr_api.h"
-#endif
-
-#include "ogr_geometry.h"
-#include "gdal_vrt.h"
-#include "vrtdataset.h"
-#include "memdataset.h"
 
 #ifdef _WIN32
 #define rint(x) floor((x) + 0.5)
 #endif
 
+/* PostgreSQL defaults */
+#define DEFAULT_SCHEMA          "public"
+#define DEFAULT_COLUMN          "rast"
+
 
 CPL_C_START
 void GDALRegister_PostGISRaster(void);
 CPL_C_END
 
+/** Note on read performance on mode=2:
+
+    There are different situations:
+
+     1) the table is registered in the raster_columns table and number of bands, minx,miny,maxx,maxy are available
+        a) no where clause, the table has a primary key and a GIST index on the raster column.
+            If the raster_columns advertize a scale_x and scale_y, use it.
+            Otherwise take the metadata of 10 rasters and compute and average scale_x, scale_y
+            With above information, we can build the dataset definition.
+
+            (Following logic is implemented in LoadSources())
+
+            During a IRasterIO() query,
+            i) we will do a SQL query to retrieve the PKID of tiles that intersect the query window.
+            ii) If some tiles are not registered as sources, then do a SQL query to fetch their metadata
+            and instanciate them and register them.
+            iii) If some tiles are not cached, then determine if the query window is not too big (w.r.t. GDAL cache),
+            and if not, then do a SQL query to fetch their raster column.
+
+            Note: if raster_columns show that all tiles have same dimensions, we can merge the query ii) and iii)
+            in the same one.
+
+        b) otherwise, do a full scan of metadata to build the sources
+
+     2) otherwise, throw a warning to the user and do a full scan of metadata is needed to build the sources
+
+     For 1b) and 2), during a IRasterIO() query, determine which sources are needed and not cached.
+
+        (Following logic is implemented in IRasterIO())
+
+        If the query window is not too big,
+            If there's a primary key, then do a SQL query on the IDs of uncached sources to fetch their raster column
+            and cache them.
+            Otherwise if there's a GIST index, do a SQL spatial query on the window to fetch their raster column,
+            and cache them (identification with registered sources is done with the top-left coordinates)
+            Otherwise do a SQL query based on the range of top-left coordinates of tiles that intersect the query window.
 
+     Conclusion: best performance is achieved with: no where clause, a primary key, a GIST index, known table extent
+                 and, with moderate performance advantage :
+                  - same scale_x, scale_y to save an initial SQL query,
+                  - same blocksize_x, blocksize_y to save one SQL query per IRasterIO()
+*/
 
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterDataset::PostGISRasterDataset(ResolutionStrategy inResolutionStrategy) {
-    pszOriginalConnectionString = NULL;
+PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
+
     papszSubdatasets = NULL;
     nSrid = -1;
+    nOverviewFactor = 1;
+    nBandsToCreate = 0;
     poConn = NULL;
-    bRegisteredInRasterColumns = false;
+    bRegularBlocking = false;
+    bAllTilesSnapToSameGrid = false;
+    
+    
+    bCheckAllTiles = CSLTestBoolean( 
+        CPLGetConfigOption("PR_ALLOW_WHOLE_TABLE_SCAN", "YES"));
+    
     pszSchema = NULL;
     pszTable = NULL;
     pszColumn = NULL;
     pszWhere = NULL;
     pszProjection = NULL;
-    resolutionStrategy = inResolutionStrategy;
-    nTiles = 0;
-    nMode = NO_MODE;
-    poDriver = NULL;
+    
     adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0.0;
-    adfGeoTransform[GEOTRSFRM_WE_RES] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
     adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
-    adfGeoTransform[GEOTRSFRM_NS_RES] = 0.0;
-    bBlocksCached = false;
-    bRegularBlocking = true;// do not change! (need to be 'true' for SetRasterProperties)
-    bAllTilesSnapToSameGrid = false;
+    adfGeoTransform[GEOTRSFRM_WE_RES] = 0;
+    adfGeoTransform[GEOTRSFRM_NS_RES] = 0;
+    
+    adfGeoTransform[GEOTRSFRM_WE_RES] =
+        CPLAtof(CPLGetConfigOption("PR_WE_RES", NO_VALID_RES));
+        
+    adfGeoTransform[GEOTRSFRM_NS_RES] =
+        CPLAtof(CPLGetConfigOption("PR_NS_RES", NO_VALID_RES));
+    
+    // Default
+    resolutionStrategy = AVERAGE_APPROX_RESOLUTION;
+    
+    const char * pszTmp = NULL;
+    // We ignore this option if we provided the desired resolution
+    if (CPLIsEqual(adfGeoTransform[GEOTRSFRM_WE_RES], CPLAtof(NO_VALID_RES)) ||
+        CPLIsEqual(adfGeoTransform[GEOTRSFRM_NS_RES], CPLAtof(NO_VALID_RES))) {
+            
+        // Resolution didn't have a valid value, so, we initiate it
+        adfGeoTransform[GEOTRSFRM_WE_RES] = 0.0;
+        adfGeoTransform[GEOTRSFRM_NS_RES] = 0.0;
+        
+        pszTmp = 
+            CPLGetConfigOption("PR_RESOLUTION_STRATEGY", "AVERAGE_APPROX");
+            
+        if (EQUAL(pszTmp, "LOWEST"))
+            resolutionStrategy = LOWEST_RESOLUTION;
+            
+        else if (EQUAL(pszTmp, "HIGHEST"))
+            resolutionStrategy = HIGHEST_RESOLUTION;
+            
+        else if (EQUAL(pszTmp, "USER"))
+            resolutionStrategy = USER_RESOLUTION;
+        
+        else if (EQUAL(pszTmp, "AVERAGE"))
+            resolutionStrategy = AVERAGE_RESOLUTION;
+    
+    }
+    
+    else {
+        resolutionStrategy = USER_RESOLUTION;
+        pszTmp = "USER";
+    }
+    
+#ifdef DEBUG_VERBOSE
+     CPLDebug("PostGIS_Raster", "PostGISRasterDataset::Constructor:"
+                "STRATEGY = %s", pszTmp);
+#endif
+
+    nTiles = 0;
+    nMode = NO_MODE;
+    poDriver = NULL;
+    
+    nRasterXSize = nRasterYSize = 0;
+    pszPrimaryKeyName = NULL;
+    bIsFastPK = false;
+    bHasTriedFetchingPrimaryKeyName = false;
+    
+    papoSourcesHolders = NULL;
+    hQuadTree = NULL;
+    
+    bHasBuiltOverviews = false;
+    nOverviewCount = 0;
+    papoOverviewDS = NULL;
+    poParentDS = NULL;
+    
+    bAssumeMultiBandReadPattern = true;
+    nNextExpectedBand = 1;
+    nXOffPrev = 0;
+    nYOffPrev = 0;
+    nXSizePrev = 0;
+    nYSizePrev = 0;
+    
+    bHasTriedHasSpatialIndex = false;
+    bHasSpatialIndex = false;
+    
+    bBuildQuadTreeDynamically = false;
+
+    bTilesSameDimension = false;
+    nTileWidth = 0;
+    nTileHeight = 0;
+
+    SetWritable(false);
+
 
     /**
      * TODO: Parametrize bAllTilesSnapToSameGrid. It controls if all the
-     * raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to test if
-     * they snap to the same grid and have the same srid. It can be the user
-     * decission, if he/she's sure all the rows pass the test and want more
-     * speed.
+     * raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to 
+     * test if they snap to the same grid and have the same srid. It can 
+     * be the user decission, if he/she's sure all the rows pass the 
+     * test and want more speed.
      **/
 
 }
@@ -103,122 +218,272 @@ PostGISRasterDataset::PostGISRasterDataset(ResolutionStrategy inResolutionStrate
  ************************/
 PostGISRasterDataset::~PostGISRasterDataset() {
 
-    if (pszSchema)
+    if (pszSchema) {
         CPLFree(pszSchema);
-    if (pszTable)
+        pszSchema = NULL;
+    }
+    
+    if (pszTable) {
         CPLFree(pszTable);
-    if (pszColumn)
+        pszTable = NULL;
+    }
+    
+    if (pszColumn) {
         CPLFree(pszColumn);
-    if (pszWhere)
+        pszColumn = NULL;
+    }
+    
+    if (pszWhere) {
         CPLFree(pszWhere);
-    if (pszProjection)
+        pszWhere = NULL;
+    }
+    
+    if (pszProjection) {
         CPLFree(pszProjection);
-    if (pszOriginalConnectionString)
-        CPLFree(pszOriginalConnectionString);
+        pszProjection = NULL;
+    }
+
+    if (pszPrimaryKeyName) {
+        CPLFree(pszPrimaryKeyName);
+        pszPrimaryKeyName = NULL;
+    }
 
-    if (papszSubdatasets)
+    if (papszSubdatasets) {
         CSLDestroy(papszSubdatasets);
+        papszSubdatasets = NULL;
+    }
+        
+    if (hQuadTree) {
+        CPLQuadTreeDestroy(hQuadTree);
+        hQuadTree = NULL;
+    }
+    
+    // Call it now so that the VRT sources
+    // are deleted and that there is no longer any code
+    // referencing the bands of the source holders.
+    // Otherwise this would go wrong because
+    // of the deleting the source holders just below.
+    CloseDependentDatasets();
+
+    if (papoSourcesHolders) {
+        int i;
+        for(i = 0; i < nTiles; i++) {
+            if (papoSourcesHolders[i])
+                delete papoSourcesHolders[i];
+            
+        }
+        
+        VSIFree(papoSourcesHolders);
+        papoSourcesHolders = NULL;
+    }
 }
 
-/**************************************************************
- * \brief Replace the single quotes by " in the input string
- *
- * Needed before tokenize function
- *************************************************************/
-static
-char * ReplaceSingleQuotes(const char * pszInput, int nLength) {
-    int i;
-    char* pszOutput = NULL;
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
 
-    if (nLength == -1)
-        nLength = strlen(pszInput);
+int PostGISRasterDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = VRTDataset::CloseDependentDatasets();
+    if( nOverviewCount > 0 )
+    {
+        int i;
+        for(i = 0; i < nOverviewCount; i++)
+        {
+            delete papoOverviewDS[i];
+        }
+        CPLFree(papoOverviewDS);
+        papoOverviewDS = NULL;
+        nOverviewCount = 0;
+        bHasDroppedRef = TRUE;
+    }
+    
+    return bHasDroppedRef;
+}
 
-    pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
+/************************************************************************/
+/*                            HasSpatialIndex()                         */
+/************************************************************************/
 
-    for (i = 0; i < nLength; i++) {
-        if (pszInput[i] == '\'')
-            pszOutput[i] = '"';
-        else
-            pszOutput[i] = pszInput[i];
+GBool PostGISRasterDataset::HasSpatialIndex()
+{
+    CPLString osCommand;
+    PGresult* poResult = NULL;
+    
+    // If exists, return it
+    if (bHasTriedHasSpatialIndex) {
+        return bHasSpatialIndex;
+    }
+    
+    bHasTriedHasSpatialIndex = true;
+
+    /* For debugging purposes only */
+    if( CSLTestBoolean(CPLGetConfigOption("PR_DISABLE_GIST", "FALSE") ) )
+        return false;
+
+    // Copyright dustymugs !!!
+    osCommand.Printf(
+    "SELECT n.nspname AS schema_name, c2.relname AS table_name, att.attname AS column_name, "
+    "       c.relname AS index_name, am.amname AS index_type "
+    "FROM pg_catalog.pg_class c "
+    "JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid "
+    "JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid "
+    "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
+    "JOIN pg_am am ON c.relam = am.oid "
+    "JOIN pg_attribute att ON att.attrelid = c2.oid "
+    "AND pg_catalog.format_type(att.atttypid, att.atttypmod) = 'raster' "
+    "WHERE c.relkind IN ('i') "
+    "AND am.amname = 'gist' "
+    "AND strpos(split_part(pg_catalog.pg_get_indexdef(i.indexrelid, 0, true), ' gist ', 2), att.attname) > 0 "
+    "AND n.nspname = '%s' "
+    "AND c2.relname = '%s' "
+    "AND att.attname = '%s' ", pszSchema, pszTable, pszColumn);
+    
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::HasSpatialIndex(): Query: %s", 
+        osCommand.c_str());
+#endif
 
+    poResult = PQexec(poConn, osCommand.c_str());
+    
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) <= 0 )
+    {
+        bHasSpatialIndex = false;
+        CPLDebug("PostGIS_Raster", "For better performance, creating a spatial index "
+                 "with 'CREATE INDEX %s_%s_%s_gist_idx ON %s.%s USING GIST (ST_ConvexHull(%s))' is advised",
+                 pszSchema, pszTable, pszColumn, pszSchema, pszTable, pszColumn);
+    }
+    else
+    {
+        bHasSpatialIndex = true;
     }
 
-    return pszOutput;
+    if( poResult )
+        PQclear(poResult);
+    return bHasSpatialIndex;
 }
 
-/**************************************************************
- * \brief Replace the quotes by single quotes in the input string
+/***********************************************************************
+ * \brief Look for a primary key in the table selected by the user
  *
- * Needed in the 'where' part of the input string
- *************************************************************/
-static
-char * ReplaceQuotes(const char * pszInput, int nLength) {
-    int i;
-    char * pszOutput = NULL;
+ * If the table does not have a primary key, it returns NULL
+ **********************************************************************/
+const char * PostGISRasterDataset::GetPrimaryKeyRef()
+{
+    CPLString osCommand;
+    PGresult* poResult = NULL;
+    
+    // If exists, return it
+    if (bHasTriedFetchingPrimaryKeyName) {
+        return pszPrimaryKeyName;
+    }
+    
+    bHasTriedFetchingPrimaryKeyName = true;
+
+    /* For debugging purposes only */
+    if( CSLTestBoolean(CPLGetConfigOption("PR_DISABLE_PK", "FALSE") ) )
+        return NULL;
+    
+    /* Determine the primary key/unique column on the table */
+    osCommand.Printf("select d.attname from pg_catalog.pg_constraint "
+        "as a join pg_catalog.pg_indexes as b on a.conname = "
+        "b.indexname join pg_catalog.pg_class as c on c.relname = "
+        "b.tablename join pg_catalog.pg_attribute as d on "
+        "c.relfilenode = d.attrelid where b.schemaname = '%s' and "
+        "b.tablename = '%s' and d.attnum = a.conkey[1] and a.contype "
+        "in ('p', 'u')", pszSchema, pszTable);
+
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s", 
+        osCommand.c_str());
+#endif
+
+    poResult = PQexec(poConn, osCommand.c_str());
+    
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) <= 0 ) {
+            
+        PQclear(poResult);
 
-    if (nLength == -1)
-        nLength = strlen(pszInput);
+        /**
+         * Maybe there is no primary key or unique constraint; a 
+         * sequence will also suffice; get the first one
+         **/
 
-    pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
+        osCommand.Printf("select cols.column_name from "
+            "information_schema.columns as cols join "
+            "information_schema.sequences as seqs on "
+            "cols.column_default like '%%'||seqs.sequence_name||'%%' "
+            "where cols.table_schema = '%s' and cols.table_name = '%s'", 
+            pszSchema, pszTable);
 
-    for (i = 0; i < nLength; i++) {
-        if (pszInput[i] == '"')
-            pszOutput[i] = '\'';
-        else
-            pszOutput[i] = pszInput[i];
-    }
+#ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s", 
+            osCommand.c_str());
+#endif
 
-    return pszOutput;
-}
+        poResult = PQexec(poConn, osCommand.c_str());
 
-/*****************************************************************************
- * \brief Split connection string into user, password, host, database...
- *
- * The parameters separated by spaces are return as a list of strings. The
- * function accepts all the PostgreSQL recognized parameter key words.
- *
- * The returned list must be freed with CSLDestroy when no longer needed
- *
- *****************************************************************************/
-static
-char** ParseConnectionString(const char * pszConnectionString) {
-    char * pszEscapedConnectionString = NULL;
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+            PQntuples(poResult) <= 0) {
 
-    /* Escape string following SQL scheme */
-    pszEscapedConnectionString = ReplaceSingleQuotes(pszConnectionString, -1);
+            CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::GetPrimaryKeyRef(): Could not "
+            "find a primary key or unique column on the specified "
+            "table %s.%s. For better performance, creating a primary key on the table is advised.",
+            pszSchema, pszTable);
+            
+            pszPrimaryKeyName = NULL; // Just in case
 
-    /* Avoid PG: part */
-    char* pszStartPos = (char*) strstr(pszEscapedConnectionString, ":") + 1;
+        }
 
-    /* Tokenize */
-    char** papszParams = CSLTokenizeString2(pszStartPos, " ",
-            CSLT_HONOURSTRINGS);
+        else {
+            pszPrimaryKeyName = CPLStrdup(PQgetvalue(poResult, 0, 0));
+        }
 
-    /* Free */
-    CPLFree(pszEscapedConnectionString);
+    }
+    
+    // Ok, get the primary key        
+    else {
+        pszPrimaryKeyName = CPLStrdup(PQgetvalue(poResult, 0, 0));
+        bIsFastPK = true;
+    }
 
-    return papszParams;
+    PQclear(poResult);
 
+    return pszPrimaryKeyName;
 }
 
-/**************************************************************************
- * \brief Look for raster tables in database and store them as subdatasets
+
+/***********************************************************************
+ * \brief Look for raster tables in database and store them as 
+ * subdatasets
  *
- * If no table is provided in connection string, the driver looks for the
- * existent raster tables in the schema given as argument. This argument,
- * however, is optional. If a NULL value is provided, the driver looks for
- * all raster tables in all schemas of the user-provided database.
+ * If no table is provided in connection string, the driver looks for 
+ * the existent raster tables in the schema given as argument. This 
+ * argument, however, is optional. If a NULL value is provided, the 
+ * driver looks for all raster tables in all schemas of the 
+ * user-provided database.
  *
- * NOTE: Permissions are managed by libpq. The driver only returns an error
- * if an error is returned when trying to access to tables not allowed to
- * the current user.
- **************************************************************************/
+ * NOTE: Permissions are managed by libpq. The driver only returns an 
+ * error if an error is returned when trying to access to tables not 
+ * allowed to the current user.
+ **********************************************************************/
 GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
-        char* pszValidConnectionString) {
+        const char* pszValidConnectionString) {
+            
     /* Be careful! These 3 vars override the class ones! */
     char* pszSchema = NULL;
     char* pszTable = NULL;
     char* pszColumn = NULL;
+    
     int i = 0;
     int nTuples = 0;
     PGresult * poResult = NULL;
@@ -229,21 +494,22 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
      * Fetch all the raster tables and store them as subdatasets
      *************************************************************/
     if (pszCurrentSchema == NULL) {
-        osCommand.Printf("select pg_namespace.nspname as schema, pg_class.relname as \
-                    table, pg_attribute.attname as column from pg_class, \
-                    pg_namespace,pg_attribute, pg_type where \
-                    pg_class.relnamespace = pg_namespace.oid and pg_class.oid = \
-                    pg_attribute.attrelid and pg_attribute.atttypid = pg_type.oid \
-                    and pg_type.typname = 'raster'");
+        osCommand.Printf("select pg_namespace.nspname as schema, "
+            "pg_class.relname as table, pg_attribute.attname as column "
+            "from pg_class, pg_namespace,pg_attribute, pg_type where "
+            "pg_class.relnamespace = pg_namespace.oid and "
+            "pg_class.oid = pg_attribute.attrelid and "
+            "pg_attribute.atttypid = pg_type.oid and "
+            "pg_type.typname = 'raster'");
 
         poResult = PQexec(poConn, osCommand.c_str());
-        if (
-                poResult == NULL ||
-                PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-                PQntuples(poResult) <= 0
-                ) {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Error browsing database for PostGIS Raster tables: %s", PQerrorMessage(poConn));
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+            PQntuples(poResult) <= 0) {
+                    
+            ReportError(CE_Failure, CPLE_AppDefined,
+                "Error browsing database for PostGIS Raster tables: %s", 
+                PQerrorMessage(poConn));
             if (poResult != NULL)
                 PQclear(poResult);
 
@@ -258,37 +524,43 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             pszColumn = PQgetvalue(poResult, i, 2);
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
-                    CPLSPrintf("PG:%s schema=%s table=%s column=%s",
-                    pszValidConnectionString, pszSchema, pszTable, pszColumn));
+                CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
+                CPLSPrintf("PG:%s schema=%s table=%s column=%s",
+                pszValidConnectionString, pszSchema, pszTable, 
+                pszColumn));
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                    CPLSPrintf("PostGIS Raster table at %s.%s (%s)", pszSchema, pszTable, pszColumn));
+                CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
+                CPLSPrintf("PostGIS Raster table at %s.%s (%s)", 
+                pszSchema, pszTable, pszColumn));
         }
 
         PQclear(poResult);
 
     }
-        /**********************************************************************
-         * Fetch all the schema's raster tables and store them as subdatasets
-         **********************************************************************/
+        /***************************************************************
+         * Fetch all the schema's raster tables and store them as 
+         * subdatasets
+         **************************************************************/
     else {
-        osCommand.Printf("select pg_class.relname as table, pg_attribute.attname \
-             as column from pg_class, pg_namespace,pg_attribute, pg_type where \
-             pg_class.relnamespace = pg_namespace.oid and pg_class.oid = \
-             pg_attribute.attrelid and pg_attribute.atttypid = pg_type.oid \
-             and pg_type.typname = 'raster' and pg_namespace.nspname = '%s'",
-                pszCurrentSchema);
+        osCommand.Printf("select pg_class.relname as table, "
+            "pg_attribute.attname as column from pg_class, "
+            "pg_namespace,pg_attribute, pg_type where "
+            "pg_class.relnamespace = pg_namespace.oid and "
+            "pg_class.oid = pg_attribute.attrelid and "
+            "pg_attribute.atttypid = pg_type.oid and "
+            "pg_type.typname = 'raster' and "
+            "pg_namespace.nspname = '%s'", pszCurrentSchema);
 
         poResult = PQexec(poConn, osCommand.c_str());
-        if (
-                poResult == NULL ||
-                PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-                PQntuples(poResult) <= 0
-                ) {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Error browsing database for PostGIS Raster tables: %s", PQerrorMessage(poConn));
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+            PQntuples(poResult) <= 0) {
+                
+            ReportError(CE_Failure, CPLE_AppDefined,
+                "Error browsing database for PostGIS Raster tables: %s", 
+                PQerrorMessage(poConn));
+                
             if (poResult != NULL)
                 PQclear(poResult);
 
@@ -302,14 +574,15 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             pszColumn = PQgetvalue(poResult, i, 1);
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
-                    CPLSPrintf("PG:%s schema=%s table=%s column=%s",
-                    pszValidConnectionString, pszCurrentSchema, pszTable, pszColumn));
+                CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
+                CPLSPrintf("PG:%s schema=%s table=%s column=%s",
+                pszValidConnectionString, pszCurrentSchema, pszTable, 
+                pszColumn));
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                    CPLSPrintf("PostGIS Raster table at %s.%s (%s)", pszCurrentSchema,
-                    pszTable, pszColumn));
+                CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
+                CPLSPrintf("PostGIS Raster table at %s.%s (%s)", 
+                pszCurrentSchema, pszTable, pszColumn));
         }
 
         PQclear(poResult);
@@ -319,730 +592,1922 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
 }
 
 
-
-
-/*************************************************************************
- * \brief Set the general raster properties.
- *
- * We must distinguish between tiled and untiled raster coverages. In
- * PostGIS Raster, there's no real difference between 'tile' and 'raster'.
- * There's only 'raster objects'. Each record of a raster table is a
- * raster object, and has its own georeference information, whether if
- * the record is a tile of a bigger raster coverage or is a complete
- * raster. So, <b>there's no a way of knowing if the rows of a raster
- * table are related or not</b>. It's user's responsibility. The only
- * thing driver can do is to suppose all the rows of a table are from
- * the same raster coverage if the user has queried for one table, without
- * specifying a where clause.
- *
- * The user is responsible to ensure that the raster layer meets the minimum
- * topological requirements for analysis. The ideal case is when all the raster
- * tiles of a continuous layer are the same size, snap to the same grid and do
- * not overlap. 
- * 
- * So, when we query for a raster table, we have 2 different cases:
- *  - The result is only one row OR there are several rows BUT the working
- *    mode is ONE_RASTER_PER_TABLE. The row(s) returned form one raster coverage.
- *    We get the whole coverage extent (except rotated rasters), and its georefence, 
- *    if possible
- *  - The result are several rows of a table AND the working mode is
- *    ONE_RASTER_PER_ROW. We assume each row is a different raster object,
- *    and is reported as a subdataset. 
- **************************************************************************/
-GBool PostGISRasterDataset::SetRasterProperties
-    (const char * pszValidConnectionString)
+/***********************************************************************
+ * \brief Look for overview tables for the bands of the current dataset
+ **********************************************************************/
+PROverview * PostGISRasterDataset::GetOverviewTables(int * pnOverviews)
 {
-    PGresult* poResult = NULL;
+    PROverview * poOV = NULL;
     CPLString osCommand;
-    int i = 0;
-    int nTuples = 0;
-    int nRasterID = 0;
-    char* pszIdColumn = NULL;
-    double tileUpperLeftX;
-    double tileUpperLeftY;
-    double tileSkewX;
-    double tileSkewY;
-    double tilePixelSizeX;
-    double tilePixelSizeY;
-    int nTileWidth = 0;
-    int nTileHeight = 0;
-    int nPreviousTileWidth = 0;
-    int nPreviousTileHeight = 0;
-    int nBlockXSize = 0, nBlockYSize = 0;
-    char szTmp[20];
-
-    /* Incorporated variables from old SetRasterBand method */
-    GBool bSignedByte = false;
-    int nBitDepth = 8;
-    char* pszDataType = NULL;
-    int iBand = 0;
-    double dfNodata = 0.0;
-    GDALDataType hDataType = GDT_Byte;
-    GBool bIsOffline = false;
-    GBool bHasNoDataValue = false;
-
-    /**************************************************************************
-     * Get the extent and the maximum number of bands of the requested raster
-     * TODO: The extent of rotated rasters could be a problem. We'll need a
-     * ST_RotatedExtent function in PostGIS. Without that function, we shouldn't
-     * allow rotated rasters
-     **************************************************************************/
-    // NOTE: can't use 'srid' alias in the GROUP BY. It doesn't work 
-    // with PostgreSQL 9.1
-
-    // First, check raster_columns view (it makes things faster. See ticket #5046)
-    if (pszWhere == NULL)
-    {
-        osCommand.Printf(
-            "select srid, nbband, st_xmin(geom) as xmin, st_xmax(geom) as xmax, " 
-            "st_ymin(geom) as ymin, st_ymax(geom) as ymax from (select srid, " 
-            "extent geom, num_bands nbband from raster_columns where "
-            "r_table_schema = '%s' and r_table_name = '%s') foo", 
-            pszSchema, pszTable);
-    }
-
-    else
-    {
-        osCommand.Printf(
-            "select srid, nbband, st_xmin(geom) as xmin, st_xmax(geom) as xmax, " 
-            "st_ymin(geom) as ymin, st_ymax(geom) as ymax from (select srid srid, " 
-            "extent geom, num_bands nbband from raster_columns where "
-            "r_table_schema = '%s' " "and r_table_name = '%s') foo where %s", 
-            pszSchema, pszTable, pszWhere);
-    }
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-        "First query: %s", osCommand.c_str());
-
-    poResult = PQexec(poConn, osCommand.c_str());
-
-    // Query execution error
-    if(poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK || 
-        PQntuples(poResult) < 0) 
-    {
-
-        CPLError(CE_Warning, CPLE_AppDefined, "Cannot find information about "
-            "%s.%s table in raster_columns view. The raster table loading "
-            "would take a lot of time. Please, execute AddRasterConstraints "
-            "PostGIS function to register this table as raster table in "
-            "raster_columns view. This will save loading time.", pszSchema,
-            pszTable);
-
-        /**
-         * Table not registered in raster_columns view. We need to check the
-         * whole table to fetch raster properties. This can take a lot of time
-         **/
-        if (pszWhere == NULL) {
-            osCommand.Printf(
-                "select srid, nbband, st_xmin(geom) as xmin, st_xmax(geom) as xmax, "
-                "st_ymin(geom) as ymin, st_ymax(geom) as ymax from (select st_srid(%s) srid, "
-                "st_extent(%s::geometry) geom, max(ST_NumBands(rast)) nbband from %s.%s "
-                "group by st_srid(%s)) foo", pszColumn, pszColumn, pszSchema, 
-                pszTable, pszColumn);
-        }
-
-        else {
-            osCommand.Printf(
-                "select srid, nbband, st_xmin(geom) as xmin, st_xmax(geom) as xmax, "
-                "st_ymin(geom) as ymin, st_ymax(geom) as ymax from (select st_srid(%s) srid, "
-                "st_extent(%s::geometry) geom, max(ST_NumBands(rast)) nbband from %s.%s "
-                "where %s group by st_srid(%s)) foo", pszColumn, pszColumn, pszSchema, 
-                pszTable, pszWhere, pszColumn);
-        }
-
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "First query: %s", osCommand.c_str());
-
-        poResult = PQexec(poConn, osCommand.c_str());
+    PGresult * poResult = NULL;
     
-        // Query execution error
-        if(poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK || 
-            PQntuples(poResult) < 0) 
-        {
+    osCommand.Printf("SELECT o_table_name, overview_factor, "
+            "o_raster_column, o_table_schema FROM raster_overviews "
+            "WHERE r_table_schema = '%s' AND r_table_name = '%s' AND "
+            "r_raster_column = '%s' ORDER BY overview_factor", this->pszSchema, this->pszTable, 
+            this->pszColumn);
+
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::GetOverviewTables(): Query: %s", 
+        osCommand.c_str());
+#endif
 
-            CPLError(CE_Failure, CPLE_AppDefined, "Error browsing database for "
-                "PostGIS Raster properties");
+    poResult = PQexec(poConn, osCommand.c_str());
 
-            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                "%s", PQerrorMessage(poConn));
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) < 0) {
+        
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error looking for overview tables: %s", 
+            PQerrorMessage(poConn));
 
-            if (poResult != NULL)
-                PQclear(poResult);
+        if (poResult)
+            PQclear(poResult);
 
-            return false;                   
-        }
+        return NULL;
     }
     
-    // No tuples
     else if (PQntuples(poResult) == 0) {
-        CPLError(CE_Failure, CPLE_AppDefined, "Error, no data found in the table that "
-            "matches your constraints. Maybe there are no rows in the table, or maybe "
-            "you provide a 'where' option with too many restrictions");
-
-        PQclear(poResult);
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::GetOverviewTables(): No overviews " 
+            "for table %s.%s", pszTable, pszSchema);
+        
+        if (poResult)
+            PQclear(poResult);
 
-        return false;
+        return NULL;
     }
-
     
-    /**
-     * TODO: We could provide an extra parameter, to transform all the tiles to
-     * the same SRID
-     **/
-    else if (PQntuples(poResult) > 1) {
-        CPLError(CE_Failure, CPLE_AppDefined,
-            "Error, the table %s.%s contains tiles with different srid. This feature "
-            "is not yet supported by the PostGIS Raster driver. Please, specify a table "
-            "that contains only tiles with the same srid or provide a 'where' constraint "
-            "to select just the tiles with the same value for srid", pszSchema, pszTable);
-
+    int nTuples = PQntuples(poResult);
+    
+    poOV = (PROverview *)VSIMalloc2(nTuples, sizeof(PROverview));
+    if (poOV == NULL) {
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error looking for overview tables");
+        
         PQclear(poResult);
-        return false;
+        
+        return NULL;
     }
-
-    // Get some information we will probably need further
-    nSrid = atoi(PQgetvalue(poResult, 0, 0));
-    nBands = atoi(PQgetvalue(poResult, 0, 1));
-    xmin = atof(PQgetvalue(poResult, 0, 2));
-    xmax = atof(PQgetvalue(poResult, 0, 3));
-    ymin = atof(PQgetvalue(poResult, 0, 4));
-    ymax = atof(PQgetvalue(poResult, 0, 5));
     
-    PQclear(poResult);
+    int iOVerview = 0;
+    for(iOVerview = 0; iOVerview < nTuples; iOVerview++) {
+        poOV[iOVerview].pszSchema = 
+            CPLStrdup(PQgetvalue(poResult, iOVerview, 3));
+            
+        poOV[iOVerview].pszTable =
+            CPLStrdup(PQgetvalue(poResult, iOVerview, 0));
+            
+        poOV[iOVerview].pszColumn = 
+            CPLStrdup(PQgetvalue(poResult, iOVerview, 2));
+            
+        poOV[iOVerview].nFactor = 
+            atoi(PQgetvalue(poResult, iOVerview, 1));
     
-    /*****************************************************************************
-     * Now, we're going to count the number of raster tiles we will have to deal 
-     * with.To save one database server round, we get the pixel size and rotation
-     *
-     * TODO: Improve the optimization, based on MAX_TILES
-     *****************************************************************************/
-    memset(szTmp, 0, sizeof(szTmp));
-    if (MAX_TILES > 0) {
-        sprintf(szTmp, "limit %d", MAX_TILES);
     }
+    
+    if (pnOverviews)
+        *pnOverviews = nTuples;
+    
+    PQclear(poResult);
+    
+    return poOV;
+}
 
+/***********************************************************************
+ * \brief Build overview datasets
+ ***********************************************************************/
+void PostGISRasterDataset::BuildOverviews()
+{
+    if( bHasBuiltOverviews || poParentDS != NULL )
+        return;
+
+    bHasBuiltOverviews = true;
+    /*******************************************************************
+     * We also get the names of the overview tables, if they exist. So,
+     * we'll can use them to create the overview datasets.
+     ******************************************************************/
+    int nOV = 0;
+    PROverview * poOV = GetOverviewTables(&nOV);
+
+    if (poOV)
+    {
+        papoOverviewDS = (PostGISRasterDataset**) CPLCalloc(nOV, sizeof(PostGISRasterDataset*));
+        nOverviewCount = 0;
 
-    if (pszWhere == NULL) {
-        osCommand.Printf(
-            "select st_scalex(%s), st_scaley(%s), st_skewx(%s), "
-            "st_skewy(%s), st_width(%s), st_height(%s) from %s.%s %s", pszColumn, pszColumn, 
-            pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, szTmp);
-    }
-
-    else {
-        osCommand.Printf(
-            "select st_scalex(%s), st_scaley(%s), st_skewx(%s), "
-            "st_skewy(%s), st_width(%s), st_height(%s) from %s.%s where %s %s", pszColumn, 
-            pszColumn, pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, 
-            pszWhere, szTmp);
+        int iOV;
+        for(iOV = 0; iOV < nOV; iOV++)
+        {
+            PostGISRasterDataset* poOvrDS = new PostGISRasterDataset();
+            poOvrDS->nOverviewFactor = poOV[iOV].nFactor;
+            poOvrDS->poConn = poConn;
+            poOvrDS->eAccess = eAccess;
+            poOvrDS->nMode = nMode;
+            poOvrDS->pszSchema = poOV[iOV].pszSchema; // takes ownership
+            poOvrDS->pszTable = poOV[iOV].pszTable; // takes ownership
+            poOvrDS->pszColumn = poOV[iOV].pszColumn; // takes ownership
+            poOvrDS->pszWhere = pszWhere ? CPLStrdup(pszWhere) : NULL;
+            poOvrDS->poParentDS = this;
+
+            if (!CSLTestBoolean(CPLGetConfigOption("PG_DIFFERED_OVERVIEWS", "YES")) &&
+                (!poOvrDS->SetRasterProperties(NULL) ||
+                poOvrDS->GetRasterCount() != GetRasterCount()))
+            {
+                delete poOvrDS;
+            }
+            else
+            {
+                papoOverviewDS[nOverviewCount ++] = poOvrDS;
+            }
+        }
+
+        VSIFree(poOV);
     }
+}
 
-    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-        "Query: %s", osCommand.c_str());
+/***********************************************************************
+ * \brief Returns overview count
+ ***********************************************************************/
+int PostGISRasterDataset::GetOverviewCount()
+{
+    BuildOverviews();
+    return nOverviewCount;
+}
 
-    poResult = PQexec(poConn, osCommand.c_str());
-    if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-        PQntuples(poResult) <= 0) {
+/***********************************************************************
+ * \brief Returns overview dataset
+ ***********************************************************************/
+PostGISRasterDataset* PostGISRasterDataset::GetOverviewDS(int iOvr)
+{
+    if( iOvr < 0 || iOvr > GetOverviewCount() )
+        return NULL;
+    return papoOverviewDS[iOvr];
+}
+ 
+/***********************************************************************
+ * \brief Calculates the destination window for a VRT source, taking 
+ * into account that the source is a PostGIS Raster tile and the 
+ * destination is the general dataset itself
+ * 
+ * This method is adapted from gdalbuildvrt as is in GDAL 1.10.0
+***********************************************************************/
+GBool PostGISRasterDataset::GetDstWin(
+    PostGISRasterTileDataset * psDP,
+    int* pnDstXOff, int* pnDstYOff, int* pnDstXSize, int* pnDstYSize)
+{
+    double we_res = this->adfGeoTransform[GEOTRSFRM_WE_RES];
+    double ns_res = this->adfGeoTransform[GEOTRSFRM_NS_RES];
+    
+    double adfTileGeoTransform[6];
+    psDP->GetGeoTransform(adfTileGeoTransform);
+    
+    *pnDstXOff = (int)
+        (0.5 + (adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X] - xmin) / we_res);
+    
+    if( ns_res < 0 )
+        *pnDstYOff = (int)
+            (0.5 + (ymax - adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y]) / -ns_res);
+    else
+        *pnDstYOff = (int)
+            (0.5 + (adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y] - ymin) / ns_res);
+    
+    *pnDstXSize = (int)
+        (0.5 + psDP->GetRasterXSize() *
+         adfTileGeoTransform[GEOTRSFRM_WE_RES] / we_res);
+    *pnDstYSize = (int)
+        (0.5 + psDP->GetRasterYSize() *
+         adfTileGeoTransform[GEOTRSFRM_NS_RES] / ns_res);
+         
+    return true;
+}
 
+/***********************************************************************
+ * \brief Add tiles bands as complex source for raster bands.
+ **********************************************************************/
+GBool PostGISRasterDataset::AddComplexSource(PostGISRasterTileDataset* poRTDS)
+{
+    // Parameters to add the tile bands as sources
+    int nDstXOff = 0;
+    int nDstYOff = 0;
+    int nDstXSize = 0;
+    int nDstYSize = 0;
+
+    // Get src and dst parameters
+    GBool bValidTile = GetDstWin(poRTDS,
+        &nDstXOff, &nDstYOff, &nDstXSize, &nDstYSize);
+    if (!bValidTile)
+        return false;
 
-        CPLError(CE_Failure, CPLE_AppDefined, "Error retrieving raster metadata");
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::AddComplexSource: "
+        "Tile bounding box from (%d, %d) of size (%d, %d) will "
+        "cover raster bounding box from (%d, %d) of size "
+        "(%d, %d)", 0, 0, 
+        poRTDS>GetRasterXSize(), 
+        poRTDS->GetRasterYSize(),
+        nDstXOff, nDstYOff, nDstXSize, nDstYSize);
+#endif
 
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "%s", PQerrorMessage(poConn));
+    // Add tiles bands as sources for the raster bands
+    for(int iBand = 0; iBand < nBandsToCreate; iBand++)
+    {
+        PostGISRasterRasterBand * prb = 
+            (PostGISRasterRasterBand *)GetRasterBand(iBand + 1);
 
-        if (poResult != NULL)
-            PQclear(poResult);
+        int bHasNoData = FALSE;
+        double dfBandNoDataValue = prb->GetNoDataValue(&bHasNoData);
+            
+        PostGISRasterTileRasterBand * prtb =
+            (PostGISRasterTileRasterBand *)
+                poRTDS->GetRasterBand(iBand + 1);
+            
+        prb->AddComplexSource(prtb, 0, 0, 
+            poRTDS->GetRasterXSize(),
+            poRTDS->GetRasterYSize(),
+            nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+            0.0, 1.0,
+            (bHasNoData) ? dfBandNoDataValue : VRT_NODATA_UNSET);
+
+        prtb->poSource = prb->papoSources[prb->nSources-1];
+    }
+    
+    return true;
+}
 
-        return false;
+/************************************************************************/
+/*                         GetMatchingSourceRef()                       */
+/************************************************************************/
+
+/**
+ * \brief Get the tile dataset that matches the given upper left pixel
+ **/
+PostGISRasterTileDataset * 
+    PostGISRasterDataset::GetMatchingSourceRef(double dfUpperLeftX,
+                                               double dfUpperLeftY)
+{
+    int i;
+    PostGISRasterTileDataset * poRTDS = NULL;
+
+    for(i = 0; i < nTiles; i++)
+    {
+        poRTDS = papoSourcesHolders[i];
+
+        if (CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+                dfUpperLeftX) &&
+            CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y], 
+                dfUpperLeftY)) {
+
+            return poRTDS;
+        }
     }
 
-    // Now we now the number of tiles that form our dataset
-    nTiles = PQntuples(poResult);
+    return NULL;
+}
 
+/************************************************************************/
+/*                           CacheTile()                                */
+/************************************************************************/
 
-    /*****************************************************************************
-     * We are going to create a whole dataset as a mosaic with all the tiles
-     ****************************************************************************/
-    if (nTiles == 1 || nMode == ONE_RASTER_PER_TABLE) {
-            
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = xmin;    
+void PostGISRasterDataset::CacheTile(const char* pszMetadata,
+                                     const char* pszRaster,
+                                     const char *pszPKID,
+                                     int nBand,
+                                     int bAllBandCaching)
+{
+    /**
+    * Get metadata record and unpack it
+    **/
+    char* pszRes = CPLStrdup(pszMetadata);
+
+    // Skip first "("
+    char* pszFilteredRes = pszRes + 1;
+    
+    // Skip last ")"
+    pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
+    
+    // Tokenize
+    char** papszParams = 
+        CSLTokenizeString2(pszFilteredRes, ",", 
+            CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
+    CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
+    
+    CPLFree(pszRes);
+    
+    double dfTilePixelSizeX = CPLAtof(papszParams[POS_UPPERLEFTX]);
+    double dfTilePixelSizeY = CPLAtof(papszParams[POS_UPPERLEFTY]);
+    int nTileXSize = atoi(papszParams[POS_WIDTH]);
+    int nTileYSize = atoi(papszParams[POS_HEIGHT]);
+
+    CSLDestroy(papszParams);
+    papszParams = NULL;
+
+    /**
+        * Get actual raster band data
+        **/
+    int nBandDataTypeSize = GDALGetDataTypeSize(GetRasterBand(nBand)->GetRasterDataType()) / 8;
+    int nExpectedBandDataSize = 
+        nTileXSize * nTileYSize * nBandDataTypeSize;
+
+    int nWKBLength = 0;
+    GByte* pbyData = CPLHexToBinary(pszRaster, &nWKBLength);
+        
+    int nExpectedBands = bAllBandCaching ? GetRasterCount() : 1;
+    int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nBandDataTypeSize, nExpectedBandDataSize) * nExpectedBands;
+    if( nWKBLength != nExpectedWKBLength )
+    {
+        CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d", nWKBLength, nExpectedWKBLength );
+        CPLFree(pbyData);
+        return;
+    }
+
+    // Do byte-swapping if necessary */
+    int bIsLittleEndian = (pbyData[0] == 1);
+#ifdef CPL_LSB
+    int bSwap = !bIsLittleEndian;
+#else
+    int bSwap = bIsLittleEndian;
+#endif
+
+    PostGISRasterTileDataset* poRTDS = NULL;
+    if( GetPrimaryKeyRef() != NULL )
+        poRTDS = GetMatchingSourceRef(pszPKID);
+    else
+        poRTDS = GetMatchingSourceRef(dfTilePixelSizeX, 
+                                      dfTilePixelSizeY);
+    if( poRTDS == NULL )
+    {
+        CPLFree(pbyData);
+        return;
+    }
+
+    for(int k=1; k <= nExpectedBands; k++)
+    {
+        GByte* pbyDataToRead = (GByte*)GET_BAND_DATA(pbyData, k, 
+                nBandDataTypeSize, nExpectedBandDataSize);
+
+        if( bSwap && nBandDataTypeSize > 1 )
+        {
+            GDALSwapWords( pbyDataToRead, nBandDataTypeSize,
+                        nTileXSize * nTileYSize,
+                        nBandDataTypeSize );
+        }
 
         /**
-         * Negative tilePixelSizeY means that the coords origin is in top left corner.
-         *
-         * This is not the common situation. Most image files store data from top to 
-         * bottom, while the projected coordinate systems utilize traditional Cartesian 
-         * coordinates with the origin in the conventional lower-left corner (bottom to
-         * top). For that reason, this parameter is normally negative.
-         *
-         **/ 
+        * Get the right PostGISRasterRasterBand
+        **/
+        int nCurBand = ( nExpectedBands > 1 ) ? k : nBand;
 
-        // Calculate geotransform fields
-        for(i = 0; i < nTiles; i++) {
-            tileSkewX = atof(PQgetvalue(poResult, i, 2));
-            tileSkewY = atof(PQgetvalue(poResult, i, 3));
-    
-            // Rotated rasters are not allowed, so far
-            // TODO: allow them
-            if (!CPLIsEqual(tileSkewX, 0.0) || !CPLIsEqual(tileSkewY, 0.0)) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDAL PostGIS Raster driver can not work with "
-                "rotated rasters yet.");
+        /**
+        * Get the right tileband
+        **/
+        GDALRasterBand * poRTB = poRTDS->GetRasterBand(nCurBand);
+
+        /**
+        * Manually add each tile data to the cache of the 
+        * matching PostGISRasterTileRasterBand.
+        **/
+        if (poRTB)
+        {
+            GDALRasterBlock* poBlock = poRTB->GetLockedBlockRef(0, 0, TRUE);
+            if( poBlock != NULL )
+            {
+                // Point block data ref to fetched data
+                memcpy(poBlock->GetDataRef(), (void *)pbyDataToRead, 
+                    nExpectedBandDataSize);
+
+                poBlock->DropLock();
+            }
+        }
+    }
+
+    CPLFree(pbyData);
+}
+
+/************************************************************************/
+/*                          LoadSources()                               */
+/************************************************************************/
+
+GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nYSize, int nBand)
+{
+    if( !bBuildQuadTreeDynamically )
+        return false;
+
+    CPLString osCommand;
+    CPLString osSpatialFilter;
+    CPLString osIDsToFetch;
+    PGresult * poResult;
+
+    int bFetchAll = FALSE;
+    if( nXOff == 0 && nYOff == 0 && nXSize == nRasterXSize && nYSize == nRasterYSize )
+    {
+        bFetchAll = TRUE;
+    }
+    else
+    {
+        CPLLocaleC oCLocale;
+        double adfProjWin[8];
+        PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin); 
+        osSpatialFilter.Printf("%s && "
+                        "ST_GeomFromText('POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))') ",
+                        //"AND ST_Intersects(%s, ST_GeomFromEWKT('SRID=%d;POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))'))",
+                        pszColumn,
+                        adfProjWin[0], adfProjWin[1],
+                        adfProjWin[2], adfProjWin[3],
+                        adfProjWin[4], adfProjWin[5],
+                        adfProjWin[6], adfProjWin[7],
+                        adfProjWin[0], adfProjWin[1]
+                        /*,pszColumn, nSrid,
+                        adfProjWin[0], adfProjWin[1],
+                        adfProjWin[2], adfProjWin[3],
+                        adfProjWin[4], adfProjWin[5],
+                        adfProjWin[6], adfProjWin[7],
+                        adfProjWin[0], adfProjWin[1]*/);
+    }
+
+    int bLoadRasters = FALSE;
+    int bAllBandCaching = FALSE;
+
+    if( nTiles > 0 && !bFetchAll )
+    {
+        osCommand.Printf("SELECT %s FROM %s.%s",
+                        pszPrimaryKeyName, pszSchema, pszTable);
+        osCommand += " WHERE ";
+        osCommand += osSpatialFilter;
+
+        osSpatialFilter = "";
+
+        poResult = PQexec(poConn, osCommand.c_str());
 
+    #ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d", 
+            osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
+    #endif
+
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+            PQntuples(poResult) < 0) {
+
+            if (poResult)
                 PQclear(poResult);
+        
+            CPLError(CE_Failure, CPLE_AppDefined, 
+                "PostGISRasterDataset::LoadSources(): %s", 
+                PQerrorMessage(poConn));
 
-                return false;
+            return false;  
+        }
+
+        if( bTilesSameDimension && nBand > 0 )
+        {
+            GIntBig nMemoryRequiredForTiles = PQntuples(poResult) * nTileWidth * nTileHeight *
+                GDALGetDataTypeSize(GetRasterBand(nBand)->GetRasterDataType()) / 8;
+            GIntBig nCacheMax = (GIntBig) GDALGetCacheMax64();
+            if( nBands * nMemoryRequiredForTiles <= nCacheMax )
+            {
+                bLoadRasters = TRUE;
+                bAllBandCaching = TRUE;
             }
-            adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = tileSkewX;
-            adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = tileSkewY;
-    
-            tilePixelSizeX = atof(PQgetvalue(poResult, i, 0));
-            tilePixelSizeY = atof(PQgetvalue(poResult, i, 1));
-
-            nTileWidth = atoi(PQgetvalue(poResult, i, 4));
-            nTileHeight = atoi(PQgetvalue(poResult, i, 5));
-
-            if (bRegularBlocking) {
-                if (nPreviousTileWidth != 0 && nPreviousTileWidth != nTileWidth)
-                    bRegularBlocking = false;
-                else if (nPreviousTileHeight != 0 && nPreviousTileHeight != nTileHeight)
-                    bRegularBlocking = false;
-                else {
-                    nPreviousTileWidth = nTileWidth;
-                    nPreviousTileHeight = nTileHeight;
-                }
+            else if( nMemoryRequiredForTiles <= nCacheMax )
+            {
+                bLoadRasters = TRUE;
             }
-            
-            // Calculate pixel size
-            if (resolutionStrategy == AVERAGE_RESOLUTION) {
-                adfGeoTransform[GEOTRSFRM_WE_RES] += tilePixelSizeX;        
-                adfGeoTransform[GEOTRSFRM_NS_RES] += tilePixelSizeY;        
+        }
+
+        int i;
+        for(i=0;i<PQntuples(poResult);i++)
+        {
+            const char* pszPKID = PQgetvalue(poResult, i, 0);
+            PostGISRasterTileDataset *poTile = GetMatchingSourceRef(pszPKID);
+            int bFetchTile = FALSE;
+            if( poTile == NULL )
+                bFetchTile = TRUE;
+            else if( bLoadRasters )
+            {
+                PostGISRasterTileRasterBand* poTileBand = 
+                    (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
+                if( !poTileBand->IsCached() )
+                    bFetchTile = TRUE;
             }
+            if( bFetchTile )
+            {
+                if( osIDsToFetch.size() != 0 )
+                    osIDsToFetch += ",";
+                osIDsToFetch += "'";
+                osIDsToFetch += pszPKID;
+                osIDsToFetch += "'";
+            }
+        }
 
-            else if (resolutionStrategy == HIGHEST_RESOLUTION)  {
-                adfGeoTransform[GEOTRSFRM_WE_RES] = MIN(adfGeoTransform[GEOTRSFRM_WE_RES], 
-                                                        atof(PQgetvalue(poResult, i, 0)));
+        PQclear(poResult);
+    }
 
-                /* Yes : as ns_res is negative, the highest resolution is the max value */
-                if (tilePixelSizeY < 0.0)
-                    adfGeoTransform[GEOTRSFRM_NS_RES] = MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
-                                                        tilePixelSizeY);
-                else
-                    adfGeoTransform[GEOTRSFRM_NS_RES] = MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
-                                                        tilePixelSizeY);                                        
-            }
+    if( bFetchAll || osIDsToFetch.size() != 0 || osSpatialFilter.size() != 0 )
+    {
+        osCommand.Printf("SELECT %s, ST_Metadata(%s)",
+                         pszPrimaryKeyName, pszColumn);
+        if( bLoadRasters )
+        {
+            if( bAllBandCaching )
+                osCommand += CPLSPrintf(", %s", pszColumn);
+            else
+                osCommand += CPLSPrintf(", ST_Band(%s, %d)", pszColumn, nBand);
+        }
+        osCommand += CPLSPrintf(" FROM %s.%s",
+                                pszSchema, pszTable);
+        if( osIDsToFetch.size() != 0 )
+        {
+            osCommand += " WHERE ";
+            osCommand += pszPrimaryKeyName;
+            osCommand += " IN (";
+            osCommand += osIDsToFetch;
+            osCommand += ")";
+        }
+        else if ( osSpatialFilter.size() != 0 )
+        {
+            osCommand += " WHERE ";
+            osCommand += osSpatialFilter;
+        }
+
+        poResult = PQexec(poConn, osCommand.c_str());
+
+#ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d", 
+            osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
+#endif
+
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+            PQntuples(poResult) < 0) {
+
+            if (poResult)
+                PQclear(poResult);
+    
+            CPLError(CE_Failure, CPLE_AppDefined, 
+                "PostGISRasterDataset::LoadSources(): %s", 
+                PQerrorMessage(poConn));
+
+            return false;  
+        }
 
-            else if (resolutionStrategy == LOWEST_RESOLUTION) {
-                adfGeoTransform[GEOTRSFRM_WE_RES] = MAX(adfGeoTransform[GEOTRSFRM_WE_RES], 
-                                                        atof(PQgetvalue(poResult, i, 0)));
-
-                /* Yes : as ns_res is negative, the lowest resolution is the min value */
-                if (tilePixelSizeY < 0.0)
-                    adfGeoTransform[GEOTRSFRM_NS_RES] = MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
-                                                        tilePixelSizeY);
-                else    
-                    adfGeoTransform[GEOTRSFRM_NS_RES] = MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
-                                                        tilePixelSizeY);
+        for(int i=0;i<PQntuples(poResult);i++)
+        {
+            const char* pszPKID = PQgetvalue(poResult, i, 0);
+            const char* pszMetadata = PQgetvalue(poResult, i, 1);
+
+            PostGISRasterTileDataset* poRTDS = GetMatchingSourceRef(pszPKID);
+            if( poRTDS == NULL )
+            {
+                poRTDS = BuildRasterTileDataset(
+                        pszMetadata, pszPKID, GetRasterCount(), NULL);
+                if( poRTDS != NULL )
+                {
+                    if( AddComplexSource(poRTDS) )
+                    {
+                        oMapPKIDToRTDS[poRTDS->pszPKID] = poRTDS;
+                        papoSourcesHolders = (PostGISRasterTileDataset**)
+                            CPLRealloc(papoSourcesHolders, sizeof(PostGISRasterTileDataset*) * (nTiles + 1));
+                        papoSourcesHolders[nTiles ++] = poRTDS;
+                        CPLQuadTreeInsert(hQuadTree, poRTDS);
+                    }
+                    else
+                    {
+                        delete poRTDS;
+                        poRTDS = NULL;
+                    }
+                }
             }
 
-            // USER_RESOLUTION
-            else {
-                // It should be provided by the user. Nothing to do here...
-                // TODO: Allow the user to provide the resolution (see gdalbuildvrt)
+            if( bLoadRasters && poRTDS != NULL )
+            {
+                const char* pszRaster = PQgetvalue(poResult, i, 2);
+                CacheTile(pszMetadata, pszRaster, pszPKID, nBand, bAllBandCaching);
             }
+        }
+
+        PQclear(poResult);
+    }
+    
+    // If we have fetched the surface of all the dataset, then all sources have
+    // been built, and we don't need to do a spatial query on following IRasterIO() calls
+    if( bFetchAll )
+        bBuildQuadTreeDynamically = false;
+    
+    return true;
+}
+
+/***********************************************************************
+ * \brief Get some useful metadata for all bands
+ * 
+ * The allocated memory is responsibility of the caller
+ **********************************************************************/
+BandMetadata * PostGISRasterDataset::GetBandsMetadata(int * pnBands)
+{
+    BandMetadata * poBMD = NULL;
+    PGresult * poResult = NULL;
+    CPLString osCommand;
+    char * pszRes = NULL;
+    char * pszFilteredRes = NULL;
+    char ** papszParams = NULL;
+        
+    if (pszWhere == NULL) {
+        osCommand.Printf("select st_bandmetadata(%s, band) from "
+        "(select %s, generate_series(1, st_numbands(%s)) band from "
+        "(select %s from %s.%s limit 1) bar) foo", pszColumn, pszColumn,
+        pszColumn, pszColumn, pszSchema, pszTable);
+    } 
+
+    else {
+        osCommand.Printf("select st_bandmetadata(%s, band) from "
+        "(select %s, generate_series(1, st_numbands(%s)) band from "
+        "(select %s from %s.%s where %s limit 1) bar) foo", pszColumn, 
+        pszColumn, pszColumn, pszColumn, pszSchema, pszTable, pszWhere);
+    }
+    
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::GetBandsMetadata(): Query: %s", 
+        osCommand.c_str());
+#endif
+
+    poResult = PQexec(poConn, osCommand.c_str());
+    /* Error getting info from database */
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) <= 0) {
+        
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error getting band metadata while creating raster "
+            "bands");
+            
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::GetBandsMetadata(): %s", 
+            PQerrorMessage(poConn));
+        
+        if (poResult)
+            PQclear(poResult);
+
+        return NULL;
+    }
+    
+    // Matches nBands
+    int nTuples = PQntuples(poResult);
+    
+    poBMD = (BandMetadata *)VSIMalloc2(nTuples, sizeof(BandMetadata));
+    if (poBMD == NULL) {
+        ReportError(CE_Failure, CPLE_OutOfMemory, 
+            "Out of memory getting metadata from bands");
+            
+        PQclear(poResult);
+        
+        return NULL;
+    }
+    
+
+    int iBand = 0;
+    
+    for(iBand = 0; iBand < nTuples; iBand++) {
+    
+        // Get metadata record
+        pszRes = CPLStrdup(PQgetvalue(poResult, iBand, 0));
+        
+        // Skip first "("
+        pszFilteredRes = pszRes + 1;
+        
+        // Skip last ")"
+        pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
+        
+        // Tokenize
+        papszParams = 
+            CSLTokenizeString2(pszFilteredRes, ",", CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
+        CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_BAND_METADATA_RECORD);
+        
+        CPLFree(pszRes);
+        
+        // If the band doesn't have nodata, NULL is returned as nodata
+        TranslateDataType(papszParams[POS_PIXELTYPE], 
+            &(poBMD[iBand].eDataType), &(poBMD[iBand].nBitsDepth),
+            &(poBMD[iBand].bSignedByte));
+            
+        if (papszParams[POS_NODATAVALUE] == NULL ||
+            EQUALN(papszParams[POS_NODATAVALUE], "NULL", 4*sizeof(char)) || 
+            EQUALN(papszParams[POS_NODATAVALUE], "f", sizeof(char)) || 
+            EQUAL(papszParams[POS_NODATAVALUE], "")) {
+        
+            poBMD[iBand].bHasNoDataValue = false;
+            poBMD[iBand].dfNoDataValue = CPLAtof(NO_VALID_RES);
+        }
+        
+        else {
+            poBMD[iBand].bHasNoDataValue = true;
+            poBMD[iBand].dfNoDataValue = 
+                CPLAtof(papszParams[POS_NODATAVALUE]);
+        }
+        
+        // TODO: Manage outdb and get path
+        poBMD[iBand].bIsOffline = (papszParams[POS_ISOUTDB] != NULL) ?
+            EQUALN(papszParams[POS_ISOUTDB], "t", sizeof(char)) :
+            false;
+        
+        CSLDestroy(papszParams);
+    }   
+    
+    if (pnBands)
+        *pnBands = nTuples;
+    
+    PQclear(poResult);
+    
+    return poBMD; 
+    
+}
+
+/***********************************************************************
+ * \brief Function to get the bounding box of each element inserted in
+ * the QuadTree index
+ **********************************************************************/
+static void GetTileBoundingBox(const void *hFeature, 
+    CPLRectObj * pBounds)
+{
+    PostGISRasterTileDataset * poRTD = 
+        (PostGISRasterTileDataset *)hFeature;
+        
+    double adfTileGeoTransform[6];
+    poRTD->GetGeoTransform(adfTileGeoTransform);
+    
+    int nTileWidth = poRTD->GetRasterXSize();
+    int nTileHeight = poRTD->GetRasterYSize();
+    
+    pBounds->minx = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X];
+    pBounds->maxx = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+         nTileWidth *
+         adfTileGeoTransform[GEOTRSFRM_WE_RES];
+    
+    if (adfTileGeoTransform[GEOTRSFRM_NS_RES] >= 0.0) {
+        pBounds->miny = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y];
+        pBounds->maxy = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+            nTileHeight *
+            adfTileGeoTransform[GEOTRSFRM_NS_RES];
+    }
+    else {
+        pBounds->maxy = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y];
+        pBounds->miny = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+            nTileHeight *
+            adfTileGeoTransform[GEOTRSFRM_NS_RES];
+    }
+    
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", "TileBoundingBox minx=%f miny=%f maxx=%f maxy=%f adfTileGeoTransform[GEOTRSFRM_NS_RES]=%f",
+             pBounds->minx, pBounds->miny, pBounds->maxx, pBounds->maxy, adfTileGeoTransform[GEOTRSFRM_NS_RES]);
+#endif
+
+    return;
+}
+
+/********************************************************
+ * \brief Builds a PostGISRasterTileDataset* object from the ST_Metadata
+ ********************************************************/
+PostGISRasterTileDataset* PostGISRasterDataset::BuildRasterTileDataset(const char* pszMetadata,
+                                                                       const char* pszPKID,
+                                                                       int nBandsFetched,
+                                                                       BandMetadata * poBandMetaData)
+{
+    // Get metadata record
+    char* pszRes = CPLStrdup(pszMetadata);
+
+    // Skip first "("
+    char* pszFilteredRes = pszRes + 1;
+    
+    // Skip last ")"
+    pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
+    
+    // Tokenize
+    char** papszParams = 
+        CSLTokenizeString2(pszFilteredRes, ",", 
+            CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
+    CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
+
+    CPLFree(pszRes);
+    
+    double tileSkewX = CPLAtof(papszParams[POS_SKEWX]);
+    double tileSkewY = CPLAtof(papszParams[POS_SKEWY]);
+
+    // Rotated rasters are not allowed, so far
+    // TODO: allow them
+    if (!CPLIsEqual(tileSkewX, 0.0) || 
+        !CPLIsEqual(tileSkewY, 0.0)) {
+        
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "GDAL PostGIS Raster driver can not work with "
+            "rotated rasters yet.");
+
+        return NULL;
+    }
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::"
+            "Tile pixel size = (%f, %f)", tilePixelSizeX, 
+            tilePixelSizeY);
+#endif
+
+    int nTileWidth = atoi(papszParams[POS_WIDTH]);
+    int nTileHeight = atoi(papszParams[POS_HEIGHT]);
+
+    /**
+        * Now, construct a PostGISRasterTileDataset, and add
+        * its bands as sources for the general raster bands
+        **/
+    int nTileBands = atoi(papszParams[POS_NBANDS]);
+    
+        /**
+        * If the source doesn't have the same number of bands than
+        * the raster band, is discarded
+        **/
+    if (nTileBands != nBandsFetched) {
+        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::"
+            "BuildRasterTileDataset(): Tile has %d "
+            "bands, and the raster has %d bands. Discarding "
+            "this tile", nTileBands, nBandsFetched);
+
+        CSLDestroy(papszParams);
+
+        return NULL;
+    }
+    
+    PostGISRasterTileDataset* poRTDS =
+        new PostGISRasterTileDataset(this, nTileWidth, nTileHeight);
+    
+    if (GetPrimaryKeyRef() != NULL)
+    {
+        poRTDS->pszPKID = CPLStrdup(pszPKID);
+    }
+    
+    poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X]=
+        CPLAtof(papszParams[POS_UPPERLEFTX]);
+        
+    poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]=
+        CPLAtof(papszParams[POS_UPPERLEFTY]);
+
+    poRTDS->adfGeoTransform[GEOTRSFRM_WE_RES]=
+        CPLAtof(papszParams[POS_SCALEX]);
+        
+    poRTDS->adfGeoTransform[GEOTRSFRM_NS_RES]=
+        CPLAtof(papszParams[POS_SCALEY]);
+ 
+    // TODO: outdb bands should be handled. Not a priority.
+    for(int j = 0; j < nTileBands; j++) {
+        
+        // Create band
+        poRTDS->SetBand(j + 1,
+            new PostGISRasterTileRasterBand(
+                poRTDS,
+                j + 1, (poBandMetaData ) ? poBandMetaData[j].eDataType : GetRasterBand(j+1)->GetRasterDataType(), 
+                (poBandMetaData ) ? poBandMetaData[j].bIsOffline : FALSE));
+    }
+    
+    CSLDestroy(papszParams);
+    
+    return poRTDS;
+}
 
-        } // end for    
 
-        if (adfGeoTransform[GEOTRSFRM_NS_RES] >= 0.0)
-            adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = ymin;
+/********************************************************
+ * \brief Updates components GEOTRSFRM_WE_RES and GEOTRSFRM_NS_RES
+ *        of dataset adfGeoTransform
+ ********************************************************/
+void PostGISRasterDataset::UpdateGlobalResolutionWithTileResolution(
+        double tilePixelSizeX, double tilePixelSizeY)
+{
+    // Calculate pixel size
+    if (resolutionStrategy == AVERAGE_RESOLUTION ||
+        resolutionStrategy == AVERAGE_APPROX_RESOLUTION) {
+        adfGeoTransform[GEOTRSFRM_WE_RES] += tilePixelSizeX;
+        adfGeoTransform[GEOTRSFRM_NS_RES] += tilePixelSizeY; 
+    }
+
+    else if (resolutionStrategy == HIGHEST_RESOLUTION)  {
+        adfGeoTransform[GEOTRSFRM_WE_RES] = 
+            MIN(adfGeoTransform[GEOTRSFRM_WE_RES], 
+                tilePixelSizeX);
+
+        /**
+            * Yes : as ns_res is negative, the highest resolution 
+            * is the max value.
+            * 
+            * Negative tilePixelSizeY means that the coords origin 
+            * is in top left corner. This is not the common 
+            * situation. Most image files store data from top to 
+            * bottom, while the projected coordinate systems 
+            * utilize traditional Cartesian coordinates with the 
+            * origin in the conventional lower-left corner (bottom 
+            * to top). For that reason, this parameter is normally 
+            * negative.
+            **/
+        if (tilePixelSizeY < 0.0)
+            adfGeoTransform[GEOTRSFRM_NS_RES] = 
+                MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
+                tilePixelSizeY);
         else
-            adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = ymax;
+            adfGeoTransform[GEOTRSFRM_NS_RES] = 
+                MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
+                tilePixelSizeY);                                        
+    }
+
+    else if (resolutionStrategy == LOWEST_RESOLUTION) {
+        adfGeoTransform[GEOTRSFRM_WE_RES] = 
+            MAX(adfGeoTransform[GEOTRSFRM_WE_RES], 
+                tilePixelSizeX);
+
+        if (tilePixelSizeY < 0.0)
+            adfGeoTransform[GEOTRSFRM_NS_RES] = 
+                MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
+                tilePixelSizeY);
+        else    
+            adfGeoTransform[GEOTRSFRM_NS_RES] = 
+                MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
+                tilePixelSizeY);
+    }
+
+}
+
+/***********************************************************************
+ * \brief Build bands
+ ***********************************************************************/
+void PostGISRasterDataset::BuildBands(BandMetadata * poBandMetaData,
+                                      int nBandsFetched)
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+        "Now constructing the raster dataset bands");
+#endif
+        
+    int iBand;
+    for (iBand = 0; iBand < nBandsFetched; iBand++) {
+            
+        SetBand(iBand + 1, new PostGISRasterRasterBand(this, iBand + 1, 
+            poBandMetaData[iBand].eDataType, 
+            poBandMetaData[iBand].bHasNoDataValue, 
+            poBandMetaData[iBand].dfNoDataValue, 
+            poBandMetaData[iBand].bIsOffline));
+        
+        // Set some band metadata items
+        GDALRasterBand * b = GetRasterBand(iBand + 1);
+        
+        if (poBandMetaData[iBand].bSignedByte) {
+            b->SetMetadataItem(
+                "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+        }
+        
+        if (poBandMetaData[iBand].nBitsDepth < 8) {
+            b->SetMetadataItem(
+            "NBITS", CPLString().Printf( "%d", 
+                poBandMetaData[iBand].nBitsDepth ),
+            "IMAGE_STRUCTURE" );
+        }
+        
+#ifdef DEBUG_VERBOSE
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+            "Band %d built", iBand + 1);
+#endif
+    }
+}
+
+/***********************************************************************
+ * \brief Construct just one dataset from all the results fetched.
+ * 
+ * This method is not very elegant. It's strongly attached to 
+ * SetRasterProperties (it assumes poResult is not NULL, and the actual
+ * results are stored at fixed positions). I just did it to avoid a
+ * huge SetRasterProperties method.
+ * 
+ * I know, this could be avoided in a better way. Like implementing a
+ * wrapper to raise queries and get results without all the checking
+ * overhead. I'd like to do it, someday...
+ **********************************************************************/
+GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
+    PGresult * poResult)
+{
+    
+    /*******************************************************************
+     * We first get the band metadata. So we'll can use it as metadata 
+     * for all the sources. 
+     * 
+     * We just fetch the band metadata from 1 tile. So, we assume that:
+     * - All the bands have the same data type
+     * - All the bands have the same NODATA value
+     * 
+     * It's user's resposibility to ensure the requested table fit in
+     * this schema. He/she may use the 'where' clause to ensure this
+     ******************************************************************/
+    int nBandsFetched = 0;
+    BandMetadata * poBandMetaData = GetBandsMetadata(&nBandsFetched);
+   
+    
+    /*******************************************************************
+     * Now, we can iterate over the input query's results (metadata 
+     * from all the database tiles). 
+     * 
+     * In this iteration, we will construct the dataset GeoTransform 
+     * array and we will add each tile's band as source for each of our
+     * rasterbands. 
+     ******************************************************************/
+    int nTiles = PQntuples(poResult);
+
+    adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = xmin;
+
+    int nField = (GetPrimaryKeyRef() != NULL) ? 1 : 0;
+    /**
+     * Optimization - Just one tile: The dataset's geotransform is the 
+     * tile's geotransform. And we don't need to construct sources for 
+     * the raster bands. We just read from the unique tile we have. So, 
+     * we avoid all the VRT stuff.
+     * 
+     * TODO: For some reason, the implementation of IRasterIO in
+     * PostGISRasterRasterBand class causes a segmentation fault when
+     * tries to call GDALRasterBand::IRasterIO. This call intends to
+     * delegate the I/O in the parent class, that will call
+     * PostGISRasterRasterBand::IReadBlock.
+     * 
+     * If you avoid PostGISRasterRasterBand::IRasterIO method, the 
+     * IReadBlock method is directly call and it works fine. 
+     * 
+     * Right now, we avoid this optimization by making the next boolean
+     * variable always true.
+     **/
+    //GBool bNeedToConstructSourcesHolders = (nTiles > 1); 
+    
+    // As the optimization is not working, we avoid it
+    GBool bNeedToConstructSourcesHolders = true;
+    
+#ifdef notdef
+    // This won't be called if the optimization is disabled
+    if (!bNeedToConstructSourcesHolders)
+    {
+        // Get metadata record
+        char* pszRes = CPLStrdup(PQgetvalue(poResult, 0, nField));
+        
+        // Skip first "("
+        char* pszFilteredRes = pszRes + 1;
+        
+        // Skip last ")"
+        pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
+        
+        // Tokenize
+        char** papszParams = 
+            CSLTokenizeString2(pszFilteredRes, ",", CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
+        CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
+        
+        CPLFree(pszRes);
+        
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 
+            CPLAtof(papszParams[POS_SKEWX]);
+            
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 
+            CPLAtof(papszParams[POS_SKEWY]);
+         
+        // Rotated rasters are not allowed, so far
+        // TODO: allow them
+        if (!CPLIsEqual(adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1], 0.0) ||
+            !CPLIsEqual(adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2], 0.0)) {
+        
+            ReportError(CE_Failure, CPLE_AppDefined, 
+                    "GDAL PostGIS Raster driver can not work with "
+                    "rotated rasters yet.");
+        
+            VSIFree(poBandMetaData); 
+            CSLDestroy(papszParams);
+            
+            return false;          
+        }
+            
+        /**
+         * We override user resolution. It only makes sense in case we
+         * have several tiles with different resolutions
+         **/ 
+        adfGeoTransform[GEOTRSFRM_WE_RES] = 
+            CPLAtof(papszParams[POS_SCALEX]);        
+        adfGeoTransform[GEOTRSFRM_NS_RES] = 
+            CPLAtof(papszParams[POS_SCALEY]);
+            
+        CSLDestroy(papszParams);
+    
+    }
+    
+    /**
+     * Several tiles: construct the dataset from metadata of all tiles,
+     * and create PostGISRasterTileDataset objects, to hold the
+     * PostGISRasterTileRasterBands objects that will be used as sources
+     **/
+    else
+#endif
+    {
+        int i;
 
-        if (resolutionStrategy == AVERAGE_RESOLUTION) {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+            "Constructing one dataset from %d tiles", nTiles);
+#endif
+        
+        papoSourcesHolders = (PostGISRasterTileDataset **)
+            VSIMalloc2(nTiles, sizeof(PostGISRasterTileDataset *));
+    
+        if (papoSourcesHolders == NULL) {
+            ReportError(CE_Failure, CPLE_OutOfMemory, 
+                "Out of memory allocating space for dataset bands "
+                "sources");
+                
+            VSIFree(poBandMetaData);
+            
+            return false;
+        }
+        
+        int nValidTiles = 0;
+        for(i = 0; i < nTiles; i++)
+        {
+            PostGISRasterTileDataset* poRTDS = 
+                BuildRasterTileDataset(PQgetvalue(poResult, i, nField),
+                                       (GetPrimaryKeyRef() != NULL) ? PQgetvalue(poResult, i, 0) : NULL,
+                                       nBandsFetched,
+                                       poBandMetaData);
+            if( poRTDS == NULL )
+                continue;
+
+            if( nOverviewFactor == 1 && resolutionStrategy != USER_RESOLUTION )
+            {
+                double tilePixelSizeX = poRTDS->adfGeoTransform[GEOTRSFRM_WE_RES];
+                double tilePixelSizeY = poRTDS->adfGeoTransform[GEOTRSFRM_NS_RES];
+
+                if( nValidTiles == 0 )
+                {
+                    adfGeoTransform[GEOTRSFRM_WE_RES] = tilePixelSizeX;
+                    adfGeoTransform[GEOTRSFRM_NS_RES] = tilePixelSizeY; 
+                }
+                else
+                {
+                    UpdateGlobalResolutionWithTileResolution(tilePixelSizeX,
+                                                            tilePixelSizeY);
+                }
+            }
+
+            papoSourcesHolders[nValidTiles++] = poRTDS;
+
+        } // end for
+        
+        nTiles = nValidTiles;
+
+        if( nOverviewFactor > 1 )
+        {
+            adfGeoTransform[GEOTRSFRM_WE_RES] = poParentDS->adfGeoTransform[GEOTRSFRM_WE_RES] * nOverviewFactor;
+            adfGeoTransform[GEOTRSFRM_NS_RES] = poParentDS->adfGeoTransform[GEOTRSFRM_NS_RES] * nOverviewFactor;
+        }
+        else if ((resolutionStrategy == AVERAGE_RESOLUTION ||
+             resolutionStrategy == AVERAGE_APPROX_RESOLUTION) && nTiles > 0) {
             adfGeoTransform[GEOTRSFRM_WE_RES] /= nTiles;
             adfGeoTransform[GEOTRSFRM_NS_RES] /= nTiles;
         }
         
-        nRasterXSize = (int) fabs(rint((xmax - xmin) / adfGeoTransform[GEOTRSFRM_WE_RES]));
-        nRasterYSize = (int) fabs(rint((ymax - ymin) / adfGeoTransform[GEOTRSFRM_NS_RES]));
+    } // end else
+    
+    /**
+     * Complete the rest of geotransform parameters
+     **/
+    if (adfGeoTransform[GEOTRSFRM_NS_RES] >= 0.0)
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = ymin;
+    else
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = ymax;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+        "GeoTransform array = (%f, %f, %f, %f, %f, %f)",
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+        adfGeoTransform[GEOTRSFRM_WE_RES],
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1], 
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y],
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2], 
+        adfGeoTransform[GEOTRSFRM_NS_RES]);
+#endif
+
+    // Calculate the raster size from the geotransform array
+    nRasterXSize = (int) 
+        fabs(rint((xmax - xmin) / 
+            adfGeoTransform[GEOTRSFRM_WE_RES]));
+    
+    nRasterYSize = (int) 
+        fabs(rint((ymax - ymin) / 
+            adfGeoTransform[GEOTRSFRM_NS_RES]));
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+        "Raster size: (%d, %d), ",nRasterXSize, nRasterYSize);
+#endif
+
+    if (nRasterXSize <= 0 || nRasterYSize <= 0) {
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Computed PostGIS Raster dimension is invalid. You've "
+            "probably specified unappropriate resolution.");
         
+        return false;
+    }
+    
+    /*******************************************************************
+     * Now construct the dataset bands
+     ******************************************************************/
+    BuildBands(poBandMetaData, nBandsFetched);
 
-        if (nRasterXSize <= 0 || nRasterYSize <= 0) {
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                "Computed PostGIS Raster dimension is invalid. You've probably specified "
-                "unappropriate resolution.");
-            return CE_Failure;
+    // And free bandmetadata
+    VSIFree(poBandMetaData);
+
+    
+    /*******************************************************************
+     * Finally, add complex sources and create a quadtree index for them
+     ******************************************************************/
+    if (bNeedToConstructSourcesHolders) {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+            "Finally, adding sources for bands");
+#endif
+        for(int iSource = 0; iSource < nTiles; iSource++)
+        {
+            PostGISRasterTileDataset* poRTDS =papoSourcesHolders[iSource];
+            if (!AddComplexSource(poRTDS))
+            {
+                CPLDebug("PostGIS_Raster",
+                    "PostGISRasterDataset::ConstructOneDatasetFromTiles:"
+                    "Bounding box of tile %d does not intersect the "
+                    "bounding box of dataset ", iSource);
+
+                continue;
+            }
+            if( poRTDS->pszPKID != NULL )
+                oMapPKIDToRTDS[poRTDS->pszPKID] = poRTDS;
+            CPLQuadTreeInsert(hQuadTree, poRTDS);
         }
+    }
 
-        /**
-         * Regular blocking: get the last values for tile width and height as block
-         * size
-         **/
-        if (bRegularBlocking) {
-            nBlockXSize = nTileWidth;
-            nBlockYSize = nTileHeight;
+    return true;
+}
+
+
+
+/***********************************************************************
+ * \brief Construct subdatasets and show them.
+ * 
+ * This method is not very elegant. It's strongly attached to 
+ * SetRasterProperties (it assumes poResult is not NULL, and the actual
+ * results are stored at fixed positions). I just did it to avoid a
+ * huge SetRasterProperties method.
+ * 
+ * I know, this could be avoided in a better way. Like implementing a
+ * wrapper to raise queries and get results without all the checking
+ * overhead. I'd like to do it, someday...
+ **********************************************************************/
+GBool PostGISRasterDataset::YieldSubdatasets(PGresult * poResult,
+const char * pszValidConnectionString)
+{
+    int nTiles = PQntuples(poResult);
+    int i = 0;
+    double dfTileUpperLeftX = 0;
+    double dfTileUpperLeftY = 0;
+    
+    papszSubdatasets = (char**)VSICalloc(2 * nTiles + 1, sizeof(char*));
+    if( papszSubdatasets == NULL )
+        return false;
+    
+    // Subdatasets identified by primary key
+    if (GetPrimaryKeyRef() != NULL) {
+        
+        for(i = 0; i < nTiles; i++) {
+            
+            const char* pszId = PQgetvalue(poResult, i, 0);
+        
+            papszSubdatasets[2 * i] = 
+                CPLStrdup(CPLSPrintf("SUBDATASET_%d_NAME=PG:%s schema=%s table=%s column=%s "
+                    "where='%s = %s'", i+ 1, pszValidConnectionString, 
+                    pszSchema, pszTable, pszColumn, pszPrimaryKeyName, 
+                    pszId));
+
+            papszSubdatasets[2 * i + 1] = 
+                CPLStrdup(CPLSPrintf("SUBDATASET_%d_DESC=PostGIS Raster at %s.%s (%s), with %s = %s", 
+                    i + 1, pszSchema, pszTable, pszColumn, pszPrimaryKeyName, 
+                    pszId));
         }
+    } 
         
-        PQclear(poResult);
-
+    // Subdatasets identified by upper left pixel
+    else {
+        
+        char * pszRes;
+        char * pszFilteredRes;
+        char ** papszParams;
+        
+        for(i = 0; i < nTiles; i++) {
+            
+            pszRes = CPLStrdup(PQgetvalue(poResult, i, 0));
+        
+            // Skip first "("
+            pszFilteredRes = pszRes + 1;
+            
+            // Skip last ")"
+            pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
+            
+            // Tokenize
+            papszParams = 
+                CSLTokenizeString2(pszFilteredRes, ",", 
+                    CSLT_HONOURSTRINGS);
+                    
+            CPLFree(pszRes);
+        
+            dfTileUpperLeftX = CPLAtof(papszParams[POS_UPPERLEFTX]);
+            dfTileUpperLeftY = CPLAtof(papszParams[POS_UPPERLEFTY]);
+        
+            CPLLocaleC oCLocale;
+            papszSubdatasets[2 * i] = 
+                CPLStrdup(CPLSPrintf("SUBDATASET_%d_NAME=PG:%s schema=%s table=%s column=%s "
+                    "where='abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 AND "
+                    "abs(ST_UpperLeftY(%s) - %.8f) < 1e-8'",
+                    i + 1, pszValidConnectionString, pszSchema, pszTable, 
+                    pszColumn, pszColumn, dfTileUpperLeftX, pszColumn, 
+                    dfTileUpperLeftY));
+
+             papszSubdatasets[2 * i + 1] = 
+                CPLStrdup(CPLSPrintf("SUBDATASET_%d_DESC=PostGIS Raster at %s.%s (%s), "
+                "UpperLeft = %.8f, %.8f", i + 1, pszSchema, pszTable, pszColumn, 
+                dfTileUpperLeftX, dfTileUpperLeftY));
+                
+            CSLDestroy(papszParams);
+        }
+    }
     
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "adfGeoTransform = {%f, %f, %f, %f, %f,%f}", adfGeoTransform[GEOTRSFRM_TOPLEFT_X],
-            adfGeoTransform[GEOTRSFRM_WE_RES], adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1], 
-            adfGeoTransform[GEOTRSFRM_TOPLEFT_Y],adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2], 
-            adfGeoTransform[GEOTRSFRM_NS_RES]);
+    /**
+     * Not a single raster fetched. Not really needed. Just to keep code clean 
+     **/
+    nRasterXSize = 0;
+    nRasterYSize = 0;
+    adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0.0;
+    adfGeoTransform[GEOTRSFRM_WE_RES] = 1.0;
+    adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
+    adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0.0;
+    adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
+    adfGeoTransform[GEOTRSFRM_NS_RES] = -1.0;
+
+    return true;
+}
 
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "Raster size = (%d, %d)", nRasterXSize, nRasterYSize);
 
 
-        /****************************************************************************
-         * Dataset parameters are set. Now, let's add the raster bands
-         ***************************************************************************/
+/***********************************************************************
+ * \brief Set the general raster properties.
+ *
+ * This method is called when the driver working mode is 
+ * ONE_RASTER_PER_ROW or ONE_RASTER_PER_TABLE.
+ * 
+ * We must distinguish between tiled and untiled raster coverages. In
+ * PostGIS Raster, there's no real difference between 'tile' and 
+ * 'raster'. There's only 'raster objects'. Each record of a raster 
+ * table is a raster object, and has its own georeference information, 
+ * whether if the record is a tile of a bigger raster coverage or is a 
+ * complete raster. So, <b>there's no a way of knowing if the rows of a 
+ * raster table are related or not</b>. It's user's responsibility, and
+ * it's managed by 'mode' parameter in connection string, which
+ * determines the driver working mode.
+ *
+ * The user is responsible to ensure that the raster layer meets the 
+ * minimum topological requirements for analysis. The ideal case is when 
+ * all the raster tiles of a continuous layer are the same size, snap to 
+ * the same grid and do not overlap. 
+ * 
+ **********************************************************************/
+GBool PostGISRasterDataset::SetRasterProperties
+    (const char * pszValidConnectionString)
+{
+    PGresult* poResult = NULL;
+    CPLString osCommand;
+    GBool bDataFoundInRasterColumns = false;
+    GBool bNeedToCheckWholeTable = false;
+
+    /*******************************************************************
+     * Get the extent and the maximum number of bands of the requested 
+     * raster-
+     * 
+     * TODO: The extent of rotated rasters could be a problem. We'll 
+     * need a ST_RotatedExtent function in PostGIS. Without that 
+     * function, we shouldn't allow rotated rasters
+     ******************************************************************/
+    if (pszWhere != NULL) {
+        osCommand.Printf(
+            "select srid, nbband, ST_XMin(geom) as xmin, "
+            "ST_XMax(geom) as xmax, ST_YMin(geom) as ymin, "
+            "ST_YMax(geom) as ymax, scale_x, scale_y from (select ST_SRID(%s) srid, "
+            "ST_Extent(%s::geometry) geom, max(ST_NumBands(%s)) "
+            "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s where %s group by ST_SRID(%s)) foo", 
+            pszColumn, pszColumn, pszColumn, pszColumn, pszColumn,
+            pszSchema, pszTable, pszWhere, 
+            pszColumn);
+            
+#ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::SetRasterProperties(): First query: %s", 
+        osCommand.c_str());
+#endif
+
+        poResult = PQexec(poConn, osCommand.c_str());
+    }
+    
+    else {
+        
+        /**
+         * Optimization: First, check raster_columns view (it makes 
+         * things faster. See ticket #5046)
+         * 
+         * This can only be applied if we don't have a 'where' clause, 
+         * because raster_columns view stores statistics about the whole
+         * table. If the user specified 'where' clause is because is 
+         * just interested in a subset of the table rows.
+         **/
+        osCommand.Printf(
+            "select srid, nbband, ST_XMin(geom) as xmin, ST_XMax(geom) "
+            "as xmax, ST_YMin(geom) as ymin, ST_YMax(geom) as ymax, "
+            "scale_x, scale_y, blocksize_x, blocksize_y, same_alignment, regular_blocking "
+            "from (select srid, extent geom, num_bands nbband, "
+            "scale_x, scale_y, blocksize_x, blocksize_y, same_alignment, regular_blocking from "
+            "raster_columns where r_table_schema = '%s' and "
+            "r_table_name = '%s') foo", pszSchema, pszTable);
+            
+#ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::SetRasterProperties(): First query: %s", 
+        osCommand.c_str());
+#endif
+        
+        poResult = PQexec(poConn, osCommand.c_str());
+            
+        // Query execution error
+        if(poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+            PQntuples(poResult) < 0) {
+            
+            bNeedToCheckWholeTable = true;
+            
+            if (poResult)
+                PQclear(poResult);
+        
+        }
+        
+        /**
+         * We didn't find anything in raster_columns view. Need to check
+         * the whole table for metadata
+         **/
+        else if (PQntuples(poResult) == 0) {
+            
+            ReportError(CE_Warning, CPLE_AppDefined, "Cannot find "
+            "information about %s.%s table in raster_columns view. The "
+            "raster table load would take a lot of time. Please, "
+            "execute AddRasterConstraints PostGIS function to register "
+            "this table as raster table in raster_columns view. This "
+            "will save a lot of time.", pszSchema, pszTable);
+            
+            PQclear(poResult);
+            
+            bNeedToCheckWholeTable = true;
+        }
+        
+        /* There's a result but the row has empty values */
+        else if (PQntuples(poResult) == 1 &&
+                 (PQgetvalue(poResult, 0, 1)[0] == '\0' ||
+                 (poParentDS == NULL &&
+                  (PQgetvalue(poResult, 0, 2)[0] == '\0' ||
+                  PQgetvalue(poResult, 0, 3)[0] == '\0' ||
+                  PQgetvalue(poResult, 0, 4)[0] == '\0' ||
+                  PQgetvalue(poResult, 0, 5)[0] == '\0'))) ) {
+            ReportError(CE_Warning, CPLE_AppDefined, "Cannot find (valid) "
+            "information about %s.%s table in raster_columns view. The "
+            "raster table load would take a lot of time. Please, "
+            "execute AddRasterConstraints PostGIS function to register "
+            "this table as raster table in raster_columns view. This "
+            "will save a lot of time.", pszSchema, pszTable);
+            
+            PQclear(poResult);
+            
+            bNeedToCheckWholeTable = true;
+        }
+        
+        
+        // We should check whole table but we can't
+        if (bNeedToCheckWholeTable && !bCheckAllTiles) {
+            ReportError(CE_Failure, CPLE_AppDefined, "Cannot find "
+            "information about %s.%s table in raster_columns view. "
+            "Please, execute AddRasterConstraints PostGIS function to "
+            "register this table as raster table in raster_columns "
+            "view. This will save a lot of time. As alternative, "
+            "provide configuration option "
+            "PR_ALLOW_WHOLE_TABLE_SCAN=YES. With this option, the "
+            "driver will work even without the table information "
+            "stored in raster_columns view, but it could perform "
+            "really slow.", pszSchema, pszTable);
+            
+            PQclear(poResult);
+            
+            return false;
+            
+        }
+        
+        
+        // We should check the whole table and we can
+        else if (bNeedToCheckWholeTable) {
+            osCommand.Printf(
+                "select srid, nbband, st_xmin(geom) as xmin, "
+                "st_xmax(geom) as xmax, st_ymin(geom) as ymin, "
+                "st_ymax(geom) as ymax, scale_x, scale_y from (select st_srid(%s) srid, "
+                "st_extent(%s::geometry) geom, max(ST_NumBands(%s)) "
+                "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s group by st_srid(%s)) foo", 
+                pszColumn, pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, pszColumn);
+                
+#ifdef DEBUG_QUERY
+            CPLDebug("PostGIS_Raster", 
+                "PostGISRasterDataset::SetRasterProperties(): "
+                "First query: %s", osCommand.c_str());
+#endif
+
+            poResult = PQexec(poConn, osCommand.c_str()); 
+        }
         
-        /* Create query to fetch metadata from db */
-        if (pszWhere == NULL) {
-            osCommand.Printf("select st_bandpixeltype(rast, band), "
-                "st_bandnodatavalue(rast, band) is null, "
-                "st_bandnodatavalue(rast, band) from (select %s, "
-                "generate_series(1, st_numbands(%s)) band from (select "
-                "rast from %s.%s limit 1) bar) foo",
-                pszColumn, pszColumn, pszSchema, pszTable);
-        } 
-
+        
+        // We already found the data in raster_columns
         else {
-            osCommand.Printf("select st_bandpixeltype(rast, band), "
-                "st_bandnodatavalue(rast, band) is null, "
-                "st_bandnodatavalue(rast, band) from (select %s, "
-                "generate_series(1, st_numbands(%s)) band from (select "
-                "rast from %s.%s where %s limit 1) bar) foo",
-                pszColumn, pszColumn, pszSchema, pszTable, pszWhere);
+            bDataFoundInRasterColumns = true;
         }
+    }
 
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "Query: %s", osCommand.c_str());
+    // Query execution error
+    if(poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        PQntuples(poResult) < 0) {
         
-        poResult = PQexec(poConn, osCommand.c_str());
-        nTuples = PQntuples(poResult);
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error browsing database for PostGIS Raster "
+            "properties : %s",  PQerrorMessage(poConn));
 
-        /* Error getting info from database */
-        if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-            nTuples <= 0) {
-            
-            CPLError(CE_Failure, CPLE_AppDefined, "Error getting band metadata "
-                "while creating raster bands");
-                
-            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): %s", 
-                    PQerrorMessage(poConn));
+        if (poResult != NULL)
+            PQclear(poResult);
+
+        return false;                  
+    
+    }
+    
+    else if (PQntuples(poResult) == 0) {
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "No results found in %s.%s. Did you specify a 'where' "
+            "clause too restrictive?", pszSchema, pszTable);
             
-            if (poResult)
-                PQclear(poResult);
+        PQclear(poResult);
+        
+        return false;
+    }
 
-            return false;
-        }
+    
+    /**
+     * Found more than one SRID value in the table. Not allowed.
+     * 
+     * TODO: We could provide an extra parameter, to transform all the 
+     * tiles to the same SRID
+     **/
+    else if (PQntuples(poResult) > 1) {
+        ReportError(CE_Failure, CPLE_AppDefined,
+            "Error, the table %s.%s contains tiles with different "
+            "srid. This feature is not yet supported by the PostGIS "
+            "Raster driver. Please, specify a table that contains only "
+            "tiles with the same srid or provide a 'where' constraint "
+            "to select just the tiles with the same value for srid", 
+            pszSchema, pszTable);
 
-        /* Create each PostGISRasterRasterBand using the band metadata */
-        for (iBand = 0; iBand < nTuples; iBand++) {
-            /**
-             * If we have more than one record here is because there are several
-             * rows, belonging to the same raster coverage, with different band
-             * metadata values. An error must be raised.
-             *
-             * TODO: Is there any way to fix this problem?
-             *
-             * TODO: Even when the difference between metadata values are only a
-             * few decimal numbers (for example: 3.0000000 and 3.0000001) they're
-             * different tuples. And in that case, they must be the same
-             **/
-            /*
-            if (nTuples > 1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "Error, the \
-                    ONE_RASTER_PER_TABLE mode can't be applied if the raster \
-                    rows don't have the same metadata for band %d",
-                    iBand + 1);
-                PQclear(poResult);
-                return false;
-            }
-            */
-
-
-            /* Get metadata and create raster band objects */
-            pszDataType = CPLStrdup(PQgetvalue(poResult, iBand, 0));
-            bHasNoDataValue = EQUALN(PQgetvalue(poResult, iBand, 1), "f", sizeof(char));
-            dfNodata = atof(PQgetvalue(poResult, iBand, 2));
-            /** 
-             * Offline rasters are not yet supported. When offline rasters are
-             * supported, they will also requires a fast 'getter', other than 
-             * the ST_BandMetaData accessor.
-             **/
-            
-            /* bIsOffline = EQUALN(PQgetvalue(poResult, iBand, 3), "t", sizeof (char));        */
-
-            if (EQUALN(pszDataType, "1BB", 3 * sizeof (char))) {
-                hDataType = GDT_Byte;
-                nBitDepth = 1;
-            } else if (EQUALN(pszDataType, "2BUI", 4 * sizeof (char))) {
-                hDataType = GDT_Byte;
-                nBitDepth = 2;
-            } else if (EQUALN(pszDataType, "4BUI", 4 * sizeof (char))) {
-                hDataType = GDT_Byte;
-                nBitDepth = 4;
-            } else if (EQUALN(pszDataType, "8BUI", 4 * sizeof (char))) {
-                hDataType = GDT_Byte;
-                nBitDepth = 8;
-            } else if (EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) {
-                hDataType = GDT_Byte;
-                /**
-                 * To indicate the unsigned byte values between 128 and 255
-                 * should be interpreted as being values between -128 and -1 for
-                 * applications that recognise the SIGNEDBYTE type.
-                 **/
-                bSignedByte = true;
-                nBitDepth = 8;
-            } else if (EQUALN(pszDataType, "16BSI", 5 * sizeof (char))) {
-                hDataType = GDT_Int16;
-                nBitDepth = 16;
-            } else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char))) {
-                hDataType = GDT_UInt16;
-                nBitDepth = 16;
-            } else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char))) {
-                hDataType = GDT_Int32;
-                nBitDepth = 32;
-            } else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char))) {
-                hDataType = GDT_UInt32;
-                nBitDepth = 32;
-            } else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char))) {
-                hDataType = GDT_Float32;
-                nBitDepth = 32;
-            } else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char))) {
-                hDataType = GDT_Float64;
-                nBitDepth = 64;
-            } else {
-                hDataType = GDT_Byte;
-                nBitDepth = 8;
-            }
+        PQclear(poResult);
+        
+        return false;
+    }
 
-            /* Create raster band object */
-            SetBand(iBand + 1, new PostGISRasterRasterBand(this, iBand + 1, hDataType,
-                bHasNoDataValue, dfNodata, bSignedByte, nBitDepth, 0, nBlockXSize, 
-                nBlockYSize, bIsOffline));
+    // Get some information we will probably need further
+    nSrid = atoi(PQgetvalue(poResult, 0, 0));
+    nBandsToCreate = atoi(PQgetvalue(poResult, 0, 1));
+    if( poParentDS != NULL )
+    {
+        /* If we are an overview of a parent dataset, we need to adjust */
+        /* to its extent, otherwise IRasterIO() will not work properly */
+        xmin = poParentDS->xmin;
+        xmax = poParentDS->xmax;
+        ymin = poParentDS->ymin;
+        ymax = poParentDS->ymax;
+    }
+    else
+    {
+        xmin = CPLAtof(PQgetvalue(poResult, 0, 2));
+        xmax = CPLAtof(PQgetvalue(poResult, 0, 3));
+        ymin = CPLAtof(PQgetvalue(poResult, 0, 4));
+        ymax = CPLAtof(PQgetvalue(poResult, 0, 5));
+    }
 
-            CPLFree(pszDataType);
-        }
+    // Create the QuadTree object
+    CPLRectObj sRect;
+    sRect.minx = xmin;
+    sRect.miny = ymin;
+    sRect.maxx = xmax;
+    sRect.maxy = ymax;
+    hQuadTree = CPLQuadTreeCreate(&sRect, GetTileBoundingBox);
+
+    double scale_x = CPLAtof(PQgetvalue(poResult, 0, 6));
+    double scale_y = CPLAtof(PQgetvalue(poResult, 0, 7));
+    if( nOverviewFactor > 1 )
+    {
+        scale_x = poParentDS->adfGeoTransform[GEOTRSFRM_WE_RES] * nOverviewFactor;
+        scale_y = poParentDS->adfGeoTransform[GEOTRSFRM_NS_RES] * nOverviewFactor;
+    }
+    else if( resolutionStrategy == USER_RESOLUTION)
+    {
+        scale_x = adfGeoTransform[GEOTRSFRM_WE_RES];
+        scale_y = adfGeoTransform[GEOTRSFRM_NS_RES];
+    }
+    
+    // These fields can only be fetched from raster_columns view
+    if (bDataFoundInRasterColumns)
+    {
+        nTileWidth = atoi(PQgetvalue(poResult, 0, 8));
+        nTileHeight = atoi(PQgetvalue(poResult, 0, 9));
+        if( nTileWidth != 0 && nTileHeight != 0 )
+            bTilesSameDimension = true;
 
-        PQclear(poResult);
+        bAllTilesSnapToSameGrid =
+            EQUALN(PQgetvalue(poResult, 0, 10), "t", sizeof(char));
+        
+        bRegularBlocking = 
+            EQUALN(PQgetvalue(poResult, 0, 11), "t", sizeof(char));
     }
 
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::SetRasterProperties: xmin = %f, "
+        "xmax = %f, ymin = %f, ymax = %f, scale_x = %f, scale_y = %f",
+             xmin, xmax, ymin, ymax, scale_x, scale_y);
+#endif
 
-    /*****************************************************************************
-     * One raster per row: collect subdatasets 
-     ****************************************************************************/
-    else {
-        /* Determine the primary key/unique column on the table */
-        osCommand.Printf("select d.attname from pg_catalog.pg_constraint as a "
-            "join pg_catalog.pg_indexes as b on a.conname = b.indexname "
-            "join pg_catalog.pg_class as c on c.relname = b.tablename "
-            "join pg_catalog.pg_attribute as d on c.relfilenode = d.attrelid "
-            "where b.schemaname = '%s' and b.tablename = '%s' and "
-            "d.attnum = a.conkey[1] and a.contype in ('p', 'u')", pszSchema, pszTable);
+    PQclear(poResult);
+    
+    /*******************************************************************
+     * Now, we fetch the metadata of all the raster tiles in the 
+     * database, that will allow us to construct VRT sources to the
+     * PostGIS Raster bands.
+     * 
+     * TODO: Improve this. If we have a big amount of tiles, it can be
+     * a problem.
+     ******************************************************************/
+    // We'll identify each tile for its primary key/unique id (ideal)
+    if (GetPrimaryKeyRef() != NULL)
+    {
+        if (pszWhere == NULL)
+        {
+            /* If we don't know the pixel size, then guess it from averaging the metadata */
+            /* of a maximum 10 rasters */
+            if( bIsFastPK && nMode == ONE_RASTER_PER_TABLE && HasSpatialIndex() &&
+                (scale_x == 0 || scale_y == 0) &&
+                resolutionStrategy == AVERAGE_APPROX_RESOLUTION )
+            {
+                osCommand.Printf("SELECT avg(scale_x) avg_scale_x, avg(scale_y) avg_scale_y FROM "
+                                 "(SELECT ST_ScaleX(%s) scale_x, ST_ScaleY(%s) scale_y FROM %s.%s LIMIT 10) foo",
+                                 pszColumn, pszColumn, pszSchema, pszTable);
+                #ifdef DEBUG_QUERY
+                    CPLDebug("PostGIS_Raster", 
+                        "PostGISRasterDataset::SetRasterProperties(): Query: %s", 
+                        osCommand.c_str());
+                #endif
+
+                poResult = PQexec(poConn, osCommand.c_str());
+                if (poResult == NULL || 
+                    PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+                    PQntuples(poResult) <= 0) {
+
+                    ReportError(CE_Failure, CPLE_AppDefined, 
+                        "Error retrieving raster metadata");
+
+                    CPLDebug("PostGIS_Raster", 
+                        "PostGISRasterDataset::SetRasterProperties(): %s", 
+                        PQerrorMessage(poConn));
 
-        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-            "Query: %s", osCommand.c_str());
+                    if (poResult != NULL)
+                        PQclear(poResult);
 
+                    return false;
+                }
 
-        poResult = PQexec(poConn, osCommand.c_str());
-        if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-            PQntuples(poResult) <= 0 ) {
+                scale_x = CPLAtof(PQgetvalue(poResult, 0, 0));
+                scale_y = CPLAtof(PQgetvalue(poResult, 0, 1));
+                CPLDebug("PostGIS_Raster",
+                         "PostGISRasterDataset::SetRasterProperties: guessed: scale_x = %f, scale_y = %f",
+                         scale_x, scale_y);
 
-            PQclear(poResult);
+                PQclear(poResult);
+            }
 
-            /*
-              Maybe there is no primary key or unique constraint;
-              a sequence will also suffice; get the first one
-            */
+            /* If we build a raster for the whole table, than we have a spatial index,
+               and a primary key, and we know the pixel size, we can build the dataset
+               immediately, and IRasterIO() queries will be able to retrieve quickly
+               the PKID of the tiles to fetch, so we don't need to scan the whole table */
+            if( bIsFastPK && nMode == ONE_RASTER_PER_TABLE && HasSpatialIndex() &&
+                scale_x != 0 && scale_y != 0 ) 
+            {
+                adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = xmin;
+                adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
+                adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = (scale_y < 0) ? ymax : ymin;
+                adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
+                adfGeoTransform[GEOTRSFRM_WE_RES] = scale_x;
+                adfGeoTransform[GEOTRSFRM_NS_RES] = scale_y;
+
+                // Calculate the raster size from the geotransform array
+                nRasterXSize = (int) 
+                    fabs(rint((xmax - xmin) / 
+                        adfGeoTransform[GEOTRSFRM_WE_RES]));
+                
+                nRasterYSize = (int) 
+                    fabs(rint((ymax - ymin) / 
+                        adfGeoTransform[GEOTRSFRM_NS_RES]));
 
-            osCommand.Printf("select cols.column_name from information_schema."
-                "columns as cols join information_schema.sequences as seqs on cols."
-                "column_default like '%%'||seqs.sequence_name||'%%' where cols."
-                "table_schema = '%s' and cols.table_name = '%s'", pszSchema, pszTable);
+            #ifdef DEBUG_VERBOSE
+                CPLDebug("PostGIS_Raster", 
+                    "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
+                    "Raster size: (%d, %d), ",nRasterXSize, nRasterYSize);
+            #endif
 
-            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                "Query: %s", osCommand.c_str());
+                if (nRasterXSize <= 0 || nRasterYSize <= 0) {
+                    ReportError(CE_Failure, CPLE_AppDefined, 
+                        "Computed PostGIS Raster dimension is invalid. You've "
+                        "probably specified unappropriate resolution.");
 
-            poResult = PQexec(poConn, osCommand.c_str());
+                    return false;
+                }
 
-            if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-                PQntuples(poResult) <= 0) {
+                bBuildQuadTreeDynamically = true;
 
-                CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                    "Could not find a primary key or unique column on the specified table; "
-                    "using UpperLeftX and UpperLeftY.");
+                /*******************************************************************
+                * Now construct the dataset bands
+                ******************************************************************/
+                int nBandsFetched = 0;
+                BandMetadata * poBandMetaData = GetBandsMetadata(&nBandsFetched);
 
+                BuildBands(poBandMetaData, nBandsFetched);
 
-                /*
-                    If no primary key or unique column found, 
-                    fall back to raster upperleft x&y
-                */
-            }
+                // And free bandmetadata
+                VSIFree(poBandMetaData);
 
-            else {
-                pszIdColumn = CPLStrdup(PQgetvalue(poResult, 0, 0));
+                return true;
             }
 
+            osCommand.Printf("select %s, st_metadata(%s) from %s.%s",
+                pszPrimaryKeyName, pszColumn, pszSchema, pszTable);
+                        
+            // srid shouldn't be necessary. It was previously checked
         }
         
-        // Ok, get the primary key        
         else {
-            pszIdColumn = CPLStrdup(PQgetvalue(poResult, 0, 0));
+            osCommand.Printf("select %s, st_metadata(%s) from %s.%s "
+                "where %s", pszPrimaryKeyName, pszColumn, pszSchema, 
+                pszTable, pszWhere);
         }
+    }
 
-        PQclear(poResult);
-
-        /* No primary key on this table. Rely on UpperLeftX and UpperLeftY */
-        if (pszIdColumn == NULL) {
-            if (pszWhere == NULL) {
-                osCommand.Printf("select ST_UpperLeftX(%s), ST_UpperLeftY(%s) from %s.%s", pszColumn, 
-                    pszColumn, pszSchema, pszTable);
-            }
-
-            else {
-                osCommand.Printf("select ST_UpperLeftX(%s), ST_UpperLeftY(%s) from %s.%s where %s", 
-                    pszColumn, pszColumn, pszSchema, pszTable, pszWhere);
-            }
-                    
-
-            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                "Query: %s", osCommand.c_str());
-
-            poResult = PQexec(poConn, osCommand.c_str());
-            if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-                PQntuples(poResult) <= 0) {
-
-                    CPLError(CE_Failure, CPLE_AppDefined, "Error retrieving raster tile metadata "
-                        "while creating raster subdatasets");
-
-                    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                        "%s", PQerrorMessage(poConn));
-
-                    if (poResult != NULL)
-                        PQclear(poResult);
-
-                    // pszIdColumn is already null
-                    return false;
-            }
-
-            nTuples = PQntuples(poResult);
-
-            /* Now create the subdatasets */
-            for (i = 0; i < nTuples; i++) {
-                tileUpperLeftX = atof(PQgetvalue(poResult, i, 0)); //upperleft x
-                tileUpperLeftY = atof(PQgetvalue(poResult, i, 1)); //upperleft y
+    // No primary key/unique id found. We rely on upper left pixel
+    else {
+        if (pszWhere == NULL) {
+            osCommand.Printf("select st_metadata(%s) from %s.%s",
+                pszColumn, pszSchema, pszTable);
+        }
+        
+        else {
+            osCommand.Printf("select st_metadata(%s) from %s.%s "
+                "where %s", pszColumn, pszSchema, pszTable, pszWhere);
+        }
+    }
+   
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::SetRasterProperties(): Query: %s", 
+        osCommand.c_str());
+#endif
 
-                papszSubdatasets = CSLSetNameValue(papszSubdatasets, 
-                    CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
-                    CPLSPrintf("PG:%s schema=%s table=%s column=%s "
-                        "where='ST_UpperLeftX(%s) = %f AND ST_UpperLeftY(%s) = %f'",
-                        pszValidConnectionString, pszSchema, pszTable, pszColumn, 
-                        pszColumn, tileUpperLeftX, pszColumn, tileUpperLeftY));
+    poResult = PQexec(poConn, osCommand.c_str());
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) <= 0) {
 
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error retrieving raster metadata");
 
-                papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                    CPLSPrintf("PostGIS Raster at %s.%s (%s), UpperLeft = %f, %f", pszSchema,
-                        pszTable, pszColumn, tileUpperLeftX, tileUpperLeftY));
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::SetRasterProperties(): %s", 
+            PQerrorMessage(poConn));
 
-            }
-    
+        if (poResult != NULL)
             PQclear(poResult);
-        }
 
-        /* There is a primary key */
-        else {
-            if (pszWhere == NULL) {
-                osCommand.Printf("select %s from %s.%s", pszIdColumn, pszSchema, pszTable);
-            }
+        return false;
+    }
 
-            else {
-                osCommand.Printf("select %s from %s.%s where %s", pszIdColumn, 
-                    pszSchema, pszTable, pszWhere);
-            }
-            
-            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
-                "Query: %s", osCommand.c_str());
-            
-            poResult = PQexec(poConn, osCommand.c_str());
-            if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-                PQntuples(poResult) <= 0) {
-                
-                CPLError(CE_Failure, CPLE_AppDefined, "Error retrieving raster row metadata "
-                        "while creating raster subdatasets");
-                
-                CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): %s", 
-                    PQerrorMessage(poConn));
-                
-                
-                if (poResult != NULL)
-                    PQclear(poResult);
-                
-                if (pszIdColumn != NULL)
-                    CPLFree(pszIdColumn);
+    // Now we know the number of tiles that form our dataset
+    nTiles = PQntuples(poResult);
+    
+    
+    /*******************************************************************
+     * We are going to create a whole dataset as a mosaic with all the 
+     * tiles. We'll consider each tile as a VRT source for 
+     * PostGISRasterRasterBand. The data will be actually read by each 
+     * of these sources, and it will be cached in the sources' caches, 
+     * not in the PostGISRasterRasterBand cache
+     ******************************************************************/
+    if (nTiles == 1 || nMode == ONE_RASTER_PER_TABLE)
+    {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::SetRasterProperties(): "
+            "Constructing one dataset from %d tiles", nTiles);
+#endif
 
-                return false;
-                
-            }
-            
-            
-            nTuples = PQntuples(poResult);
-            
-            /* Now, create the subdatasets */
-            for (i = 0; i < nTuples; i++) {
-                // this is the raster ID (or unique column)
-                nRasterID = atoi(PQgetvalue(poResult, i, 0));
-                
-                papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
-                    CPLSPrintf("PG:%s schema=%s table=%s column=%s where='%s = %d'",
-                        pszValidConnectionString, pszSchema, pszTable, pszColumn, 
-                        pszIdColumn, nRasterID));
-                        
-                    
-                papszSubdatasets = CSLSetNameValue(papszSubdatasets,
-                    CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                    CPLSPrintf("PostGIS Raster at %s.%s (%s), %s = %d", pszSchema,
-                        pszTable, pszColumn, pszIdColumn, nRasterID));
-            }
-            
-            PQclear(poResult);
-        }
+        GBool res = ConstructOneDatasetFromTiles(poResult);
         
-        /**
-         * Not a single raster fetched. Not really needed. Just to keep code clean 
-         **/
-        nRasterXSize = 0;
-        nRasterYSize = 0;
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0.0;
-        adfGeoTransform[GEOTRSFRM_WE_RES] = 1.0;
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0.0;
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
-        adfGeoTransform[GEOTRSFRM_NS_RES] = -1.0;
+        PQclear(poResult);
         
-        if (pszIdColumn != NULL)
-            CPLFree(pszIdColumn);
+        return res;
     }
     
 
-    return true;
-}
+    /***************************************************************
+     * One raster per row: collect subdatasets 
+     **************************************************************/ 
+    else if (nMode == ONE_RASTER_PER_ROW) {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::SetRasterProperties(): "
+            "Reporting %d datasets", nTiles);
+#endif
 
-/******************************************************************************
- * \brief Get the connection information for a filename.
- ******************************************************************************/
+        GBool res = YieldSubdatasets(poResult, 
+            pszValidConnectionString);
+        
+        PQclear(poResult);
+        
+        return res;
+    }
+        
+    /***************************************************************
+     * Wrong mode: error 
+     **************************************************************/
+    else {
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Wrong driver working mode. You must specify mode = 1 or "
+            "mode = 2 in the connection string. Check PostGIS Raster "
+            "documentation at "
+            "http://trac.osgeo.org/gdal/wiki/frmts_wtkraster.html "
+            "for further information about working modes.");
+            
+        PQclear(poResult);
+            
+        return false;
+    }
+}
+         
+    
+/***********************************************************************
+ * \brief Get the connection information for a filename. 
+ * 
+ * This method extracts these dataset parameters from the connection 
+ * string, if present:
+ * - pszSchema: The schema where the table belongs
+ * - pszTable: The table's name
+ * - pszColumn: The raster column's name
+ * - pszWhere: A where constraint to apply to the table's rows
+ * - pszHost: The PostgreSQL host
+ * - pszPort: The PostgreSQL port
+ * - pszUser: The PostgreSQL user
+ * - pszPassword: The PostgreSQL password
+ * - nMode: The connection mode
+ * 
+ * If any of there parameters is not present in the connection string,
+ * default values are taken. nMode is deducted from the rest of
+ * parameters if not provided.
+ * 
+ * Apart from that, bBrowseDatabase is set to TRUE if the mode is 
+ * BROWSE_SCHEMA or BROWSE_DATABASE
+ **********************************************************************/
 static GBool
 GetConnectionInfo(const char * pszFilename, 
-    char ** ppszConnectionString, char ** ppszSchema, char ** ppszTable, 
+    char ** ppszConnectionString, char ** ppszDbname, char ** ppszSchema, char ** ppszTable, 
     char ** ppszColumn, char ** ppszWhere, char ** ppszHost, 
     char ** ppszPort, char ** ppszUser, char ** ppszPassword, 
-    int * nMode, GBool * bBrowseDatabase)
+    WorkingMode * nMode, GBool * bBrowseDatabase)
 {
     int nPos = -1, i;
     char * pszTmp = NULL;
@@ -1051,27 +2516,26 @@ GetConnectionInfo(const char * pszFilename,
         return false;
     }
 
-    /**************************************************************************
+    /*******************************************************************
      * Get mode:
-     *  - 1. ONE_RASTER_PER_ROW: Each row is considered as a separate raster
-     *  - 2. ONE_RASTER_PER_TABLE: All the table rows are considered as a whole
-     *      raster coverage
-     **************************************************************************/
+     *  - 1. ONE_RASTER_PER_ROW: Each row is considered as a separate 
+     *      raster
+     *  - 2. ONE_RASTER_PER_TABLE: All the table rows are considered as 
+     *      a whole raster coverage
+     ******************************************************************/
     nPos = CSLFindName(papszParams, "mode");
     if (nPos != -1) {
-        *nMode = atoi(CPLParseNameValue(papszParams[nPos], NULL));
-
-        if (*nMode != ONE_RASTER_PER_ROW && *nMode != ONE_RASTER_PER_TABLE) {
-            /* Unrecognized mode, using default one */
-            /*
-            CPLError(CE_Warning, CPLE_AppDefined, "Undefined working mode (%d)."
-                    " Valid working modes are 1 (ONE_RASTER_PER_ROW) and 2"
-                    " (ONE_RASTER_PER_TABLE). Using ONE_RASTER_PER_TABLE"
-                    " by default", nMode);
-             */
-            *nMode = ONE_RASTER_PER_ROW;
+        int tmp;
+        tmp = atoi(CPLParseNameValue(papszParams[nPos], NULL));
+        
+        // default value
+        *nMode = ONE_RASTER_PER_ROW;
+        
+        if (tmp == 2) {
+            *nMode = ONE_RASTER_PER_TABLE;
         }
 
+
         /* Remove the mode from connection string */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
     }
@@ -1093,6 +2557,9 @@ GetConnectionInfo(const char * pszFilename,
         return false;
     }
 
+    *ppszDbname = 
+        CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+
     /**
      * Case 2: There's database name, but no table name: activate a flag
      * for browsing the database, fetching all the schemas that contain
@@ -1105,14 +2572,16 @@ GetConnectionInfo(const char * pszFilename,
         /* Get schema name, if exist */
         nPos = CSLFindName(papszParams, "schema");
         if (nPos != -1) {
-            *ppszSchema = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+            *ppszSchema = 
+                CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+                
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
 
         /**
-         * Remove the rest of the parameters, if exist (they mustn't be present
-         * if we want a valid PQ connection string)
+         * Remove the rest of the parameters, if exist (they mustn't be 
+         * present if we want a valid PQ connection string)
          **/
         nPos = CSLFindName(papszParams, "column");
         if (nPos != -1) {
@@ -1126,25 +2595,28 @@ GetConnectionInfo(const char * pszFilename,
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
     } else {
-        *ppszTable = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+        *ppszTable = 
+            CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
         /* Delete this pair from params array */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
 
         /**
          * Case 3: There's database and table name, but no column
-         * name: Use a default column name and use the table to create the
-         * dataset
+         * name: Use a default column name and use the table to create 
+         * the dataset
          **/
         nPos = CSLFindName(papszParams, "column");
         if (nPos == -1) {
             *ppszColumn = CPLStrdup(DEFAULT_COLUMN);
         }
         /**
-         * Case 4: There's database, table and column name: Use the table to
-         * create a dataset
+         * Case 4: There's database, table and column name: Use the 
+         * table to create a dataset
          **/
         else {
-            *ppszColumn = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+            *ppszColumn = 
+                CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+                
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
@@ -1154,14 +2626,18 @@ GetConnectionInfo(const char * pszFilename,
         if (nPos == -1) {
             *ppszSchema = CPLStrdup(DEFAULT_SCHEMA);
         } else {
-            *ppszSchema = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+            *ppszSchema = 
+                CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+                
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
 
         nPos = CSLFindName(papszParams, "where");
         if (nPos != -1) {
-            *ppszWhere = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+            *ppszWhere = 
+                CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+                
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
@@ -1180,108 +2656,136 @@ GetConnectionInfo(const char * pszFilename,
     *ppszConnectionString = (char*) CPLCalloc(strlen(pszFilename),
             sizeof (char));
     for (i = 0; i < CSLCount(papszParams); i++) {
-        *ppszConnectionString = strncat(*ppszConnectionString, papszParams[i], strlen(papszParams[i]));
-        *ppszConnectionString = strncat(*ppszConnectionString, " ", strlen(" "));
+        *ppszConnectionString = 
+            strncat(*ppszConnectionString, papszParams[i], 
+                strlen(papszParams[i]));
+                
+        *ppszConnectionString = 
+            strncat(*ppszConnectionString, " ", strlen(" "));
     }
 
     nPos = CSLFindName(papszParams, "host");
     if (nPos != -1) {
-        *ppszHost = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+        *ppszHost = 
+            CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
-    else if (getenv("PGHOST") != NULL) {
-        *ppszHost = CPLStrdup(getenv("PGHOST"));
+    else if (CPLGetConfigOption("PGHOST", NULL) != NULL) {
+        *ppszHost = CPLStrdup(CPLGetConfigOption("PGHOST", NULL));
     }
-    else {
+    else
+        *ppszHost = NULL;
+    /*else {
         CPLError(CE_Failure, CPLE_AppDefined,
-                "Host parameter must be provided, or PGHOST environment "
-                "variable must be set. Please set the host and try again.");
+            "Host parameter must be provided, or PGHOST environment "
+            "variable must be set. Please set the host and try again.");
 
         CSLDestroy(papszParams);
 
         return false;
-    }
+    }*/
 
     nPos = CSLFindName(papszParams, "port");
     if (nPos != -1) {
-        *ppszPort = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+        *ppszPort = 
+            CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
-    else if (getenv("PGPORT") != NULL ) {
-        *ppszPort = CPLStrdup(getenv("PGPORT"));
+    else if (CPLGetConfigOption("PGPORT", NULL) != NULL ) {
+        *ppszPort = CPLStrdup(CPLGetConfigOption("PGPORT", NULL));
     }
-    else {
+    else
+        *ppszPort = NULL;
+    /*else {
         CPLError(CE_Failure, CPLE_AppDefined,
-                "Port parameter must be provided, or PGPORT environment "
-                "variable must be set. Please set the port and try again.");
+            "Port parameter must be provided, or PGPORT environment "
+            "variable must be set. Please set the port and try again.");
 
         CSLDestroy(papszParams);
 
         return false;
-    }
+    }*/
 
     nPos = CSLFindName(papszParams, "user");
     if (nPos != -1) {
-        *ppszUser = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+        *ppszUser = 
+            CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
-    else if (getenv("PGUSER") != NULL ) {
-        *ppszUser = CPLStrdup(getenv("PGUSER"));
+    else if (CPLGetConfigOption("PGUSER", NULL) != NULL ) {
+        *ppszUser = CPLStrdup(CPLGetConfigOption("PGUSER", NULL));
     }
-    else {
+    else
+        *ppszUser = NULL;
+    /*else {
         CPLError(CE_Failure, CPLE_AppDefined,
-                "User parameter must be provided, or PGUSER environment "
-                "variable must be set. Please set the user and try again.");
+            "User parameter must be provided, or PGUSER environment "
+            "variable must be set. Please set the user and try again.");
 
         CSLDestroy(papszParams);
 
         return false;
-    }
+    }*/
 
     nPos = CSLFindName(papszParams, "password");
     if (nPos != -1) {
-        *ppszPassword = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
+        *ppszPassword = 
+            CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
-    else {
-        // if PGPASSWORD is not set, ppszPassword is set to an empty string.
-        // this is okay, since there may be configurations in pg_hba.conf
-        // that don't require any password to connect
-        *ppszPassword = CPLStrdup(getenv("PGPASSWORD"));
+    else if (CPLGetConfigOption("PGPASSWORD", NULL) != NULL ) {
+        *ppszPassword = CPLStrdup(CPLGetConfigOption("PGPASSWORD", NULL));
     }
+    else
+        *ppszPassword = NULL;
 
     CSLDestroy(papszParams);
 
-    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::GetConnectionInfo(): "
-        "Mode: %d\nSchema: %s\nTable: %s\nColumn: %s\nWhere: %s\n"
-        "Host: %s\nPort: %s\nUser: %s\nPassword: %s\nConnection String: %s", 
-        *nMode, *ppszSchema, *ppszTable, *ppszColumn, 
-        *ppszWhere, *ppszHost, *ppszPort, *ppszUser, *ppszPassword, *ppszConnectionString);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::GetConnectionInfo(): "
+        "Mode: %d\nDbname: %s\nSchema: %s\nTable: %s\nColumn: %s\nWhere: %s\n"
+        "Host: %s\nPort: %s\nUser: %s\nPassword: %s\n"
+        "Connection String: %s\n", 
+        *nMode, *ppszDbname,
+        *ppszSchema ? *ppszSchema : "(null)",
+        *ppszTable ? *ppszTable : "(null)",
+        *ppszColumn ? *ppszColumn : "(null)",
+        *ppszWhere ? *ppszWhere : "(null)", 
+        *ppszHost ? *ppszHost : "(null)",
+        *ppszPort ? *ppszPort : "(null)",
+        *ppszUser ? *ppszUser : "(null)",
+        *ppszPassword ? *ppszPassword : "(null)", 
+        *ppszConnectionString);
+#endif
 
     return true;
 }
 
-/******************************************************************************
+/***********************************************************************
  * \brief Create a connection to a postgres database
- ******************************************************************************/
+ **********************************************************************/
 static PGconn *
 GetConnection(const char * pszFilename, char ** ppszConnectionString,
-    char ** ppszSchema, char ** ppszTable, char ** ppszColumn, char ** ppszWhere, 
-    int * nMode, GBool * bBrowseDatabase) 
+    char ** ppszSchema, char ** ppszTable, char ** ppszColumn, 
+    char ** ppszWhere, WorkingMode * nMode, GBool * bBrowseDatabase) 
 {
     PostGISRasterDriver * poDriver;
     PGconn * poConn = NULL;
+    char * pszDbname = NULL;
     char * pszHost = NULL;
     char * pszPort = NULL;
     char * pszUser = NULL;
     char * pszPassword = NULL;
 
-    if (GetConnectionInfo(pszFilename, ppszConnectionString, ppszSchema, 
+    if (GetConnectionInfo(pszFilename, ppszConnectionString, &pszDbname, ppszSchema, 
         ppszTable, ppszColumn, ppszWhere, &pszHost, &pszPort, &pszUser, 
         &pszPassword, nMode, bBrowseDatabase)) 
     {
-        /********************************************************************
+        /**************************************************************
          * Open a new database connection
-         ********************************************************************/
-        poDriver = (PostGISRasterDriver *)GDALGetDriverByName("PostGISRaster");
+         **************************************************************/
+        poDriver = 
+            (PostGISRasterDriver *)GDALGetDriverByName("PostGISRaster");
+            
         poConn = poDriver->GetConnection(*ppszConnectionString,
-                pszHost, pszPort, pszUser, pszPassword);
+                pszDbname, pszHost, pszPort, pszUser);
 
         if (poConn == NULL) {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1289,6 +2793,7 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
         }
     }
 
+    CPLFree(pszDbname);
     CPLFree(pszHost);
     CPLFree(pszPort);
     CPLFree(pszUser);
@@ -1297,10 +2802,24 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
     return poConn;
 }
 
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
+
+int PostGISRasterDataset::Identify(GDALOpenInfo* poOpenInfo)
+{
+    if (poOpenInfo->pszFilename == NULL ||
+        poOpenInfo->fp != NULL ||
+        !EQUALN(poOpenInfo->pszFilename, "PG:", 3))
+    {
+        return FALSE;
+    }
+    return TRUE;
+}
 
-/******************************************************************************
- * \brief Open a connection with PostgreSQL. The connection string will have
- * the PostgreSQL accepted format, plus the next key=value pairs:
+/***********************************************************************
+ * \brief Open a connection with PostgreSQL. The connection string will 
+ * have the PostgreSQL accepted format, plus the next key=value pairs:
  *  schema = <schema_name>
  *  table = <table_name>
  *  column = <column_name>
@@ -1308,41 +2827,28 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
  *  mode = <working mode> (1 or 2)
  *
  * These pairs are used for selecting the right raster table.
- *****************************************************************************/
+ **********************************************************************/
 GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
     char* pszConnectionString = NULL;
     char* pszSchema = NULL;
     char* pszTable = NULL;
     char* pszColumn = NULL;
     char* pszWhere = NULL;
-    int nMode = -1;
+    WorkingMode nMode = NO_MODE;
     PGconn * poConn = NULL;
     PostGISRasterDataset* poDS = NULL;
     GBool bBrowseDatabase = false;
     CPLString osCommand;
-    char * pszTmp;
 
     /**************************
      * Check input parameter
      **************************/
-    if (poOpenInfo->pszFilename == NULL ||
-            poOpenInfo->fp != NULL ||
-            !EQUALN(poOpenInfo->pszFilename, "PG:", 3))
-    {
-        /**
-         * Drivers must quietly return NULL if the passed file is not of
-         * their format. They should only produce an error if the file
-         * does appear to be of their supported format, but for some
-         * reason, unsupported or corrupt
-         */
+    if (!Identify(poOpenInfo))
         return NULL;
-    }
 
-    pszTmp = CPLStrdup(poOpenInfo->pszFilename);
-    
-    poConn = GetConnection((char *)poOpenInfo->pszFilename,
-        &pszConnectionString, &pszSchema, &pszTable, &pszColumn, &pszWhere,
-        &nMode, &bBrowseDatabase);
+    poConn = GetConnection(poOpenInfo->pszFilename,
+        &pszConnectionString, &pszSchema, &pszTable, &pszColumn, 
+        &pszWhere, &nMode, &bBrowseDatabase);
     if (poConn == NULL) {
         CPLFree(pszConnectionString);
         CPLFree(pszSchema);
@@ -1353,10 +2859,10 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
     }
     
 
-    /*************************************************************************
-     * No table will be read. Only shows information about the existent raster
-     * tables
-     *************************************************************************/
+    /*******************************************************************
+     * No table will be read. Only shows information about the existent 
+     * raster tables
+     ******************************************************************/
     if (bBrowseDatabase) {
         /**
          * Creates empty dataset object, only for subdatasets
@@ -1366,14 +2872,6 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         poDS->eAccess = GA_ReadOnly;
         //poDS->poDriver = poDriver;
         poDS->nMode = (pszSchema) ? BROWSE_SCHEMA : BROWSE_DATABASE;
-        poDS->nRasterXSize = 0;
-        poDS->nRasterYSize = 0;
-        poDS->adfGeoTransform[0] = 0.0;
-        poDS->adfGeoTransform[1] = 0.0;
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = 0.0;
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = 0.0;
 
         /**
          * Look for raster tables at database and
@@ -1404,11 +2902,10 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         if (pszWhere)
             CPLFree(pszWhere);
     }
-        /***********************************************************************
-         * A table will be read: Fetch raster properties from db. Pay attention
-         * to the block size: if the raster is blocked at database, the block
-         * size can be fetched from each block size, if regular blocking table
-         **********************************************************************/
+    
+    /*******************************************************************
+     * A table will be read as dataset: Fetch raster properties from db. 
+     ******************************************************************/
     else {
         poDS = new PostGISRasterDataset();
         poDS->poConn = poConn;
@@ -1424,21 +2921,16 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         /**
          * Fetch basic raster metadata from db
          **/
-
+#ifdef DEBUG_VERBOSE
         CPLDebug("PostGIS_Raster", "Open:: connection string = %s",
             pszConnectionString);
-        
+#endif
+
         if (!poDS->SetRasterProperties(pszConnectionString)) {
             CPLFree(pszConnectionString);
             delete poDS;
             return NULL;
         }
-
-        poDS->pszOriginalConnectionString = pszTmp;
-        
-        CPLDebug("PostGIS_Raster", "Open:: original connection string = %s",
-            poDS->pszOriginalConnectionString);
-
     }
 
     CPLFree(pszConnectionString);
@@ -1446,6 +2938,17 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
 
 }
 
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **PostGISRasterDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
 /*****************************************
  * \brief Get Metadata from raster
  * TODO: Add more options (the result of
@@ -1482,10 +2985,6 @@ const char* PostGISRasterDataset::GetProjectionRef() {
     poResult = PQexec(this->poConn, osCommand.c_str());
     if (poResult && PQresultStatus(poResult) == PGRES_TUPLES_OK
             && PQntuples(poResult) > 0) {
-        /*
-         * TODO: Memory leak detected with valgrind caused by allocation here.
-         * Even when the return string is freed
-         */
         pszProjection = CPLStrdup(PQgetvalue(poResult, 0, 0));
     }
 
@@ -1511,7 +3010,7 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
      * Check if the dataset allows updating
      *****************************************************************/
     if (GetAccess() != GA_Update) {
-        CPLError(CE_Failure, CPLE_NoWriteAccess,
+        ReportError(CE_Failure, CPLE_NoWriteAccess,
                 "This driver doesn't allow write access");
         return CE_Failure;
     }
@@ -1540,7 +3039,7 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
                 nSrid, pszTable, pszColumn);
         poResult = PQexec(poConn, osCommand.c_str());
         if (poResult == NULL || PQresultStatus(poResult) != PGRES_COMMAND_OK) {
-            CPLError(CE_Failure, CPLE_AppDefined,
+            ReportError(CE_Failure, CPLE_AppDefined,
                     "Couldn't update raster_columns table: %s",
                     PQerrorMessage(poConn));
             return CE_Failure;
@@ -1573,7 +3072,7 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
             poResult = PQexec(poConn, osCommand.c_str());
             if (poResult == NULL ||
                     PQresultStatus(poResult) != PGRES_COMMAND_OK) {
-                CPLError(CE_Failure, CPLE_AppDefined,
+                ReportError(CE_Failure, CPLE_AppDefined,
                         "Couldn't update raster_columns table: %s",
                         PQerrorMessage(poConn));
                 return CE_Failure;
@@ -1584,7 +3083,7 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
             return CE_None;
         }
         else {
-            CPLError(CE_Failure, CPLE_WrongFormat,
+            ReportError(CE_Failure, CPLE_WrongFormat,
                     "Couldn't find WKT neither proj4 definition");
             return CE_Failure;
         }
@@ -1594,16 +3093,11 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
 /********************************************************
  * \brief Set the affine transformation coefficients
  ********************************************************/
-CPLErr PostGISRasterDataset::SetGeoTransform(double* padfTransform) {
-    if (!padfTransform)
+CPLErr PostGISRasterDataset::SetGeoTransform(double* padfGeoTransform) {
+    if (!padfGeoTransform)
         return CE_Failure;
 
-    adfGeoTransform[0] = padfTransform[0];
-    adfGeoTransform[1] = padfTransform[1];
-    adfGeoTransform[2] = padfTransform[2];
-    adfGeoTransform[3] = padfTransform[3];
-    adfGeoTransform[4] = padfTransform[4];
-    adfGeoTransform[5] = padfTransform[5];
+    memcpy(adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
 
     return CE_None;
 }
@@ -1611,18 +3105,42 @@ CPLErr PostGISRasterDataset::SetGeoTransform(double* padfTransform) {
 /********************************************************
  * \brief Get the affine transformation coefficients
  ********************************************************/
-CPLErr PostGISRasterDataset::GetGeoTransform(double * padfTransform) {
+CPLErr PostGISRasterDataset::GetGeoTransform(double * padfGeoTransform) {
+
     // copy necessary values in supplied buffer
-    padfTransform[0] = adfGeoTransform[0];
-    padfTransform[1] = adfGeoTransform[1];
-    padfTransform[2] = adfGeoTransform[2];
-    padfTransform[3] = adfGeoTransform[3];
-    padfTransform[4] = adfGeoTransform[4];
-    padfTransform[5] = adfGeoTransform[5];
+    memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
+    
+    if( nRasterXSize == 0 && nRasterYSize == 0 )
+        return CE_Failure;
+    
+    /* To avoid QGIS trying to create a warped VRT for what is really */
+    /* an ungeoreferenced dataset */
+    if( CPLIsEqual(padfGeoTransform[0], 0.0) &&
+        CPLIsEqual(padfGeoTransform[1], 1.0) &&
+        CPLIsEqual(padfGeoTransform[2], 0.0) &&
+        CPLIsEqual(padfGeoTransform[3], 0.0) &&
+        CPLIsEqual(padfGeoTransform[4], 0.0) &&
+        CPLIsEqual(padfGeoTransform[5], 1.0) )
+    {
+        return CE_Failure;
+    }
 
     return CE_None;
 }
 
+
+/*********************************************************
+ * \brief Fetch files forming dataset. 
+ * 
+ * We need to define this method because the VRTDataset
+ * method doesn't check for NULL FileList before trying
+ * to collect the names of all sources' file list.
+ *********************************************************/
+char **PostGISRasterDataset::GetFileList()
+{
+	return NULL;
+}
+
 /********************************************************
  * \brief Create a copy of a PostGIS Raster dataset.
  ********************************************************/
@@ -1636,13 +3154,23 @@ PostGISRasterDataset::CreateCopy( const char * pszFilename,
     char* pszColumn = NULL;
     char* pszWhere = NULL;
     GBool bBrowseDatabase = false;
-    int nMode;
+    WorkingMode nMode;
     char* pszConnectionString = NULL;
     const char* pszSubdatasetName;
     PGconn * poConn = NULL;
     PGresult * poResult = NULL;
     CPLString osCommand;
     GBool bInsertSuccess;
+    
+    if( poGSrcDS->GetDriver() != GDALGetDriverByName("PostGISRaster") )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported, 
+            "PostGISRasterDataset::CreateCopy() only works on source "
+            "datasets that are PostGISRaster" );
+        return NULL;
+    }
+    
+    // Now we can do the cast
     PostGISRasterDataset *poSrcDS = (PostGISRasterDataset *)poGSrcDS;
     PostGISRasterDataset *poSubDS;
 
@@ -1932,8 +3460,10 @@ PostGISRasterDataset::InsertRaster(PGconn * poConn,
             poSrcDS->pszSchema, poSrcDS->pszTable, poSrcDS->pszWhere);
     }
 
+#ifdef DEBUG_QUERY
     CPLDebug("PostGIS_Raster", "PostGISRasterDataset::InsertRaster(): Query = %s",
         osCommand.c_str());
+#endif
 
     poResult = PQexec(poConn, osCommand.c_str());
     if (
@@ -1966,7 +3496,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
     char* pszWhere = NULL;
     GBool bBrowseDatabase;
     char* pszConnectionString = NULL;
-    int nMode;
+    WorkingMode nMode;
     PGconn * poConn = NULL;
     PGresult * poResult = NULL;
     CPLString osCommand;
@@ -2055,6 +3585,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
         poResult = PQexec(poConn, "commit");
         if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_COMMAND_OK) {
+                
             CPLError(CE_Failure, CPLE_AppDefined,
                 "Error committing database transaction: %s",
                 PQerrorMessage(poConn));
@@ -2080,12 +3611,68 @@ PostGISRasterDataset::Delete(const char* pszFilename)
     return nError;
 }
 
-/************************************************************************/
-/*                          GDALRegister_PostGISRaster()                */
+/***********************************************************************
+ * \brief Create an array with all the coordinates needed to construct
+ * a polygon using ST_PolygonFromText.
+ **********************************************************************/
+GBool PostGISRasterDataset::PolygonFromCoords(
+    int nXOff, int nYOff, int nXEndOff, int nYEndOff, 
+    double adfProjWin[8])
+{
+    // We first construct a polygon to intersect with
+    int ulx = nXOff;
+    int uly = nYOff;
+    int lrx = nXEndOff;
+    int lry = nYEndOff;
+
+    double xRes = adfGeoTransform[GEOTRSFRM_WE_RES]; 
+    double yRes = adfGeoTransform[GEOTRSFRM_NS_RES]; 
+
+    adfProjWin[0] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
+                    ulx * xRes + 
+                    uly * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
+    adfProjWin[1] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
+                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+                    uly * yRes;
+    adfProjWin[2] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
+                    lrx * xRes + 
+                    uly * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
+    adfProjWin[3] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
+                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+                    uly * yRes;
+    adfProjWin[4] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
+                    lrx * xRes + 
+                    lry * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
+    adfProjWin[5] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
+                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+                    lry * yRes;
+    adfProjWin[6] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
+                    ulx * xRes + 
+                    lry * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
+    adfProjWin[7] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
+                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+                    lry * yRes;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterDataset::PolygonFromCoords: constructed "
+        "polygon: POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, "
+        "%.17f %.17f, %.17f %.17f))", adfProjWin[0], adfProjWin[1], 
+        adfProjWin[2], adfProjWin[3], adfProjWin[4], adfProjWin[5], 
+        adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1]);
+#endif
 
-/************************************************************************/
+    return true;
+}
+
+/***********************************************************************
+ * GDALRegister_PostGISRaster()                
+ **********************************************************************/
 void GDALRegister_PostGISRaster() {
     GDALDriver *poDriver;
+    
+    if (! GDAL_CHECK_VERSION("PostGISRaster driver"))
+        return;
 
     if (GDALGetDriverByName("PostGISRaster") == NULL) {
         poDriver = new PostGISRasterDriver();
@@ -2096,6 +3683,7 @@ void GDALRegister_PostGISRaster() {
         poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 
         poDriver->pfnOpen = PostGISRasterDataset::Open;
+        poDriver->pfnIdentify = PostGISRasterDataset::Identify;
         poDriver->pfnCreateCopy = PostGISRasterDataset::CreateCopy;
         poDriver->pfnDelete = PostGISRasterDataset::Delete;
 
diff --git a/frmts/postgisraster/postgisrasterdriver.cpp b/frmts/postgisraster/postgisrasterdriver.cpp
index ada52c4..aec1fa1 100644
--- a/frmts/postgisraster/postgisrasterdriver.cpp
+++ b/frmts/postgisraster/postgisrasterdriver.cpp
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo at deimos-space.com
+ * Copyright (c) 2013, Even Rouault
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,34 +29,26 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 #include "postgisraster.h"
-#include "cpl_string.h"
+#include "cpl_multiproc.h"
 
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterDriver::PostGISRasterDriver() {
-    papoConnection = NULL;
-    nRefCount = 0;
+PostGISRasterDriver::PostGISRasterDriver()
+{
+    hMutex = NULL;
 }
 
 /************************
  * \brief Destructor
  ************************/
 PostGISRasterDriver::~PostGISRasterDriver() {
-    int i = 0;
 
-    for (i = 0; i < nRefCount; i++) {
-        /*
-         * Segmentation fault here. Tested CPLFree and delete. Same result
-         */
-        if (papoConnection[i]) {
-            PQfinish(papoConnection[i]);
-        }
-
-    }
-
-    if (papoConnection)
-        CPLFree(papoConnection);
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    std::map<CPLString, PGconn*>::iterator oIter = oMapConnection.begin();
+    for(; oIter != oMapConnection.end(); ++oIter )
+        PQfinish(oIter->second);
 }
 
 /***************************************************************************
@@ -64,7 +57,7 @@ PostGISRasterDriver::~PostGISRasterDriver() {
  * The PostGIS Raster driver keeps the connection with the PostgreSQL database
  * server for as long it leaves. Following PostGISRasterDataset instance 
  * can re-use the existing connection as long it used the same database, 
- * same user name, same password and same port.
+ * same host, port and user name.
  *
  * The PostGIS Raster driver will keep a list of all the successful 
  * connections so, when connection is requested and it does not exist
@@ -75,26 +68,31 @@ PostGISRasterDriver::~PostGISRasterDriver() {
  *
  ***************************************************************************/
 PGconn* PostGISRasterDriver::GetConnection(const char* pszConnectionString,
-        const char * pszHostIn, const char * pszPortIn, const char * pszUserIn,
-        const char * pszPasswordIn) {
-    int i = 0;
+        const char * pszDbnameIn, const char * pszHostIn, const char * pszPortIn, const char * pszUserIn)
+{
     PGconn * poConn = NULL;
+    
+    if( pszHostIn == NULL ) pszHostIn = "(null)";
+    if( pszPortIn == NULL ) pszPortIn = "(null)";
+    if( pszUserIn == NULL ) pszUserIn = "(null)";
+    CPLString osKey = pszDbnameIn;
+    osKey += "-";
+    osKey += pszHostIn;
+    osKey += "-";
+    osKey += pszPortIn;
+    osKey += "-";
+    osKey += pszUserIn;
+    osKey += "-";
+    osKey += CPLSPrintf(CPL_FRMT_GIB, CPLGetPID());
 
     /**
-     * Look for an existing connection in the list
+     * Look for an existing connection in the map
      **/
-    for (i = 0; i < nRefCount; i++) {
-        CPLDebug("PostGIS_Raster", "PostGISRasterDriver::GetConnection(): "
-            "User: %s\nPassword: %s\nHost: %s\nPort: %s", pszUserIn,
-            pszPasswordIn, pszHostIn, pszPortIn);
-        if (EQUAL(pszUserIn, PQuser(papoConnection[i])) &&
-                EQUAL(pszPasswordIn, PQpass(papoConnection[i])) &&
-                EQUAL(pszHostIn, PQhost(papoConnection[i])) &&
-                EQUAL(pszPortIn, PQport(papoConnection[i]))) {
-            return papoConnection[i];
-        }
+    CPLMutexHolderD(&hMutex);
+    std::map<CPLString, PGconn*>::iterator oIter = oMapConnection.find(osKey);
+    if( oIter != oMapConnection.end() )
+        return oIter->second;
 
-    }
 
     /**
      * There's no existing connection. Create a new one.
@@ -102,29 +100,17 @@ PGconn* PostGISRasterDriver::GetConnection(const char* pszConnectionString,
     poConn = PQconnectdb(pszConnectionString);
     if (poConn == NULL ||
             PQstatus(poConn) == CONNECTION_BAD) {
-        CPLError(CE_Failure, CPLE_AppDefined, "PGconnectcb failed: %s\n",
+        CPLError(CE_Failure, CPLE_AppDefined, "PQconnectdb failed: %s\n",
                 PQerrorMessage(poConn));
         PQfinish(poConn);
         return NULL;
     }
 
     /**
-     * Save connection in connection list.
+     * Save connection in the connection map.
      **/
-    nRefCount++;
-    papoConnection = (PGconn**) CPLRealloc(papoConnection,
-            sizeof (PGconn*) * nRefCount);
-    if (NULL != papoConnection) {
-        papoConnection[nRefCount - 1] = poConn;
-        return poConn;
-    }
-    else {
-        CPLError(CE_Failure, CPLE_AppDefined, "Reallocation for new connection\
-                        failed.\n");
-        PQfinish(poConn);
-        return NULL;
-    }
-
+    oMapConnection[osKey] = poConn;
+    return poConn;
 }
 
 
diff --git a/frmts/postgisraster/postgisrasterrasterband.cpp b/frmts/postgisraster/postgisrasterrasterband.cpp
index 74077fa..419f1e6 100644
--- a/frmts/postgisraster/postgisrasterrasterband.cpp
+++ b/frmts/postgisraster/postgisrasterrasterband.cpp
@@ -1,303 +1,277 @@
-/******************************************************************************
- * File :    PostGISRasterRasterBand.cpp
+/***********************************************************************
+ * File :    postgisrasterrasterband.cpp
  * Project:  PostGIS Raster driver
- * Purpose:  GDAL Raster Band implementation for PostGIS Raster driver 
- * Author:   Jorge Arevalo, jorgearevalo at deimos-space.com
+ * Purpose:  GDAL RasterBand implementation for PostGIS Raster driver
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ *                          jorgearevalo at libregis.org
  * 
- * Last changes:
- * $Id: $
+ * Author:	 David Zwarg, dzwarg at azavea.com
  *
- ******************************************************************************
- * Copyright (c) 2009 - 2011, Jorge Arevalo, jorge.arevalo at deimos-space.com
+ * Last changes: $Id: $
  *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
+ ***********************************************************************
+ * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
+ * Copyright (c) 2013, Even Rouault
  *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************/
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ **********************************************************************/
 #include "postgisraster.h"
-#include "ogr_api.h"
-#include "ogr_geometry.h"
-#include "gdal_priv.h"
-#include "gdal.h"
-#include <string>
-#include "cpl_string.h"
-#include "gdal_vrt.h"
-#include "vrtdataset.h"
-#include "memdataset.h"
-
 
 /**
  * \brief Constructor.
- * Parameters:
- *  - PostGISRasterDataset *: The Dataset this band belongs to
- *  - int: the band number
- *  - GDALDataType: The data type for this band
- *  - double: The nodata value.  Could be any kind of data (GByte, GUInt16,
- *          GInt32...) but the variable has the bigger type.
- *  - GBool: if the data type is signed byte or not. If yes, the SIGNEDBYTE
- *          metadata value is added to IMAGE_STRUCTURE domain
- *  - int: The bit depth, to add NBITS as metadata value in IMAGE_STRUCTURE
- *          domain.
- *  TODO: Comment the rest of parameters
+ * 
+ * nBand it's just necessary for overview band creation
  */
-PostGISRasterRasterBand::PostGISRasterRasterBand(PostGISRasterDataset *poDS,
-        int nBand, GDALDataType hDataType, GBool bHasNoDataValue, double dfNodata, 
-        GBool bSignedByte,int nBitDepth, int nFactor, int nBlockXSize, int nBlockYSize,
-        GBool bIsOffline, char * inPszSchema, char * inPszTable, char * inPszColumn)
+PostGISRasterRasterBand::PostGISRasterRasterBand(
+    PostGISRasterDataset * poDS, int nBand,
+    GDALDataType eDataType, GBool bNoDataValueSet, double dfNodata, 
+    GBool bIsOffline = false) : 
+    VRTSourcedRasterBand(poDS, nBand)
 {
-
     /* Basic properties */
     this->poDS = poDS;
-    this->nBand = nBand;
     this->bIsOffline = bIsOffline;
+    this->nBand = nBand;
+    
+    this->eDataType = eDataType;
+    this->bNoDataValueSet = bNoDataValueSet;
+    this->dfNoDataValue = dfNodata;
+
+    this->pszSchema = poDS->pszSchema;
+    this->pszTable = poDS->pszTable;
+    this->pszColumn = poDS->pszColumn; 
+
+    nRasterXSize = poDS->GetRasterXSize();
+    nRasterYSize = poDS->GetRasterYSize();
+
+    /*******************************************************************
+     * Finally, set the block size. We apply the same logic than in VRT 
+     * driver.
+     * 
+     * We limit the size of a block with MAX_BLOCK_SIZE here to prevent
+     * arrangements of just one big tile.
+     * 
+     * This value is just used in case whe only have 1 tile in the
+     * table. Otherwise, the reading operations are performed by the
+     * sources, not the PostGISRasterBand object itself.
+     ******************************************************************/
+    this->nBlockXSize = MIN(MAX_BLOCK_SIZE, this->nRasterXSize);
+    this->nBlockYSize = MIN(MAX_BLOCK_SIZE, this->nRasterYSize);
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterRasterBand constructor: Band created (srid = %d)", 
+        poDS->nSrid);
+    
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterRasterBand constructor: Band size: (%d X %d)", 
+        nRasterXSize, nRasterYSize);
+        
+    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
+        "Block size (%dx%d)", this->nBlockXSize, this->nBlockYSize);
+#endif
+}
 
-    eAccess = poDS->GetAccess();
-    eDataType = hDataType;
-    this->bHasNoDataValue = bHasNoDataValue;
-    dfNoDataValue = dfNodata;
-
-    if (poDS->nBands == 1) {
-        eBandInterp = GCI_GrayIndex;
-    }
-
-    else if (poDS->nBands == 3) {
-        if (nBand == 1)
-            eBandInterp = GCI_RedBand;
-        else if( nBand == 2 )
-            eBandInterp = GCI_GreenBand;
-        else if( nBand == 3 )
-            eBandInterp = GCI_BlueBand;
-        else
-            eBandInterp = GCI_Undefined;
-    }
-
+/***********************************************
+ * \brief: Band destructor
+ ***********************************************/
+PostGISRasterRasterBand::~PostGISRasterRasterBand()
+{
+}
+ 
+#ifdef notdef
+/***********************************************************************
+ * \brief Set the block data to the null value if it is set, or zero if 
+ * there is no null data value.
+ * Parameters:
+ *  - void *: the block data
+ * Returns: nothing
+ **********************************************************************/
+void PostGISRasterRasterBand::NullBlock(void *pData) 
+{
+    int nWords = nBlockXSize * nBlockYSize;
+    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+    
+    int bNoDataSet;
+    double dfNoData = GetNoDataValue(&bNoDataSet);
+    if (!bNoDataSet) {
+        memset(pData, 0, nWords * nDataTypeSize);
+    } 
+    
     else {
-        eBandInterp = GCI_Undefined;
+        GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                      pData, eDataType, nDataTypeSize,
+                      nWords);
     }
+}
 
-
-
-    /**************************************************************************
-     * TODO: Set a non arbitrary blocksize. In case or regular blocking, this is 
-     * easy, otherwise, does it make any sense? Any single tile has its own 
-     * dimensions.
-     *************************************************************************/
-    if (poDS->bRegularBlocking) {
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
-            "Band %d has regular blocking", nBand);
+/***********************************************************************
+ * \brief Returns the metadata for this band
+ * 
+ * If the metadata is actually stored in band's properties, simply 
+ * returns them. Otherwise, it raises a query to fetch metadata
+ * FROM db
+ **********************************************************************/ 
+GBool PostGISRasterRasterBand::GetBandMetadata(
+    GDALDataType * peDataType, GBool * pbHasNoData, double * pdfNoData)
+{
+    // No need to raise a query
+    if (eDataType != GDT_Unknown) {
+        if (peDataType)
+            *peDataType = eDataType;
+            
+        if (pbHasNoData)
+            *pbHasNoData = bNoDataValueSet;
+            
+        if (pdfNoData)
+            *pdfNoData = dfNoDataValue;
+            
+        return true;
+    }
     
-        this->nBlockXSize = nBlockXSize;
-        this->nBlockYSize = nBlockYSize;
+    /**
+     * Queries are expensive. So, we only raise them if all parameters 
+     * are not null
+     **/
+    if (!peDataType || !pbHasNoData || !pdfNoData) {
+        return false;
     }
+    
+    /**
+     * It is safe to assume all the tiles will have the same values for
+     * metadata properties. That was checked during band's construction
+     * (or we simply trusted the user, to avoid expensive checkings). 
+     * So, we can limit the results to just one.
+     **/
+    int nTuples = 0;
+    CPLString osCommand = NULL;
+    PGresult * poResult = NULL;
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+    
+    osCommand.Printf("st_bandpixeltype(%s, %d), "
+        "st_bandnodatavalue(%s, %d) is not null, "
+        "st_bandnodatavalue(%s, %d) FROM %s.%s limit 1", pszColumn, 
+        nBand, pszColumn, nBand, pszColumn, nBand, pszSchema, pszTable);
+        
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterRasterBand::GetBandMetadata(): Query: %s", 
+        osCommand.c_str());
+#endif
+    
+    poResult = PQexec(poRDS->poConn, osCommand.c_str());
+    nTuples = PQntuples(poResult);
+    
+    /* Error getting info FROM database */
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        nTuples <= 0) {
+        
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error getting band metadata while creating raster "
+            "bands");
+            
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterDataset::GetBandMetadata(): %s", 
+            PQerrorMessage(poRDS->poConn));
+        
+        if (poResult)
+            PQclear(poResult);
 
-    else {
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
-            "Band %d does not have regular blocking", nBand);
-
-        /*
-        this->nBlockXSize = MIN(poDS->nRasterXSize, DEFAULT_BLOCK_X_SIZE); 
-        this->nBlockYSize = MIN(poDS->nRasterYSize, DEFAULT_BLOCK_Y_SIZE);
-        */
-
-        this->nBlockXSize = poDS->nRasterXSize;
-        this->nBlockYSize = 1;
+        return false;
     }
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
-        "Block size (%dx%d)", this->nBlockXSize, this->nBlockYSize);
-        
+    
+    // Fill band metadata values
+    GBool bSignedByte = false;
+    int nBitsDepth = 8;
+    char* pszDataType = NULL;
+    
+    pszDataType = CPLStrdup(PQgetvalue(poResult, 0, 0));
+    
+    TranslateDataType(pszDataType, &eDataType, &nBitsDepth, 
+            &bSignedByte);
+            
     // Add pixeltype to image structure domain
-    if (bSignedByte == true) {
+    if (bSignedByte) {
         SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
     }
 
     // Add NBITS to metadata only for sub-byte types
-    if (nBitDepth < 8)
-        SetMetadataItem("NBITS", CPLString().Printf( "%d", nBitDepth ),
+    if (nBitsDepth < 8)
+        SetMetadataItem("NBITS", CPLString().Printf( "%d", nBitsDepth ),
             "IMAGE_STRUCTURE" );
-
-
-    nOverviewFactor = nFactor;
-
-    this->pszSchema = (inPszSchema) ? inPszSchema : poDS->pszSchema; 
-    this->pszTable = (inPszTable) ? inPszTable : poDS->pszTable; 
-    this->pszColumn = (inPszColumn) ? inPszColumn : poDS->pszColumn; 
-
-    /**********************************************************
-     * Check overviews. Query RASTER_OVERVIEWS table for
-     * existing overviews, only in case we are on level 0
-     * TODO: can we do this without querying RASTER_OVERVIEWS?
-     * How do we know the number of overviews? Is an inphinite
-     * loop...
-     **********************************************************/
-    if (nOverviewFactor == 0) {    
-
-        CPLString osCommand;
-        PGresult * poResult = NULL;
-        int i = 0;
-        int nFetchOvFactor = 0;
-        char * pszOvSchema = NULL;
-        char * pszOvTable = NULL;
-        char * pszOvColumn = NULL;
-
-        nRasterXSize = poDS->GetRasterXSize();
-        nRasterYSize = poDS->GetRasterYSize();
- 
-        osCommand.Printf("select o_table_name, overview_factor, o_raster_column, "
-                "o_table_schema from raster_overviews where r_table_schema = "
-                "'%s' and r_table_name = '%s' and r_raster_column = '%s'",
-                poDS->pszSchema, poDS->pszTable, poDS->pszColumn);
-
-        poResult = PQexec(poDS->poConn, osCommand.c_str());
-        if (poResult != NULL && PQresultStatus(poResult) == PGRES_TUPLES_OK &&
-                PQntuples(poResult) > 0) {
             
-            /* Create overviews */
-            nOverviewCount = PQntuples(poResult);           
-            papoOverviews = (PostGISRasterRasterBand **)VSICalloc(nOverviewCount,
-                    sizeof(PostGISRasterRasterBand *));
-            if (papoOverviews == NULL) {
-                CPLError(CE_Warning, CPLE_OutOfMemory, "Couldn't create "
-                        "overviews for band %d\n", nBand);              
-                PQclear(poResult);
-                return;
-            }
-                       
-            for(i = 0; i < nOverviewCount; i++) {
-        
-                CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
-                    "Creating overview for band %d", nBand);
-
-                nFetchOvFactor = atoi(PQgetvalue(poResult, i, 1));
-                pszOvSchema = CPLStrdup(PQgetvalue(poResult, i, 3));
-                pszOvTable = CPLStrdup(PQgetvalue(poResult, i, 0));
-                pszOvColumn = CPLStrdup(PQgetvalue(poResult, i, 2));
- 
-                /**
-                 * NOTE: Overview bands are not considered to be a part of a
-                 * dataset, but we use the same dataset for all the overview
-                 * bands just for simplification (we'll need to access the table
-                 * and schema names). But in method GetDataset, NULL is return
-                 * if we're talking about an overview band
-                 */
-                papoOverviews[i] = new PostGISRasterRasterBand(poDS, nBand,
-                        hDataType, bHasNoDataValue, dfNodata, bSignedByte, nBitDepth,
-                        nFetchOvFactor, nBlockXSize, nBlockYSize, bIsOffline, pszOvSchema,
-                        pszOvTable, pszOvColumn);
-
-            }
-
-            PQclear(poResult);
-
-        }
-
-        else {
+    CPLFree(pszDataType);
             
-            CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
-                "Band %d does not have overviews", nBand);
-            nOverviewCount = 0;
-            papoOverviews = NULL;
-            if (poResult)
-                PQclear(poResult);
-        }
-    }
-
-    /************************************
-     * We are in an overview level. Set
-     * raster size to its value 
-     ************************************/
-    else {
-
-        /* 
-         * No overviews inside an overview (all the overviews are from original
-         * band
-         */
-        nOverviewCount = 0;
-        papoOverviews = NULL;
-
-        
-        nRasterXSize = (int) floor((double)poDS->GetRasterXSize() / nOverviewFactor);
-        nRasterYSize = (int) floor((double)poDS->GetRasterYSize() / nOverviewFactor);        
-    }
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand constructor: Band "
-            "created (srid = %d)", poDS->nSrid);
+    bNoDataValueSet = 
+            EQUALN(PQgetvalue(poResult, 0, 1), "t", sizeof(char));
+            
+    dfNoDataValue = CPLAtof(PQgetvalue(poResult, 0, 2));
+    
+    // Fill output arguments
+    *peDataType = eDataType;
+    *pbHasNoData = bNoDataValueSet;
+    *pdfNoData = dfNoDataValue;
     
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand constructor: Band "
-            "size: (%d X %d)", nRasterXSize, nRasterYSize);
+    return true;
 }
-
-/***********************************************
- * \brief: Band destructor
- ***********************************************/
-PostGISRasterRasterBand::~PostGISRasterRasterBand()
+#endif
+
+/********************************************************
+ * \brief Set nodata value to a buffer
+ ********************************************************/
+void PostGISRasterRasterBand::NullBuffer(void* pData,
+                                         int nBufXSize,
+                                         int nBufYSize,
+                                         GDALDataType eBufType, 
+                                         int nPixelSpace,
+                                         int nLineSpace)
 {
-    int i;
-
-    if (papoOverviews) {
-        for(i = 0; i < nOverviewCount; i++)
-            delete papoOverviews[i];
-
-        CPLFree(papoOverviews);
+    int j;
+    for(j = 0; j < nBufYSize; j++)
+    {
+        double dfVal = 0.0;
+        if( bNoDataValueSet )
+            dfVal = dfNoDataValue;
+        GDALCopyWords(&dfVal, GDT_Float64, 0,
+                    (GByte*)pData + j * nLineSpace, eBufType, nPixelSpace,
+                    nBufXSize);
     }
 }
-    
 
-/**
- *
- **/
-GDALDataType PostGISRasterRasterBand::TranslateDataType(const char * pszDataType)
-{
-    if (EQUALN(pszDataType, "1BB", 3 * sizeof (char)) ||
-        EQUALN(pszDataType, "2BUI", 4 * sizeof (char)) ||
-        EQUALN(pszDataType, "4BUI", 4 * sizeof (char)) ||
-        EQUALN(pszDataType, "8BUI", 4 * sizeof (char)) ||
-        EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) 
-        
-        return GDT_Byte;
-
-    else if (EQUALN(pszDataType, "16BSI", 5 * sizeof (char)))
-        return GDT_Int16;
 
-    else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char)))
-        return GDT_UInt16;
-    
-    else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char)))
-        return GDT_Int32;
-    
-    else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char)))
-        return GDT_UInt32;
-
-    else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char)))
-        return GDT_Float32;
-
-    else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char)))
-        return GDT_Float64;
-
-    else
-        return GDT_Unknown;
+/********************************************************
+ * \brief SortTilesByPKID
+ ********************************************************/
+static int SortTilesByPKID(const void* a, const void* b)
+{
+    PostGISRasterTileDataset* pa = *(PostGISRasterTileDataset** )a;
+    PostGISRasterTileDataset* pb = *(PostGISRasterTileDataset** )b;
+    return strcmp(pa->GetPKID(), pb->GetPKID());
 }
 
-
-
 /**
  * Read/write a region of image data for this band.
  *
- * This method allows reading a region of a PostGISRasterBanda into a buffer. 
+ * This method allows reading a region of a PostGISRasterBand into a buffer. 
  * The write support is still under development
  *
  * The function fetches all the raster data that intersects with the region
@@ -306,487 +280,478 @@ GDALDataType PostGISRasterRasterBand::TranslateDataType(const char * pszDataType
  * It automatically takes care of data type translation if the data type
  * (eBufType) of the buffer is different than that of the PostGISRasterRasterBand.
  *
- * The nPixelSpace and nLineSpace parameters allow reading into from various 
+ * The nPixelSpace and nLineSpace parameters allow reading into FROM various 
  * organization of buffers.
  *
  * @param eRWFlag Either GF_Read to read a region of data (GF_Write, to write
  * a region of data, yet not supported)
  *
  * @param nXOff The pixel offset to the top left corner of the region of the
- * band to be accessed. This would be zero to start from the left side.
+ * band to be accessed. This would be zero to start FROM the left side.
  *
  * @param nYOff The line offset to the top left corner of the region of the band
- * to be accessed. This would be zero to start from the top.
+ * to be accessed. This would be zero to start FROM the top.
  *
  * @param nXSize The width of the region of the band to be accessed in pixels.
  *
  * @param nYSize The height of the region of the band to be accessed in lines.
  *
- * @param pData The buffer into which the data should be read, or from which it
+ * @param pData The buffer into which the data should be read, or FROM which it
  * should be written. This buffer must contain at least
  * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized in
  * left to right,top to bottom pixel order. Spacing is controlled by the
  * nPixelSpace, and nLineSpace parameters.
  *
  * @param nBufXSize the width of the buffer image into which the desired region
- * is to be read, or from which it is to be written.
+ * is to be read, or FROM which it is to be written.
  *
  * @param nBufYSize the height of the buffer image into which the desired region
- * is to be read, or from which it is to be written.
+ * is to be read, or FROM which it is to be written.
  *
  * @param eBufType the type of the pixel values in the pData data buffer. The
- * pixel values will automatically be translated to/from the
+ * pixel values will automatically be translated to/FROM the
  * PostGISRasterRasterBand data type as needed.
  *
- * @param nPixelSpace The byte offset from the start of one pixel value in pData
+ * @param nPixelSpace The byte offset FROM the start of one pixel value in pData
  * to the start of the next pixel value within a scanline. If defaulted (0) the
  * size of the datatype eBufType is used.
  *
- * @param nLineSpace The byte offset from the start of one scanline in pData to
+ * @param nLineSpace The byte offset FROM the start of one scanline in pData to
  * the start of the next. If defaulted (0) the size of the datatype
  * eBufType * nBufXSize is used.
  *
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
 
-CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
-    int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize,
-    GDALDataType eBufType, int nPixelSpace, int nLineSpace)
+CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, 
+    int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, 
+    int nBufYSize, GDALDataType eBufType, int nPixelSpace, 
+    int nLineSpace)
 {
-    double adfTransform[6];
-    double adfProjWin[8];
-    int ulx, uly, lrx, lry;
-    CPLString osCommand;
-    PGresult* poResult = NULL;
-    int iTuplesIndex;
-    int nTuples = 0;
-    GByte* pbyData = NULL;
-    GByte** ppbyBandData = NULL;
-    int nWKBLength = 0;
-    int nBandDataLength;
-    int nBandDataSize;
-    int nBufDataSize;
-    int nTileWidth;
-    int nTileHeight;
-    double dfTileScaleX;
-    double dfTileScaleY;
-    double dfTileUpperLeftX;
-    double dfTileUpperLeftY;
-    char * pszDataType = NULL; 
-    GDALDataType eTileDataType;
-    int nTileDataTypeSize;
-    double dfTileBandNoDataValue;
-    VRTDatasetH vrtDataset;
-    GDALDataset ** memDatasets;
-    GDALRasterBandH memRasterBand;
-    GDALRasterBandH vrtRasterBand;
-    char szMemOpenInfo[100];
-    char szTmp[64];
-    char szTileWidth[64];
-    char szTileHeight[64];
-    CPLErr err;
-    PostGISRasterDataset * poPostGISRasterDS = (PostGISRasterDataset*)poDS;
-    int nSrcXOff, nSrcYOff, nDstXOff, nDstYOff;
-    int nDstXSize, nDstYSize;
-    double xRes, yRes;
-
     /**
      * TODO: Write support not implemented yet
      **/
     if (eRWFlag == GF_Write) {
-        CPLError(CE_Failure, CPLE_NotSupported,
+        ReportError(CE_Failure, CPLE_NotSupported,
             "Writing through PostGIS Raster band not supported yet");
         
         return CE_Failure;
     }
-    
-    nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
-    nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
-            
 
-    /**************************************************************************
-     * Do we have overviews that would be appropriate to satisfy this request?                                                   
-     *************************************************************************/
-    if( (nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0 ) {
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-            "nBufXSize = %d, nBufYSize = %d, nXSize = %d, nYSize = %d "
-            "- OverviewRasterIO call", nBufXSize, nBufYSize, nXSize, nYSize);
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, 
-            nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace ) == CE_None )
+    /*******************************************************************
+     * Do we have overviews that would be appropriate to satisfy this
+     * request?                                                   
+     ******************************************************************/
+    if( (nBufXSize < nXSize || nBufYSize < nYSize) && 
+        GetOverviewCount() > 0 )
+    {
+        if(OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+            pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, 
+            nLineSpace) == CE_None)
                 
         return CE_None;
     }
 
-    /**************************************************************************
-     * Get all the raster rows that are intersected by the window requested
-     *************************************************************************/     
-    // We first construct a polygon to intersect with
-    poPostGISRasterDS->GetGeoTransform(adfTransform);
-    ulx = nXOff;
-    uly = nYOff;
-    lrx = nXOff + nXSize * nBandDataSize;
-    lry = nYOff + nYSize * nBandDataSize;
-
-    // Calculate right pixel resolution
-    xRes = (nOverviewFactor == 0) ? 
-        adfTransform[GEOTRSFRM_WE_RES] :
-        adfTransform[GEOTRSFRM_WE_RES] * nOverviewFactor; 
-    
-    yRes = (nOverviewFactor == 0) ? 
-        adfTransform[GEOTRSFRM_NS_RES] :
-        adfTransform[GEOTRSFRM_NS_RES] * nOverviewFactor; 
-
-    adfProjWin[0] = adfTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    ulx * xRes + 
-                    uly * adfTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[1] = adfTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    ulx * adfTransform[GEOTRSFRM_ROTATION_PARAM2] + 
-                    uly * yRes;
-    adfProjWin[2] = adfTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    lrx * xRes + 
-                    uly * adfTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[3] = adfTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    lrx * adfTransform[GEOTRSFRM_ROTATION_PARAM2] + 
-                    uly * yRes;
-    adfProjWin[4] = adfTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    lrx * xRes + 
-                    lry * adfTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[5] = adfTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    lrx * adfTransform[GEOTRSFRM_ROTATION_PARAM2] + 
-                    lry * yRes;
-    adfProjWin[6] = adfTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    ulx * xRes + 
-                    lry * adfTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[7] = adfTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    ulx * adfTransform[GEOTRSFRM_ROTATION_PARAM2] + 
-                    lry * yRes;
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-        "Buffer size = (%d, %d), Region size = (%d, %d)",
-        nBufXSize, nBufYSize, nXSize, nYSize);
-
-    if (poPostGISRasterDS->pszWhere == NULL) {
-        osCommand.Printf("SELECT st_band(%s, %d), st_width(%s), st_height(%s), st_bandpixeltype(%s, %d), "
-            "st_bandnodatavalue(%s, %d), st_scalex(%s), st_scaley(%s), st_upperleftx(%s), st_upperlefty(%s) "
-            "FROM %s.%s WHERE st_intersects(%s, st_polygonfromtext('POLYGON((%.17f %.17f, %.17f %.17f, "
-            "%.17f %.17f, %.17f %.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszColumn, pszColumn, pszColumn, nBand, pszColumn, 
-            nBand, pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, pszColumn, 
-            adfProjWin[0], adfProjWin[1], adfProjWin[2], adfProjWin[3],  adfProjWin[4], adfProjWin[5], 
-            adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1], poPostGISRasterDS->nSrid);
-    }
-
-    else {
-        osCommand.Printf("SELECT st_band(%s, %d), st_width(%s), st_height(%s), st_bandpixeltype(%s, %d), "
-            "st_bandnodatavalue(%s, %d), st_scalex(%s), st_scaley(%s), st_upperleftx(%s), st_upperlefty(%s) "
-            "FROM %s.%s WHERE (%s) AND st_intersects(%s, st_polygonfromtext('POLYGON((%.17f %.17f, %.17f %.17f, "
-            "%.17f %.17f, %.17f %.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszColumn, pszColumn, pszColumn, nBand, pszColumn, 
-            nBand, pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, poPostGISRasterDS->pszWhere, 
-            pszColumn, adfProjWin[0], adfProjWin[1], adfProjWin[2], adfProjWin[3], adfProjWin[4], adfProjWin[5], 
-            adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1], poPostGISRasterDS->nSrid);
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+
+    int bSameWindowAsOtherBand =
+        (nXOff == poRDS->nXOffPrev &&
+         nYOff == poRDS->nYOffPrev &&
+         nXSize == poRDS->nXSizePrev &&
+         nYSize == poRDS->nYSizePrev);
+    poRDS->nXOffPrev = nXOff;
+    poRDS->nYOffPrev = nYOff;
+    poRDS->nXSizePrev = nXSize;
+    poRDS->nYSizePrev = nYSize;
+
+    /* Logic to determine if bands are read in order 1, 2, ... N */
+    /* If so, then use multi-band caching, otherwise do just single band caching */
+    if( poRDS->bAssumeMultiBandReadPattern )
+    {
+        if( nBand != poRDS->nNextExpectedBand )
+        {
+            CPLDebug("PostGIS_Raster",
+                    "Disabling multi-band caching since band access pattern does not match");
+            poRDS->bAssumeMultiBandReadPattern = false;
+            poRDS->nNextExpectedBand = 1;
+        }
+        else
+        {
+            poRDS->nNextExpectedBand ++;
+            if( poRDS->nNextExpectedBand > poRDS->GetRasterCount() )
+                poRDS->nNextExpectedBand = 1;
+        }
     }
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): Query = %s", osCommand.c_str());
-
-    poResult = PQexec(poPostGISRasterDS->poConn, osCommand.c_str());
-    if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK || 
-        PQntuples(poResult) < 0) {
-        
-        if (poResult)
-            PQclear(poResult);
- 
-        CPLError(CE_Failure, CPLE_AppDefined, "Error retrieving raster data from database");
-
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): %s", 
-            PQerrorMessage(poPostGISRasterDS->poConn));
-        
-        return CE_Failure;  
+    else
+    {
+        if( nBand == poRDS->nNextExpectedBand )
+        {
+            poRDS->nNextExpectedBand ++;
+            if( poRDS->nNextExpectedBand > poRDS->GetRasterCount() )
+            {
+                CPLDebug("PostGIS_Raster", "Re-enabling multi-band caching");
+                poRDS->bAssumeMultiBandReadPattern = true;
+                poRDS->nNextExpectedBand = 1;
+            }
+        }
     }
-
-    /**
-     * No data. Return the buffer filled with nodata values
-     **/
-    else if (PQntuples(poResult) == 0) {
-        PQclear(poResult);
+    
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+            "PostGISRasterRasterBand::IRasterIO: "
+            "nBand = %d, nXOff = %d, nYOff = %d, nXSize = %d, nYSize = %d, nBufXSize = %d, nBufYSize = %d",
+             nBand, nXOff, nYOff, nXSize,  nYSize, nBufXSize, nBufYSize);
+#endif
+
+#ifdef notdef
+    /*******************************************************************
+     * Optimization: We just have one tile. So, we can read it with
+     * IReadBlock
+     * 
+     * TODO: Review it. It's not working (see comment in 
+     * PostGISRasterDataset::ConstructOneDatasetFromTiles)
+     ******************************************************************/
+    
+    if (poRDS->nTiles == 1) {
         
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): Null block");
-
-        memset(pData, dfNoDataValue, nBufDataSize * nBufXSize * nBufYSize);
-
-        return CE_None; 
+        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, 
+            nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, 
+            nLineSpace);
     }
+#endif    
     
-
-    nTuples = PQntuples(poResult);
-
-    /**************************************************************************
-     * Allocate memory for MEM dataset
-     * TODO: In case of memory error, provide a different alternative
-     *************************************************************************/
-    memDatasets = (GDALDataset **)VSICalloc(nTuples, sizeof(GDALDataset *));
-    if (!memDatasets) {
-        PQclear(poResult);  
-        CPLError(CE_Failure, CPLE_AppDefined, "Memory error while trying to read band data "
-            "from database");
-
-        return CE_Failure;
+    /*******************************************************************
+     * Several tiles: we first look in all our sources caches. Missing
+     * blocks are queried
+     ******************************************************************/
+    double adfProjWin[8];
+    int nFeatureCount = 0;
+    CPLRectObj sAoi;
+
+    poRDS->PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin); 
+    // (p[6], p[7]) is the minimum (x, y), and (p[2], p[3]) the max
+    sAoi.minx = adfProjWin[6];
+    sAoi.maxx = adfProjWin[2];
+    if( adfProjWin[7] < adfProjWin[3] )
+    {
+        sAoi.miny = adfProjWin[7];
+        sAoi.maxy = adfProjWin[3];
+    }
+    else
+    {
+        sAoi.maxy = adfProjWin[7];
+        sAoi.miny = adfProjWin[3];
     }
-    
 
-    /**************************************************************************
-     * Create an empty in-memory VRT dataset
-     * TODO: In case of memory error, provide a different alternative
-     *************************************************************************/
-    vrtDataset = VRTCreate(nXSize, nYSize);
-    if (!vrtDataset) {
-        PQclear(poResult);
-        CPLFree(memDatasets);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PostGIS_Raster", 
+            "PostGISRasterRasterBand::IRasterIO: "
+            "Intersection box: (%f, %f) - (%f, %f)", sAoi.minx, 
+            sAoi.miny, sAoi.maxx, sAoi.maxy);
+#endif
+
+    if (poRDS->hQuadTree == NULL)
+    {
+        ReportError(CE_Failure, CPLE_AppDefined,
+            "Could not read metadata index.");
+        return CE_Failure; 
+    }
 
-        CPLError(CE_Failure, CPLE_AppDefined, "Memory error while trying to read band data "
-            "from database");
+    NullBuffer(pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace);
 
-        return CE_Failure;
+    if( poRDS->bBuildQuadTreeDynamically && !bSameWindowAsOtherBand )
+    {
+        if( !(poRDS->LoadSources(nXOff, nYOff, nXSize, nYSize, nBand)) )
+            return CE_Failure;
     }
 
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: VRT Dataset "
-        "of (%d, %d) created", nXSize, nYSize);
-    
-    
-    // NOTE: Do NOT add a Dataset description, or the VRT file will be written to disk.
-    // This is a memory only dataset.
-    GDALSetProjection(vrtDataset, GDALGetProjectionRef((GDALDatasetH)this->poDS));
-    GDALSetGeoTransform(vrtDataset, adfTransform);
+    // Matching sources, to avoid a dumb for loop over the sources
+    PostGISRasterTileDataset ** papsMatchingTiles = 
+        (PostGISRasterTileDataset **)
+            CPLQuadTreeSearch(poRDS->hQuadTree, &sAoi, &nFeatureCount);
+         
+    // No blocks found. This is not an error (the raster may have holes)
+    if (nFeatureCount == 0) {
+        CPLFree(papsMatchingTiles);
+ 
+        return CE_None; 
+    }
 
+    int i;
 
     /**
-     * Create one VRT Raster Band. It will contain the same band of all tiles
-     * as Simple Sources
-     **/
-    VRTAddBand(vrtDataset, eDataType, NULL);
-    vrtRasterBand = GDALGetRasterBand(vrtDataset, 1);
+     * We need to store the max, min coords for the missing tiles in
+     * any place. This is as good as any other
+     **/ 
+    sAoi.minx = 0.0;
+    sAoi.miny = 0.0;
+    sAoi.maxx = 0.0;
+    sAoi.maxy = 0.0;
     
+    GIntBig nMemoryRequiredForTiles = 0;
+    CPLString osIDsToFetch;
+    int nTilesToFetch = 0;
+    int nBandDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+
+    // Loop just over the intersecting sources
+    for(i = 0; i < nFeatureCount; i++) {
+        PostGISRasterTileDataset *poTile = papsMatchingTiles[i];
+        PostGISRasterTileRasterBand* poTileBand = 
+            (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
+
+        nMemoryRequiredForTiles += poTileBand->GetXSize() * poTileBand->GetYSize() *
+            nBandDataTypeSize;
+        
+        // Missing tile: we'll need to query for it
+        if (!poTileBand->IsCached()) {
+            
+            // If we have a PKID, add the tile PKID to the list
+            if (poTile->pszPKID != NULL)
+            {
+                if( osIDsToFetch.size() != 0 )
+                    osIDsToFetch += ",";
+                osIDsToFetch += "'";
+                osIDsToFetch += poTile->pszPKID;
+                osIDsToFetch += "'";
+            }
 
-    /**
-     * Allocate memory for MEM data pointers
-     **/
-    ppbyBandData = (GByte **)VSICalloc(nTuples, sizeof(GByte *));
-    if (!ppbyBandData) {
-        PQclear(poResult);
-        CPLFree(memDatasets);
-        GDALClose(vrtDataset);
-
-        CPLError(CE_Failure, CPLE_AppDefined, "Memory error while trying to read band data "
-            "from database");
-    
-        return CE_Failure;
-    }
-    
-    /**************************************************************************
-     * Now, for each block, create a MEM dataset
-     * TODO: What if whe have a really BIG amount of data fetched from db? CURSORS
-     *************************************************************************/
-    for(iTuplesIndex = 0; iTuplesIndex < nTuples; iTuplesIndex++) { 
-        /**
-         * Fetch data from result
-         **/
-        pbyData = CPLHexToBinary(PQgetvalue(poResult, iTuplesIndex, 0), &nWKBLength);
-        nTileWidth = atoi(PQgetvalue(poResult, iTuplesIndex, 1));
-        nTileHeight = atoi(PQgetvalue(poResult, iTuplesIndex, 2));
-        pszDataType = CPLStrdup(PQgetvalue(poResult, iTuplesIndex, 3));
-        dfTileBandNoDataValue = atof(PQgetvalue(poResult, iTuplesIndex, 4));
-        dfTileScaleX = atof(PQgetvalue(poResult, iTuplesIndex, 5));
-        dfTileScaleY = atof(PQgetvalue(poResult, iTuplesIndex, 6));
-        dfTileUpperLeftX = atof(PQgetvalue(poResult, iTuplesIndex, 7));
-        dfTileUpperLeftY = atof(PQgetvalue(poResult, iTuplesIndex, 8));
-
-
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: Tile of "
-            "(%d, %d) px created. With pixel size of (%f, %f) and located at "
-            "(%f, %f)", nTileWidth, nTileHeight, dfTileScaleX, dfTileScaleY,
-            dfTileUpperLeftX, dfTileUpperLeftY);
+            double dfTileMinX, dfTileMinY, dfTileMaxX, dfTileMaxY;
+            poTile->GetExtent(&dfTileMinX, &dfTileMinY,
+                              &dfTileMaxX, &dfTileMaxY);
+
+            /**
+             * We keep the general max and min values of all the missing
+             * tiles, to raise a query that intersect just that area.
+             * 
+             * TODO: In case of just a few tiles and very separated,
+             * this strategy is clearly suboptimal. We'll get our
+             * missing tiles, but with a lot of other not needed tiles.
+             * 
+             * A possible optimization will be to simply rely on the
+             * I/O method of the source (must be implemented), in case
+             * we have minus than a reasonable amount of tiles missing.
+             * Another criteria to decide would be how separated the
+             * tiles are. Two queries for just two adjacent tiles is 
+             * also a dumb strategy.
+             **/
+            if( nTilesToFetch == 0 )
+            {
+                sAoi.minx = dfTileMinX;
+                sAoi.miny = dfTileMinY;
+                sAoi.maxx = dfTileMaxX;
+                sAoi.maxy = dfTileMaxY;
+            }
+            else
+            {
+                if (dfTileMinX < sAoi.minx)
+                    sAoi.minx = dfTileMinX;
+                    
+                if (dfTileMinY < sAoi.miny)
+                    sAoi.miny = dfTileMinY;
+                    
+                if (dfTileMaxX > sAoi.maxx)
+                    sAoi.maxx = dfTileMaxX;
+                    
+                if (dfTileMaxY > sAoi.maxy)
+                    sAoi.maxy = dfTileMaxY;
+            }
+            
+            nTilesToFetch ++;
             
-        /**
-         * Calculate some useful parameters
-         **/
-        eTileDataType = TranslateDataType(pszDataType);
-        nTileDataTypeSize = GDALGetDataTypeSize(eTileDataType) / 8;
-        
-        nBandDataLength = nTileWidth * nTileHeight * nTileDataTypeSize;
-        ppbyBandData[iTuplesIndex] = (GByte *)
-            VSIMalloc(nBandDataLength * sizeof(GByte));
-
-        if (!ppbyBandData[iTuplesIndex]) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Could not allocate memory for "
-                "MEMDataset, skipping. The result image may contain gaps");
-            continue;
         }
+    }
 
-        /**
-         * Get the pointer to the band pixels
-         **/ 
-        memcpy(ppbyBandData[iTuplesIndex], 
-            GET_BAND_DATA(pbyData, 1, nTileDataTypeSize, nBandDataLength),
-            nBandDataLength);
-        
-        /**
-         * Create new MEM dataset, based on in-memory array, to hold the pixels.
-         * The dataset will only have 1 band
-         **/
-        memset(szTmp, 0, sizeof(szTmp));
-        CPLPrintPointer(szTmp, ppbyBandData[iTuplesIndex], sizeof(szTmp));
-
-        memset(szTileWidth, 0, sizeof(szTileWidth));
-        CPLPrintInt32(szTileWidth, (GInt32)nTileWidth, sizeof(nTileWidth));
-        memset(szTileHeight, 0, sizeof(szTileHeight));
-        CPLPrintInt32(szTileHeight, (GInt32)nTileHeight, sizeof(nTileHeight));
-        
-        memset(szMemOpenInfo, 0, sizeof(szMemOpenInfo));
-        sprintf(szMemOpenInfo, "MEM:::DATAPOINTER=%s,PIXELS=%d,LINES=%d,DATATYPE=%s",
-            szTmp, nTileWidth, nTileHeight, GDALGetDataTypeName(eTileDataType));
-        
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: MEMDataset "
-            "open info = %s", szMemOpenInfo);
-
-        GDALOpenInfo oOpenInfo(szMemOpenInfo, GA_ReadOnly, NULL);
-    
-        memDatasets[iTuplesIndex] = MEMDataset::Open(&oOpenInfo);
-        if (!memDatasets[iTuplesIndex]) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Could not create MEMDataset, "
-                "skipping. The result image may contain gaps");
-            continue;
+    /* Determine caching strategy */
+    int bAllBandCaching = FALSE;
+    if (nTilesToFetch > 0)
+    {
+        GIntBig nCacheMax = (GIntBig) GDALGetCacheMax64();
+        if( nMemoryRequiredForTiles > nCacheMax )
+        {
+            CPLDebug("PostGIS_Raster",
+                    "For best performance, the block cache should be able to store " CPL_FRMT_GIB
+                    " bytes for the tiles of the requested window, "
+                    "but it is only " CPL_FRMT_GIB " byte large",
+                    nMemoryRequiredForTiles, nCacheMax );
+            nTilesToFetch = 0;
         }
-         
-        GDALSetDescription(memDatasets[iTuplesIndex], szMemOpenInfo);
-
-        /** 
-         * Get MEM raster band, to add it as simple source.
-         **/
-        memRasterBand = (GDALRasterBandH)memDatasets[iTuplesIndex]->GetRasterBand(1);
-        if (!memRasterBand) {
-            CPLError(CE_Warning, CPLE_AppDefined, "Could not get MEMRasterBand , "
-                "skipping. The result image may contain gaps");
-            continue;
-        } 
         
-        ((MEMRasterBand *)memRasterBand)->SetNoDataValue(dfTileBandNoDataValue);
-
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: Adding "
-            "VRT Complex Source");
+        if( poRDS->GetRasterCount() > 1 && poRDS->bAssumeMultiBandReadPattern )
+        {
+            GIntBig nMemoryRequiredForTilesAllBands =
+                nMemoryRequiredForTiles * poRDS->GetRasterCount();
+            if( nMemoryRequiredForTilesAllBands <= nCacheMax )
+            {
+                bAllBandCaching = TRUE;
+            }
+            else
+            {
+                CPLDebug("PostGIS_Raster", "Caching only this band, but not all bands. "
+                         "Cache should be " CPL_FRMT_GIB " byte large for that",
+                         nMemoryRequiredForTilesAllBands);
+            }
+        }
+    }
+    
+    // Raise a query for missing tiles and cache them
+    if (nTilesToFetch > 0) {
         
         /**
-         * Get source and destination windows for the simple source (first check source
-         * and destination bounding boxes match. Otherwise, skip this data)
+         * There are several options here, to raise the query.
+         * - Get all the tiles which PKID is in a list of missing 
+         *   PKIDs.
+         * - Get all the tiles that intersect a polygon constructed
+         *   based on the (min - max) values calculated before.
+         * - Get all the tiles with upper left pixel included in the
+         *   range (min - max) calculated before.
+         * 
+         * The first option is the most efficient one when a PKID exists.
+         * After that, the second one is the most efficient one when a
+         * spatial index exists.
+         * The third one is the only one available when neither a PKID or spatial
+         * index exist.
          **/ 
-        
-        if (dfTileUpperLeftX + nTileWidth * dfTileScaleX < adfProjWin[0]) {
-            CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-                "dfTileUpperLeftX = %f, nTileWidth = %d, dfTileScaleX = %f, "
-                "RasterDataset minx = %f", dfTileUpperLeftX, nTileWidth, dfTileScaleX,
-                adfProjWin[0]);
-            continue;
-        }
-
-        if (dfTileUpperLeftX > adfProjWin[4]) {
-            CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-                "dfTileUpperLeftX = %f, RasterDataset maxx = %f", dfTileUpperLeftX, 
-                adfProjWin[4]);
-            continue;
-        }   
-
-        if (dfTileUpperLeftY + nTileHeight * dfTileScaleY > adfProjWin[1]) {
-            CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-                "dfTileUpperLeftY = %f, nTileHeight = %d, ns res = %f, "
-                "RasterDataset maxy = %f", dfTileUpperLeftY, nTileHeight, dfTileScaleY,
-                adfProjWin[1]);
-            continue;
-        }
+        CPLString osCommand;
+        PGresult * poResult;
 
-        if (dfTileUpperLeftY < adfProjWin[5]) {
-            CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO: "
-                "dfTileUpperLeftY = %f, RasterDataset miny = %f", dfTileUpperLeftY, 
-                adfProjWin[5]);
-            continue;
-        }
+        CPLString osRasterToFetch;
+        if (bAllBandCaching)
+            osRasterToFetch = pszColumn;
+        else
+            osRasterToFetch.Printf("ST_Band(%s, %d)", pszColumn, nBand);
+
+        int bHasWhere = FALSE;
+        if (osIDsToFetch.size() && (poRDS->bIsFastPK || !(poRDS->HasSpatialIndex())) ) {
+            osCommand.Printf("SELECT %s, "
+                "ST_Metadata(%s), %s FROM %s.%s",
+                osRasterToFetch.c_str(), pszColumn,
+                poRDS->GetPrimaryKeyRef(), pszSchema, pszTable);
+            if( nTilesToFetch < poRDS->nTiles || poRDS->bBuildQuadTreeDynamically )
+            {
+                bHasWhere = TRUE;
+                osCommand += " WHERE ";
+                osCommand += poRDS->pszPrimaryKeyName;
+                osCommand += " IN (";
+                osCommand += osIDsToFetch;
+                osCommand += ")";
+            }
+        } 
         
-
-        if (dfTileUpperLeftX < adfProjWin[0]) {
-            nSrcXOff = (int)((adfProjWin[0] - dfTileUpperLeftX) / 
-                dfTileScaleX + 0.5);
-            nDstXOff = 0;
-        }
-
         else {
-            nSrcXOff = 0;
-            nDstXOff = (int)(0.5 + (dfTileUpperLeftX - adfProjWin[0]) /     
-                xRes);
-        }
-
-        if (adfProjWin[1] < dfTileUpperLeftY) {
-            nSrcYOff = (int)((dfTileUpperLeftY - adfProjWin[1]) / 
-                fabs(dfTileScaleY) + 0.5);
-            nDstYOff = 0;
+            CPLLocaleC oCLocale; // Force C locale to avoid commas instead of decimal points (for QGIS e.g.)
+            bHasWhere = TRUE;
+            osCommand.Printf("SELECT %s, ST_Metadata(%s), %s FROM %s.%s WHERE ",
+                             osRasterToFetch.c_str(), pszColumn,
+                             (poRDS->GetPrimaryKeyRef()) ? poRDS->GetPrimaryKeyRef() : "'foo'",
+                             pszSchema, pszTable);
+            if( poRDS->HasSpatialIndex() )
+            {
+                osCommand += CPLSPrintf("%s && "
+                        "ST_GeomFromText('POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))')",
+                        pszColumn,
+                        adfProjWin[0], adfProjWin[1],
+                        adfProjWin[2], adfProjWin[3],
+                        adfProjWin[4], adfProjWin[5],
+                        adfProjWin[6], adfProjWin[7],
+                        adfProjWin[0], adfProjWin[1]);
+            }
+            else
+            {
+                #define EPS 1e-5
+                osCommand += CPLSPrintf("ST_UpperLeftX(%s)"
+                    " BETWEEN %f AND %f AND ST_UpperLeftY(%s) BETWEEN "
+                    "%f AND %f", pszColumn, sAoi.minx-EPS, sAoi.maxx+EPS, 
+                    pszColumn, sAoi.miny-EPS, sAoi.maxy+EPS);
+            }
         }
-
-        else {
-            nSrcYOff = 0;
-            nDstYOff = (int)(0.5 + (adfProjWin[1] - dfTileUpperLeftY) / 
-                fabs(yRes));
+    
+        if( poRDS->pszWhere != NULL )
+        {
+            if( bHasWhere )
+                osCommand += " AND (";
+            else
+                osCommand += " WHERE (";
+            osCommand += poRDS->pszWhere;
+            osCommand += ")";
         }
-
-        nDstXSize = (int)(0.5 + nTileWidth * dfTileScaleX / xRes);
-        nDstYSize = (int)(0.5 + nTileHeight * fabs(dfTileScaleY) / fabs(yRes));
+        
+        poResult = PQexec(poRDS->poConn, osCommand.c_str());
+         
+#ifdef DEBUG_QUERY
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterRasterBand::IRasterIO(): Query = \"%s\" --> number of rows = %d", 
+            osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
+#endif
+        
+        if (poResult == NULL || 
+            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+            PQntuples(poResult) < 0) {
+            
+            if (poResult)
+                PQclear(poResult);
      
+            CPLError(CE_Failure, CPLE_AppDefined, 
+                "PostGISRasterRasterBand::IRasterIO(): %s", 
+                PQerrorMessage(poRDS->poConn));
+            
+            // Free the object that holds pointers to matching tiles
+            CPLFree(papsMatchingTiles);
+            return CE_Failure;  
+        }
 
         /**
-         * Add the mem raster band as new complex source band (so, I can specify a nodata value)
+         * No data. Return the buffer filled with nodata values
          **/
-        VRTAddComplexSource(vrtRasterBand, memRasterBand, nSrcXOff, nSrcYOff, nTileWidth, nTileHeight,
-            nDstXOff, nDstYOff, nDstXSize, nDstYSize, 0, 1, dfTileBandNoDataValue);
+        else if (PQntuples(poResult) == 0) {
+            PQclear(poResult);
 
-        CPLFree(pbyData);
-        CPLFree(pszDataType);
+            // Free the object that holds pointers to matching tiles
+            CPLFree(papsMatchingTiles);
+            return CE_None; 
+        }
     
+        /**
+         * Ok, we loop over the results
+         **/
+        int nTuples = PQntuples(poResult);
+        for(i = 0; i < nTuples; i++)
+        {
+            const char* pszMetadata = PQgetvalue(poResult, i, 1);
+            const char* pszRaster = PQgetvalue(poResult, i, 0);
+            const char *pszPKID = (poRDS->GetPrimaryKeyRef() != NULL) ?  PQgetvalue(poResult, i, 2) : NULL;
+            poRDS->CacheTile(pszMetadata, pszRaster, pszPKID, nBand, bAllBandCaching);
+        } // All tiles have been added to cache
 
-        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): VRT complex source added");
+        PQclear(poResult);
+    } // End missing tiles
+
+/* -------------------------------------------------------------------- */
+/*      Overlay each source in turn over top this.                      */
+/* -------------------------------------------------------------------- */
+
+    CPLErr eErr = CE_None;
+    /* Sort tiles by ascending PKID, so that the draw order is determinist */
+    if( poRDS->GetPrimaryKeyRef() != NULL )
+    {
+        qsort(papsMatchingTiles, nFeatureCount, sizeof(PostGISRasterTileDataset*),
+              SortTilesByPKID);
     }
- 
-    PQclear(poResult);
-    
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): VRT dataset created");
-
-    /**
-     * We've constructed the VRT Dataset based on the window requested. So, we always
-     * start from 0
-     **/
-    nXOff = nYOff = 0;
-
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): The window requested is "
-        "from (%d, %d) of size (%d, %d). Buffer of size (%d, %d)", nXOff, nYOff, 
-        nXSize, nYSize, nBufXSize, nBufYSize);
-
-    // Execute VRT RasterIO over the band
-    err = ((VRTRasterBand *)vrtRasterBand)->RasterIO(eRWFlag, nXOff, nYOff, nXSize, 
-        nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace);
 
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): Data read");
-
-    GDALClose(vrtDataset);
-    
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): VRTDataset released");
-    
-    // Free resources
-    for(iTuplesIndex = 0; iTuplesIndex < nTuples; iTuplesIndex++) {
-        if (ppbyBandData[iTuplesIndex])
-            VSIFree(ppbyBandData[iTuplesIndex]);
-        delete memDatasets[iTuplesIndex];
-        //GDALClose(memDatasets[iTuplesIndex]);
+    for(i = 0; i < nFeatureCount && eErr == CE_None; i++)
+    {
+        PostGISRasterTileDataset *poTile = papsMatchingTiles[i];
+        PostGISRasterTileRasterBand* poTileBand = 
+            (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
+        eErr = 
+            poTileBand->poSource->RasterIO( nXOff, nYOff, nXSize, nYSize, 
+                                            pData, nBufXSize, nBufYSize, 
+                                            eBufType, nPixelSpace, nLineSpace);
     }
-    VSIFree(ppbyBandData);
-    VSIFree(memDatasets);
     
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IRasterIO(): MEMDatasets were released");
+    // Free the object that holds pointers to matching tiles
+    CPLFree(papsMatchingTiles);
 
-    return err;
-        
+    return eErr;
 }
 
 /**
@@ -812,7 +777,7 @@ CPLErr PostGISRasterRasterBand::SetNoDataValue(double dfNewValue) {
  */
 double PostGISRasterRasterBand::GetNoDataValue(int *pbSuccess) {
     if (pbSuccess != NULL)
-        *pbSuccess = (int) bHasNoDataValue;
+        *pbSuccess = (int) bNoDataValueSet;
 
     return dfNoDataValue;
 }
@@ -822,9 +787,8 @@ double PostGISRasterRasterBand::GetNoDataValue(int *pbSuccess) {
  ***************************************************/
 int PostGISRasterRasterBand::GetOverviewCount()
 {
-    return (nOverviewFactor) ?
-        0 :
-        nOverviewCount;
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+    return poRDS->GetOverviewCount();
 }
 
 /**********************************************************
@@ -832,38 +796,141 @@ int PostGISRasterRasterBand::GetOverviewCount()
  **********************************************************/
 GDALRasterBand * PostGISRasterRasterBand::GetOverview(int i)
 {
-    return (i >= 0 && i < GetOverviewCount()) ? 
-        (GDALRasterBand *)papoOverviews[i] : GDALRasterBand::GetOverview(i);
+    if (i < 0 || i >= GetOverviewCount())
+        return NULL;
+    
+    PostGISRasterDataset* poRDS = (PostGISRasterDataset *)poDS;
+    PostGISRasterDataset* poOverviewDS = poRDS->GetOverviewDS(i);
+    if( poOverviewDS->nBands == 0 )
+    {
+        if (!poOverviewDS->SetRasterProperties(NULL) ||
+             poOverviewDS->GetRasterCount() != poRDS->GetRasterCount())
+        {
+            CPLDebug("PostGIS_Raster",
+                     "Request for overview %d of band %d failed", i, nBand);
+            return NULL;
+        }
+    }
+
+    return poOverviewDS->GetRasterBand(nBand);
 }
 
+#ifdef notdef
 /*****************************************************
  * \brief Read a natural block of raster band data
  *****************************************************/
-CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
-        pImage)
+CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, 
+        int nBlockYOff, void * pImage)
 {
-    int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
-    int nReadXSize, nReadYSize;
+    PGresult * poResult = NULL;
+    CPLString osCommand;
+    int nXOff = 0;
+    int nYOff = 0;
+    int nNaturalBlockXSize = 0;
+    int nNaturalBlockYSize = 0;
+    double adfProjWin[8];
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+    
+    int nPixelSize = GDALGetDataTypeSize(eDataType) / 8;
+    
+    // Construct a polygon to intersect with
+    GetBlockSize(&nNaturalBlockXSize, &nNaturalBlockYSize);
+    
+    nXOff = nBlockXOff * nNaturalBlockXSize;
+    nYOff = nBlockYOff * nNaturalBlockYSize;
+    
+    poRDS->PolygonFromCoords(nXOff, nYOff, nXOff + nNaturalBlockXSize, nYOff + nNaturalBlockYSize, adfProjWin);
+    
+    // Raise the query
+    if (poRDS->pszWhere == NULL) {
+        osCommand.Printf("SELECT st_band(%s, %d) FROM %s.%s "
+            "WHERE st_intersects(%s, ST_PolygonFromText"
+            "('POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, %.17f "
+            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema, 
+            pszTable, pszColumn, adfProjWin[0], adfProjWin[1], 
+            adfProjWin[2], adfProjWin[3],  adfProjWin[4], adfProjWin[5], 
+            adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1], 
+            poRDS->nSrid);
+    }
 
-    if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
-        nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
-    else
-        nReadXSize = nBlockXSize;
+    else {
+        osCommand.Printf("SELECT st_band(%s, %d) FROM %s.%s WHERE (%s) "
+            "AND st_intersects(%s, ST_PolygonFromText"
+            "('POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, %.17f "
+            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema, 
+            pszTable, poRDS->pszWhere, pszColumn, adfProjWin[0], 
+            adfProjWin[1], adfProjWin[2], adfProjWin[3], adfProjWin[4], 
+            adfProjWin[5], adfProjWin[6], adfProjWin[7], adfProjWin[0], 
+            adfProjWin[1], poRDS->nSrid);
+    }
 
-    if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
-        nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
-    else
-        nReadYSize = nBlockYSize;
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterRasterBand::IReadBlock(): Query = %s", 
+            osCommand.c_str());
+#endif
+
+    poResult = PQexec(poRDS->poConn, osCommand.c_str());
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        PQntuples(poResult) < 0) {
+        
+        if (poResult)
+            PQclear(poResult);
+ 
+        ReportError(CE_Failure, CPLE_AppDefined, 
+            "Error retrieving raster data FROM database");
+
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterRasterBand::IRasterIO(): %s", 
+                PQerrorMessage(poRDS->poConn));
+        
+        return CE_Failure;  
+    }
+
+    /**
+     * No data. Return the buffer filled with nodata values
+     **/
+    else if (PQntuples(poResult) == 0) {
+        PQclear(poResult);
+        
+        CPLDebug("PostGIS_Raster", 
+            "PostGISRasterRasterBand::IRasterIO(): Null block");
 
-    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IReadBlock: "
-        "Calling to IRasterIO");
+        NullBlock(pImage);
 
-    return IRasterIO( GF_Read, 
-                      nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize, 
-                      nReadXSize, nReadYSize, 
-                      pImage, nReadXSize, nReadYSize, eDataType, 
-                      nPixelSize, nPixelSize * nBlockXSize );
+        return CE_None; 
+    }
+    
+    
+    /**
+     * Ok, we get the data. Only data size, without payload 
+     * 
+     * TODO: Check byte order
+     **/
+    int nExpectedDataSize = nNaturalBlockXSize * nNaturalBlockYSize *
+        nPixelSize;
+        
+    int nWKBLength = 0;
+    
+    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), 
+        &nWKBLength);
+        
+    char * pbyDataToRead = (char*)GET_BAND_DATA(pbyData,nBand, 
+            nPixelSize, nExpectedDataSize);
+
+    memcpy(pImage, pbyDataToRead, nExpectedDataSize * sizeof(char));
+    
+    CPLDebug("PostGIS_Raster", "IReadBlock: Copied %d bytes FROM block "
+            "(%d, %d) to %p", nExpectedDataSize, nBlockXOff, 
+            nBlockYOff, pImage);
+
+    CPLFree(pbyData);
+    PQclear(poResult);
+
+    return CE_None;
 }
+#endif
 
 /**
  * \brief How should this band be interpreted as color?
@@ -872,5 +939,75 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
  **/
 GDALColorInterp PostGISRasterRasterBand::GetColorInterpretation()
 {
-    return eBandInterp; 
+    if (poDS->GetRasterCount() == 1) {
+        eColorInterp = GCI_GrayIndex;
+    }
+
+    else if (poDS->GetRasterCount() == 3) {
+        if (nBand == 1)
+            eColorInterp = GCI_RedBand;
+        else if( nBand == 2 )
+            eColorInterp = GCI_GreenBand;
+        else if( nBand == 3 )
+            eColorInterp = GCI_BlueBand;
+        else
+            eColorInterp = GCI_Undefined;
+    }
+
+    else {
+        eColorInterp = GCI_Undefined;
+    }
+    
+    return eColorInterp; 
+}
+
+/************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double PostGISRasterRasterBand::GetMinimum( int *pbSuccess )
+{
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+    if( poRDS->bBuildQuadTreeDynamically && poRDS->nTiles == 0 )
+    {
+        if( pbSuccess )
+            *pbSuccess = FALSE;
+        return 0.0;
+    }
+    return VRTSourcedRasterBand::GetMaximum(pbSuccess);
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double PostGISRasterRasterBand::GetMaximum( int *pbSuccess )
+{
+    PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
+    if( poRDS->bBuildQuadTreeDynamically && poRDS->nTiles == 0 )
+    {
+        if( pbSuccess )
+            *pbSuccess = FALSE;
+        return 0.0;
+    }
+    return VRTSourcedRasterBand::GetMaximum(pbSuccess);
+}
+
+/************************************************************************/
+/*                       ComputeRasterMinMax()                          */
+/************************************************************************/
+
+CPLErr PostGISRasterRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
+{
+    if( nRasterXSize < 1024 && nRasterYSize < 1024 )
+        return VRTSourcedRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
+
+    int nOverviewCount = GetOverviewCount();
+    for(int i = 0; i < nOverviewCount; i++)
+    {
+        if( GetOverview(i)->GetXSize() < 1024 && GetOverview(i)->GetYSize() < 1024 )
+            return GetOverview(i)->ComputeRasterMinMax(bApproxOK, adfMinMax);
+    }
+    
+    return CE_Failure;
 }
diff --git a/frmts/postgisraster/postgisrastertiledataset.cpp b/frmts/postgisraster/postgisrastertiledataset.cpp
new file mode 100644
index 0000000..3520602
--- /dev/null
+++ b/frmts/postgisraster/postgisrastertiledataset.cpp
@@ -0,0 +1,114 @@
+/***********************************************************************
+ * File :    postgisrastertiledataset.cpp
+ * Project:  PostGIS Raster driver
+ * Purpose:  GDAL Dataset implementation for PostGIS Raster tile
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ *                          jorgearevalo at libregis.org
+ *
+ * Last changes: $Id: $
+ *
+ ***********************************************************************
+ * Copyright (c) 2013, Jorge Arevalo
+ * Copyright (c) 2013, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ ************************************************************************/
+#include "postgisraster.h"
+
+/************************
+ * \brief Constructor
+ ************************/
+PostGISRasterTileDataset::PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
+                                                   int nXSize, 
+                                                   int nYSize)
+{
+    this->poRDS = poRDS;
+    this->pszPKID = NULL;
+    this->nRasterXSize = nXSize;
+    this->nRasterYSize = nYSize;
+
+    adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0;
+    adfGeoTransform[GEOTRSFRM_WE_RES] = 1;
+    adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0;
+    adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0;
+    adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0;
+    adfGeoTransform[GEOTRSFRM_NS_RES] = 1;
+}
+
+
+/************************
+ * \brief Destructor
+ ************************/
+PostGISRasterTileDataset::~PostGISRasterTileDataset()
+{
+    if (pszPKID) {
+        CPLFree(pszPKID);
+        pszPKID = NULL;
+    }
+}
+
+/********************************************************
+ * \brief Get the affine transformation coefficients
+ ********************************************************/
+CPLErr PostGISRasterTileDataset::GetGeoTransform(double * padfTransform) {
+    // copy necessary values in supplied buffer
+    padfTransform[0] = adfGeoTransform[0];
+    padfTransform[1] = adfGeoTransform[1];
+    padfTransform[2] = adfGeoTransform[2];
+    padfTransform[3] = adfGeoTransform[3];
+    padfTransform[4] = adfGeoTransform[4];
+    padfTransform[5] = adfGeoTransform[5];
+
+    return CE_None;
+}
+
+/********************************************************
+ * \brief Return spatial extent of tile
+ ********************************************************/
+void PostGISRasterTileDataset::GetExtent(double* pdfMinX, double* pdfMinY,
+                                         double* pdfMaxX, double* pdfMaxY)
+{
+    // FIXME; incorrect in case of non 0 rotation terms
+
+    double dfMinX = adfGeoTransform[GEOTRSFRM_TOPLEFT_X];
+    double dfMaxY = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
+
+    double dfMaxX = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
+            nRasterXSize * adfGeoTransform[GEOTRSFRM_WE_RES] + 
+            nRasterYSize * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
+            
+    double dfMinY = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
+            nRasterXSize * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +  
+            nRasterYSize * adfGeoTransform[GEOTRSFRM_NS_RES];
+
+    // In case yres > 0
+    if( dfMinY > dfMaxY )
+    {
+        double dfTemp = dfMinY;
+        dfMinY = dfMaxY;
+        dfMaxY = dfTemp;
+    }
+    
+    *pdfMinX = dfMinX;
+    *pdfMinY = dfMinY;
+    *pdfMaxX = dfMaxX;
+    *pdfMaxY = dfMaxY;
+}
diff --git a/frmts/postgisraster/postgisrastertilerasterband.cpp b/frmts/postgisraster/postgisrastertilerasterband.cpp
new file mode 100644
index 0000000..5397bad
--- /dev/null
+++ b/frmts/postgisraster/postgisrastertilerasterband.cpp
@@ -0,0 +1,194 @@
+/***********************************************************************
+ * File :    postgisrastertilerasterband.cpp
+ * Project:  PostGIS Raster driver
+ * Purpose:  GDAL Tile RasterBand implementation for PostGIS Raster 
+ * driver
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ *                          jorgearevalo at libregis.org
+ * Last changes: $Id: $
+ *
+ ***********************************************************************
+ * Copyright (c) 2009 - 2013, Jorge Arevalo
+ * Copyright (c) 2013, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ **********************************************************************/
+#include "postgisraster.h"
+
+/************************
+ * \brief Constructor
+ ************************/
+PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
+    PostGISRasterTileDataset * poRTDS, int nBand,
+    GDALDataType eDataType, GBool bIsOffline)
+{
+    /* Basic properties */
+    this->poDS = poRTDS;
+    this->bIsOffline = bIsOffline;
+    this->nBand = nBand;
+    
+#if 0
+    CPLDebug("PostGIS_Raster", 
+        "PostGISRasterTileRasterBand::Constructor: Raster tile dataset "
+        "of dimensions %dx%d", poRTDS->GetRasterXSize(), 
+        poRTDS->GetRasterYSize());
+#endif
+
+    this->eDataType = eDataType;
+
+    nRasterXSize = poRTDS->GetRasterXSize();
+    nRasterYSize = poRTDS->GetRasterYSize();
+
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = nRasterYSize;
+}
+
+
+/************************
+ * \brief Destructor
+ ************************/
+PostGISRasterTileRasterBand::~PostGISRasterTileRasterBand()
+{
+}
+
+/***********************************************************************
+ * \brief Returns true if the (only) block is stored in the cache
+ **********************************************************************/ 
+GBool PostGISRasterTileRasterBand::IsCached()
+{
+    GDALRasterBlock * poBlock = TryGetLockedBlockRef(0, 0);
+    if (poBlock != NULL) {
+        poBlock->DropLock();
+        return true;
+    }
+    
+    return false;
+}
+
+/*****************************************************
+ * \brief Read a natural block of raster band data
+ *****************************************************/
+CPLErr PostGISRasterTileRasterBand::IReadBlock(int nBlockXOff, 
+    int nBlockYOff, void * pImage)
+{
+    CPLString osCommand;
+    PGresult * poResult = NULL;
+    int nWKBLength = 0;
+    
+    int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
+    
+    PostGISRasterTileDataset * poRTDS = 
+        (PostGISRasterTileDataset *)poDS;
+        
+    // Get by PKID
+    if (poRTDS->poRDS->pszPrimaryKeyName) {
+        osCommand.Printf("select st_band(%s, %d) from %s.%s where "
+            "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable,
+            poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID);
+
+    }
+    
+    // Get by upperleft
+    else {
+        CPLLocaleC oCLocale; // Force C locale to avoid commas instead of decimal points (for QGIS e.g.)
+        osCommand.Printf("select st_band(%s, %d) from %s.%s where "
+            "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8", 
+            poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn, 
+            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn, 
+            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);
+        
+    }
+    
+    poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str());
+    
+#ifdef DEBUG_QUERY
+    CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::IReadBlock(): "
+             "Query = \"%s\" --> number of rows = %d",
+             osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
+#endif
+
+    if (poResult == NULL || 
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+        PQntuples(poResult) <= 0) {
+            
+        if (poResult)
+            PQclear(poResult);
+            
+        ReportError(CE_Failure, CPLE_AppDefined,
+            "Error getting block of data (upperpixel = %f, %f)",
+                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);
+            
+        return CE_Failure;
+    }
+
+
+    // TODO: Check this
+    if (bIsOffline) {
+        CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb "
+            "storage. This feature isn't still available");
+        
+        PQclear(poResult);    
+        return CE_Failure;
+    }
+    
+    /* Copy only data size, without payload */
+    int nExpectedDataSize = 
+        nBlockXSize * nBlockYSize * nPixelSize;
+        
+    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), 
+        &nWKBLength);
+    int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize);
+    CPLErr eRet = CE_None;
+    if( nWKBLength != nExpectedWKBLength )
+    {
+        CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d", nWKBLength, nExpectedWKBLength );
+        eRet = CE_Failure;
+    }
+    else
+    {
+        GByte * pbyDataToRead = 
+        (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize, 
+            nExpectedDataSize);
+
+        // Do byte-swapping if necessary */
+        int bIsLittleEndian = (pbyData[0] == 1);
+#ifdef CPL_LSB
+        int bSwap = !bIsLittleEndian;
+#else
+        int bSwap = bIsLittleEndian;
+#endif
+        if( bSwap && nPixelSize > 1 )
+        {
+            GDALSwapWords( pbyDataToRead, nPixelSize,
+                           nBlockXSize * nBlockYSize,
+                           nPixelSize );
+        }
+
+        memcpy(pImage, pbyDataToRead, nExpectedDataSize);
+    }
+
+    CPLFree(pbyData);
+    PQclear(poResult);
+
+    return eRet;
+}
+
diff --git a/frmts/postgisraster/postgisrastertools.cpp b/frmts/postgisraster/postgisrastertools.cpp
new file mode 100644
index 0000000..5b4d58d
--- /dev/null
+++ b/frmts/postgisraster/postgisrastertools.cpp
@@ -0,0 +1,226 @@
+/***********************************************************************
+ * File :    postgisrastertools.cpp
+ * Project:  PostGIS Raster driver
+ * Purpose:  Tools for PostGIS Raster driver
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
+ *                          jorgearevalo at libregis.org
+ * 
+ * Author:	 David Zwarg, dzwarg at azavea.com
+ *
+ * Last changes: $Id: $
+ *
+ ***********************************************************************
+ * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * SOFTWARE.
+ **********************************************************************/
+ #include "postgisraster.h"
+ 
+ 
+ /**********************************************************************
+ * \brief Replace the quotes by single quotes in the input string
+ *
+ * Needed in the 'where' part of the input string
+ **********************************************************************/
+char * ReplaceQuotes(const char * pszInput, int nLength) {
+    int i;
+    char * pszOutput = NULL;
+
+    if (nLength == -1)
+        nLength = strlen(pszInput);
+
+    pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
+
+    for (i = 0; i < nLength; i++) {
+        if (pszInput[i] == '"')
+            pszOutput[i] = '\'';
+        else
+            pszOutput[i] = pszInput[i];
+    }
+
+    return pszOutput;
+}
+
+/**************************************************************
+ * \brief Replace the single quotes by " in the input string
+ *
+ * Needed before tokenize function
+ *************************************************************/
+char * ReplaceSingleQuotes(const char * pszInput, int nLength) {
+    int i;
+    char* pszOutput = NULL;
+
+    if (nLength == -1)
+        nLength = strlen(pszInput);
+
+    pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
+
+    for (i = 0; i < nLength; i++) {
+        if (pszInput[i] == '\'')
+            pszOutput[i] = '"';
+        else
+            pszOutput[i] = pszInput[i];
+
+    }
+
+    return pszOutput;
+}
+
+
+/***********************************************************************
+ * \brief Split connection string into user, password, host, database...
+ *
+ * The parameters separated by spaces are return as a list of strings.
+ * The function accepts all the PostgreSQL recognized parameter keywords.
+ *
+ * The returned list must be freed with CSLDestroy when no longer needed
+ **********************************************************************/
+char** ParseConnectionString(const char * pszConnectionString) {
+    char * pszEscapedConnectionString = NULL;
+
+    /* Escape string following SQL scheme */
+    pszEscapedConnectionString = 
+        ReplaceSingleQuotes(pszConnectionString, -1);
+
+    /* Avoid PG: part */
+    char* pszStartPos = (char*) 
+        strstr(pszEscapedConnectionString, ":") + 1;
+
+    /* Tokenize */
+    char** papszParams = 
+        CSLTokenizeString2(pszStartPos, " ", CSLT_HONOURSTRINGS);
+
+    /* Free */
+    CPLFree(pszEscapedConnectionString);
+
+    return papszParams;
+}
+
+/***********************************************************************
+ * \brief Translate a PostGIS Raster datatype string in a valid 
+ * GDALDataType object.
+ **********************************************************************/
+GBool TranslateDataType(const char * pszDataType,
+        GDALDataType * poDataType = NULL, int * pnBitsDepth = NULL,
+        GBool * pbSignedByte = NULL)
+{
+    if (!pszDataType)
+        return false;
+
+    if (pbSignedByte)
+        *pbSignedByte = false;
+
+    if (EQUALN(pszDataType, "1BB", 3 * sizeof(char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 1;
+        if (poDataType)
+            *poDataType = GDT_Byte;
+    }
+
+    else if (EQUALN(pszDataType, "2BUI", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 2;
+        if (poDataType)
+            *poDataType = GDT_Byte;
+    }
+
+    else if (EQUALN(pszDataType, "4BUI", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 4;
+        if (poDataType)
+            *poDataType = GDT_Byte;
+    }
+
+    else if (EQUALN(pszDataType, "8BUI", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 8;
+        if (poDataType)
+            *poDataType = GDT_Byte;
+    }
+
+    else if (EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 8;
+        if (poDataType)
+            *poDataType = GDT_Byte;
+
+        /**
+         * To indicate the unsigned byte values between 128 and 255
+         * should be interpreted as being values between -128 and -1 for
+         * applications that recognize the SIGNEDBYTE type.
+         **/
+        if (pbSignedByte)
+            *pbSignedByte = true;
+    }
+    else if (EQUALN(pszDataType, "16BSI", 5 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 16;
+        if (poDataType)
+            *poDataType = GDT_Int16;
+    }
+
+    else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 16;
+        if (poDataType)
+            *poDataType = GDT_UInt16;
+    }
+
+    else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 32;
+        if (poDataType)
+            *poDataType = GDT_Int32;
+    }
+
+    else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 32;
+        if (poDataType)
+            *poDataType = GDT_UInt32;
+    }
+
+    else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 32;
+        if (poDataType)
+            *poDataType = GDT_Float32;
+    }
+
+    else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char))) {
+        if (pnBitsDepth)
+            *pnBitsDepth = 64;
+        if (poDataType)
+            *poDataType = GDT_Float64;
+    }
+
+    else {
+        if (pnBitsDepth)
+            *pnBitsDepth = -1;
+        if (poDataType)
+            *poDataType = GDT_Unknown;
+
+        return false;
+    }
+
+    return true;
+}
+
diff --git a/frmts/r/rdataset.cpp b/frmts/r/rdataset.cpp
index 87868e6..44af32f 100644
--- a/frmts/r/rdataset.cpp
+++ b/frmts/r/rdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  R Format Driver
  * Purpose:  Read/write R stats package object format.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "../raw/rawdataset.h"
 
-CPL_CVSID("$Id: rdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: rdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_R(void);
diff --git a/frmts/rasdaman/rasdamandataset.cpp b/frmts/rasdaman/rasdamandataset.cpp
index e6c2011..96abd7c 100644
--- a/frmts/rasdaman/rasdamandataset.cpp
+++ b/frmts/rasdaman/rasdamandataset.cpp
@@ -1,11 +1,12 @@
 /******************************************************************************
- * $Id: rasdamandataset.cpp 23362 2011-11-11 11:11:52Z rouault $
+ * $Id: rasdamandataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  * Project:  rasdaman Driver
- * Purpose:  Implement Rasdaman GDAL driver 
+ * Purpose:  Implement Rasdaman GDAL driver
  * Author:   Constantin Jucovschi, jucovschi at yahoo.com
  *
  ******************************************************************************
  * Copyright (c) 2010, Constantin Jucovschi
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,6 +33,7 @@
 #include "regex.h"
 #include <string>
 #include <memory>
+#include <map>
 
 
 #define __EXECUTABLE__
@@ -42,7 +44,7 @@
 
 #include "rasodmg/database.hh"
 
-CPL_CVSID("$Id: rasdamandataset.cpp 23362 2011-11-11 11:11:52Z rouault $");
+CPL_CVSID("$Id: rasdamandataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 CPL_C_START
@@ -50,12 +52,58 @@ void	GDALRegister_RASDAMAN(void);
 CPL_C_END
 
 
+class Subset
+{
+public:
+  Subset(int x_lo, int x_hi, int y_lo, int y_hi)
+    : m_x_lo(x_lo), m_x_hi(x_hi),  m_y_lo(y_lo),  m_y_hi(y_hi)
+  {}
+
+  bool operator < (const Subset& rhs) const {
+    if (m_x_lo < rhs.m_x_lo || m_x_hi < rhs.m_x_hi
+        || m_y_lo < rhs.m_y_lo || m_y_hi < rhs.m_y_hi) {
+
+      return true;
+    }
+    return false;
+  }
+
+  bool contains(const Subset& other) const {
+    return m_x_lo <= other.m_x_lo && m_x_hi >= other.m_x_hi
+        && m_y_lo <= other.m_y_lo && m_y_hi >= other.m_y_hi;
+  }
+
+  bool within(const Subset& other) const {
+    return other.contains(*this);
+  }
+
+  void operator = (const Subset& rhs) {
+    m_x_lo = rhs.m_x_lo;
+    m_x_hi = rhs.m_x_hi;
+    m_y_lo = rhs.m_y_lo;
+    m_y_hi = rhs.m_y_hi;
+  }
+
+  int x_lo() const { return m_x_lo; }
+  int x_hi() const { return m_x_hi; }
+  int y_lo() const { return m_y_lo; }
+  int y_hi() const { return m_y_hi; }
+
+private:
+  int m_x_lo;
+  int m_x_hi;
+  int m_y_lo;
+  int m_y_hi;
+};
+
+
 /************************************************************************/
 /* ==================================================================== */
-/*				RasdamanDataset				*/
+/*        RasdamanDataset                                               */
 /* ==================================================================== */
 /************************************************************************/
 
+typedef std::map<Subset, r_Ref<r_GMarray> > ArrayCache;
 
 class RasdamanRasterBand;
 static CPLString getQuery(const char *templateString, const char* x_lo, const char* x_hi, const char* y_lo, const char* y_hi);
@@ -64,15 +112,35 @@ class RasdamanDataset : public GDALPamDataset
 {
   friend class RasdamanRasterBand;
 
-  public:
-		~RasdamanDataset();
-    
-    static GDALDataset *Open( GDALOpenInfo * );
+public:
+  RasdamanDataset(const char*, int, const char*, const char*, const char*);
+  ~RasdamanDataset();
+
+  static GDALDataset *Open( GDALOpenInfo * );
+
+protected:
+
+  virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                            void *, int, int, GDALDataType,
+                            int, int *, int, int, int );
 
 private:
+
+  ArrayCache m_array_cache;
+
+  r_Ref<r_GMarray>& request_array(int x_lo, int x_hi, int y_lo, int y_hi, int& offsetX, int& offsetY);
+  r_Ref<r_GMarray>& request_array(const Subset&, int& offsetX, int& offsetY);
+
+  void clear_array_cache();
+
+  r_Set<r_Ref_Any> execute(const char* string);
+
   void getTypes(const r_Base_Type* baseType, int &counter, int pos);
   void createBands(const char* queryString);
 
+  r_Database database;
+  r_Transaction transaction;
+  
   CPLString queryParam;
   CPLString host;
   int port;
@@ -86,146 +154,277 @@ private:
 };
 
 /************************************************************************/
+/*                            RasdamanDataset()                         */
+/************************************************************************/
+
+RasdamanDataset::RasdamanDataset(const char* _host, int _port, const char* _username,
+                                 const char* _userpassword, const char* _databasename)
+  : host(_host), port(_port), username(_username), userpassword(_userpassword),
+    databasename(_databasename)
+{
+  database.set_servername(host, port);
+  database.set_useridentification(username, userpassword);
+  database.open(databasename);
+}
+
+/************************************************************************/
+/*                            ~RasdamanDataset()                        */
+/************************************************************************/
+
+RasdamanDataset::~RasdamanDataset()
+{
+  if (transaction.get_status() == r_Transaction::active) {
+    transaction.commit();
+  }
+  database.close();
+  FlushCache();
+}
+
+
+CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType, 
+                               int nBandCount, int *panBandMap,
+                               int nPixelSpace, int nLineSpace, int nBandSpace)
+{
+  if (eRWFlag != GF_Read) {
+    CPLError(CE_Failure, CPLE_NoWriteAccess, "Write support is not implemented.");
+    return CE_Failure;
+  }
+  
+  transaction.begin(r_Transaction::read_only);
+  
+  /* TODO: Setup database access/transaction */
+  int dummyX, dummyY;
+  /* Cache the whole image region */
+  CPLDebug("rasdaman", "Pre-caching region (%d, %d, %d, %d).", nXOff, nXOff + nXSize, nYOff, nYOff + nYSize);
+  request_array(nXOff, nXOff + nXSize, nYOff, nYOff + nYSize, dummyX, dummyY);
+
+  CPLErr ret = GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                                      nBufXSize, nBufYSize, eBufType, nBandCount,
+                                      panBandMap, nPixelSpace, nLineSpace, nBandSpace);
+
+  transaction.commit();
+  
+  /* Clear the cache */
+  clear_array_cache();
+
+  return ret;
+}
+
+
+r_Ref<r_GMarray>& RasdamanDataset::request_array(int x_lo, int x_hi, int y_lo, int y_hi, int& offsetX, int& offsetY)
+{
+  return request_array(Subset(x_lo, x_hi, y_lo, y_hi), offsetX, offsetY);
+};
+
+r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offsetX, int& offsetY)
+{
+  // set the offsets to 0
+  offsetX = 0; offsetY = 0;
+  
+  // check whether or not the subset was already requested
+  ArrayCache::iterator it = m_array_cache.find(subset);
+  if (it != m_array_cache.end()) {
+    CPLDebug("rasdaman", "Fetching tile (%d, %d, %d, %d) from cache.",
+          subset.x_lo(), subset.x_hi(), subset.y_lo(), subset.y_hi());
+
+    return it->second;
+  }
+
+  // check if any tile contains the requested one
+  for(it = m_array_cache.begin(); it != m_array_cache.end(); ++it) {
+    if (it->first.contains(subset)) {
+      const Subset& existing = it->first;
+
+      // TODO: check if offsets are correct
+      offsetX = subset.x_lo() - existing.x_lo();
+      offsetY = subset.y_lo() - existing.y_lo();
+      
+      CPLDebug("rasdaman", "Found matching tile (%d, %d, %d, %d) for requested tile (%d, %d, %d, %d). Offests are (%d, %d).",
+            existing.x_lo(), existing.x_hi(), existing.y_lo(), existing.y_hi(),
+            subset.x_lo(), subset.x_hi(), subset.y_lo(), subset.y_hi(),
+            offsetX, offsetY);
+      
+      
+      return it->second;
+    }
+  }
+
+  if (transaction.get_status() != r_Transaction::active) {
+    transaction.begin(r_Transaction::read_only);
+  }
+
+  CPLDebug("rasdaman", "Tile (%d, %d, %d, %d) not found in cache, requesting it.",
+        subset.x_lo(), subset.x_hi(), subset.y_lo(), subset.y_hi());
+
+  char x_lo[11], x_hi[11], y_lo[11], y_hi[11];
+
+  snprintf(x_lo, sizeof(x_lo), "%d", subset.x_lo());
+  snprintf(x_hi, sizeof(x_hi), "%d", subset.x_hi());
+  snprintf(y_lo, sizeof(y_lo), "%d", subset.y_lo());
+  snprintf(y_hi, sizeof(y_hi), "%d", subset.y_hi());
+
+  CPLString queryString = getQuery(queryParam, x_lo, x_hi, y_lo, y_hi);
+
+  r_Set<r_Ref_Any> result_set = execute(queryString);
+  if (result_set.get_element_type_schema()->type_id() == r_Type::MARRAYTYPE) {
+    // TODO: throw exception
+  }
+
+  if (result_set.cardinality() != 1) {
+    // TODO: throw exception
+  }
+  
+  r_Ref<r_GMarray> result_array = r_Ref<r_GMarray>(*result_set.create_iterator());
+  //std::auto_ptr<r_GMarray> ptr(new r_GMarray);
+  //r_GMarray* ptr_ = ptr.get();
+  //(*ptr) = *result_array;
+  //std::pair<ArrayCache::iterator, bool> inserted = m_array_cache.insert(ArrayCache::value_type(subset, ptr));
+  
+  std::pair<ArrayCache::iterator, bool> inserted = m_array_cache.insert(ArrayCache::value_type(subset, result_array));
+
+  return inserted.first->second;//*(ptr);
+};
+
+
+void RasdamanDataset::clear_array_cache() {
+  m_array_cache.clear();
+};
+
+/************************************************************************/
 /* ==================================================================== */
-/*                            RasdamanRasterBand                             */
+/*                            RasdamanRasterBand                        */
 /* ==================================================================== */
 /************************************************************************/
 
 class RasdamanRasterBand : public GDALPamRasterBand
 {
   friend class RasdamanDataset;
-  
+
   int          nRecordSize;
   int          typeOffset;
   int          typeSize;
-  
+
 public:
-  
+
   RasdamanRasterBand( RasdamanDataset *, int, GDALDataType type, int offset, int size, int nBlockXSize, int nBlockYSize );
   ~RasdamanRasterBand();
-  
+
   virtual CPLErr IReadBlock( int, int, void * );
 };
 
+/************************************************************************/
+/*  RasdamanParams                                                      */
+/************************************************************************/
+
+/*struct RasdamanParams
+{
+  RasdamanParams(const char* dataset_info);
+
+  void connect(const r_Database&);
+
+  const char *query;
+  const char *host;
+  const int port;
+  const char *username;
+  const char *password;
+};*/
+
 
 /************************************************************************/
-/*                           RasdamanRasterBand()                            */
+/*                           RasdamanRasterBand()                       */
 /************************************************************************/
 
 RasdamanRasterBand::RasdamanRasterBand( RasdamanDataset *poDS, int nBand, GDALDataType type, int offset, int size, int nBlockXSize, int nBlockYSize )
 {
   this->poDS = poDS;
   this->nBand = nBand;
-  
+
   eDataType = type;
   typeSize = size;
   typeOffset = offset;
 
   this->nBlockXSize = nBlockXSize;
   this->nBlockYSize = nBlockYSize;
-    
+
   nRecordSize = nBlockXSize * nBlockYSize * typeSize;
 }
 
 /************************************************************************/
-/*                          ~RasdamanRasterBand()                            */
+/*                          ~RasdamanRasterBand()                       */
 /************************************************************************/
 
 RasdamanRasterBand::~RasdamanRasterBand()
-{
-
-}
+{}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
 CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-				       void * pImage )
-  
+                                       void * pImage )
 {
-  //cerr << "Read block " << nBlockXOff << " " << nBlockYOff << endl;
   RasdamanDataset *poGDS = (RasdamanDataset *) poDS;
-  
-  r_Database database;  
-  r_Transaction transaction;
 
   memset(pImage, 0, nRecordSize);
 
   try {
-    database.set_servername(poGDS->host, poGDS->port);
-    database.set_useridentification(poGDS->username, poGDS->userpassword);
-    database.open(poGDS->databasename);
-    transaction.begin();
+    int x_lo = nBlockXOff * nBlockXSize,
+        x_hi = MIN(poGDS->nRasterXSize, (nBlockXOff + 1) * nBlockXSize),
+        y_lo = nBlockYOff * nBlockYSize,
+        y_hi = MIN(poGDS->nRasterYSize, (nBlockYOff + 1) * nBlockYSize),
+        offsetX = 0, offsetY = 0;
+    
+    r_Ref<r_GMarray>& gmdd = poGDS->request_array(x_lo, x_hi, y_lo, y_hi, offsetX, offsetY);
 
-    char x_lo[11], x_hi[11], y_lo[11], y_hi[11];
     int xPos = poGDS->xPos;
     int yPos = poGDS->yPos;
-    
-    sprintf(x_lo, "%d", nBlockXOff * nBlockXSize);
-    sprintf(x_hi, "%d", (nBlockXOff+1) * nBlockXSize-1);
-    sprintf(y_lo, "%d", nBlockYOff * nBlockYSize);
-    sprintf(y_hi, "%d", (nBlockYOff+1) * nBlockYSize-1);
-    CPLString queryString = getQuery(poGDS->queryParam, x_lo, x_hi, y_lo, y_hi);
   
-    r_Set<r_Ref_Any> result_set;
-    r_OQL_Query query (queryString);
-    r_oql_execute (query, result_set);
-    if (result_set.get_element_type_schema()->type_id() == r_Type::MARRAYTYPE) {
-      r_Iterator<r_Ref_Any> iter = result_set.create_iterator();
-      r_Ref<r_GMarray> gmdd = r_Ref<r_GMarray>(*iter);
-      r_Minterval sp = gmdd->spatial_domain();
-      r_Point extent = sp.get_extent();
-      r_Point base = sp.get_origin();
-      int tileX = extent[xPos];
-      int tileY = extent[yPos];
-      r_Point access = base;
-      char *resultPtr;
-      for (int j=0; j<tileY; ++j) {
-	for (int i=0; i<tileX; ++i) {
-	  resultPtr = (char*)pImage + (j*nBlockYSize+i)*typeSize;
-	  access[xPos] = base[xPos]+i;
-	  access[yPos] = base[yPos]+j;
-	  const char *data = (*gmdd)[access] + typeOffset;
-	  memcpy(resultPtr, data, typeSize);
-	}
+    r_Minterval sp = gmdd->spatial_domain();
+    r_Point extent = sp.get_extent();
+    r_Point base = sp.get_origin();
+    
+    int extentX = extent[xPos];
+    int extentY = extent[yPos];
+
+    CPLDebug("rasdaman", "Extents (%d, %d).", extentX, extentY);
+
+    r_Point access = base;
+    char *resultPtr;
+
+    for(int y = y_lo; y < y_hi; ++y) {
+      for(int x = x_lo; x < x_hi; ++x) {
+        resultPtr = (char*)pImage + ((y - y_lo) * nBlockXSize + x - x_lo) * typeSize;
+        //resultPtr = (char*) pImage
+        access[xPos] = x;// base[xPos] + offsetX; TODO: check if required
+        access[yPos] = y;// base[yPos] + offsetY;
+        const char *data = (*gmdd)[access] + typeOffset;
+        memcpy(resultPtr, data, typeSize);
       }
     }
-    
-    transaction.commit();
-    database.close();
-  } catch (r_Error error) {
+  }
+  catch (r_Error error) {
     CPLError(CE_Failure, CPLE_AppDefined, "%s", error.what());
     return CPLGetLastErrorType();
   }
+  
   return CE_None;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				RasdamanDataset				*/
+/*                            RasdamanDataset                           */
 /* ==================================================================== */
 /************************************************************************/
 
-/************************************************************************/
-/*                            ~RasdamanDataset()                             */
-/************************************************************************/
-
-RasdamanDataset::~RasdamanDataset()
-{
-  FlushCache();
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
 static CPLString getOption(const char *string, regmatch_t cMatch, const char* defaultValue) {
   if (cMatch.rm_eo == -1 || cMatch.rm_so == -1)
     return defaultValue;
   char *result = new char[cMatch.rm_eo-cMatch.rm_so+1];
-  strncpy(result, string+cMatch.rm_so, cMatch.rm_eo-cMatch.rm_so);
-  result[cMatch.rm_eo-cMatch.rm_so]=0;
+  strncpy(result, string + cMatch.rm_so, cMatch.rm_eo - cMatch.rm_so);
+  result[cMatch.rm_eo-cMatch.rm_so] = 0;
   CPLString osResult = result;
   delete[] result;
   return osResult;
@@ -235,49 +434,33 @@ static int getOption(const char *string, regmatch_t cMatch, int defaultValue) {
   if (cMatch.rm_eo == -1 || cMatch.rm_so == -1)
     return defaultValue;
   char *result = new char[cMatch.rm_eo-cMatch.rm_so+1];
-  strncpy(result, string+cMatch.rm_so, cMatch.rm_eo-cMatch.rm_so);
-  result[cMatch.rm_eo-cMatch.rm_so]=0;
+  strncpy(result, string + cMatch.rm_so, cMatch.rm_eo - cMatch.rm_so);
+  result[cMatch.rm_eo-cMatch.rm_so] = 0;
   int nRet = atoi(result);
   delete[] result;
   return nRet;
 }
 
-static CPLString getQuery(const char *templateString, const char* x_lo, const char* x_hi, const char* y_lo, const char* y_hi) {
-  static regex_t* replaceRegEx = NULL;
-  regmatch_t match[3];
-  if (replaceRegEx == NULL) {
-    replaceRegEx = new regex_t;
-    regcomp(replaceRegEx, "\\$(x|y)_(lo|hi)", REG_EXTENDED);    
+void replace(CPLString& str, const char *from, const char *to) {
+  if(strlen(from) == 0)
+    return;
+  size_t start_pos = 0;
+  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
+    str.replace(start_pos, strlen(from), to);
+    start_pos += strlen(to); // In case 'to' contains 'from', like replacing 'x' with 'yx'
   }
+}
 
-  int pos = 0, resPos = 0;
-  char *result = new char[strlen(templateString)*2];
-
-  while (regexec(replaceRegEx, templateString+pos, 3, match, 0) == 0) {
-    strncpy(result+resPos, templateString+pos, match[1].rm_so-1);
-    resPos += match[1].rm_so-1;
-    if (templateString[pos+match[1].rm_so]=='x') {
-      if (templateString[pos+match[2].rm_so]=='h') {
-	strcpy(result+resPos, x_hi); resPos+=strlen(x_hi);
-      } else {
-	strcpy(result+resPos, x_lo); resPos+=strlen(x_lo);
-      }
-    } else {
-      if (templateString[pos+match[2].rm_so]=='h') {
-	strcpy(result+resPos, y_hi); resPos+=strlen(y_hi);
-      } else {
-	strcpy(result+resPos, y_lo); resPos+=strlen(y_lo);
-      }
-    }
-    pos += match[2].rm_eo;
-  }
-  int rest = strlen(templateString+pos);
-  strncpy(result+resPos, templateString+pos, rest);
-  resPos += rest;
-  result[resPos]='\0';
-  CPLString osResult = result;
-  delete[] result;
-  return osResult;
+
+static CPLString getQuery(const char *templateString, const char* x_lo, const char* x_hi, const char* y_lo, const char* y_hi) {
+  CPLString result(templateString);
+
+  replace(result, "$x_lo", x_lo);
+  replace(result, "$x_hi", x_hi);
+  replace(result, "$y_lo", y_lo);
+  replace(result, "$y_hi", y_hi);
+  
+  return result;
 }
 
 GDALDataType mapRasdamanTypesToGDAL(r_Type::r_Type_Id typeId) {
@@ -310,11 +493,11 @@ void RasdamanDataset::getTypes(const r_Base_Type* baseType, int &counter, int po
   if (baseType->isStructType()) {
     r_Structure_Type* tp = (r_Structure_Type*) baseType;
     int elem = tp->count_elements();
-    for (int i=0; i<elem; ++i) {
+    for (int i = 0; i < elem; ++i) {
       r_Attribute attr = (*tp)[i];
       getTypes(&attr.type_of(), counter, attr.global_offset());
     }
-    
+
   }
   if (baseType->isPrimitiveType()) {
     r_Primitive_Type *primType = (r_Primitive_Type*)baseType;
@@ -337,6 +520,14 @@ void RasdamanDataset::createBands(const char* queryString) {
   }
 }
 
+r_Set<r_Ref_Any> RasdamanDataset::execute(const char* string) {
+  CPLDebug("rasdaman", "Executing query '%s'.", string);
+  r_Set<r_Ref_Any> result_set;
+  r_OQL_Query query(string);
+  r_oql_execute(query, result_set);
+  return result_set;
+}
+
 
 static int getExtent(const char *queryString, int &pos) {
   r_Set<r_Ref_Any> result_set;
@@ -348,11 +539,11 @@ static int getExtent(const char *queryString, int &pos) {
     r_Point extent = interv->get_extent();
     int dim = extent.dimension();
     int result = -1;
-    for (int i=0; i<dim; ++i) {
+    for (int i = 0; i < dim; ++i) {
       if (extent[i] == 1)
-	continue;
+        continue;
       if (result != -1)
-	return -1;
+        return -1;
       result = extent[i];
       pos = i;
     }
@@ -371,7 +562,7 @@ static int getExtent(const char *queryString, int &pos) {
 
 GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-  // buffer to communicate errors 
+  // buffer to communicate errors
   char errbuffer[4096];
 
   // fast checks if current module should handle the request
@@ -392,30 +583,30 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
   // array to store matching subexpressions
   regmatch_t matches[10];
 
-  #define QUERY_POSITION 2
-  #define SERVER_POSITION 3
-  #define PORT_POSITION 4
-  #define USERNAME_POSITION 5
-  #define USERPASSWORD_POSITION 6
-  #define DATABASE_POSITION 7
-  #define TILEXSIZE_POSITION 8
-  #define TILEYSIZE_POSITION 9
+#define QUERY_POSITION 2
+#define SERVER_POSITION 3
+#define PORT_POSITION 4
+#define USERNAME_POSITION 5
+#define USERPASSWORD_POSITION 6
+#define DATABASE_POSITION 7
+#define TILEXSIZE_POSITION 8
+#define TILEYSIZE_POSITION 9
 
-  int result = regcomp(&optionRegEx, "^rasdaman:(query='([[:alnum:][:punct:] ]+)'|host='([[:alnum:]]+)'|port=([0-9]+)|user='([[:alnum:]]+)'|password='([[:alnum:]]+)'|database '([[:alnum:]]+)'|tileXSize=([0-9]+)|tileYSize=([0-9]+)| )*", REG_EXTENDED);
+  int result = regcomp(&optionRegEx, "^rasdaman:(query='([[:alnum:][:punct:] ]+)'|host='([[:alnum:][:punct:]]+)'|port=([0-9]+)|user='([[:alnum:]]+)'|password='([[:alnum:]]+)'|database='([[:alnum:]]+)'|tileXSize=([0-9]+)|tileYSize=([0-9]+)| )*", REG_EXTENDED);
 
-  // should never happen 
+  // should never happen
   if (result != 0) {
     regerror(result, &optionRegEx, errbuffer, 4096);
     CPLError(CE_Failure, CPLE_AppDefined, "Internal error at compiling option parsing regex: %s", errbuffer);
-    return NULL; 
+    return NULL;
   }
 
   result = regcomp(&queryRegEx, "^select ([[:alnum:][:punct:] ]*) from ([[:alnum:][:punct:] ]*)$", REG_EXTENDED);
-  // should never happen 
+  // should never happen
   if (result != 0) {
     regerror(result, &queryRegEx, errbuffer, 4096);
     CPLError(CE_Failure, CPLE_AppDefined, "Internal error at compiling option parsing regex: %s", errbuffer);
-    return NULL; 
+    return NULL;
   }
 
   // executing option parsing regex on the connection string and checking if it succeeds
@@ -425,18 +616,18 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLError(CE_Failure, CPLE_AppDefined, "Parsing opening parameters failed with error: %s", errbuffer);
     regfree(&optionRegEx);
     regfree(&queryRegEx);
-    return NULL; 
+    return NULL;
   }
 
   regfree(&optionRegEx);
-  
 
-  // checking if the whole expressions was matches, if not give an error where 
+
+  // checking if the whole expressions was matches, if not give an error where
   // the matching stopped and exit
   if (size_t(matches[0].rm_eo) < strlen(connString)) {
-    CPLError(CE_Failure, CPLE_AppDefined, "Parsing opening parameters failed with error: %s", connString+matches[0].rm_eo);
+    CPLError(CE_Failure, CPLE_AppDefined, "Parsing opening parameters failed with error: %s", connString + matches[0].rm_eo);
     regfree(&queryRegEx);
-    return NULL; 
+    return NULL;
   }
 
   CPLString queryParam = getOption(connString, matches[QUERY_POSITION], (const char*)NULL);
@@ -453,7 +644,7 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
     regerror(result, &queryRegEx, errbuffer, 4096);
     CPLError(CE_Failure, CPLE_AppDefined, "Parsing query parameter failed with error: %s", errbuffer);
     regfree(&queryRegEx);
-    return NULL; 
+    return NULL;
   }
 
   regfree(&queryRegEx);
@@ -463,23 +654,24 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
   osQueryString += ") from ";
   osQueryString += getOption(queryParam, matches[2], "");
 
+  CPLDebug("rasdaman", "osQueryString: %s", osQueryString.c_str());
+
   CPLString queryX = getQuery(osQueryString, "*", "*", "0", "0");
   CPLString queryY = getQuery(osQueryString, "0", "0", "*", "*");
   CPLString queryUnit = getQuery(queryParam, "0", "0", "0", "0");
 
-  stringstream queryStream;
-  
-  r_Transaction transaction;
-
-  RasdamanDataset *rasDataset = new RasdamanDataset();
+  CPLDebug("rasdaman", "queryX: %s", queryX.c_str());
+  CPLDebug("rasdaman", "queryY: %s", queryY.c_str());
+  CPLDebug("rasdaman", "queryUnit: %s", queryUnit.c_str());
 
-  r_Database database;  
+  RasdamanDataset *rasDataset = NULL;
   try {
-    database.set_servername(host, port);
-    database.set_useridentification(username, userpassword);
-    database.open(databasename);
-    transaction.begin();
-    
+    rasDataset = new RasdamanDataset(host, port, username, userpassword, databasename);
+    //getMyExtent(osQueryString, posX, sizeX, posY, sizeY);
+
+    r_Transaction transaction;
+    transaction.begin(r_Transaction::read_only);
+
     int dimX = getExtent(queryX, rasDataset->xPos);
     int dimY = getExtent(queryY, rasDataset->yPos);
     rasDataset->nRasterXSize = dimX;
@@ -489,18 +681,21 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
     rasDataset->createBands(queryUnit);
 
     transaction.commit();
-    database.close();
+
+    rasDataset->queryParam = queryParam;
+    rasDataset->host = host;
+    rasDataset->port = port;
+    rasDataset->username = username;
+    rasDataset->userpassword = userpassword;
+    rasDataset->databasename = databasename;
+
+    return rasDataset;
   } catch (r_Error error) {
     CPLError(CE_Failure, CPLE_AppDefined, "%s", error.what());
     delete rasDataset;
     return NULL;
   }
-  rasDataset->queryParam = queryParam;
-  rasDataset->host = host;
-  rasDataset->port = port;
-  rasDataset->username = username;
-  rasDataset->userpassword = userpassword;
-  rasDataset->databasename = databasename;
+  
 
   return rasDataset;
 }
@@ -512,20 +707,21 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
 extern void GDALRegister_RASDAMAN()
 
 {
-    GDALDriver	*poDriver;
+  GDALDriver	*poDriver;
 
-    if( GDALGetDriverByName( "RASDAMAN" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "RASDAMAN" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "RASDAMAN" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_rasdaman.html" );
+  if( GDALGetDriverByName( "RASDAMAN" ) == NULL )
+  {
+    poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = RasdamanDataset::Open;
+    poDriver->SetDescription( "RASDAMAN" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "RASDAMAN" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_rasdaman.html" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = RasdamanDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+  }
 }
+
diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp
index 4bc1848..d26c7e3 100644
--- a/frmts/rasterlite/rasterlitecreatecopy.cpp
+++ b/frmts/rasterlite/rasterlitecreatecopy.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: rasterlitecreatecopy.cpp 25391 2012-12-29 19:20:46Z rouault $
+ * $Id: rasterlitecreatecopy.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitecreatecopy.cpp 25391 2012-12-29 19:20:46Z rouault $");
+CPL_CVSID("$Id: rasterlitecreatecopy.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                  RasterliteGetTileDriverOptions ()                   */
diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp
index cc47c5b..9cb0dd8 100644
--- a/frmts/rasterlite/rasterlitedataset.cpp
+++ b/frmts/rasterlite/rasterlitedataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: rasterlitedataset.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: rasterlitedataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitedataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: rasterlitedataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            RasterliteBand()                          */
@@ -658,6 +658,17 @@ void RasterliteDataset::AddSubDataset( const char* pszDSName)
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **RasterliteDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", "IMAGE_STRUCTURE", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
@@ -1163,7 +1174,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             //printf("[%d] xres=%.15f yres=%.15f\n", i,
             //       poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
             
-            if (poDS->padfXResolutions[i] <= 0 || poDS->padfXResolutions[i] <= 0)
+            if (poDS->padfXResolutions[i] <= 0 || poDS->padfYResolutions[i] <= 0)
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "res=%d, xres=%.15f, yres=%.15f",
diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h
index ce44f7a..be1d9cc 100644
--- a/frmts/rasterlite/rasterlitedataset.h
+++ b/frmts/rasterlite/rasterlitedataset.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: rasterlitedataset.h 24674 2012-07-10 20:41:35Z rouault $
+ * $Id: rasterlitedataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -52,6 +52,7 @@ class RasterliteDataset : public GDALPamDataset
                  
     virtual     ~RasterliteDataset();
     
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char *pszDomain );
     virtual const char *GetMetadataItem( const char *pszName, 
                                          const char *pszDomain );
diff --git a/frmts/rasterlite/rasterliteoverviews.cpp b/frmts/rasterlite/rasterliteoverviews.cpp
index 6d51a5a..a8bfa77 100644
--- a/frmts/rasterlite/rasterliteoverviews.cpp
+++ b/frmts/rasterlite/rasterliteoverviews.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: rasterliteoverviews.cpp 25391 2012-12-29 19:20:46Z rouault $
+ * $Id: rasterliteoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterliteoverviews.cpp 25391 2012-12-29 19:20:46Z rouault $");
+CPL_CVSID("$Id: rasterliteoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         ReloadOverviews()                            */
diff --git a/frmts/raw/GNUmakefile b/frmts/raw/GNUmakefile
index 604fc43..914f764 100644
--- a/frmts/raw/GNUmakefile
+++ b/frmts/raw/GNUmakefile
@@ -8,7 +8,8 @@ OBJ	=	rawdataset.o ehdrdataset.o pauxdataset.o doq1dataset.o \
 		atlsci_spheroid.o btdataset.o landataset.o cpgdataset.o \
 		idadataset.o ndfdataset.o dipxdataset.o genbindataset.o \
 		lcpdataset.o eirdataset.o gtxdataset.o loslasdataset.o \
-		ntv2dataset.o ace2dataset.o snodasdataset.o ctable2dataset.o
+		ntv2dataset.o ace2dataset.o snodasdataset.o ctable2dataset.o \
+		krodataset.o
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
 
diff --git a/frmts/raw/ace2dataset.cpp b/frmts/raw/ace2dataset.cpp
index f1c8728..f2ab309 100644
--- a/frmts/raw/ace2dataset.cpp
+++ b/frmts/raw/ace2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ace2dataset.cpp 23772 2012-01-21 08:31:07Z rouault $
+ * $Id: ace2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ACE2 Driver
  * Purpose:  Implementation of ACE2 elevation format read support.
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "rawdataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ace2dataset.cpp 23772 2012-01-21 08:31:07Z rouault $");
+CPL_CVSID("$Id: ace2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_ACE2(void);
diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp
index 69ead2f..114c5d9 100644
--- a/frmts/raw/btdataset.cpp
+++ b/frmts/raw/btdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: btdataset.cpp 26358 2013-08-21 20:12:38Z rouault $
+ * $Id: btdataset.cpp 27192 2014-04-16 09:59:42Z rouault $
  *
  * Project:  VTP .bt Driver
  * Purpose:  Implementation of VTP .bt elevation format read/write support.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "rawdataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: btdataset.cpp 26358 2013-08-21 20:12:38Z rouault $");
+CPL_CVSID("$Id: btdataset.cpp 27192 2014-04-16 09:59:42Z rouault $");
 
 CPL_C_START
 void    GDALRegister_BT(void);
@@ -691,8 +692,6 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
             nDatum = 6202;
         else if( nDatum == 4 )
             nDatum = 6203;
-        else if( nDatum == 4 )
-            nDatum = 6203;
         else if( nDatum == 6 )
             nDatum = 6222;
         else if( nDatum == 7 )
diff --git a/frmts/raw/cpgdataset.cpp b/frmts/raw/cpgdataset.cpp
index ed1b0d8..6f050cc 100644
--- a/frmts/raw/cpgdataset.cpp
+++ b/frmts/raw/cpgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpgdataset.cpp 18073 2009-11-22 01:01:14Z rouault $
+ * $Id: cpgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Convair PolGASP data (.img/.hdr format). 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpgdataset.cpp 18073 2009-11-22 01:01:14Z rouault $");
+CPL_CVSID("$Id: cpgdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_CPG(void);
diff --git a/frmts/raw/dipxdataset.cpp b/frmts/raw/dipxdataset.cpp
index 1b5acb4..ea3e7ea 100644
--- a/frmts/raw/dipxdataset.cpp
+++ b/frmts/raw/dipxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
+ * $Id: dipxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implementation for ELAS DIPEx format variant.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
+CPL_CVSID("$Id: dipxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_DIPEx(void);
diff --git a/frmts/raw/doq1dataset.cpp b/frmts/raw/doq1dataset.cpp
index a701f3e..250ac99 100644
--- a/frmts/raw/doq1dataset.cpp
+++ b/frmts/raw/doq1dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq1dataset.cpp 21717 2011-02-13 20:16:30Z rouault $
+ * $Id: doq1dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  USGS DOQ Driver (First Generation Format)
  * Purpose:  Implementation of DOQ1Dataset
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: doq1dataset.cpp 21717 2011-02-13 20:16:30Z rouault $");
+CPL_CVSID("$Id: doq1dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static double DOQGetField( unsigned char *, int );
 static void DOQGetDescription( GDALDataset *, unsigned char * );
diff --git a/frmts/raw/doq2dataset.cpp b/frmts/raw/doq2dataset.cpp
index 4ad42d2..c080f8e 100644
--- a/frmts/raw/doq2dataset.cpp
+++ b/frmts/raw/doq2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $
+ * $Id: doq2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  USGS DOQ Driver (Second Generation Format)
  * Purpose:  Implementation of DOQ2Dataset
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Derrick J Brashear
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $");
+CPL_CVSID("$Id: doq2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_DOQ2(void);
diff --git a/frmts/raw/ehdrdataset.cpp b/frmts/raw/ehdrdataset.cpp
index 38f9d70..f4f1cf2 100644
--- a/frmts/raw/ehdrdataset.cpp
+++ b/frmts/raw/ehdrdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ehdrdataset.cpp 25701 2013-03-07 14:28:02Z rouault $
+ * $Id: ehdrdataset.cpp 27192 2014-04-16 09:59:42Z rouault $
  *
  * Project:  ESRI .hdr Driver
  * Purpose:  Implementation of EHdrDataset
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ehdrdataset.cpp 25701 2013-03-07 14:28:02Z rouault $");
+CPL_CVSID("$Id: ehdrdataset.cpp 27192 2014-04-16 09:59:42Z rouault $");
 
 CPL_C_START
 void	GDALRegister_EHdr(void);
@@ -236,6 +237,7 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                   "Failed to read %u bytes at offset %lu.\n%s",
                   nLineBytes, (unsigned long)nLineStart, 
                   VSIStrerror( errno ) );
+        CPLFree( pabyBuffer );
         return CE_Failure;
     }
 
@@ -300,6 +302,7 @@ CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                   "Failed to read %u bytes at offset %lu.\n%s",
                   nLineBytes, (unsigned long)nLineStart, 
                   VSIStrerror( errno ) );
+        CPLFree( pabyBuffer );
         return CE_Failure;
     }
 
@@ -1830,6 +1833,7 @@ GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename,
     {
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "EHdr driver does not support source dataset with zero band.\n");
+        CSLDestroy( papszAdjustedOptions );
         return NULL;
     }
 
@@ -1866,6 +1870,9 @@ GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename,
                                            papszAdjustedOptions, 
                                            pfnProgress, pProgressData );
     CSLDestroy( papszAdjustedOptions );
+    
+    if( poOutDS != NULL )
+        poOutDS->FlushCache();
 
     return poOutDS;
 }
diff --git a/frmts/raw/eirdataset.cpp b/frmts/raw/eirdataset.cpp
index 8d5a4e5..15a4949 100644
--- a/frmts/raw/eirdataset.cpp
+++ b/frmts/raw/eirdataset.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp
index 57f48bc..02fd840 100644
--- a/frmts/raw/envidataset.cpp
+++ b/frmts/raw/envidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envidataset.cpp 25660 2013-02-21 20:56:07Z rouault $
+ * $Id: envidataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ENVI .hdr Driver
  * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: envidataset.cpp 25660 2013-02-21 20:56:07Z rouault $");
+CPL_CVSID("$Id: envidataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void GDALRegister_ENVI(void);
diff --git a/frmts/raw/fastdataset.cpp b/frmts/raw/fastdataset.cpp
index c1506bd..2fd6127 100644
--- a/frmts/raw/fastdataset.cpp
+++ b/frmts/raw/fastdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fastdataset.cpp 22610 2011-06-28 21:20:06Z rouault $
+ * $Id: fastdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EOSAT FAST Format reader
  * Purpose:  Reads Landsat FAST-L7A, IRS 1C/1D
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fastdataset.cpp 22610 2011-06-28 21:20:06Z rouault $");
+CPL_CVSID("$Id: fastdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_FAST(void);
diff --git a/frmts/raw/frmt_lcp.html b/frmts/raw/frmt_lcp.html
index 2d3e098..d094954 100644
--- a/frmts/raw/frmt_lcp.html
+++ b/frmts/raw/frmt_lcp.html
@@ -13,8 +13,7 @@ FLAMMAP, and FBAT (<a href="http://www.fire.org">www.fire.org</a>). The bands of
 terrain, tree canopy, and surface fuel. The
 <a href="http://landfire.cr.usgs.gov/viewer">USGS National Map for LANDFIRE</a>
 distributes data in LCP format, and 
-programs such as FARSITE and <a href="http://www.landfire.gov/datatool.php">LFDAT</a> can create LCP files from a set of input rasters. 
-The GDAL driver for LCP supports reading only.</p>
+programs such as FARSITE and <a href="http://www.landfire.gov/datatool.php">LFDAT</a> can create LCP files from a set of input rasters.</p>
 <p>An LCP file (.lcp) is basically a raw format with a 7,316-byte header 
 described below. The data type for all bands is 16-bit signed integer. Bands are 
 interleaved by pixel. Five bands are required: elevation, slope, aspect, fuel 
@@ -45,6 +44,46 @@ projections are possible.</p>
 </blockquote>
 <p><b>Note:</b> The LCP driver derives from the RawDataset helper class declared 
 in gdal/frmts/raw. It should be implemented as gdal/frmts/raw/lcpdataset.cpp.</p>
+<h3>Creation Options</h3>
+The LCP driver supports CreateCopy() and metadata values can be set via
+creation options.  Below is a list of options with default values listed first.
+<li><p><b>ELEVATION_UNIT=[METERS/FEET]</b>: Vertical unit for elevation
+band.</p></li>
+
+<li><p><b>SLOPE_UNIT=[DEGREES/PERCENT]</b></p></li>
+<li><p><b>ASPECT_UNIT=[AZIMUTH_DEGREES/GRASS_CATEGORIES/GRASS_DEGRESS]</b></p></li>
+<li><p><b>FUEL_MODEL_OPTION=[NO_CUSTOM_AND_NO_FILE/CUSTOM_AND_NO_FILE/
+    NO_CUSTOM_AND_FILE/CUSTOM_AND_FILE]</b>: Specify whether or not custom
+    fuel models are used, and if a custom fuel model file is present.</p></li>
+<li><p><b>CANOPY_COV_UNIT=[PERCENT/CATEGORIES]</b></p></li>
+<li><p><b>CANOPY_HT_UNIT=[METERS_X_10/FEET/METERS/FEET_X_10]</b></p></li>
+<li><p><b>CBH_UNIT=[METERS_X_10/METERS/FEET/FEET_X_10]</b></p></li>
+<li><p><b>CBD_UNIT=[KG_PER_CUBIC_METER_X_100/POUND_PER_CUBIC_FOOT/
+    KG_PER_CUBIC_METER/POUND_PER_CUBIC_FOOT_X_1000/TONS_PER_ACRE_X_100]</b></p></li>
+<li><p><b>DUFF_UNIT=[MG_PER_HECTARE_X_10/TONS_PER_ACRE_X_10]</b></p></li>
+<li><p><b>CALCULATE_STATS=[YES/NO]</b>: Calculate and write the min/max for
+    each band and write the appropriate flags and values in the header.  This is
+    mostly a legacy feature used for creating legends.</p></li>
+<li><p><b>CLASSIFY_DATA=[YES/NO]</b>: Classify the data into 100 unique values
+    or less and write and write the appropriate flags and values in the header.
+    This is mostly a legacy feature used for creating legends.</p></li>
+<li><p><b>LINEAR_UNIT=[SET_FROM_SRS/METER/FOOT/KILOMETER]</b>: Set the
+    linear unit, overriding (if it can be calculated) the value in the
+    associated spatial reference.  If no spatial reference is available, it
+    defaults to METER.</p></li>
+<li><p><b>LATITUDE=[-90-90]</b>: Override the latitude from the spatial
+    reference.  If no spatial reference is available, this should be set,
+    otherwise creation will fail.</p></li>
+<li><p><b>DESCRIPTION=[...]</b>: A short description(less than 512 characters)
+    of the dataset</p></li>
+
+Creation options that are units of linear measure are fairly lenient.
+METERS=METER and FOOT=FEET for the most part.
+
+<p><b>Note:</b> CreateCopy does not scale or change any data.  By setting the
+units for various bands, it is assumed that the values are in the specified
+units.</p>
+
 <p><b>LCP header format:</b></p>
 <table border="1" cellspacing="1" width="885">
   <tr>
diff --git a/frmts/raw/fujibasdataset.cpp b/frmts/raw/fujibasdataset.cpp
index 6d44b0d..39de6fb 100644
--- a/frmts/raw/fujibasdataset.cpp
+++ b/frmts/raw/fujibasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fujibasdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: fujibasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  eCognition
  * Purpose:  Implementation of FUJI BAS Format
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: fujibasdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: fujibasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_FujiBAS(void);
diff --git a/frmts/raw/genbindataset.cpp b/frmts/raw/genbindataset.cpp
index 1ef29fd..683780f 100644
--- a/frmts/raw/genbindataset.cpp
+++ b/frmts/raw/genbindataset.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/raw/gscdataset.cpp b/frmts/raw/gscdataset.cpp
index 163d6b0..0a79fb0 100644
--- a/frmts/raw/gscdataset.cpp
+++ b/frmts/raw/gscdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gscdataset.cpp 21715 2011-02-13 19:18:59Z rouault $
+ * $Id: gscdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GSC Geogrid format driver.
  * Purpose:  Implements support for reading and writing GSC Geogrid format.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gscdataset.cpp 21715 2011-02-13 19:18:59Z rouault $");
+CPL_CVSID("$Id: gscdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/raw/gtxdataset.cpp b/frmts/raw/gtxdataset.cpp
index bc90060..cd19cd5 100644
--- a/frmts/raw/gtxdataset.cpp
+++ b/frmts/raw/gtxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtxdataset.cpp 25795 2013-03-24 13:16:52Z rouault $
+ * $Id: gtxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Vertical Datum Transformation
  * Purpose:  Implementation of NOAA .gtx vertical datum shift file format.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gtxdataset.cpp 25795 2013-03-24 13:16:52Z rouault $");
+CPL_CVSID("$Id: gtxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /**
 
@@ -213,12 +214,17 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
-    poDS->SetBand( 
-        1, new RawRasterBand( poDS, 1, poDS->fpImage, 
+    RawRasterBand *poBand = new RawRasterBand( poDS, 1, poDS->fpImage, 
                               (poDS->nRasterYSize-1)*poDS->nRasterXSize*nDTSize + 40,
                               nDTSize, poDS->nRasterXSize * -nDTSize,
                               eDT,
-                              !CPL_IS_LSB, TRUE, FALSE ) );
+                              !CPL_IS_LSB, TRUE, FALSE );
+    if (eDT == GDT_Float64)
+      poBand->SetNoDataValue( -88.8888 );
+    else
+      /* GDT_Float32 */
+      poBand->SetNoDataValue( (double)-88.8888f );
+    poDS->SetBand( 1, poBand );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -405,4 +411,3 @@ void GDALRegister_GTX()
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
 }
-
diff --git a/frmts/raw/hkvdataset.cpp b/frmts/raw/hkvdataset.cpp
index 0dfef08..d7489bf 100644
--- a/frmts/raw/hkvdataset.cpp
+++ b/frmts/raw/hkvdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hkvdataset.cpp 24590 2012-06-16 16:34:48Z rouault $
+ * $Id: hkvdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis HKV labelled blob support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_spatialref.h"
 #include "atlsci_spheroid.h"
 
-CPL_CVSID("$Id: hkvdataset.cpp 24590 2012-06-16 16:34:48Z rouault $");
+CPL_CVSID("$Id: hkvdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HKV(void);
diff --git a/frmts/raw/idadataset.cpp b/frmts/raw/idadataset.cpp
index cda9ae6..76b6bd0 100644
--- a/frmts/raw/idadataset.cpp
+++ b/frmts/raw/idadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: idadataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: idadataset.cpp 26117 2013-06-29 20:22:34Z rouault $
  *
  * Project:  IDA Raster Driver
  * Purpose:  Implemenents IDA driver/dataset/rasterband.
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "gdal_rat.h"
 
-CPL_CVSID("$Id: idadataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: idadataset.cpp 26117 2013-06-29 20:22:34Z rouault $");
 
 CPL_C_START
 void	GDALRegister_IDA(void);
@@ -116,7 +116,7 @@ class IDARasterBand : public RawRasterBand
     		IDARasterBand( IDADataset *poDSIn, FILE *fpRaw, int nXSize );
     virtual     ~IDARasterBand();
 
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable *GetColorTable();
     virtual double GetOffset( int *pbSuccess = NULL );
@@ -269,7 +269,7 @@ GDALColorInterp IDARasterBand::GetColorInterpretation()
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT() 
+GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT() 
 
 {
     if( poRAT )
@@ -586,7 +586,7 @@ void IDADataset::ReadColorTable()
 /* -------------------------------------------------------------------- */
 /*      Create a RAT to populate.                                       */
 /* -------------------------------------------------------------------- */
-    GDALRasterAttributeTable *poRAT = new GDALRasterAttributeTable();
+    GDALRasterAttributeTable *poRAT = new GDALDefaultRasterAttributeTable();
 
     poRAT->CreateColumn( "FROM", GFT_Integer, GFU_Min );
     poRAT->CreateColumn( "TO", GFT_Integer, GFU_Max );
diff --git a/frmts/raw/krodataset.cpp b/frmts/raw/krodataset.cpp
new file mode 100644
index 0000000..f9fb7be
--- /dev/null
+++ b/frmts/raw/krodataset.cpp
@@ -0,0 +1,317 @@
+/******************************************************************************
+ * $Id: krodataset.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  KRO format reader/writer
+ * Purpose:  Implementation of KOLOR Raw Format
+ * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
+ * Financial Support: SITES (http://www.sites.fr)
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "rawdataset.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: krodataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/* http://www.autopano.net/wiki-en/Format_KRO */
+
+/************************************************************************/
+/* ==================================================================== */
+/*                                KRODataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class KRODataset : public RawDataset
+{
+  public:
+    VSILFILE	*fpImage;	// image data file.
+
+  public:
+                    KRODataset();
+                   ~KRODataset();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char * pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char ** papszOptions );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                                  KRODataset                          */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                              KRODataset()                            */
+/************************************************************************/
+
+KRODataset::KRODataset()
+{
+    fpImage = NULL;
+}
+
+/************************************************************************/
+/*                             ~KRODataset()                            */
+/************************************************************************/
+
+KRODataset::~KRODataset()
+
+{
+    FlushCache();
+
+    if( fpImage != NULL )
+        VSIFCloseL( fpImage );
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int KRODataset::Identify( GDALOpenInfo *poOpenInfo )
+
+{
+    if( poOpenInfo->nHeaderBytes < 20 )
+        return FALSE;
+
+    if( !EQUALN((const char *)poOpenInfo->pabyHeader, "KRO\x01", 4 ) )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    KRODataset 	*poDS;
+
+    poDS = new KRODataset();
+    poDS->eAccess = poOpenInfo->eAccess;
+
+/* -------------------------------------------------------------------- */
+/*      Open the file.                                                  */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->eAccess == GA_ReadOnly )
+        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+    else
+        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
+
+    if( poDS->fpImage == NULL )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the file header.                                           */
+/* -------------------------------------------------------------------- */
+    char  achHeader[20];
+    int   nXSize, nYSize, nDepth, nComp;
+
+    VSIFReadL( achHeader, 1, 20, poDS->fpImage );
+
+    memcpy(&nXSize, achHeader + 4, 4);
+    CPL_MSBPTR32( &nXSize );
+
+    memcpy(&nYSize, achHeader + 8, 4);
+    CPL_MSBPTR32( &nYSize );
+
+    memcpy(&nDepth, achHeader + 12, 4);
+    CPL_MSBPTR32( &nDepth );
+
+    memcpy(&nComp, achHeader + 16, 4);
+    CPL_MSBPTR32( &nComp );
+
+    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
+        !GDALCheckBandCount(nComp, FALSE))
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+
+    GDALDataType eDT;
+    if( nDepth == 8 )
+        eDT = GDT_Byte;
+    else if( nDepth == 16 )
+        eDT = GDT_UInt16;
+    else if( nDepth == 32 )
+        eDT = GDT_Float32;
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unhandled depth : %d", nDepth);
+        delete poDS;
+        return NULL;
+    }
+
+    int nDataTypeSize = nDepth / 8;
+
+/* -------------------------------------------------------------------- */
+/*      Create bands.                                                   */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < nComp; iBand++ )
+    {
+        RawRasterBand *poBand = 
+            new RawRasterBand( poDS, iBand+1, poDS->fpImage, 
+                               20 + nDataTypeSize * iBand,
+                               nComp * nDataTypeSize,
+                               poDS->nRasterXSize * nComp * nDataTypeSize,
+                               eDT, !CPL_IS_LSB, TRUE, FALSE );
+        if( nComp == 3 || nComp == 4 )
+        {
+            poBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + iBand) );
+        }
+        poDS->SetBand( iBand+1, poBand );
+    }
+
+    if( nComp > 1 )
+        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+GDALDataset *KRODataset::Create( const char * pszFilename,
+                                  int nXSize, int nYSize, int nBands,
+                                  GDALDataType eType,
+                                  char ** papszOptions )
+
+{
+    if( eType != GDT_Byte && eType != GDT_UInt16 && eType != GDT_Float32 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to create KRO file with unsupported data type '%s'.",
+                 GDALGetDataTypeName( eType ) );
+        return NULL;
+    }
+
+    VSILFILE    *fp;
+    
+/* -------------------------------------------------------------------- */
+/*      Try to create file.                                             */
+/* -------------------------------------------------------------------- */
+    fp = VSIFOpenL( pszFilename, "wb" );
+    
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Attempt to create file `%s' failed.\n",
+                  pszFilename );
+        return NULL;
+    }
+
+    int nRet = 0;
+    nRet += VSIFWriteL("KRO\01", 4, 1, fp);
+
+    int nTmp;
+/* -------------------------------------------------------------------- */
+/*      Create a file level header.                                     */
+/* -------------------------------------------------------------------- */
+    nTmp = nXSize;
+    CPL_MSBPTR32(&nTmp);
+    nRet += VSIFWriteL(&nTmp, 4, 1, fp);
+
+    nTmp = nYSize;
+    CPL_MSBPTR32(&nTmp);
+    nRet += VSIFWriteL(&nTmp, 4, 1, fp);
+
+    nTmp = GDALGetDataTypeSize(eType);
+    CPL_MSBPTR32(&nTmp);
+    nRet += VSIFWriteL(&nTmp, 4, 1, fp);
+
+    nTmp = nBands;
+    CPL_MSBPTR32(&nTmp);
+    nRet += VSIFWriteL(&nTmp, 4, 1, fp);
+
+/* -------------------------------------------------------------------- */
+/*      Zero out image data                                             */
+/* -------------------------------------------------------------------- */
+
+    VSIFSeekL(fp, (vsi_l_offset)nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8) * nBands - 1,
+              SEEK_CUR);
+    GByte byNul = 0;
+    nRet += VSIFWriteL(&byNul, 1, 1, fp);
+    VSIFCloseL(fp);
+
+    if( nRet != 6 )
+        return NULL;
+
+    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+}
+
+/************************************************************************/
+/*                         GDALRegister_KRO()                           */
+/************************************************************************/
+
+void GDALRegister_KRO()
+
+{
+    GDALDriver	*poDriver;
+
+    if( GDALGetDriverByName( "KRO" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "KRO" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                   "KOLOR Raw" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kro" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
+                                   "Byte UInt16 Float32" );
+
+        poDriver->pfnIdentify = KRODataset::Identify;
+        poDriver->pfnOpen = KRODataset::Open;
+        poDriver->pfnCreate = KRODataset::Create;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/raw/landataset.cpp b/frmts/raw/landataset.cpp
index 29f3bcf..ea8c77e 100644
--- a/frmts/raw/landataset.cpp
+++ b/frmts/raw/landataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $
+ * $Id: landataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  eCognition
  * Purpose:  Implementation of Erdas .LAN / .GIS format.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
+CPL_CVSID("$Id: landataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_LAN(void);
diff --git a/frmts/raw/lcpdataset.cpp b/frmts/raw/lcpdataset.cpp
index f998c0b..4914836 100644
--- a/frmts/raw/lcpdataset.cpp
+++ b/frmts/raw/lcpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: lcpdataset.cpp 26210 2013-07-26 02:26:38Z kyle $
+ * $Id: lcpdataset.cpp 27050 2014-03-18 00:09:03Z kyle $
  *
  * Project:  LCP Driver
  * Purpose:  FARSITE v.4 Landscape file (.lcp) reader for GDAL
@@ -7,6 +7,8 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Chris Toney
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2013, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,16 +30,21 @@
  ****************************************************************************/
 
 #include "rawdataset.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: lcpdataset.cpp 26210 2013-07-26 02:26:38Z kyle $");
+CPL_CVSID("$Id: lcpdataset.cpp 27050 2014-03-18 00:09:03Z kyle $");
 
 CPL_C_START
 void    GDALRegister_LCP(void);
 CPL_C_END
 
 #define LCP_HEADER_SIZE 7316
+#define LCP_MAX_BANDS   10
+#define LCP_MAX_PATH    256
+#define LCP_MAX_DESC    512
+#define LCP_MAX_CLASSES 100
 
 /************************************************************************/
 /* ==================================================================== */
@@ -53,6 +60,10 @@ class LCPDataset : public RawDataset
     CPLString   osPrjFilename;
     char        *pszProjection;
 
+    static CPLErr ClassifyBandData( GDALRasterBand *poBand,
+                                    GInt32 *pnNumClasses,
+                                    GInt32 *panClasses );
+
   public:
                 LCPDataset();
                 ~LCPDataset();
@@ -63,7 +74,11 @@ class LCPDataset : public RawDataset
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
-
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
     virtual const char *GetProjectionRef(void);
 
     int bHaveProjection;
@@ -189,10 +204,9 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "The LCP driver does not support update access to existing"
-                  " datasets.\n" );
+                  " datasets." );
         return NULL;
     }
-    
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -295,6 +309,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
 
    pszList = (char*)CPLMalloc(2048);
+   pszList[0] = '\0';
 
    for( int iBand = 1; iBand <= nBands; iBand++ )
    {
@@ -744,7 +759,927 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     return( poDS );
 }
- 
+
+/************************************************************************/
+/*                          ClassifyBandData()                          */
+/*  Classify a band and store 99 or fewer unique values.  If there are  */
+/*  more than 99 unique values, then set pnNumClasses to -1 as a flag   */
+/*  that represents this.  These are legacy values in the header, and   */
+/*  while we should never deprecate them, we could possibly not         */
+/*  calculate them by default.                                          */
+/************************************************************************/
+
+CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
+                                     GInt32 *pnNumClasses,
+                                     GInt32 *panClasses )
+{
+    if( pnNumClasses == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid pointer for panClasses" );
+        return CE_Failure;
+    }
+
+    if( panClasses == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid pointer for panClasses" );
+        *pnNumClasses = -1;
+        return CE_Failure;
+    }
+
+    if( poBand == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid band passed to ClassifyBandData()" );
+        *pnNumClasses = -1;
+        memset( panClasses, 0, 400 );
+        return CE_Failure;
+    }
+
+    int nXSize = poBand->GetXSize();
+    int nYSize = poBand->GetYSize();
+    double dfMax, dfDummy;
+    poBand->GetStatistics( FALSE, TRUE, &dfDummy, &dfMax, &dfDummy, &dfDummy );
+
+    int nSpan = (int)dfMax;
+    GInt16 *panValues = (GInt16*)CPLMalloc( sizeof( GInt16 ) * nXSize );
+    GByte *pabyFlags = (GByte*)CPLMalloc( sizeof( GByte ) * nSpan + 1 );
+    memset( pabyFlags, 0, nSpan + 1 );
+
+    int nFound = 0;
+    int bTooMany = FALSE;
+    CPLErr eErr = CE_None;
+    for( int iLine = 0; iLine < nYSize; iLine++ )
+    {
+        eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                 panValues, nXSize, 1, 
+                                 GDT_Int16, 0, 0 );
+        for( int iPixel = 0; iPixel < nXSize; iPixel++ )
+        {
+            if( panValues[iPixel] == -9999 )
+            {
+                continue;
+            }
+            if( nFound > 99 )
+            {
+                CPLDebug( "LCP", "Found more that 100 unique values in " \
+                                 "band %d.  Not 'classifying' the data.",
+                                 poBand->GetBand() );
+                nFound = -1;
+                bTooMany = TRUE;
+                break;
+            }
+            if( bTooMany )
+            {
+                break;
+            }
+            if( pabyFlags[panValues[iPixel]] == 0 )
+            {
+                pabyFlags[panValues[iPixel]] = 1;
+                nFound++;
+            }
+        }
+    }
+    CPLAssert( nFound <= 100 );
+    /*
+    ** The classes are always padded with a leading 0.  This was for aligning
+    ** offsets, or making it a 1-based array instead of 0-based.
+    */
+    panClasses[0] = 0;
+    int nIndex = 1;
+    for( int j = 0; j < nSpan + 1; j++ )
+    {
+        if( pabyFlags[j] == 1 )
+        {
+            panClasses[nIndex++] = j;
+        }
+    }
+    *pnNumClasses = nFound;
+    CPLFree( (void*)pabyFlags );
+    CPLFree( (void*)panValues );
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          CreateCopy()                                */
+/************************************************************************/
+
+GDALDataset *LCPDataset::CreateCopy( const char * pszFilename, 
+                                     GDALDataset * poSrcDS, 
+                                     int bStrict, char ** papszOptions,
+                                     GDALProgressFunc pfnProgress,
+                                     void * pProgressData )
+
+{
+
+    int  nBands = poSrcDS->GetRasterCount();
+    int  nXSize = poSrcDS->GetRasterXSize();
+    int  nYSize = poSrcDS->GetRasterYSize();
+
+/* -------------------------------------------------------------------- */
+/*      Verify input options.                                           */
+/* -------------------------------------------------------------------- */
+    if( nBands != 5 && nBands != 7 && nBands != 8 && nBands != 10 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "LCP driver doesn't support %d bands.  Must be 5, 7, 8 "
+                  "or 10 bands.", nBands );
+        return NULL;
+    }
+
+    GDALDataType eType = poSrcDS->GetRasterBand( 1 )->GetRasterDataType();
+    if( eType != GDT_Int16 && bStrict )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "LCP only supports 16-bit signed integer data types." );
+        return NULL;
+    }
+    else if( eType != GDT_Int16 )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Setting data type to 16-bit integer." );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      What schema do we have (ground/crown fuels)                     */
+/* -------------------------------------------------------------------- */
+    int bHaveCrownFuels = FALSE;
+    int bHaveGroundFuels = FALSE;
+
+    if( nBands == 8 || nBands == 10 )
+    {
+        bHaveCrownFuels = TRUE;
+    }
+    if( nBands == 7 || nBands == 10 )
+    {
+        bHaveGroundFuels = TRUE;
+    }
+
+    /*
+    ** Since units are 'configurable', we should check for user
+    ** defined units.  This is a bit cumbersome, but the user should
+    ** be allowed to specify none to get default units/options.  Use 
+    ** default units every chance we get.
+    */
+    GInt16 panMetadata[LCP_MAX_BANDS];
+    int i;
+    GInt32 nTemp;
+    double dfTemp;
+    const char *pszTemp;
+
+    panMetadata[0] = 0; /* ELEVATION_UNIT */
+    panMetadata[1] = 0; /* SLOPE_UNIT */
+    panMetadata[2] = 2; /* ASPECT_UNIT */
+    panMetadata[3] = 0; /* FUEL_MODEL_OPTION */
+    panMetadata[4] = 1; /* CANOPY_COV_UNIT */
+    panMetadata[5] = 3; /* CANOPY_HT_UNIT */
+    panMetadata[6] = 3; /* CBH_UNIT */
+    panMetadata[7] = 3; /* CBD_UNIT */
+    panMetadata[8] = 1; /* DUFF_UNIT */
+    panMetadata[9] = 0; /* CWD_OPTION */
+    /* Check the units/options for user overrides */
+    pszTemp = CSLFetchNameValueDef( papszOptions, "ELEVATION_UNIT", "METERS" );
+    if( EQUALN( pszTemp, "METER", 5 ) )
+    {
+        panMetadata[0] = 0;
+    }
+    else if( EQUAL( pszTemp, "FEET" ) || EQUAL( pszTemp, "FOOT" ) )
+    {
+        panMetadata[0] = 1;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value (%s) for ELEVATION_UNIT.",
+                  pszTemp );
+        return NULL;
+    }
+
+    pszTemp = CSLFetchNameValueDef( papszOptions, "SLOPE_UNIT", "DEGREES" );
+    if( EQUAL( pszTemp, "DEGREES" ) )
+    {
+        panMetadata[1] = 0;
+    }
+    else if( EQUAL( pszTemp, "PERCENT" ) )
+    {
+        panMetadata[1] = 1;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value (%s) for SLOPE_UNIT.",
+                  pszTemp );
+        return NULL;
+    }
+
+    pszTemp = CSLFetchNameValueDef( papszOptions, "ASPECT_UNIT",
+                                    "AZIMUTH_DEGREES" );
+    if( EQUAL( pszTemp, "GRASS_CATEGORIES" ) )
+    {
+        panMetadata[2] = 0;
+    }
+    else if( EQUAL( pszTemp, "GRASS_DEGREES" ) )
+    {
+        panMetadata[2] = 1;
+    }
+    else if( EQUAL( pszTemp, "AZIMUTH_DEGREES" ) )
+    {
+        panMetadata[2] = 2;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value (%s) for ASPECT_UNIT.",
+                  pszTemp );
+        return NULL;
+    }
+
+    pszTemp = CSLFetchNameValueDef( papszOptions, "FUEL_MODEL_OPTION",
+                                    "NO_CUSTOM_AND_NO_FILE" );
+    if( EQUAL( pszTemp, "NO_CUSTOM_AND_NO_FILE" ) )
+    {
+        panMetadata[3] = 0;
+    }
+    else if( EQUAL( pszTemp, "CUSTOM_AND_NO_FILE" ) )
+    {
+        panMetadata[3] = 1;
+    }
+    else if( EQUAL( pszTemp, "NO_CUSTOM_AND_FILE" ) )
+    {
+        panMetadata[3] = 2;
+    }
+    else if( EQUAL( pszTemp, "CUSTOM_AND_FILE" ) )
+    {
+        panMetadata[3] = 3;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value (%s) for FUEL_MODEL_OPTION.",
+                  pszTemp );
+        return NULL;
+    }
+
+    pszTemp = CSLFetchNameValueDef( papszOptions, "CANOPY_COV_UNIT",
+                                    "PERCENT" );
+    if( EQUAL( pszTemp, "CATEGORIES" ) )
+    {
+        panMetadata[4] = 0;
+    }
+    else if( EQUAL( pszTemp, "PERCENT" ) )
+    {
+        panMetadata[4] = 1;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value (%s) for CANOPY_COV_UNIT.",
+                  pszTemp );
+        return NULL;
+    }
+
+    if( bHaveCrownFuels )
+    {
+        pszTemp = CSLFetchNameValueDef( papszOptions, "CANOPY_HT_UNIT",
+                                        "METERS_X_10" );
+        if( EQUAL( pszTemp, "METERS" ) || EQUAL( pszTemp, "METER" ) )
+        {
+            panMetadata[5] = 1;
+        }
+        else if( EQUAL( pszTemp, "FEET" ) || EQUAL( pszTemp, "FOOT" ) )
+        {
+            panMetadata[5] = 2;
+        }
+        else if( EQUAL( pszTemp, "METERS_X_10" )  ||
+                 EQUAL( pszTemp, "METER_X_10" ) )
+        {
+            panMetadata[5] = 3;
+        }
+        else if( EQUAL( pszTemp, "FEET_X_10" ) || EQUAL( pszTemp, "FOOT_X_10" ) )
+        {
+            panMetadata[5] = 4;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid value (%s) for CANOPY_HT_UNIT.",
+                      pszTemp );
+            return NULL;
+        }
+
+        pszTemp = CSLFetchNameValueDef( papszOptions, "CBH_UNIT",
+                                        "METERS_X_10" );
+        if( EQUAL( pszTemp, "METERS" ) || EQUAL( pszTemp, "METER" ) )
+        {
+            panMetadata[6] = 1;
+        }
+        else if( EQUAL( pszTemp, "FEET" ) || EQUAL( pszTemp, "FOOT" ) )
+        {
+            panMetadata[6] = 2;
+        }
+        else if( EQUAL( pszTemp, "METERS_X_10" ) ||
+                 EQUAL( pszTemp, "METER_X_10" ) )
+        {
+            panMetadata[6] = 3;
+        }
+        else if( EQUAL( pszTemp, "FEET_X_10" ) || EQUAL( pszTemp, "FOOT_X_10" ) )
+        {
+            panMetadata[6] = 4;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid value (%s) for CBH_UNIT.",
+                      pszTemp );
+            return NULL;
+        }
+
+        pszTemp = CSLFetchNameValueDef( papszOptions, "CBD_UNIT",
+                                        "KG_PER_CUBIC_METER_X_100" );
+        if( EQUAL( pszTemp, "KG_PER_CUBIC_METER" ) )
+        {
+            panMetadata[7] = 1;
+        }
+        else if( EQUAL( pszTemp, "POUND_PER_CUBIC_FOOT" ) )
+        {
+            panMetadata[7] = 2;
+        }
+        else if( EQUAL( pszTemp, "KG_PER_CUBIC_METER_X_100" ) )
+        {
+            panMetadata[7] = 3;
+        }
+        else if( EQUAL( pszTemp, "POUND_PER_CUBIC_FOOT_X_1000" ) )
+        {
+            panMetadata[7] = 4;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid value (%s) for CBD_UNIT.",
+                      pszTemp );
+            return NULL;
+        }
+    }
+
+    if( bHaveGroundFuels )
+    {
+        pszTemp = CSLFetchNameValueDef( papszOptions, "DUFF_UNIT",
+                                        "MG_PER_HECTARE_X_10" );
+        if( EQUAL( pszTemp, "MG_PER_HECTARE_X_10" ) )
+        {
+            panMetadata[8] = 1;
+        }
+        else if ( EQUAL( pszTemp, "TONS_PER_ACRE_X_10" ) )
+        {
+            panMetadata[8] = 2;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid value (%s) for DUFF_UNIT.",
+                      pszTemp );
+            return NULL;
+        }
+
+        if( bHaveGroundFuels )
+        {
+            panMetadata[9] = 1;
+        }
+        else
+        {
+            panMetadata[9] = 0;
+        }
+    }
+
+    /*
+    ** Calculate the stats for each band.  The binary file carries along
+    ** these metadata for display purposes(?).
+    */
+    int bCalculateStats = CSLFetchBoolean( papszOptions, "CALCULATE_STATS",
+                                           TRUE );
+    int bClassifyData = CSLFetchBoolean( papszOptions, "CLASSIFY_DATA",
+                                         TRUE );
+    /*
+    ** We should have stats if we classify, we'll get them anyway.
+    */
+    if( bClassifyData && !bCalculateStats )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Ignoring request to not calculate statistics, " \
+                  "because CLASSIFY_DATA was set to ON" );
+        bCalculateStats = TRUE;
+    }
+
+    pszTemp = CSLFetchNameValueDef( papszOptions, "LINEAR_UNIT",
+                                    "SET_FROM_SRS" );
+    int nLinearUnits = 0;
+    int bSetLinearUnits = FALSE;
+    if( EQUAL( pszTemp, "SET_FROM_SRS" ) )
+    {
+        bSetLinearUnits = TRUE;
+    }
+    else if( EQUALN( pszTemp, "METER", 5 ) )
+    {
+        nLinearUnits = 0;
+    }
+    else if( EQUAL( pszTemp, "FOOT" ) || EQUAL( pszTemp, "FEET" ) )
+    {
+        nLinearUnits = 1;
+    }
+    else if( EQUALN( pszTemp, "KILOMETER", 9 ) )
+    {
+        nLinearUnits = 2;
+    }
+    int bCalculateLatitude = TRUE;
+    int nLatitude;
+    if( CSLFetchNameValue( papszOptions, "LATITUDE" ) != NULL )
+    {
+        bCalculateLatitude = FALSE;
+        nLatitude = atoi( CSLFetchNameValue( papszOptions, "LATITUDE" ) );
+        if( nLatitude > 90 || nLatitude < -90 )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                      "Invalid value (%d) for LATITUDE.", nLatitude );
+            return NULL;
+        }
+    }
+    /*
+    ** If no latitude is supplied, attempt to extract the central latitude
+    ** from the image.  It must be set either manually or here, otherwise
+    ** we fail.
+    */
+    double adfSrcGeoTransform[6];
+    poSrcDS->GetGeoTransform( adfSrcGeoTransform );
+    OGRSpatialReference oSrcSRS, oDstSRS;
+    const char *pszWkt = poSrcDS->GetProjectionRef();
+    double dfLongitude = 0.0;
+    double dfLatitude = 0.0;
+    if( !bCalculateLatitude )
+    {
+        dfLatitude = nLatitude;
+    }
+    else if( !EQUAL( pszWkt, "" ) )
+    {
+        oSrcSRS.importFromWkt( (char**)&pszWkt );
+        oDstSRS.importFromEPSG( 4269 );
+        OGRCoordinateTransformation *poCT;
+        poCT = (OGRCoordinateTransformation*)
+            OGRCreateCoordinateTransformation( &oSrcSRS, &oDstSRS );
+        int nErr;
+        if( poCT != NULL )
+        {
+            dfLatitude = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize / 2;
+            nErr = (int)poCT->Transform( 1, &dfLongitude, &dfLatitude );
+            if( !nErr )
+            {
+                dfLatitude = 0.0;
+                /*
+                ** For the most part, this is an invalid LCP, but it is a
+                ** changeable value in Flammap/Farsite, etc.  We should
+                ** probably be strict here all the time.
+                */
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Could not calculate latitude from spatial " \
+                          "reference and LATITUDE was not set." );
+                return NULL;
+            }
+        }
+        OGRCoordinateTransformation::DestroyCT( poCT );
+    }
+    else
+    {
+        /*
+        ** See comment above on failure to transform.
+        */
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Could not calculate latitude from spatial reference " \
+                  "and LATITUDE was not set." );
+        return NULL;
+    }
+    /*
+    ** Set the linear units if the metadata item wasn't already set, and we
+    ** have an SRS.
+    */
+    if( bSetLinearUnits && !EQUAL( pszWkt, "" ) )
+    {
+        const char *pszUnit;
+        pszUnit = oSrcSRS.GetAttrValue( "UNIT", 0 );
+        if( pszUnit == NULL )
+        {
+            if( bStrict )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Could not parse linear unit." );
+                return NULL;
+            }
+            else
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Could not parse linear unit, using meters" );
+                nLinearUnits = 0;
+            }
+        }
+        else
+        {
+            CPLDebug( "LCP", "Setting linear unit to %s", pszUnit );
+            if( EQUAL( pszUnit, "meter" ) || EQUAL( pszUnit, "metre" ) )
+            {
+                nLinearUnits = 0;
+            }
+            else if( EQUAL( pszUnit, "feet" ) || EQUAL( pszUnit, "foot" ) )
+            {
+                nLinearUnits = 1;
+            }
+            else if( EQUALN( pszUnit, "kilomet", 7 ) )
+            {
+                nLinearUnits = 2;
+            }
+            else
+            {
+                if( bStrict )
+                nLinearUnits = 0;
+            }
+            pszUnit = oSrcSRS.GetAttrValue( "UNIT", 1 );
+            if( pszUnit != NULL )
+            {
+                double dfScale = atof( pszUnit );
+                if( dfScale != 1.0 )
+                {
+                    if( bStrict )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Unit scale is %lf (!=1.0). It is not " \
+                                  "supported.", dfScale );
+                        return NULL;
+                    }
+                    else
+                    {
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                                  "Unit scale is %lf (!=1.0). It is not " \
+                                  "supported, ignoring.", dfScale );
+                    }
+                }
+            }
+        }
+    }
+    else if( bSetLinearUnits )
+    {
+        /*
+        ** This can be defaulted if it isn't a strict creation.
+        */
+        if( bStrict )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Could not parse linear unit from spatial reference "
+                      "and LINEAR_UNIT was not set." );
+            return NULL;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Could not parse linear unit from spatial reference "
+                      "and LINEAR_UNIT was not set, defaulting to meters." );
+            nLinearUnits = 0;
+        }
+    }
+
+    const char *pszDescription =
+        CSLFetchNameValueDef( papszOptions, "DESCRIPTION",
+                              "LCP file created by GDAL." );
+
+    /*
+    ** Loop through and get the stats for the bands if we need to calculate
+    ** them.  This probably should be done when we copy the data over to the
+    ** destination dataset, since we load the values into memory, but this is
+    ** much simpler code using GDALRasterBand->GetStatistics().  We also may
+    ** need to classify the data (number of unique values and a list of those
+    ** values if the number of unique values is > 100.  It is currently unclear
+    ** how these data are used though, so we will implement that at some point
+    ** if need be.
+    */
+    GDALRasterBand *poBand;
+    double *padfMin = (double*)CPLMalloc( sizeof( double ) * nBands );
+    double *padfMax = (double*)CPLMalloc( sizeof( double ) * nBands );
+    double dfDummy;
+    GInt32 *panFound = (GInt32*)VSIMalloc2( sizeof( GInt32 ), nBands );
+    GInt32 *panClasses = (GInt32*)VSIMalloc3( sizeof( GInt32 ), nBands, LCP_MAX_CLASSES );
+    /*
+    ** Initialize these arrays to zeros
+    */
+    memset( panFound, 0, sizeof( GInt32 ) * nBands );
+    memset( panClasses, 0, sizeof( GInt32 ) * nBands * LCP_MAX_CLASSES );
+
+    CPLErr eErr;
+    if( bCalculateStats )
+    {
+        for( i = 0; i < nBands; i++ )
+        {
+            poBand = poSrcDS->GetRasterBand( i + 1 );
+            eErr = poBand->GetStatistics( FALSE, TRUE, &padfMin[i],
+                                          &padfMax[i], &dfDummy, &dfDummy );
+            if( eErr != CE_None )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined, "Failed to properly " \
+                                                       "calculate statistics "
+                                                       "on band %d", i );
+                padfMin[i] = 0.0;
+                padfMax[i] = 0.0;
+            }
+            /*
+            ** See comment above.
+            */
+            if( bClassifyData )
+            {
+                eErr = ClassifyBandData( poBand, panFound+ i,
+                                         panClasses + ( i * LCP_MAX_CLASSES ) );
+            }
+        }
+    }
+
+    VSILFILE *fp;
+
+    fp = VSIFOpenL( pszFilename, "wb" );
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Unable to create lcp file %s.", pszFilename );
+        CPLFree( padfMin );
+        CPLFree( padfMax );
+        CPLFree( panFound );
+        CPLFree( panClasses );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write the header                                                */
+/* -------------------------------------------------------------------- */
+
+    nTemp = bHaveCrownFuels ? 21 : 20;
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+    nTemp = bHaveGroundFuels ? 21 : 20;
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+
+    nTemp = (GInt32)( dfLatitude + 0.5 );
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+    dfLongitude = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
+    CPL_LSBPTR64( &dfLongitude );
+    VSIFWriteL( &dfLongitude, 8, 1, fp );
+    dfLongitude = adfSrcGeoTransform[0];
+    CPL_LSBPTR64( &dfLongitude );
+    VSIFWriteL( &dfLongitude, 8, 1, fp );
+    dfLatitude = adfSrcGeoTransform[3];
+    CPL_LSBPTR64( &dfLatitude );
+    VSIFWriteL( &dfLatitude, 8, 1, fp );
+    dfLatitude = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize;
+    CPL_LSBPTR64( &dfLatitude );
+    VSIFWriteL( &dfLatitude, 8, 1, fp );
+
+    /*
+    ** Swap the two classification arrays if we are writing them, and they need
+    ** to be swapped.
+    */
+#ifdef CPL_MSB
+    if( bClassifyData )
+    {
+        GDALSwapWords( panFound, 2, nBands, 2 );
+        GDALSwapWords( panClasses, 2, LCP_MAX_CLASSES, 2 );
+    }
+#endif
+
+    if( bCalculateStats )
+    {
+        for( i = 0; i < nBands; i++ )
+        {
+            /*
+            ** If we don't have Crown fuels, but do have Ground fuels, we
+            ** have to 'fast forward'.
+            */
+            if( i == 5 && !bHaveCrownFuels && bHaveGroundFuels )
+            {
+                VSIFSeekL( fp, 3340, SEEK_SET );
+            }
+            nTemp = (GInt32)padfMin[i];
+            CPL_LSBINT32PTR( &nTemp );
+            VSIFWriteL( &nTemp, 4, 1, fp );
+            nTemp = (GInt32)padfMax[i];
+            CPL_LSBINT32PTR( &nTemp );
+            VSIFWriteL( &nTemp, 4, 1, fp );
+            if( bClassifyData )
+            {
+                /*
+                ** These two arrays were swapped in their entirety above.
+                */
+                VSIFWriteL( panFound + i, 4, 1, fp );
+                VSIFWriteL( panClasses + ( i * LCP_MAX_CLASSES ), 4, 100, fp );
+            }
+            else
+            {
+                nTemp = -1;
+                CPL_LSBINT32PTR( &nTemp );
+                VSIFWriteL( &nTemp, 4, 1, fp );
+                VSIFSeekL( fp, 400, SEEK_CUR );
+            }
+        }
+    }
+    else
+    {
+        VSIFSeekL( fp, 4164, SEEK_SET );
+    }
+    CPLFree( (void*)padfMin );
+    CPLFree( (void*)padfMax );
+    CPLFree( (void*)panFound );
+    CPLFree( (void*)panClasses );
+
+    /*
+    ** Should be at one of 3 locations, 2104, 3340, or 4164.
+    */
+    CPLAssert( VSIFTellL( fp ) == 2104  ||
+               VSIFTellL( fp ) == 3340  ||
+               VSIFTellL( fp ) == 4164 );
+    VSIFSeekL( fp, 4164, SEEK_SET );
+
+    /* Image size */
+    nTemp = (GInt32)nXSize;
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+    nTemp = (GInt32)nYSize;
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+
+    /* X and Y boundaries */
+    /* max x */
+    dfTemp = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+    /* min x */
+    dfTemp = adfSrcGeoTransform[0];
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+    /* max y */
+    dfTemp = adfSrcGeoTransform[3];
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+    /* min y */
+    dfTemp = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize;
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+
+    nTemp = nLinearUnits;
+    CPL_LSBINT32PTR( &nTemp );
+    VSIFWriteL( &nTemp, 4, 1, fp );
+
+    /* Resolution */
+    /* x resolution */
+    dfTemp = adfSrcGeoTransform[1];
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+    /* y resolution */
+    dfTemp = fabs( adfSrcGeoTransform[5] );
+    CPL_LSBPTR64( &dfTemp );
+    VSIFWriteL( &dfTemp, 8, 1, fp );
+
+#ifdef CPL_MSB
+    GDALSwapWords( panMetadata, 2, LCP_MAX_BANDS, 2 );
+#endif
+    VSIFWriteL( panMetadata, 2, LCP_MAX_BANDS, fp );
+
+    /* Write the source filenames */
+    char **papszFileList = poSrcDS->GetFileList();
+    if( papszFileList != NULL )
+    {
+        for( i = 0; i < nBands; i++ )
+        {
+            if( i == 5 && !bHaveCrownFuels && bHaveGroundFuels )
+            {
+                VSIFSeekL( fp, 6292, SEEK_SET );
+            }
+            VSIFWriteL( papszFileList[0], 1,
+                        CPLStrnlen( papszFileList[0], LCP_MAX_PATH ), fp );
+            VSIFSeekL( fp, 4244 + ( 256 * ( i+1 ) ), SEEK_SET );
+        }
+    }
+    /*
+    ** No file list, mem driver, etc.
+    */
+    else
+    {
+        VSIFSeekL( fp, 6804, SEEK_SET );
+    }
+    CSLDestroy( papszFileList );
+    /*
+    ** Should be at location 5524, 6292 or 6804.
+    */
+    CPLAssert( VSIFTellL( fp ) == 5524 ||
+               VSIFTellL( fp ) == 6292 ||
+               VSIFTellL( fp ) == 6804 );
+    VSIFSeekL( fp, 6804, SEEK_SET );
+
+    /* Description */
+    VSIFWriteL( pszDescription, 1, CPLStrnlen( pszDescription, LCP_MAX_DESC ),
+                fp );
+    /*
+    ** Should be at or below location 7316, all done with the header.
+    */
+    CPLAssert( VSIFTellL( fp ) <= 7316 );
+    VSIFSeekL( fp, 7316, SEEK_SET );
+
+/* -------------------------------------------------------------------- */
+/*      Loop over image, copying image data.                            */
+/* -------------------------------------------------------------------- */
+
+    GInt16 *panScanline = (GInt16 *)VSIMalloc3( 2, nBands, nXSize );
+
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        VSIFCloseL( fp );
+        VSIFree( (void*)panScanline );
+        return NULL;
+    }
+    for( int iLine = 0; iLine < nYSize; iLine++ )
+    {
+        for( int iBand = 0; iBand < nBands; iBand++ )
+        {
+            GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
+            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                     panScanline + iBand, nXSize, 1, GDT_Int16,
+                                     nBands * 2, nBands * nXSize * 2 );
+            /* Not sure what to do here */
+            if( eErr != CE_None )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined, "Error reported in " \
+                                                       "RasterIO" );
+                /*
+                ** CPLError( eErr, CPLE_AppDefined, 
+                **           "Error reported in RasterIO" );
+                */
+            }
+        }
+#ifdef CPL_MSB
+        GDALSwapWords( panScanline, 2, nBands * nXSize, 2 );
+#endif
+        VSIFWriteL( panScanline, 2, nBands * nXSize, fp );
+
+        if( !pfnProgress( iLine / (double)nYSize, NULL, pProgressData ) )
+        {
+            VSIFree( (void*)panScanline );
+            VSIFCloseL( fp );
+            return NULL;
+        }
+    }
+    VSIFree( panScanline );
+    VSIFCloseL( fp );
+    if( !pfnProgress( 1.0, NULL, pProgressData ) )
+    {
+        return NULL;
+    }
+
+    /*
+    ** Try to write projection file.  *Most* landfire data follows ESRI
+    **style projection files, so we use the same code as the AAIGrid driver.
+    */
+    const char  *pszOriginalProjection;
+
+    pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
+    if( !EQUAL( pszOriginalProjection, "" ) )
+    {
+        char                    *pszDirname, *pszBasename;
+        char                    *pszPrjFilename;
+        char                    *pszESRIProjection = NULL;
+        VSILFILE                *fp;
+        OGRSpatialReference     oSRS;
+
+        pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
+        pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
+
+        pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
+        fp = VSIFOpenL( pszPrjFilename, "wt" );
+        if (fp != NULL)
+        {
+            oSRS.importFromWkt( (char **) &pszOriginalProjection );
+            oSRS.morphToESRI();
+            oSRS.exportToWkt( &pszESRIProjection );
+            VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
+
+            VSIFCloseL( fp );
+            CPLFree( pszESRIProjection );
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to create file %s.", pszPrjFilename );
+        }
+        CPLFree( pszDirname );
+        CPLFree( pszBasename );
+        CPLFree( pszPrjFilename );
+    }
+    return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+}
+
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -777,9 +1712,72 @@ void GDALRegister_LCP()
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"   <Option name='ELEVATION_UNIT' type='string-select' default='METERS' description='Elevation units'>"
+"       <Value>METERS</Value>"
+"       <Value>FEET</Value>"
+"   </Option>"
+"   <Option name='SLOPE_UNIT' type='string-select' default='DEGREES' description='Slope units'>"
+"       <Value>DEGREES</Value>"
+"       <Value>PERCENT</Value>"
+"   </Option>"
+"   <Option name='ASPECT_UNIT' type='string-select' default='AZIMUTH_DEGREES'>"
+"       <Value>GRASS_CATEGORIES</Value>"
+"       <Value>AZIMUTH_DEGREES</Value>"
+"       <Value>GRASS_DEGREES</Value>"
+"   </Option>"
+"   <Option name='FUEL_MODEL_OPTION' type='string-select' default='NO_CUSTOM_AND_NO_FILE'>"
+"       <Value>NO_CUSTOM_AND_NO_FILE</Value>"
+"       <Value>CUSTOM_AND_NO_FILE</Value>"
+"       <Value>NO_CUSTOM_AND_FILE</Value>"
+"       <Value>CUSTOM_AND_FILE</Value>"
+"   </Option>"
+"   <Option name='CANOPY_COV_UNIT' type='string-select' default='PERCENT'>"
+"       <Value>CATEGORIES</Value>"
+"       <Value>PERCENT</Value>"
+"   </Option>"
+"   <Option name='CANOPY_HT_UNIT' type='string-select' default='METERS_X_10'>"
+"       <Value>METERS</Value>"
+"       <Value>FEET</Value>"
+"       <Value>METERS_X_10</Value>"
+"       <Value>FEET_X_10</Value>"
+"   </Option>"
+"   <Option name='CBH_UNIT' type='string-select' default='METERS_X_10'>"
+"       <Value>METERS</Value>"
+"       <Value>FEET</Value>"
+"       <Value>METERS_X_10</Value>"
+"       <Value>FEET_X_10</Value>"
+"   </Option>"
+"   <Option name='CBD_UNIT' type='string-select' default='KG_PER_CUBIC_METER_X_100'>"
+"       <Value>KG_PER_CUBIC_METER</Value>"
+"       <Value>POUND_PER_CUBIC_FOOT</Value>"
+"       <Value>KG_PER_CUBIC_METER_X_100</Value>"
+"       <Value>POUND_PER_CUBIC_FOOT_X_1000</Value>"
+"   </Option>"
+"   <Option name='DUFF_UNIT' type='string-select' default='MG_PER_HECTARE_X_10'>"
+"       <Value>MG_PER_HECTARE_X_10</Value>"
+"       <Value>TONS_PER_ACRE_X_10</Value>"
+"   </Option>"
+/* I don't think we need to override this, but maybe? */
+/*"   <Option name='CWD_OPTION' type='boolean' default='FALSE' description='Override logic for setting the coarse woody presence'/>" */
+"   <Option name='CALCULATE_STATS' type='boolean' default='YES' description='Write the stats to the lcp'/>"
+"   <Option name='CLASSIFY_DATA' type='boolean' default='YES' description='Write the stats to the lcp'/>"
+"   <Option name='LINEAR_UNIT' type='string-select' default='SET_FROM_SRS' description='Set the linear units in the lcp'>"
+"       <Value>SET_FROM_SRS</Value>"
+"       <Value>METER</Value>"
+"       <Value>FOOT</Value>"
+"       <Value>KILOMETER</Value>"
+"   </Option>"
+"   <Option name='LATITUDE' type='int' default='' description='Set the latitude for the dataset, this overrides the driver trying to set it programmatically in EPSG:4269'/>"
+"   <Option name='DESCRIPTION' type='string' default='LCP file created by GDAL' description='A short description of the lcp file'/>"
+"</CreationOptionList>" );
         poDriver->pfnOpen = LCPDataset::Open;
+        poDriver->pfnCreateCopy = LCPDataset::CreateCopy;
         poDriver->pfnIdentify = LCPDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+   }
 }
+
diff --git a/frmts/raw/makefile.vc b/frmts/raw/makefile.vc
index 0229f44..0f18321 100644
--- a/frmts/raw/makefile.vc
+++ b/frmts/raw/makefile.vc
@@ -7,7 +7,7 @@ OBJ	=	rawdataset.obj ehdrdataset.obj pauxdataset.obj doq1dataset.obj\
 		ndfdataset.obj dipxdataset.obj genbindataset.obj \
 		lcpdataset.obj eirdataset.obj gtxdataset.obj loslasdataset.obj \
 		ntv2dataset.obj ace2dataset.obj snodasdataset.obj \
-		ctable2dataset.obj
+		ctable2dataset.obj krodataset.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/raw/mffdataset.cpp b/frmts/raw/mffdataset.cpp
index b877bc1..d725857 100644
--- a/frmts/raw/mffdataset.cpp
+++ b/frmts/raw/mffdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mffdataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: mffdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis MFF Support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_spatialref.h"
 #include "atlsci_spheroid.h"
 
-CPL_CVSID("$Id: mffdataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: mffdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_MFF(void);
diff --git a/frmts/raw/ndfdataset.cpp b/frmts/raw/ndfdataset.cpp
index f6b7abd..cbccf31 100644
--- a/frmts/raw/ndfdataset.cpp
+++ b/frmts/raw/ndfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ndfdataset.cpp 21749 2011-02-19 12:25:29Z rouault $
+ * $Id: ndfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NDF Driver
  * Purpose:  Implementation of NLAPS Data Format read support.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ndfdataset.cpp 21749 2011-02-19 12:25:29Z rouault $");
+CPL_CVSID("$Id: ndfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/raw/ntv2dataset.cpp b/frmts/raw/ntv2dataset.cpp
index d038df6..b922974 100644
--- a/frmts/raw/ntv2dataset.cpp
+++ b/frmts/raw/ntv2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntv2dataset.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: ntv2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of NTv2 datum shift format used in Canada, France, 
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Frank Warmerdam
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ntv2dataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: ntv2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /** 
  * The header for the file, and each grid consists of 11 16byte records.
diff --git a/frmts/raw/pauxdataset.cpp b/frmts/raw/pauxdataset.cpp
index 63e6d40..149f0e6 100644
--- a/frmts/raw/pauxdataset.cpp
+++ b/frmts/raw/pauxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pauxdataset.cpp 21225 2010-12-09 19:49:33Z warmerdam $
+ * $Id: pauxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PCI .aux Driver
  * Purpose:  Implementation of PAuxDataset
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: pauxdataset.cpp 21225 2010-12-09 19:49:33Z warmerdam $");
+CPL_CVSID("$Id: pauxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PAux(void);
diff --git a/frmts/raw/pnmdataset.cpp b/frmts/raw/pnmdataset.cpp
index 0fb395b..c2fb5d7 100644
--- a/frmts/raw/pnmdataset.cpp
+++ b/frmts/raw/pnmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pnmdataset.cpp 21696 2011-02-12 20:35:50Z rouault $
+ * $Id: pnmdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PNM Driver
  * Purpose:  Portable anymap file format imlementation
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: pnmdataset.cpp 21696 2011-02-12 20:35:50Z rouault $");
+CPL_CVSID("$Id: pnmdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_PNM(void);
diff --git a/frmts/raw/rawdataset.cpp b/frmts/raw/rawdataset.cpp
index 554bb6f..6c0ec1c 100644
--- a/frmts/raw/rawdataset.cpp
+++ b/frmts/raw/rawdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rawdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rawdataset.cpp 27194 2014-04-16 10:07:21Z rouault $
  *
  * Project:  Generic Raw Binary Driver
  * Purpose:  Implementation of RawDataset and RawRasterBand classes.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rawdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: rawdataset.cpp 27194 2014-04-16 10:07:21Z rouault $");
 
 /************************************************************************/
 /*                           RawRasterBand()                            */
@@ -280,8 +281,8 @@ CPLErr RawRasterBand::AccessLine( int iLine )
         if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ %d.\n",
-                  iLine, (int) (nImgOffset + (vsi_l_offset)iLine * nLineOffset) );
+                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".\n",
+                  iLine, nImgOffset + (vsi_l_offset)iLine * nLineOffset );
             return CE_Failure;
         }
         else
@@ -437,8 +438,8 @@ CPLErr RawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( Seek( nWriteStart, SEEK_SET ) == -1 ) 
     {
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ %d to write to file.\n",
-                  nBlockYOff, (int) (nImgOffset + nBlockYOff * nLineOffset) );
+                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB " to write to file.\n",
+                  nBlockYOff, nImgOffset + nBlockYOff * nLineOffset );
         
         eErr = CE_Failure;
     }
@@ -541,15 +542,16 @@ CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
 }
 
 /************************************************************************/
-/*                          IsLineLoaded()                              */
+/*               IsSignificantNumberOfLinesLoaded()                     */
 /*                                                                      */
-/*  Check whether at least one scanline from the specified block of     */
-/*  lines is cached.                                                    */
+/*  Check if there is a significant number of scanlines (>20%) from the */
+/*  specified block of lines already cached.                            */
 /************************************************************************/
 
-int RawRasterBand::IsLineLoaded( int nLineOff, int nLines )
+int RawRasterBand::IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines )
 {
     int         iLine;
+    int         nCountLoaded = 0;
 
     for ( iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
     {
@@ -557,7 +559,11 @@ int RawRasterBand::IsLineLoaded( int nLineOff, int nLines )
         if( poBlock != NULL )
         {
             poBlock->DropLock();
-            return TRUE;
+            nCountLoaded ++;
+            if( nCountLoaded > nLines / 20 )
+            {
+                return TRUE;
+            }
         }
     }
 
@@ -565,19 +571,12 @@ int RawRasterBand::IsLineLoaded( int nLineOff, int nLines )
 }
 
 /************************************************************************/
-/*                             IRasterIO()                              */
+/*                           CanUseDirectIO()                           */
 /************************************************************************/
 
-CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
-                                 int nXOff, int nYOff, int nXSize, int nYSize,
-                                 void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType,
-                                 int nPixelSpace, int nLineSpace )
-
+int RawRasterBand::CanUseDirectIO(int nXOff, int nYOff, int nXSize, int nYSize,
+                                  GDALDataType eBufType)
 {
-    int         nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
-    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
-    int         nBytesToRW = nPixelOffset * nXSize;
 
 /* -------------------------------------------------------------------- */
 /* Use direct IO without caching if:                                    */
@@ -588,31 +587,56 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*                                                                      */
 /* the length of a scanline on disk is more than 50000 bytes, and the   */
 /* width of the requested chunk is less than 40% of the whole scanline  */
-/* and none of the requested scanlines are already in the cache.        */
+/* and no significant number of requested scanlines are already in the  */
+/* cache.                                                               */
 /* -------------------------------------------------------------------- */
     if( nPixelOffset < 0 ) 
     {
-        return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
-                                          nXSize, nYSize,
-                                          pData, nBufXSize, nBufYSize,
-                                          eBufType,
-                                          nPixelSpace, nLineSpace );
+        return FALSE;
     }
 
-    if ( !CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
+    const char* pszGDAL_ONE_BIG_READ = CPLGetConfigOption( "GDAL_ONE_BIG_READ", NULL);
+    if ( pszGDAL_ONE_BIG_READ == NULL )
     {
+        int         nBytesToRW = nPixelOffset * nXSize;
         if ( nLineSize < 50000
              || nBytesToRW > nLineSize / 5 * 2
-             || IsLineLoaded( nYOff, nYSize ) )
+             || IsSignificantNumberOfLinesLoaded( nYOff, nYSize ) )
         {
 
-            return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
-                                              nXSize, nYSize,
-                                              pData, nBufXSize, nBufYSize,
-                                              eBufType,
-                                              nPixelSpace, nLineSpace );
+            return FALSE;
         }
+        return TRUE;
     }
+    else
+        return CSLTestBoolean(pszGDAL_ONE_BIG_READ);
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 int nPixelSpace, int nLineSpace )
+
+{
+    int         nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
+    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
+    int         nBytesToRW = nPixelOffset * nXSize;
+
+    if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
+    {
+        return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
+                                          nXSize, nYSize,
+                                          pData, nBufXSize, nBufYSize,
+                                          eBufType,
+                                          nPixelSpace, nLineSpace );
+    }
+
+    CPLDebug("RAW", "Using direct IO implementation");
 
 /* ==================================================================== */
 /*   Read data.                                                         */
@@ -644,16 +668,14 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
              && nPixelSpace == nBufDataSize
              && nLineSpace == nPixelSpace * nXSize )
         {
-            if ( AccessBlock( nImgOffset
-                              + (vsi_l_offset)nYOff * nLineOffset + nXOff,
+            vsi_l_offset nOffset = nImgOffset
+                              + (vsi_l_offset)nYOff * nLineOffset + nXOff;
+            if ( AccessBlock( nOffset,
                               nXSize * nYSize * nBandDataSize, pData ) != CE_None )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to read %d bytes at %lu.",
-                          nXSize * nYSize * nBandDataSize,
-                          (unsigned long)
-                          (nImgOffset + (vsi_l_offset)nYOff * nLineOffset
-                           + nXOff) );
+                          "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
+                          nXSize * nYSize * nBandDataSize, nOffset);
             }
         }
 
@@ -674,19 +696,16 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
             for ( iLine = 0; iLine < nBufYSize; iLine++ )
             {
-                if ( AccessBlock( nImgOffset
+                vsi_l_offset nOffset = nImgOffset
                                   + ((vsi_l_offset)nYOff
-                                  + (int)(iLine * dfSrcYInc)) * nLineOffset
-                                  + nXOff * nPixelOffset,
+                                  + (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset
+                                  + nXOff * nPixelOffset;
+                if ( AccessBlock( nOffset,
                                   nBytesToRW, pabyData ) != CE_None )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to read %d bytes at %lu.",
-                              nBytesToRW,
-                              (unsigned long)(nImgOffset
-                              + ((vsi_l_offset)nYOff
-                              + (int)(iLine * dfSrcYInc)) * nLineOffset
-                              + nXOff * nPixelOffset) );
+                              "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
+                              nBytesToRW, nOffset );
                 }
 
 /* -------------------------------------------------------------------- */
@@ -696,7 +715,7 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
                     GDALCopyWords( pabyData, eDataType, nPixelOffset,
-                                   (GByte *)pData + iLine * nLineSpace,
+                                   (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
                                    eBufType, nPixelSpace, nXSize );
                 }
                 else
@@ -706,10 +725,10 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
                         GDALCopyWords( pabyData +
-                                       (int)(iPixel * dfSrcXInc) * nPixelOffset,
-                                       eDataType, 0,
-                                       (GByte *)pData + iLine * nLineSpace +
-                                       iPixel * nBufDataSize,
+                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
+                                       eDataType, nPixelOffset,
+                                       (GByte *)pData + (vsi_l_offset)iLine * nLineSpace +
+                                       (vsi_l_offset)iPixel * nPixelSpace,
                                        eBufType, nPixelSpace, 1 );
                     }
                 }
@@ -759,13 +778,12 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Seek to the right block.                                        */
 /* -------------------------------------------------------------------- */
-            if( Seek( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff,
-                      SEEK_SET) == -1 )
+            vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff;
+            if( Seek( nOffset, SEEK_SET) == -1 )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to seek to %lu to write data.\n",
-                          (unsigned long)(nImgOffset + (vsi_l_offset)nYOff
-                                          * nLineOffset + nXOff) );
+                          "Failed to seek to " CPL_FRMT_GUIB " to write data.\n",
+                          nOffset);
         
                 return CE_Failure;
             }
@@ -823,7 +841,7 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             for ( iLine = 0; iLine < nBufYSize; iLine++ )
             {
                 nBlockOff = nImgOffset
-                    + ((vsi_l_offset)nYOff + (int)(iLine*dfSrcYInc))*nLineOffset
+                    + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset
                     + nXOff * nPixelOffset;
 
 /* -------------------------------------------------------------------- */
@@ -839,7 +857,7 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
-                    GDALCopyWords( (GByte *)pData + iLine * nLineSpace,
+                    GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
                                    eBufType, nPixelSpace,
                                    pabyData, eDataType, nPixelOffset, nXSize );
                 }
@@ -849,12 +867,12 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
                     for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
-                        GDALCopyWords( (GByte *)pData+iLine*nLineSpace +
-                                       iPixel * nBufDataSize,
+                        GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace +
+                                       (vsi_l_offset)iPixel * nPixelSpace,
                                        eBufType, nPixelSpace,
                                        pabyData +
-                                       (int)(iPixel * dfSrcXInc) * nPixelOffset,
-                                       eDataType, 0, 1 );
+                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
+                                       eDataType, nPixelOffset, 1 );
                     }
                 }
 
@@ -883,8 +901,8 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( Seek( nBlockOff, SEEK_SET) == -1 )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to seek to %ld to read.\n",
-                              (long)nBlockOff );
+                              "Failed to seek to " CPL_FRMT_GUIB " to read.\n",
+                              nBlockOff );
 
                     return CE_Failure;
                 }
@@ -1058,6 +1076,49 @@ GDALColorInterp RawRasterBand::GetColorInterpretation()
 }
 
 /************************************************************************/
+/*                           GetVirtualMemAuto()                        */
+/************************************************************************/
+
+CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                                  int *pnPixelSpace,
+                                                  GIntBig *pnLineSpace,
+                                                  char **papszOptions )
+{
+    CPLAssert(pnPixelSpace);
+    CPLAssert(pnLineSpace);
+
+    vsi_l_offset nSize =  (vsi_l_offset)(nRasterYSize - 1) * nLineOffset +
+        (nRasterXSize - 1) * nPixelOffset + GDALGetDataTypeSize(eDataType) / 8;
+
+    if( !bIsVSIL || VSIFGetNativeFileDescriptorL(fpRawL) == NULL ||
+        !CPLIsVirtualMemFileMapAvailable() || (eDataType != GDT_Byte && !bNativeOrder) ||
+        (size_t)nSize != nSize || nPixelOffset < 0 || nLineOffset < 0 ||
+        CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
+    {
+        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                                 pnLineSpace, papszOptions);
+    }
+
+    FlushCache();
+
+    CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
+        fpRawL, nImgOffset, nSize,
+        (eRWFlag == GF_Write) ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
+        NULL, NULL);
+    if( pVMem == NULL )
+    {
+        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                                 pnLineSpace, papszOptions);
+    }
+    else
+    {
+        *pnPixelSpace = nPixelOffset;
+        *pnLineSpace = nLineOffset;
+        return pVMem;
+    }
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*      RawDataset                                                      */
 /* ==================================================================== */
@@ -1097,14 +1158,53 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nPixelSpace, int nLineSpace, int nBandSpace )
 
 {
-/*    if( nBandCount > 1 )
-        return GDALDataset::BlockBasedRasterIO( 
-            eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
-            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
-    else*/
-        return 
-            GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+    const char* pszInterleave;
+
+    /* The default GDALDataset::IRasterIO() implementation would go to */
+    /* BlockBasedRasterIO if the dataset is interleaved. However if the */
+    /* access pattern is compatible with DirectIO() we don't want to go */
+    /* BlockBasedRasterIO, but rather used our optimized path in RawRasterBand::IRasterIO() */
+    if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
+        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
+        EQUAL(pszInterleave, "PIXEL"))
+    {
+        int iBandIndex;
+        for(iBandIndex = 0; iBandIndex < nBandCount; iBandIndex ++ )
+        {
+            RawRasterBand* poBand = (RawRasterBand*) GetRasterBand(panBandMap[iBandIndex]);
+            if( !poBand->CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
+            {
+                break;
+            }
+        }
+        if( iBandIndex == nBandCount )
+        {
+            CPLErr eErr = CE_None;
+            for( iBandIndex = 0; 
+                iBandIndex < nBandCount && eErr == CE_None; 
+                iBandIndex++ )
+            {
+                GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
+                GByte *pabyBandData;
+
+                if (poBand == NULL)
+                {
+                    eErr = CE_Failure;
+                    break;
+                }
+
+                pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+                
+                eErr = poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+                                        (void *) pabyBandData, nBufXSize, nBufYSize,
+                                        eBufType, nPixelSpace, nLineSpace );
+            }
+
+            return eErr;
+        }
+    }
+
+    return  GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                     pData, nBufXSize, nBufYSize, eBufType, 
                                     nBandCount, panBandMap, 
                                     nPixelSpace, nLineSpace, nBandSpace );
diff --git a/frmts/raw/rawdataset.h b/frmts/raw/rawdataset.h
index 0e779b5..80cdbe2 100644
--- a/frmts/raw/rawdataset.h
+++ b/frmts/raw/rawdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rawdataset.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rawdataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Raw Translator
  * Purpose:  Implementation of RawDataset class.  Intented to be subclassed
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -102,13 +103,16 @@ protected:
 
     CPLErr      AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
                              void * pData );
-    int         IsLineLoaded( int nLineOff, int nLines );
+    int         IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines );
     void        Initialize();
 
     virtual CPLErr  IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int );
 
+    int         CanUseDirectIO(int nXOff, int nYOff, int nXSize, int nYSize,
+                               GDALDataType eBufType);
+
 public:
 
                  RawRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
@@ -140,6 +144,11 @@ public:
 
     virtual CPLErr  FlushCache();
 
+    virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                               int *pnPixelSpace,
+                                               GIntBig *pnLineSpace,
+                                               char **papszOptions );
+
     CPLErr          AccessLine( int iLine );
 
     void            SetAccess( GDALAccess eAccess );
diff --git a/frmts/raw/snodasdataset.cpp b/frmts/raw/snodasdataset.cpp
index ec1f544..04e2ad9 100644
--- a/frmts/raw/snodasdataset.cpp
+++ b/frmts/raw/snodasdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: snodasdataset.cpp 21984 2011-03-19 17:22:58Z rouault $
+ * $Id: snodasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SNODAS driver
  * Purpose:  Implementation of SNODASDataset
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: snodasdataset.cpp 21984 2011-03-19 17:22:58Z rouault $");
+CPL_CVSID("$Id: snodasdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // g++ -g -Wall -fPIC frmts/raw/snodasdataset.cpp -shared -o gdal_SNODAS.so -Iport -Igcore -Ifrmts/raw -Iogr -L. -lgdal
 
diff --git a/frmts/rik/rikdataset.cpp b/frmts/rik/rikdataset.cpp
index 7d160ae..150449b 100644
--- a/frmts/rik/rikdataset.cpp
+++ b/frmts/rik/rikdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rikdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
+ * $Id: rikdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  RIK Reader
  * Purpose:  All code for RIK Reader
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Daniel Wallner <daniel.wallner at bredband.net>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include <zlib.h>
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: rikdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
+CPL_CVSID("$Id: rikdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_RIK(void);
diff --git a/frmts/rmf/rmfdataset.cpp b/frmts/rmf/rmfdataset.cpp
index 32a76ff..6b717ce 100644
--- a/frmts/rmf/rmfdataset.cpp
+++ b/frmts/rmf/rmfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.cpp 24731 2012-08-03 17:02:56Z rouault $
+ * $Id: rmfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Read/write raster files used in GIS "Integratsia"
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 
 #include "rmfdataset.h"
 
-CPL_CVSID("$Id: rmfdataset.cpp 24731 2012-08-03 17:02:56Z rouault $");
+CPL_CVSID("$Id: rmfdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_RMF(void);
diff --git a/frmts/rmf/rmfdem.cpp b/frmts/rmf/rmfdem.cpp
index fe67fef..78779a9 100644
--- a/frmts/rmf/rmfdem.cpp
+++ b/frmts/rmf/rmfdem.cpp
@@ -245,7 +245,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
 
                 while ( nCount-- > 0 )
                 {
-                    nCode =*((GInt32 *)pabyTempIn) & 0x0FFF;
+                    nCode =*((GInt32 *)pabyTempIn) & 0x00FFFFFF;
                     pabyTempIn += 3;
                     if ( nCode > RANGE_INT24 )
                         nCode |= INV_INT24;
diff --git a/frmts/rs2/rs2dataset.cpp b/frmts/rs2/rs2dataset.cpp
index fef51ff..3f6044c 100644
--- a/frmts/rs2/rs2dataset.cpp
+++ b/frmts/rs2/rs2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rs2dataset.cpp 25658 2013-02-19 18:56:59Z warmerdam $
+ * $Id: rs2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Radarsat 2 - XML Products (product.xml) driver
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: rs2dataset.cpp 25658 2013-02-19 18:56:59Z warmerdam $");
+CPL_CVSID("$Id: rs2dataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_RS2(void);
@@ -104,6 +105,7 @@ class RS2Dataset : public GDALPamDataset
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
 
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char * pszDomain = "" );
     virtual char **GetFileList(void);
 
@@ -1479,6 +1481,17 @@ CPLErr RS2Dataset::GetGeoTransform( double * padfTransform )
 
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **RS2Dataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/frmts/saga/sagadataset.cpp b/frmts/saga/sagadataset.cpp
index ab8e3d1..66478df 100644
--- a/frmts/saga/sagadataset.cpp
+++ b/frmts/saga/sagadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sagadataset.cpp 22699 2011-07-11 18:12:32Z rouault $
+ * $Id: sagadataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  * Project:  SAGA GIS Binary Driver
  * Purpose:  Implements the SAGA GIS Binary Grid Format.
  * Author:   Volker Wichmann, wichmann at laserdata.at
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Volker Wichmann <wichmann at laserdata.at>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,8 +35,9 @@
 #include <assert.h>
 
 #include "gdal_pam.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: sagadataset.cpp 22699 2011-07-11 18:12:32Z rouault $");
+CPL_CVSID("$Id: sagadataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef INT_MAX
 # define INT_MAX 2147483647
@@ -75,8 +77,10 @@ class SAGADataset : public GDALPamDataset
 									double dfCellsize, double dfNoData,
 									double dfZFactor, bool bTopToBottom );
     VSILFILE				*fp;
+    char                *pszProjection;
 
   public:
+        SAGADataset();
 		~SAGADataset();
 
 		static GDALDataset		*Open( GDALOpenInfo * );
@@ -90,6 +94,8 @@ class SAGADataset : public GDALPamDataset
 										GDALProgressFunc pfnProgress,
 										void *pProgressData );
 		
+        virtual const char     *GetProjectionRef(void);
+        virtual CPLErr          SetProjection( const char * );
         virtual char          **GetFileList();
 
 		CPLErr					GetGeoTransform( double *padfGeoTransform );
@@ -299,16 +305,23 @@ double SAGARasterBand::GetNoDataValue( int * pbSuccess )
     return m_NoData;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              SAGADataset	                            */
 /* ==================================================================== */
 /************************************************************************/
 
+
+SAGADataset::SAGADataset()
+
+{
+    pszProjection = CPLStrdup("");
+}
+
 SAGADataset::~SAGADataset()
 
 {
+    CPLFree( pszProjection );
     FlushCache();
     if( fp != NULL )
         VSIFCloseL( fp );
@@ -323,7 +336,7 @@ char** SAGADataset::GetFileList()
 {
     CPLString osPath = CPLGetPath( GetDescription() );
     CPLString osName = CPLGetBasename( GetDescription() );
-    CPLString osHDRFilename;
+    VSIStatBufL sStatBuf;
 
     char **papszFileList = NULL;
 
@@ -331,13 +344,75 @@ char** SAGADataset::GetFileList()
     papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
-    osHDRFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
-    papszFileList = CSLAddString( papszFileList, osHDRFilename );
+    CPLString osFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
+    papszFileList = CSLAddString( papszFileList, osFilename );
+
+    // projections file.
+    osFilename = CPLFormCIFilename( osPath, osName, "prj" );
+    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+        papszFileList = CSLAddString( papszFileList, osFilename );
     
     return papszFileList;
 }
 
 /************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *SAGADataset::GetProjectionRef()
+
+{
+    if (pszProjection && strlen(pszProjection) > 0)
+        return pszProjection;
+
+    return GDALPamDataset::GetProjectionRef();
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr SAGADataset::SetProjection( const char *pszSRS )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Reset coordinate system on the dataset.                         */
+/* -------------------------------------------------------------------- */
+    CPLFree( pszProjection );
+    pszProjection = CPLStrdup( pszSRS );
+
+    if( strlen(pszSRS) == 0 )
+        return CE_None;
+
+/* -------------------------------------------------------------------- */
+/*      Convert to ESRI WKT.                                            */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReference oSRS( pszSRS );
+    char *pszESRI_SRS = NULL;
+
+    oSRS.morphToESRI();
+    oSRS.exportToWkt( &pszESRI_SRS );
+
+/* -------------------------------------------------------------------- */
+/*      Write to .prj file.                                             */
+/* -------------------------------------------------------------------- */
+    CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
+    VSILFILE *fp;
+
+    fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
+    if( fp != NULL )
+    {
+        VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), fp );
+        VSIFWriteL( (void *) "\n", 1, 1, fp );
+        VSIFCloseL( fp );
+    }
+
+    CPLFree( pszESRI_SRS );
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -571,6 +646,31 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
+/*      Check for a .prj file.                                          */
+/* -------------------------------------------------------------------- */
+    const char  *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
+
+    fp = VSIFOpenL( pszPrjFilename, "r" );
+
+    if( fp != NULL )
+    {
+        char  **papszLines;
+        OGRSpatialReference oSRS;
+
+        VSIFCloseL( fp );
+        
+        papszLines = CSLLoad( pszPrjFilename );
+
+        if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
+        {
+            CPLFree( poDS->pszProjection );
+            oSRS.exportToWkt( &(poDS->pszProjection) );
+        }
+
+        CSLDestroy( papszLines );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
@@ -964,6 +1064,8 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
     poDstDS->SetGeoTransform( adfGeoTransform );
+    
+    poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
 
     return poDstDS;
 }
diff --git a/frmts/sdts/sdts_al.h b/frmts/sdts/sdts_al.h
index 9c0854f..faa83cf 100644
--- a/frmts/sdts/sdts_al.h
+++ b/frmts/sdts/sdts_al.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdts_al.h 25839 2013-04-02 18:54:20Z rouault $
+ * $Id: sdts_al.h 26613 2013-11-14 17:42:08Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Include file for entire SDTS Abstraction Layer functions.
@@ -28,7 +28,7 @@
  ****************************************************************************/
 
 #ifndef SDTS_AL_H_INCLUDED
-#define STDS_AL_H_INCLUDED
+#define SDTS_AL_H_INCLUDED
 
 #include "cpl_conv.h"
 #include "iso8211.h"
@@ -677,4 +677,4 @@ class SDTSTransfer
     SDTSIndexedReader **papoLayerReader;
 };
 
-#endif /* ndef SDTS_AL_H_INCLUDED */
+#endif /* ifndef SDTS_AL_H_INCLUDED */
diff --git a/frmts/sdts/sdtsdataset.cpp b/frmts/sdts/sdtsdataset.cpp
index 93d4d77..0cc3e67 100644
--- a/frmts/sdts/sdtsdataset.cpp
+++ b/frmts/sdts/sdtsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
+ * $Id: sdtsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  GDALDataset driver for SDTS Raster translator.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: sdtsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
+CPL_CVSID("$Id: sdtsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /**
  \file sdtsdataset.cpp
diff --git a/frmts/sdts/sdtslib.cpp b/frmts/sdts/sdtslib.cpp
index ec1f0ba..e2ef9ba 100644
--- a/frmts/sdts/sdtslib.cpp
+++ b/frmts/sdts/sdtslib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtslib.cpp 25839 2013-04-02 18:54:20Z rouault $
+ * $Id: sdtslib.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Various utility functions that apply to all SDTS profiles.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "sdts_al.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sdtslib.cpp 25839 2013-04-02 18:54:20Z rouault $");
+CPL_CVSID("$Id: sdtslib.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            SDTSFeature()                             */
diff --git a/frmts/sdts/sdtsrasterreader.cpp b/frmts/sdts/sdtsrasterreader.cpp
index fb5ae61..c484a19 100644
--- a/frmts/sdts/sdtsrasterreader.cpp
+++ b/frmts/sdts/sdtsrasterreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsrasterreader.cpp 25839 2013-04-02 18:54:20Z rouault $
+ * $Id: sdtsrasterreader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSRasterReader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsrasterreader.cpp 25839 2013-04-02 18:54:20Z rouault $");
+CPL_CVSID("$Id: sdtsrasterreader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          SDTSRasterReader()                          */
diff --git a/frmts/sgi/sgidataset.cpp b/frmts/sgi/sgidataset.cpp
index 4e4e31b..208d5ef 100644
--- a/frmts/sgi/sgidataset.cpp
+++ b/frmts/sgi/sgidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: sgidataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SGI Image Driver
  * Purpose:  Implement SGI Image Support based on Paul Bourke's SGI Image code.
@@ -11,6 +11,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: sgidataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_SGI(void);
diff --git a/frmts/srtmhgt/srtmhgtdataset.cpp b/frmts/srtmhgt/srtmhgtdataset.cpp
index 9858648..aefdb82 100644
--- a/frmts/srtmhgt/srtmhgtdataset.cpp
+++ b/frmts/srtmhgt/srtmhgtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srtmhgtdataset.cpp 22163 2011-04-14 21:26:21Z rouault $
+ * $Id: srtmhgtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SRTM HGT Driver
  * Purpose:  SRTM HGT File Read Support.
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 
 #define SRTMHG_NODATA_VALUE -32768
 
-CPL_CVSID("$Id: srtmhgtdataset.cpp 22163 2011-04-14 21:26:21Z rouault $");
+CPL_CVSID("$Id: srtmhgtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_SRTMHGT(void);
diff --git a/frmts/til/tildataset.cpp b/frmts/til/tildataset.cpp
index 31c6c1f..7451835 100644
--- a/frmts/til/tildataset.cpp
+++ b/frmts/til/tildataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tildataset.cpp 25588 2013-01-31 21:09:01Z bishop $
+ * $Id: tildataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EarthWatch .TIL Driver
  * Purpose:  Implementation of the TILDataset class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_multiproc.h"
 #include "cplkeywordparser.h"
 
-CPL_CVSID("$Id: tildataset.cpp 25588 2013-01-31 21:09:01Z bishop $");
+CPL_CVSID("$Id: tildataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/tsx/tsxdataset.cpp b/frmts/tsx/tsxdataset.cpp
index d1eb859..c32ce52 100644
--- a/frmts/tsx/tsxdataset.cpp
+++ b/frmts/tsx/tsxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tsxdataset.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: tsxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:     TerraSAR-X XML Product Support
  * Purpose:     Support for TerraSAR-X XML Metadata files
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Philippe Vachon <philippe at cowpig.ca>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 
 #define MAX_GCPS 5000    //this should be more than enough ground control points
 
-CPL_CVSID("$Id: tsxdataset.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: tsxdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void GDALRegister_TSX(void);
diff --git a/frmts/usgsdem/usgsdem_create.cpp b/frmts/usgsdem/usgsdem_create.cpp
index 526a8c4..12c7c8b 100644
--- a/frmts/usgsdem/usgsdem_create.cpp
+++ b/frmts/usgsdem/usgsdem_create.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: usgsdem_create.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: usgsdem_create.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  USGS DEM Driver
  * Purpose:  CreateCopy() implementation.
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "gdalwarper.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: usgsdem_create.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: usgsdem_create.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef struct 
 {
diff --git a/frmts/usgsdem/usgsdemdataset.cpp b/frmts/usgsdem/usgsdemdataset.cpp
index 879b221..86bd73c 100644
--- a/frmts/usgsdem/usgsdemdataset.cpp
+++ b/frmts/usgsdem/usgsdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: usgsdemdataset.cpp 25675 2013-02-23 15:33:45Z rouault $
+ * $Id: usgsdemdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  USGS DEM Driver
  * Purpose:  All reader for USGS DEM Reader
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: usgsdemdataset.cpp 25675 2013-02-23 15:33:45Z rouault $");
+CPL_CVSID("$Id: usgsdemdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void	GDALRegister_USGSDEM(void);
diff --git a/frmts/vrt/vrt_tutorial.dox b/frmts/vrt/vrt_tutorial.dox
index bc1aacb..3cd84b8 100644
--- a/frmts/vrt/vrt_tutorial.dox
+++ b/frmts/vrt/vrt_tutorial.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: vrt_tutorial.dox 24950 2012-09-22 13:54:36Z rouault $ */
+/* $Id: vrt_tutorial.dox 27110 2014-03-28 21:29:20Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -293,6 +293,14 @@ DestRect elements), but it provides support to rescale and offset
 the range of the source values. Certain regions of the source
 can be masked by specifying the NODATA value.
 
+Starting with GDAL 1.11, alternatively to linear scaling, non-linear
+scaling using a power function can be used by specifying the Exponent,
+SrcMin, SrcMax, DstMin and DstMax elements. If SrcMin and SrcMax are
+not specified, they are computed from the source minimum and maximum
+value (which might require analyzing the whole source dataset). Exponent
+must be positive. (Those 5 values can be set with the -exponent and -scale
+options of gdal_translate.)
+
 The ComplexSource supports adding a custom lookup table to transform 
 the source values to the destination. The LUT can be specified using
 the following form:
@@ -315,8 +323,8 @@ in the following order:
 <ol>
 <li>Nodata masking</li>
 <li>Color table expansion</li>
-<li>Applying the scale ratio</li>
-<li>Applying the scale offset</li>
+<li>For linear scaling, applying the scale ratio, then scale offset</li>
+<li>For non-linear scaling, apply (DstMax-DstMin) * pow( (SrcValue-SrcMin) / (SrcMax-SrcMin), Exponent) + DstMin</li>
 <li>Table lookup</li>
 </ol>
 
@@ -333,6 +341,23 @@ in the following order:
       <DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
     </ComplexSource>
 \endcode
+
+Non-linear scaling:
+
+\code
+    <ComplexSource>
+      <SourceFilename relativeToVRT="1">16bit.tif</SourceFilename>
+      <SourceBand>1</SourceBand>
+      <Exponent>0.75</Exponent>
+      <SrcMin>0</SrcMin>
+      <SrcMax>65535</SrcMax>
+      <DstMin>0</DstMin>
+      <DstMax>255</DstMax>
+      <SrcRect xOff="0" yOff="0" xSize="512" ySize="512"/>
+      <DstRect xOff="0" yOff="0" xSize="512" ySize="512"/>
+    </ComplexSource>
+\endcode
+
 </li>
 
 <li> <b>KernelFilteredSource</b>: This is a pixel source derived from the
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index c7dc873..0906c39 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 25769 2013-03-19 07:50:17Z antonio $
+ * $Id: vrtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: vrtdataset.cpp 25769 2013-03-19 07:50:17Z antonio $");
+CPL_CVSID("$Id: vrtdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -58,7 +59,7 @@ VRTDataset::VRTDataset( int nXSize, int nYSize )
 
     nGCPCount = 0;
     pasGCPList = NULL;
-    pszGCPProjection = CPLStrdup("");
+    pszGCPProjection = NULL;
 
     pszVRTPath = NULL;
 
@@ -230,51 +231,10 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
  /* -------------------------------------------------------------------- */
     if( nGCPCount > 0 )
     {
-        CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
-                                                  "GCPList" );
-
-        CPLXMLNode* psLastChild = NULL;
-
-        if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 )
-        {
-            CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection );
-            psLastChild = psGCPList->psChild;
-        }
-
-        for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
-        {
-            CPLXMLNode *psXMLGCP;
-            GDAL_GCP *psGCP = pasGCPList + iGCP;
-
-            psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
-
-            if( psLastChild == NULL )
-                psGCPList->psChild = psXMLGCP;
-            else
-                psLastChild->psNext = psXMLGCP;
-            psLastChild = psXMLGCP;
-
-            CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
-
-            if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
-                CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
-
-            CPLSetXMLValue( psXMLGCP, "#Pixel", 
-                            CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Line", 
-                            CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
-
-            CPLSetXMLValue( psXMLGCP, "#X", 
-                            CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Y", 
-                            CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
-
-            if( psGCP->dfGCPZ != 0.0 )
-                CPLSetXMLValue( psXMLGCP, "#GCPZ", 
-                                CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
-        }
+        GDALSerializeGCPListToXML( psDSTree,
+                                   pasGCPList,
+                                   nGCPCount,
+                                   pszGCPProjection );
     }
 
     /* -------------------------------------------------------------------- */
@@ -380,55 +340,12 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 
     if( psGCPList != NULL )
     {
-        CPLXMLNode *psXMLGCP;
-        OGRSpatialReference oSRS;
-        const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
-
-        CPLFree( pszGCPProjection );
-
-        if( strlen(pszRawProj) > 0 
-            && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
-            oSRS.exportToWkt( &pszGCPProjection );
-        else
-            pszGCPProjection = CPLStrdup("");
-
-        // Count GCPs.
-        int  nGCPMax = 0;
-         
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-            nGCPMax++;
-         
-        pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
-         
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-        {
-            GDAL_GCP *psGCP = pasGCPList + nGCPCount;
-
-            if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
-                psXMLGCP->eType != CXT_Element )
-                continue;
-             
-            GDALInitGCPs( 1, psGCP );
-             
-            CPLFree( psGCP->pszId );
-            psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
-             
-            CPLFree( psGCP->pszInfo );
-            psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
-             
-            psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
-            psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
-             
-            psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
-            psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
-            psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
-
-            nGCPCount++;
-        }
+        GDALDeserializeGCPListFromXML( psGCPList,
+                                       &pasGCPList,
+                                       &nGCPCount,
+                                       &pszGCPProjection );
     }
-     
+
 /* -------------------------------------------------------------------- */
 /*      Apply any dataset level metadata.                               */
 /* -------------------------------------------------------------------- */
@@ -542,7 +459,10 @@ int VRTDataset::GetGCPCount()
 const char *VRTDataset::GetGCPProjection()
 
 {
-    return pszGCPProjection;
+    if( pszGCPProjection == NULL )
+        return "";
+    else
+        return pszGCPProjection;
 }
 
 /************************************************************************/
@@ -923,7 +843,8 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 /*      Collect required information.                                   */
 /* -------------------------------------------------------------------- */
         if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
-            nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));
+            nImageOffset = CPLScanUIntBig(
+                CSLFetchNameValue(papszOptions, "ImageOffset"), 20);
 
         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
@@ -1360,7 +1281,7 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
     {
         bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
     }
-    if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
+    if (bCompatibleForDatasetIO && eRWFlag == GF_Read)
     {
         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
         {
diff --git a/frmts/vrt/vrtdataset.h b/frmts/vrt/vrtdataset.h
index be0dcf1..766fb13 100644
--- a/frmts/vrt/vrtdataset.h
+++ b/frmts/vrt/vrtdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.h 25569 2013-01-26 22:32:26Z rouault $
+ * $Id: vrtdataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Declaration of virtual gdal dataset classes.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -71,7 +72,7 @@ public:
 /*                              VRTSource                               */
 /************************************************************************/
 
-class VRTSource 
+class CPL_DLL VRTSource 
 {
 public:
     virtual ~VRTSource();
@@ -348,6 +349,8 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
 /*                         VRTSourcedRasterBand                         */
 /************************************************************************/
 
+class VRTSimpleSource;
+
 class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
 {
   private:
@@ -374,6 +377,7 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
                               void *, int, int, GDALDataType,
                               int, int );
 
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
     virtual char      **GetMetadata( const char * pszDomain = "" );
@@ -425,6 +429,13 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     CPLErr         AddFuncSource( VRTImageReadFunc pfnReadFunc, void *hCBData,
                                   double dfNoDataValue = VRT_NODATA_UNSET );
 
+    void           ConfigureSource(VRTSimpleSource *poSimpleSource,
+                                           GDALRasterBand *poSrcBand,
+                                           int bAddAsMaskBand,
+                                           int nSrcXOff, int nSrcYOff,
+                                           int nSrcXSize, int nSrcYSize,
+                                           int nDstXOff, int nDstYOff,
+                                           int nDstXSize, int nDstYSize);
 
     virtual CPLErr IReadBlock( int, int, void * );
     
@@ -544,6 +555,7 @@ class VRTDriver : public GDALDriver
 
     char         **papszSourceParsers;
 
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr      SetMetadata( char ** papszMetadata,
                                      const char * pszDomain = "" );
@@ -557,7 +569,7 @@ class VRTDriver : public GDALDriver
 /*                           VRTSimpleSource                            */
 /************************************************************************/
 
-class VRTSimpleSource : public VRTSource
+class CPL_DLL VRTSimpleSource : public VRTSource
 {
 protected:
     GDALRasterBand      *poRasterBand;
@@ -671,9 +683,30 @@ public:
 /*                           VRTComplexSource                           */
 /************************************************************************/
 
-class VRTComplexSource : public VRTSimpleSource
+typedef enum
+{
+    VRT_SCALING_NONE,
+    VRT_SCALING_LINEAR,
+    VRT_SCALING_EXPONENTIAL,
+} VRTComplexSourceScaling;
+
+class CPL_DLL VRTComplexSource : public VRTSimpleSource
 {
 protected:
+    VRTComplexSourceScaling eScalingType;
+    double         dfScaleOff; /* for linear scaling */
+    double         dfScaleRatio; /* for linear scaling */
+
+    /* For non-linear scaling with a power function. */
+    int            bSrcMinMaxDefined;
+    double         dfSrcMin;
+    double         dfSrcMax;
+    double         dfDstMin;
+    double         dfDstMax;
+    double         dfExponent;
+
+    int            nColorTableComponent;
+
     CPLErr          RasterIOInternal( int nReqXOff, int nReqYOff,
                                       int nReqXSize, int nReqYSize,
                                       void *pData, int nOutXSize, int nOutYSize,
@@ -708,14 +741,19 @@ public:
     virtual const char* GetType() { return "ComplexSource"; }
 
     double  LookupValue( double dfInput );
+    
+    void    SetLinearScaling(double dfOffset, double dfScale);
+    void    SetPowerScaling(double dfExponent,
+                            double dfSrcMin,
+                            double dfSrcMax,
+                            double dfDstMin,
+                            double dfDstMax);
+    void    SetColorTableComponent(int nComponent);
 
-    int            bDoScaling;
-    double         dfScaleOff;
-    double         dfScaleRatio;
     double         *padfLUTInputs;
     double         *padfLUTOutputs;
     int            nLUTItemCount;
-    int            nColorTableComponent;
+
 };
 
 /************************************************************************/
diff --git a/frmts/vrt/vrtderivedrasterband.cpp b/frmts/vrt/vrtderivedrasterband.cpp
index 73f6905..3c2e80d 100644
--- a/frmts/vrt/vrtderivedrasterband.cpp
+++ b/frmts/vrt/vrtderivedrasterband.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005 Vexcel Corp.
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/vrt/vrtdriver.cpp b/frmts/vrt/vrtdriver.cpp
index 51c3197..07d4bc2 100644
--- a/frmts/vrt/vrtdriver.cpp
+++ b/frmts/vrt/vrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $
+ * $Id: vrtdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDriver
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "gdal_alg_priv.h"
 
-CPL_CVSID("$Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $");
+CPL_CVSID("$Id: vrtdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                             VRTDriver()                              */
@@ -63,6 +64,17 @@ VRTDriver::~VRTDriver()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **VRTDriver::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDriver::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SourceParsers", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/frmts/vrt/vrtfilters.cpp b/frmts/vrt/vrtfilters.cpp
index 3db4f59..dbbb7aa 100644
--- a/frmts/vrt/vrtfilters.cpp
+++ b/frmts/vrt/vrtfilters.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtfilters.cpp 24530 2012-06-02 16:28:14Z rouault $
+ * $Id: vrtfilters.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of some filter types.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtfilters.cpp 24530 2012-06-02 16:28:14Z rouault $");
+CPL_CVSID("$Id: vrtfilters.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -79,11 +80,11 @@ void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount,
 
 {
     if( nTypeCount > 
-        (int) sizeof(sizeof(aeSupportedTypes)/sizeof(GDALDataType)) )
+        (int) (sizeof(aeSupportedTypes)/sizeof(GDALDataType)) )
     {
         CPLAssert( FALSE );
         nTypeCount = (int) 
-            sizeof(sizeof(aeSupportedTypes)/sizeof(GDALDataType));
+            (sizeof(aeSupportedTypes)/sizeof(GDALDataType));
     }
 
     nSupportedTypesCount = nTypeCount;
diff --git a/frmts/vrt/vrtrasterband.cpp b/frmts/vrt/vrtrasterband.cpp
index e58d54b..62c4c65 100644
--- a/frmts/vrt/vrtrasterband.cpp
+++ b/frmts/vrt/vrtrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrasterband.cpp 25873 2013-04-07 11:06:58Z rouault $
+ * $Id: vrtrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRasterBand
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtrasterband.cpp 25873 2013-04-07 11:06:58Z rouault $");
+CPL_CVSID("$Id: vrtrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/vrt/vrtrawrasterband.cpp b/frmts/vrt/vrtrawrasterband.cpp
index ecfb2bd..e6136d1 100644
--- a/frmts/vrt/vrtrawrasterband.cpp
+++ b/frmts/vrt/vrtrawrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrawrasterband.cpp 25567 2013-01-26 21:55:28Z rouault $
+ * $Id: vrtrawrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRawRasterBand
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: vrtrawrasterband.cpp 25567 2013-01-26 21:55:28Z rouault $");
+CPL_CVSID("$Id: vrtrawrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -331,7 +332,8 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
     int nPixelOffset, nLineOffset;
     int nWordDataSize = GDALGetDataTypeSize( GetRasterDataType() ) / 8;
 
-    nImageOffset = atoi(CPLGetXMLValue( psTree, "ImageOffset", "0") );
+    nImageOffset = CPLScanUIntBig(
+        CPLGetXMLValue( psTree, "ImageOffset", "0"), 20);
 
     if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) == NULL )
         nPixelOffset = nWordDataSize;
@@ -403,17 +405,16 @@ CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Set other layout information.                                   */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "ImageOffset", 
-        CPLSPrintf("%d",(int) poRawRaster->GetImgOffset()) );
+    char szOffset[22];
     
-    CPLCreateXMLElementAndValue( 
-        psTree, "PixelOffset", 
-        CPLSPrintf("%d",(int) poRawRaster->GetPixelOffset()) );
+    CPLPrintUIntBig(szOffset, poRawRaster->GetImgOffset(), sizeof(szOffset)-1);
+    CPLCreateXMLElementAndValue(psTree, "ImageOffset", szOffset);
     
-    CPLCreateXMLElementAndValue( 
-        psTree, "LineOffset", 
-        CPLSPrintf("%d",(int) poRawRaster->GetLineOffset()) );
+    CPLPrintUIntBig(szOffset, poRawRaster->GetPixelOffset(),sizeof(szOffset)-1);
+    CPLCreateXMLElementAndValue(psTree, "PixelOffset", szOffset);
+    
+    CPLPrintUIntBig(szOffset, poRawRaster->GetLineOffset(), sizeof(szOffset)-1);
+    CPLCreateXMLElementAndValue(psTree, "LineOffset", szOffset);
 
 #if CPL_IS_LSB == 1
     if( poRawRaster->GetNativeOrder() )
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index d099735..4ccbb2c 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 26091 2013-06-18 19:24:25Z rouault $
+ * $Id: vrtsourcedrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 26091 2013-06-18 19:24:25Z rouault $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -693,17 +694,16 @@ CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 }
 
 /************************************************************************/
-/*                          AddSimpleSource()                           */
+/*                          ConfigureSource()                           */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand, 
-                                       int nSrcXOff, int nSrcYOff, 
-                                       int nSrcXSize, int nSrcYSize, 
-                                       int nDstXOff, int nDstYOff, 
-                                       int nDstXSize, int nDstYSize,
-                                       const char *pszResampling, 
-                                       double dfNoDataValue )
-
+void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
+                                           GDALRasterBand *poSrcBand,
+                                           int bAddAsMaskBand,
+                                           int nSrcXOff, int nSrcYOff,
+                                           int nSrcXSize, int nSrcYSize,
+                                           int nDstXOff, int nDstYOff,
+                                           int nDstXSize, int nDstYSize)
 {
 /* -------------------------------------------------------------------- */
 /*      Default source and dest rectangles.                             */
@@ -724,6 +724,41 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
         nDstYSize = nRasterYSize;
     }
 
+    if( bAddAsMaskBand )
+        poSimpleSource->SetSrcMaskBand( poSrcBand );
+    else
+        poSimpleSource->SetSrcBand( poSrcBand );
+    poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
+    poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+
+/* -------------------------------------------------------------------- */
+/*      Default source and dest rectangles.                             */
+/* -------------------------------------------------------------------- */
+    if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
+         nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
+        bEqualAreas = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      If we can get the associated GDALDataset, add a reference to it.*/
+/* -------------------------------------------------------------------- */
+    if( poSrcBand->GetDataset() != NULL )
+        poSrcBand->GetDataset()->Reference();
+
+}
+
+/************************************************************************/
+/*                          AddSimpleSource()                           */
+/************************************************************************/
+
+CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand, 
+                                       int nSrcXOff, int nSrcYOff, 
+                                       int nSrcXSize, int nSrcYSize, 
+                                       int nDstXOff, int nDstYOff, 
+                                       int nDstXSize, int nDstYSize,
+                                       const char *pszResampling, 
+                                       double dfNoDataValue )
+
+{
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
@@ -741,27 +776,18 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
                 "neighbour sampled simple sources on Virtual Datasources." );
     }
 
-    poSimpleSource->SetSrcBand( poSrcBand );
-    poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
-    poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+    ConfigureSource(poSimpleSource,
+                    poSrcBand,
+                    FALSE,
+                    nSrcXOff, nSrcYOff,
+                    nSrcXSize, nSrcYSize,
+                    nDstXOff, nDstYOff,
+                    nDstXSize, nDstYSize);
 
     if( dfNoDataValue != VRT_NODATA_UNSET )
         poSimpleSource->SetNoDataValue( dfNoDataValue );
 
 /* -------------------------------------------------------------------- */
-/*      Default source and dest rectangles.                             */
-/* -------------------------------------------------------------------- */
-    if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
-         nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
-        bEqualAreas = TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      If we can get the associated GDALDataset, add a reference to it.*/
-/* -------------------------------------------------------------------- */
-    if( poSrcBand->GetDataset() != NULL )
-        poSrcBand->GetDataset()->Reference();
-
-/* -------------------------------------------------------------------- */
 /*      add to list.                                                    */
 /* -------------------------------------------------------------------- */
     return AddSource( poSimpleSource );
@@ -779,44 +805,17 @@ CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
                                                 int nDstXSize, int nDstYSize )
 {
 /* -------------------------------------------------------------------- */
-/*      Default source and dest rectangles.                             */
-/* -------------------------------------------------------------------- */
-    if( nSrcYSize == -1 )
-    {
-        nSrcXOff = 0;
-        nSrcYOff = 0;
-        nSrcXSize = poSrcBand->GetXSize();
-        nSrcYSize = poSrcBand->GetYSize();
-    }
-
-    if( nDstYSize == -1 )
-    {
-        nDstXOff = 0;
-        nDstYOff = 0;
-        nDstXSize = nRasterXSize;
-        nDstYSize = nRasterYSize;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
     VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
-    poSimpleSource->SetSrcMaskBand( poSrcBand );
-    poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
-    poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 
-/* -------------------------------------------------------------------- */
-/*      Default source and dest rectangles.                             */
-/* -------------------------------------------------------------------- */
-    if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
-         nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
-        bEqualAreas = TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      If we can get the associated GDALDataset, add a reference to it.*/
-/* -------------------------------------------------------------------- */
-    if( poSrcBand->GetDataset() != NULL )
-        poSrcBand->GetDataset()->Reference();
+    ConfigureSource(poSimpleSource,
+                    poSrcBand,
+                    TRUE,
+                    nSrcXOff, nSrcYOff,
+                    nSrcXSize, nSrcYSize,
+                    nDstXOff, nDstYOff,
+                    nDstXSize, nDstYSize);
 
 /* -------------------------------------------------------------------- */
 /*      add to list.                                                    */
@@ -868,34 +867,19 @@ CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Default source and dest rectangles.                             */
-/* -------------------------------------------------------------------- */
-    if( nSrcYSize == -1 )
-    {
-        nSrcXOff = 0;
-        nSrcYOff = 0;
-        nSrcXSize = poSrcBand->GetXSize();
-        nSrcYSize = poSrcBand->GetYSize();
-    }
-
-    if( nDstYSize == -1 )
-    {
-        nDstXOff = 0;
-        nDstYOff = 0;
-        nDstXSize = nRasterXSize;
-        nDstYSize = nRasterYSize;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
     VRTComplexSource *poSource;
 
     poSource = new VRTComplexSource();
 
-    poSource->SetSrcBand( poSrcBand );
-    poSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
-    poSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+    ConfigureSource(poSource,
+                    poSrcBand,
+                    FALSE,
+                    nSrcXOff, nSrcYOff,
+                    nSrcXSize, nSrcYSize,
+                    nDstXOff, nDstYOff,
+                    nDstXSize, nDstYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Set complex parameters.                                         */
@@ -904,20 +888,9 @@ CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
         poSource->SetNoDataValue( dfNoDataValue );
 
     if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
-    {
-        poSource->bDoScaling = TRUE;
-        poSource->dfScaleOff = dfScaleOff;
-        poSource->dfScaleRatio = dfScaleRatio;
-          
-    }
+        poSource->SetLinearScaling(dfScaleOff, dfScaleRatio);
 
-    poSource->nColorTableComponent = nColorTableComponent;
-
-/* -------------------------------------------------------------------- */
-/*      If we can get the associated GDALDataset, add a reference to it.*/
-/* -------------------------------------------------------------------- */
-    if( poSrcBand->GetDataset() != NULL )
-        poSrcBand->GetDataset()->Reference();
+    poSource->SetColorTableComponent(nColorTableComponent);
 
 /* -------------------------------------------------------------------- */
 /*      add to list.                                                    */
@@ -999,6 +972,16 @@ CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
 
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **VRTSourcedRasterBand::GetMetadataDomainList()
+{
+    return CSLAddString(GDALRasterBand::GetMetadataDomainList(), "LocationInfo");
+}
+
+
+/************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index 3fe898b..460c089 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $
+ * $Id: vrtsources.cpp 27080 2014-03-23 00:26:43Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 27080 2014-03-23 00:26:43Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -175,6 +176,14 @@ void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
+static const char* apszSpecialSyntax[] = { "HDF5:\"{FILENAME}\":{ANY}",
+                                            "HDF5:{FILENAME}:{ANY}",
+                                            "NETCDF:\"{FILENAME}\":{ANY}",
+                                            "NETCDF:{FILENAME}:{ANY}",
+                                            "NITF_IM:{ANY}:{FILENAME}",
+                                            "PDF:{ANY}:{FILENAME}",
+                                            "RASTERLITE:{FILENAME},{ANY}" };
+
 CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
 
 {
@@ -204,6 +213,7 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
 
     VSIStatBufL sStat;
+    CPLString osTmp;
     if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
          strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
     {
@@ -221,6 +231,52 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     {
         pszRelativePath = poDS->GetDescription();
         bRelativeToVRT = FALSE;
+        for( size_t i = 0; i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]); i ++)
+        {
+            const char* pszSyntax = apszSpecialSyntax[i];
+            CPLString osPrefix(pszSyntax);
+            osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
+            if( pszSyntax[osPrefix.size()] == '"' )
+                osPrefix += '"';
+            if( EQUALN(pszRelativePath, osPrefix, osPrefix.size()) )
+            {
+                if( EQUALN(pszSyntax + osPrefix.size(), "{ANY}", strlen("{ANY}")) )
+                {
+                    const char* pszLastPart = strrchr(pszRelativePath, ':') + 1;
+                    /* CSV:z:/foo.xyz */
+                    if( (pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
+                        pszLastPart - pszRelativePath >= 3 && pszLastPart[-3] == ':' )
+                        pszLastPart -= 2;
+                    CPLString osPrefixFilename = pszRelativePath;
+                    osPrefixFilename.resize(pszLastPart - pszRelativePath);
+                    pszRelativePath =
+                        CPLExtractRelativePath( pszVRTPath, pszLastPart,
+                                    &bRelativeToVRT );
+                    osTmp = osPrefixFilename + pszRelativePath;
+                    pszRelativePath = osTmp.c_str();
+                }
+                else if( EQUALN(pszSyntax + osPrefix.size(), "{FILENAME}", strlen("{FILENAME}")) )
+                {
+                    CPLString osFilename(pszRelativePath + osPrefix.size());
+                    size_t nPos = 0;
+                    if( osFilename.size() >= 3 && osFilename[1] == ':' &&
+                        (osFilename[2] == '\\' || osFilename[2] == '/') )
+                        nPos = 2;
+                    nPos = osFilename.find(pszSyntax[osPrefix.size() + strlen("{FILENAME}")], nPos);
+                    if( nPos != std::string::npos )
+                    {
+                        CPLString osSuffix = osFilename.substr(nPos);
+                        osFilename.resize(nPos);
+                        pszRelativePath =
+                            CPLExtractRelativePath( pszVRTPath, osFilename,
+                                        &bRelativeToVRT );
+                        osTmp = osPrefix + pszRelativePath + osSuffix;
+                        pszRelativePath = osTmp.c_str();
+                    }
+                }
+                break;
+            }
+        }
     }
     else
     {
@@ -312,8 +368,54 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     if( pszVRTPath != NULL
         && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
     {
-        pszSrcDSName = CPLStrdup(
-            CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
+        int bDone = FALSE;
+        for( size_t i = 0; i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]); i ++)
+        {
+            const char* pszSyntax = apszSpecialSyntax[i];
+            CPLString osPrefix(pszSyntax);
+            osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
+            if( pszSyntax[osPrefix.size()] == '"' )
+                osPrefix += '"';
+            if( EQUALN(pszFilename, osPrefix, osPrefix.size()) )
+            {
+                if( EQUALN(pszSyntax + osPrefix.size(), "{ANY}", strlen("{ANY}")) )
+                {
+                    const char* pszLastPart = strrchr(pszFilename, ':') + 1;
+                    /* CSV:z:/foo.xyz */
+                    if( (pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
+                        pszLastPart - pszFilename >= 3 && pszLastPart[-3] == ':' )
+                        pszLastPart -= 2;
+                    CPLString osPrefixFilename = pszFilename;
+                    osPrefixFilename.resize(pszLastPart - pszFilename);
+                    pszSrcDSName = CPLStrdup( (osPrefixFilename +
+                        CPLProjectRelativeFilename( pszVRTPath, pszLastPart )).c_str() );
+                    bDone = TRUE;
+                }
+                else if( EQUALN(pszSyntax + osPrefix.size(), "{FILENAME}", strlen("{FILENAME}")) )
+                {
+                    CPLString osFilename(pszFilename + osPrefix.size());
+                    size_t nPos = 0;
+                    if( osFilename.size() >= 3 && osFilename[1] == ':' &&
+                        (osFilename[2] == '\\' || osFilename[2] == '/') )
+                        nPos = 2;
+                    nPos = osFilename.find(pszSyntax[osPrefix.size() + strlen("{FILENAME}")], nPos);
+                    if( nPos != std::string::npos )
+                    {
+                        CPLString osSuffix = osFilename.substr(nPos);
+                        osFilename.resize(nPos);
+                        pszSrcDSName = CPLStrdup( (osPrefix +
+                            CPLProjectRelativeFilename( pszVRTPath, osFilename ) + osSuffix).c_str() );
+                        bDone = TRUE;
+                    }
+                }
+                break;
+            }
+        }
+        if( !bDone )
+        {
+            pszSrcDSName = CPLStrdup(
+                CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
+        }
     }
     else
         pszSrcDSName = CPLStrdup( pszFilename );
@@ -1255,7 +1357,7 @@ CPLErr VRTAveragedSource::GetHistogram( int nXSize, int nYSize,
 VRTComplexSource::VRTComplexSource()
 
 {
-    bDoScaling = FALSE;
+    eScalingType = VRT_SCALING_NONE;
     dfScaleOff = 0.0;
     dfScaleRatio = 1.0;
     
@@ -1266,6 +1368,13 @@ VRTComplexSource::VRTComplexSource()
     padfLUTOutputs = NULL;
     nLUTItemCount = 0;
     nColorTableComponent = 0;
+
+    bSrcMinMaxDefined = FALSE;
+    dfSrcMin = 0.0;
+    dfSrcMax = 0.0;
+    dfDstMin = 0.0;
+    dfDstMax = 0.0;
+    dfExponent = 1.0;
 }
 
 VRTComplexSource::~VRTComplexSource()
@@ -1300,12 +1409,34 @@ CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
                             CPLSPrintf("%g", dfNoDataValue) );
     }
         
-    if( bDoScaling )
+    switch( eScalingType )
     {
-        CPLSetXMLValue( psSrc, "ScaleOffset", 
-                        CPLSPrintf("%g", dfScaleOff) );
-        CPLSetXMLValue( psSrc, "ScaleRatio", 
-                        CPLSPrintf("%g", dfScaleRatio) );
+        case VRT_SCALING_NONE:
+            break;
+
+        case VRT_SCALING_LINEAR:
+        {
+            CPLSetXMLValue( psSrc, "ScaleOffset", 
+                            CPLSPrintf("%g", dfScaleOff) );
+            CPLSetXMLValue( psSrc, "ScaleRatio", 
+                            CPLSPrintf("%g", dfScaleRatio) );
+            break;
+        }
+
+        case VRT_SCALING_EXPONENTIAL:
+        {
+            CPLSetXMLValue( psSrc, "Exponent", 
+                            CPLSPrintf("%g", dfExponent) );
+            CPLSetXMLValue( psSrc, "SrcMin", 
+                            CPLSPrintf("%g", dfSrcMin) );
+            CPLSetXMLValue( psSrc, "SrcMax", 
+                            CPLSPrintf("%g", dfSrcMax) );
+            CPLSetXMLValue( psSrc, "DstMin", 
+                            CPLSPrintf("%g", dfDstMin) );
+            CPLSetXMLValue( psSrc, "DstMax", 
+                            CPLSPrintf("%g", dfDstMax) );
+            break;
+        }
     }
 
     if ( nLUTItemCount )
@@ -1348,10 +1479,28 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
     {
-        bDoScaling = TRUE;
+        eScalingType = VRT_SCALING_LINEAR;
         dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
         dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
     }
+    else if( CPLGetXMLValue(psSrc, "Exponent", NULL) != NULL &&
+             CPLGetXMLValue(psSrc, "DstMin", NULL) != NULL && 
+             CPLGetXMLValue(psSrc, "DstMax", NULL) != NULL )
+    {
+        eScalingType = VRT_SCALING_EXPONENTIAL;
+        dfExponent = atof(CPLGetXMLValue(psSrc, "Exponent", "1.0") );
+
+        if( CPLGetXMLValue(psSrc, "SrcMin", NULL) != NULL 
+         && CPLGetXMLValue(psSrc, "SrcMax", NULL) != NULL )
+        {
+            dfSrcMin = atof(CPLGetXMLValue(psSrc, "SrcMin", "0.0") );
+            dfSrcMax = atof(CPLGetXMLValue(psSrc, "SrcMax", "0.0") );
+            bSrcMinMaxDefined = TRUE;
+        }
+
+        dfDstMin = atof(CPLGetXMLValue(psSrc, "DstMin", "0.0") );
+        dfDstMax = atof(CPLGetXMLValue(psSrc, "DstMax", "0.0") );
+    }
 
     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
     {
@@ -1456,6 +1605,45 @@ VRTComplexSource::LookupValue( double dfInput )
 }
 
 /************************************************************************/
+/*                         SetLinearScaling()                           */
+/************************************************************************/
+
+void VRTComplexSource::SetLinearScaling(double dfOffset, double dfScale)
+{
+    eScalingType = VRT_SCALING_LINEAR;
+    dfScaleOff = dfOffset;
+    dfScaleRatio = dfScale;
+}
+
+/************************************************************************/
+/*                         SetPowerScaling()                           */
+/************************************************************************/
+
+void VRTComplexSource::SetPowerScaling(double dfExponent,
+                                       double dfSrcMin,
+                                       double dfSrcMax,
+                                       double dfDstMin,
+                                       double dfDstMax)
+{
+    eScalingType = VRT_SCALING_EXPONENTIAL;
+    this->dfExponent = dfExponent;
+    this->dfSrcMin = dfSrcMin;
+    this->dfSrcMax = dfSrcMax;
+    this->dfDstMin = dfDstMin;
+    this->dfDstMax = dfDstMax;
+    bSrcMinMaxDefined = TRUE;
+}
+
+/************************************************************************/
+/*                    SetColorTableComponent()                          */
+/************************************************************************/
+
+void VRTComplexSource::SetColorTableComponent(int nComponent)
+{
+    nColorTableComponent = nComponent;
+}
+
+/************************************************************************/
 /*                              RasterIO()                              */
 /************************************************************************/
 
@@ -1509,7 +1697,7 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
     int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
     int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
 
-    if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
+    if( eScalingType == VRT_SCALING_LINEAR && bNoDataSet == FALSE && dfScaleRatio == 0)
     {
 /* -------------------------------------------------------------------- */
 /*      Optimization when outputing a constant value                    */
@@ -1599,8 +1787,39 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                     }
                 }
 
-                if( bDoScaling )
+                if( eScalingType == VRT_SCALING_LINEAR )
                     fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
+                else if( eScalingType == VRT_SCALING_EXPONENTIAL )
+                {
+                    if( !bSrcMinMaxDefined )
+                    {
+                        int bSuccessMin = FALSE, bSuccessMax = FALSE;
+                        double adfMinMax[2];
+                        adfMinMax[0] = poRasterBand->GetMinimum(&bSuccessMin);
+                        adfMinMax[1] = poRasterBand->GetMaximum(&bSuccessMax);
+                        if( (bSuccessMin && bSuccessMax) ||
+                            poRasterBand->ComputeRasterMinMax( TRUE, adfMinMax ) == CE_None )
+                        {
+                            dfSrcMin = adfMinMax[0];
+                            dfSrcMax = adfMinMax[1];
+                            bSrcMinMaxDefined = TRUE;
+                        }
+                        else
+                        {
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                    "Cannot determine source min/max value");
+                            return CE_Failure;
+                        }
+                    }
+
+                    double dfPowVal =
+                        (fResult - dfSrcMin) / (dfSrcMax - dfSrcMin);
+                    if( dfPowVal < 0.0 )
+                        dfPowVal = 0.0;
+                    else if( dfPowVal > 1.0 )
+                        dfPowVal = 1.0;
+                    fResult = (float) (dfDstMax - dfDstMin) * pow( dfPowVal, dfExponent ) + dfDstMin;
+                }
 
                 if (nLUTItemCount)
                     fResult = (float) LookupValue( fResult );
@@ -1619,7 +1838,7 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 
                 /* Do not use color table */
 
-                if( bDoScaling )
+                if( eScalingType == VRT_SCALING_LINEAR )
                 {
                     afResult[0] = (float) (afResult[0] * dfScaleRatio + dfScaleOff);
                     afResult[1] = (float) (afResult[1] * dfScaleRatio + dfScaleOff);
diff --git a/frmts/vrt/vrtwarped.cpp b/frmts/vrt/vrtwarped.cpp
index 7efac2e..d20b77e 100644
--- a/frmts/vrt/vrtwarped.cpp
+++ b/frmts/vrt/vrtwarped.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtwarped.cpp 25884 2013-04-09 17:04:16Z etourigny $
+ * $Id: vrtwarped.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTWarpedRasterBand *and VRTWarpedDataset.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "gdal_alg_priv.h"
 #include <cassert>
 
-CPL_CVSID("$Id: vrtwarped.cpp 25884 2013-04-09 17:04:16Z etourigny $");
+CPL_CVSID("$Id: vrtwarped.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      GDALAutoCreateWarpedVRT()                       */
@@ -146,6 +147,12 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
         GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer, 
                                  psWO->pTransformerArg, 
                                  adfDstGeoTransform, &nDstPixels, &nDstLines );
+    if( eErr != CE_None )
+    {
+        GDALDestroyTransformer( psWO->pTransformerArg );
+        GDALDestroyWarpOptions( psWO );
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Update the transformer to include an output geotransform        */
@@ -1022,16 +1029,21 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
 /*      the VRT file if possible.  Adjust accordingly.                  */
 /* -------------------------------------------------------------------- */
         CPLXMLNode *psSDS = CPLGetXMLNode( psWOTree, "SourceDataset" );
-        int bRelativeToVRT;
-        char *pszRelativePath;
+        int bRelativeToVRT = FALSE;
+        VSIStatBufL  sStat;
 
-        pszRelativePath = 
-            CPLStrdup(
+        if( VSIStatExL( psSDS->psChild->pszValue, &sStat, 
+                        VSI_STAT_EXISTS_FLAG) == 0 ) 
+        {
+            char *pszRelativePath;
+        
+            pszRelativePath = CPLStrdup(
                 CPLExtractRelativePath( pszVRTPath, psSDS->psChild->pszValue, 
                                         &bRelativeToVRT ) );
 
-        CPLFree( psSDS->psChild->pszValue );
-        psSDS->psChild->pszValue = pszRelativePath;
+            CPLFree( psSDS->psChild->pszValue );
+            psSDS->psChild->pszValue = pszRelativePath;
+        }
 
         CPLCreateXMLNode( 
             CPLCreateXMLNode( psSDS, CXT_Attribute, "relativeToVRT" ), 
diff --git a/frmts/wcs/httpdriver.cpp b/frmts/wcs/httpdriver.cpp
index 6cda68d..74ee381 100644
--- a/frmts/wcs/httpdriver.cpp
+++ b/frmts/wcs/httpdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wcsdataset.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: httpdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of an HTTP fetching driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_http.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: wcsdataset.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: httpdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /************************************************************************/
@@ -139,8 +140,11 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening this result as a gdaldataset.                       */
 /* -------------------------------------------------------------------- */
+    /* suppress errors as not all drivers support /vsimem */
+    CPLPushErrorHandler( CPLQuietErrorHandler );
     GDALDataset *poDS = (GDALDataset *) 
         GDALOpen( osResultFilename, GA_ReadOnly );
+    CPLPopErrorHandler();
 
 /* -------------------------------------------------------------------- */
 /*      If opening it in memory didn't work, perhaps we need to         */
diff --git a/frmts/wcs/wcsdataset.cpp b/frmts/wcs/wcsdataset.cpp
index 50f1a23..9f2bf08 100644
--- a/frmts/wcs/wcsdataset.cpp
+++ b/frmts/wcs/wcsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wcsdataset.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: wcsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WCS.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_http.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: wcsdataset.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+CPL_CVSID("$Id: wcsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -106,6 +107,7 @@ class CPL_DLL WCSDataset : public GDALPamDataset
     virtual const char *GetProjectionRef(void);
     virtual char **GetFileList(void);
 
+    virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char *pszDomain );
 };
 
@@ -391,6 +393,7 @@ CPLErr WCSRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 double WCSRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
+    CPLLocaleC  oLocaleEnforcer;
     const char *pszSV = CPLGetXMLValue( poODS->psService, "NoDataValue", NULL);
 
     if( pszSV == NULL )
@@ -945,6 +948,7 @@ int WCSDataset::DescribeCoverage()
 int WCSDataset::ExtractGridInfo100()
 
 {
+    CPLLocaleC  oLocaleEnforcer; 
     CPLXMLNode * psCO = CPLGetXMLNode( psService, "CoverageOffering" );
 
     if( psCO == NULL )
@@ -1274,6 +1278,7 @@ static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,
                              double &dfUpperX, double &dfUpperY )
 
 {
+    CPLLocaleC  oLocaleEnforcer; 
     int nRet = TRUE;
 
     osCRS = CPLGetXMLValue( psBoundingBox, "crs", "" );
@@ -1311,6 +1316,8 @@ static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,
 int WCSDataset::ExtractGridInfo()
 
 {
+    CPLLocaleC  oLocaleEnforcer; 
+
     if( nVersion == 100 )
         return ExtractGridInfo100();
 
@@ -2337,6 +2344,17 @@ char **WCSDataset::GetFileList()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **WCSDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:CoverageOffering", NULL);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/frmts/webp/frmt_webp.html b/frmts/webp/frmt_webp.html
index 23491bf..7f36fc6 100644
--- a/frmts/webp/frmt_webp.html
+++ b/frmts/webp/frmt_webp.html
@@ -16,7 +16,7 @@ A WebP file consists of VP8 image data, and a container based on RIFF.</p>
 
 <p>The driver rely on the Open Source WebP library (BSD licenced). The WebP library (at least in its
 version 0.1) only offers compression and decompression of whole images, so RAM might be a limitation
-when dealing with big images.</p>
+when dealing with big images (which are limited to 16383x16383 pixels).</p>
 
 <p>The WEBP driver supports 3 bands (RGB) images. It also supports 4 bands (RGBA) starting with GDAL 1.10 and libwebp 0.1.4.</p>
 
@@ -44,7 +44,7 @@ lossless compression will be used.<p></li>
 <p>See Also:</p>
 
 <ul>
-<li><a href="http://code.google.com/intl/fr/speed/webp/">WebP home page</a></li>
+<li><a href="https://developers.google.com/speed/webp/">WebP home page</a></li>
 </ul>
 
 </body>
diff --git a/frmts/webp/webpdataset.cpp b/frmts/webp/webpdataset.cpp
index 354aab9..050f7c0 100644
--- a/frmts/webp/webpdataset.cpp
+++ b/frmts/webp/webpdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: webpdataset.cpp 25570 2013-01-27 00:22:37Z rouault $
+ * $Id: webpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL WEBP Driver
  * Purpose:  Implement GDAL WEBP Support based on libwebp
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "webp/decode.h"
 #include "webp/encode.h"
 
-CPL_CVSID("$Id: webpdataset.cpp 25570 2013-01-27 00:22:37Z rouault $");
+CPL_CVSID("$Id: webpdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_WEBP(void);
@@ -67,6 +67,7 @@ class WEBPDataset : public GDALPamDataset
                                    void *, int, int, GDALDataType,
                                    int, int *, int, int, int );
 
+    virtual char      **GetMetadataDomainList();
     virtual char  **GetMetadata( const char * pszDomain = "" );
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -188,6 +189,17 @@ WEBPDataset::~WEBPDataset()
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **WEBPDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "xml:XMP", NULL);
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 
diff --git a/frmts/wms/GNUmakefile b/frmts/wms/GNUmakefile
index 66fa3db..f45d5d9 100644
--- a/frmts/wms/GNUmakefile
+++ b/frmts/wms/GNUmakefile
@@ -1,8 +1,9 @@
 
 include ../../GDALmake.opt
 
-OBJ =	cache.o dataset.o gdalhttp.o md5.o minidriver.o \
-	rasterband.o stuff.o wmsdriver.o minidriver_wms.o \
+OBJ =	gdalwmscache.o gdalwmsdataset.o gdalwmsrasterband.o \
+	gdalhttp.o md5.o minidriver.o \
+	wmsutils.o wmsdriver.o minidriver_wms.o \
 	minidriver_tileservice.o minidriver_worldwind.o \
 	minidriver_tms.o minidriver_tiled_wms.o wmsmetadataset.o \
 	minidriver_virtualearth.o
diff --git a/frmts/wms/cache.cpp b/frmts/wms/cache.cpp
deleted file mode 100644
index 7009f06..0000000
--- a/frmts/wms/cache.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/******************************************************************************
- * $Id: cache.cpp 21880 2011-02-27 14:28:26Z rouault $
- *
- * Project:  WMS Client Driver
- * Purpose:  Implementation of Dataset and RasterBand classes for WMS
- *           and other similar services.
- * Author:   Adam Nowacki, nowak at xpam.de
- *
- ******************************************************************************
- * Copyright (c) 2007, Adam Nowacki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "stdinc.h"
-
-GDALWMSCache::GDALWMSCache() {
-    m_cache_path = "./gdalwmscache";
-    m_postfix = "";
-    m_cache_depth = 2;
-}
-
-GDALWMSCache::~GDALWMSCache() {
-}
-
-CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
-    const char *cache_path = CPLGetXMLValue(config, "Path", "./gdalwmscache");
-    m_cache_path = cache_path;
-
-    const char *cache_depth = CPLGetXMLValue(config, "Depth", "2");
-    m_cache_depth = atoi(cache_depth);
-
-    const char *cache_extension = CPLGetXMLValue(config, "Extension", "");
-    m_postfix = cache_extension;
-
-    return CE_None;
-}
-
-CPLErr GDALWMSCache::Write(const char *key, const CPLString &file_name) {
-    CPLString cache_file(KeyToCacheFile(key));
-    //	printf("GDALWMSCache::Write(%s, %s) -> %s\n", key, file_name.c_str());
-    if (CPLCopyFile(cache_file.c_str(), file_name.c_str()) != CE_None) {
-        MakeDirs(cache_file.c_str());
-        CPLCopyFile(cache_file.c_str(), file_name.c_str());
-    }
-
-    return CE_None;
-}
-
-CPLErr GDALWMSCache::Read(const char *key, CPLString *file_name) {
-    CPLErr ret = CE_Failure;
-    CPLString cache_file(KeyToCacheFile(key));
-    VSILFILE* fp = VSIFOpenL(cache_file.c_str(), "rb");
-    if (fp != NULL)
-    {
-        VSIFCloseL(fp);
-        *file_name = cache_file;
-        ret = CE_None;
-    }
-    //    printf("GDALWMSCache::Read(...) -> %s\n", cache_file.c_str());
-
-    return ret;
-}
-
-CPLString GDALWMSCache::KeyToCacheFile(const char *key) {
-    CPLString hash(MD5String(key));
-    CPLString cache_file(m_cache_path);
-
-    if (cache_file.size() && (cache_file[cache_file.size() - 1] != '/')) cache_file.append(1, '/');
-    for (int i = 0; i < m_cache_depth; ++i) {
-        cache_file.append(1, hash[i]);
-        cache_file.append(1, '/');
-    }
-    cache_file.append(hash);
-    cache_file.append(m_postfix);
-    return cache_file;
-}
diff --git a/frmts/wms/dataset.cpp b/frmts/wms/dataset.cpp
deleted file mode 100644
index c234311..0000000
--- a/frmts/wms/dataset.cpp
+++ /dev/null
@@ -1,676 +0,0 @@
-/******************************************************************************
- * $Id: dataset.cpp 25776 2013-03-20 20:46:48Z rouault $
- *
- * Project:  WMS Client Driver
- * Purpose:  Implementation of Dataset and RasterBand classes for WMS
- *           and other similar services.
- * Author:   Adam Nowacki, nowak at xpam.de
- *
- ******************************************************************************
- * Copyright (c) 2007, Adam Nowacki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************
- *
- * dataset.cpp:
- * Initialization of the GDALWMSdriver, parsing the XML configuration file, 
- * instantiation of the minidrivers and accessors used by minidrivers
- *
- ***************************************************************************/ 
-
-
-#include "stdinc.h"
-
-GDALWMSDataset::GDALWMSDataset() {
-    m_mini_driver = 0;
-    m_cache = 0;
-    m_hint.m_valid = false;
-    m_data_type = GDT_Byte;
-    m_clamp_requests = true;
-    m_unsafeSsl = false;
-    m_data_window.m_sx = -1;
-    nBands = 0;
-    m_default_block_size_x = 1024;
-    m_default_block_size_y = 1024;
-    m_bNeedsDataWindow = TRUE;
-    m_default_tile_count_x = 1;
-    m_default_tile_count_y = 1;
-    m_default_overview_count = -1;
-    m_zeroblock_on_serverexceptions = 0;
-    m_poColorTable = NULL;
-}
-
-GDALWMSDataset::~GDALWMSDataset() {
-    if (m_mini_driver) delete m_mini_driver;
-    if (m_cache) delete m_cache;
-    if (m_poColorTable) delete m_poColorTable;
-}
-
-CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
-    CPLErr ret = CE_None;
-
-    char* pszXML = CPLSerializeXMLTree( config );
-    if (pszXML)
-    {
-        m_osXML = pszXML;
-        CPLFree(pszXML);
-    }
-
-    // Initialize the minidriver, which can set parameters for the dataset using member functions
-    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
-    if (service_node != NULL)
-    {
-        const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
-        if (!service_name.empty())
-        {
-            GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
-            GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
-            if (mdf != NULL)
-            {
-                m_mini_driver = mdf->New();
-                m_mini_driver->m_parent_dataset = this;
-                if (m_mini_driver->Initialize(service_node) == CE_None)
-                {
-                    m_mini_driver_caps.m_capabilities_version = -1;
-                    m_mini_driver->GetCapabilities(&m_mini_driver_caps);
-                    if (m_mini_driver_caps.m_capabilities_version == -1)
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
-                        ret = CE_Failure;
-                    }
-                }
-                else
-                {
-                    delete m_mini_driver;
-                    m_mini_driver = NULL;
-
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
-                    ret = CE_Failure;
-                }
-            }
-            else
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                                "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
-                ret = CE_Failure;
-            }
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
-            ret = CE_Failure;
-        }
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
-        ret = CE_Failure;
-    }
-
-
-    /*
-    Parameters that could be set by minidriver already, based on server side information.
-    If the size is set, minidriver has done this already
-    A "server" side minidriver needs to set at least:
-      - Blocksize (x and y)
-      - Clamp flag (defaults to true)
-      - DataWindow
-      - Band Count
-      - Data Type
-    It should also initialize and register the bands and overviews.
-    */
-
-    if (m_data_window.m_sx<1)
-    {
-        int nOverviews = 0;
-
-        if (ret == CE_None)
-        {
-            m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
-            m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
-            if (m_block_size_x <= 0 || m_block_size_y <= 0)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
-                ret = CE_Failure;
-            }
-        }
-
-        if (ret == CE_None)
-        {
-            m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
-            if (m_clamp_requests<0)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
-                ret = CE_Failure;
-            }
-        }
-
-        if (ret == CE_None)
-        {
-            CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
-            if (data_window_node == NULL && m_bNeedsDataWindow)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
-                ret = CE_Failure;
-            }
-            else
-            {
-                CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
-                CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
-                CPLString osDefaultOverviewCount;
-                osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
-                osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
-                osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
-                osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
-                osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
-                osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
-                if (m_default_data_window.m_tlevel >= 0)
-                    osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
-                if (m_default_overview_count >= 0)
-                    osDefaultOverviewCount.Printf("%d", m_default_overview_count);
-                const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
-                const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
-                const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
-                const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
-                const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
-                const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
-                const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
-                const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
-                const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
-                const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
-                const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
-                const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
-                const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
-
-                if (ret == CE_None)
-                {
-                    if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0'))
-                    {
-                        m_data_window.m_x0 = atof(ulx);
-                        m_data_window.m_y0 = atof(uly);
-                        m_data_window.m_x1 = atof(lrx);
-                        m_data_window.m_y1 = atof(lry);
-                    }
-                    else
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined,
-                                 "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
-                        ret = CE_Failure;
-                    }
-                }
-
-                m_data_window.m_tlevel = atoi(tlevel);
-
-                if (ret == CE_None)
-                {
-                    if ((sx[0] != '\0') && (sy[0] != '\0'))
-                    {
-                        m_data_window.m_sx = atoi(sx);
-                        m_data_window.m_sy = atoi(sy);
-                    }
-                    else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0'))
-                    {
-                        int tile_count_x = atoi(str_tile_count_x);
-                        int tile_count_y = atoi(str_tile_count_y);
-                        m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
-                        m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
-                    }
-                    else
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined,
-                                 "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
-                        ret = CE_Failure;
-                    }
-                }
-                if (ret == CE_None)
-                {
-                    if ((tx[0] != '\0') && (ty[0] != '\0'))
-                    {
-                        m_data_window.m_tx = atoi(tx);
-                        m_data_window.m_ty = atoi(ty);
-                    }
-                    else
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined,
-                                 "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
-                        ret = CE_Failure;
-                    }
-                }
-
-                if (ret == CE_None)
-                {
-                    if (overview_count[0] != '\0')
-                    {
-                        nOverviews = atoi(overview_count);
-                    }
-                    else if (tlevel[0] != '\0')
-                    {
-                        nOverviews = m_data_window.m_tlevel;
-                    }
-                    else
-                    {
-                        const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
-                        double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
-                            - log(static_cast<double>(min_overview_size)) / log(2.0);
-                        nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
-                    }
-                }
-                if (ret == CE_None)
-                {
-                    CPLString y_origin_str = y_origin;
-                    if (y_origin_str == "top") {
-                        m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
-                    } else if (y_origin_str == "bottom") {
-                        m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
-                    } else if (y_origin_str == "default") {
-                        m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
-                    } else {
-                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to "
-                            "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
-                        ret = CE_Failure;
-                    }
-                }
-            }
-        }
-
-        if (ret == CE_None)
-        {
-            if (nBands<1)
-                nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
-            if (nBands<1)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "GDALWMS: Bad number of bands.");
-                ret = CE_Failure;
-            }
-        }
-
-        if (ret == CE_None)
-        {
-            const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
-            m_data_type = GDALGetDataTypeByName( data_type );
-            if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
-                ret = CE_Failure;
-            }
-        }
-
-        // Initialize the bands and the overviews.  Assumes overviews are powers of two
-        if (ret == CE_None)
-        {
-            nRasterXSize = m_data_window.m_sx;
-            nRasterYSize = m_data_window.m_sy;
-
-            if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
-                !GDALCheckBandCount(nBands, TRUE))
-            {
-                return CE_Failure;
-            }
-
-            GDALColorInterp default_color_interp[4][4] = {
-                { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
-                { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
-                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
-                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
-            };
-            for (int i = 0; i < nBands; ++i)
-            {
-                GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
-                GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
-                band->m_color_interp = color_interp;
-                SetBand(i + 1, band);
-                double scale = 0.5;
-                for (int j = 0; j < nOverviews; ++j)
-                {
-                    band->AddOverview(scale);
-                    band->m_color_interp = color_interp;
-                    scale *= 0.5;
-                }
-            }
-        }
-    }
-    
-    // UserPwd 
-    const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
-    if (pszUserPwd[0] != '\0')
-        m_osUserPwd = pszUserPwd;
-
-    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
-    if (pszUserAgent[0] != '\0')
-        m_osUserAgent = pszUserAgent;
-    
-    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
-    if (pszReferer[0] != '\0')
-        m_osReferer = pszReferer;
-    
-    if (ret == CE_None) {
-        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
-        if(pszHttpZeroBlockCodes == '\0') {
-            m_http_zeroblock_codes.push_back(204);
-        } else {
-            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
-            int nCount = CSLCount(kv);
-            for(int i=0; i<nCount; i++) {
-                int code = atoi(kv[i]);
-                if(code <= 0) {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
-                            kv[i]);
-                    ret = CE_Failure;
-                    break;
-                }
-                m_http_zeroblock_codes.push_back(code);
-            }
-            CSLDestroy(kv);
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
-        if(pszZeroExceptions[0] != '\0') {
-            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
-            if (m_zeroblock_on_serverexceptions == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
-                     pszZeroExceptions);
-                ret = CE_Failure;
-            }
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
-        if (max_conn[0] != '\0') {
-            m_http_max_conn = atoi(max_conn);
-        } else {
-            m_http_max_conn = 2;
-        }
-    }
-    if (ret == CE_None) {
-        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
-        if (timeout[0] != '\0') {
-            m_http_timeout = atoi(timeout);
-        } else {
-            m_http_timeout = 300;
-        }
-    }
-    if (ret == CE_None) {
-        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
-        if (offline_mode[0] != '\0') {
-            const int offline_mode_bool = StrToBool(offline_mode);
-            if (offline_mode_bool == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
-                ret = CE_Failure;
-            } else {
-                m_offline_mode = offline_mode_bool;
-            }
-        } else {
-            m_offline_mode = 0;
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
-        if (advise_read[0] != '\0') {
-            const int advise_read_bool = StrToBool(advise_read);
-            if (advise_read_bool == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
-                ret = CE_Failure;
-            } else {
-                m_use_advise_read = advise_read_bool;
-            }
-        } else {
-            m_use_advise_read = 0;
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
-        if (m_use_advise_read) {
-            if (verify_advise_read[0] != '\0') {
-                const int verify_advise_read_bool = StrToBool(verify_advise_read);
-                if (verify_advise_read_bool == -1) {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
-                    ret = CE_Failure;
-                } else {
-                    m_verify_advise_read = verify_advise_read_bool;
-                }
-            } else {
-                m_verify_advise_read = 1;
-            }
-        }
-    }
-
-    // Let the local configuration override the minidriver supplied projection
-
-    if (ret == CE_None) {
-        const char *proj = CPLGetXMLValue(config, "Projection", "");
-        if (proj[0] != '\0') {
-            m_projection = ProjToWKT(proj);
-            if (m_projection.size() == 0) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
-                ret = CE_Failure;
-            }
-        }
-    }
-
-    // Same for Min, Max and NoData, defined per band or per dataset
-    // If they are set as null strings, they clear the server declared values
-    if (ret == CE_None) {
-       // Data values are attributes, they include NoData Min and Max
-       // TODO: document those options
-       if (0!=CPLGetXMLNode(config,"DataValues")) {
-           const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
-           if (nodata!=NULL) WMSSetNoDataValue(nodata);
-           const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
-           if (min!=NULL) WMSSetMinValue(min);
-           const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
-           if (max!=NULL) WMSSetMaxValue(max);
-       }
-    }
-
-    if (ret == CE_None) {
-        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
-        if (cache_node != NULL) {
-            m_cache = new GDALWMSCache();
-            if (m_cache->Initialize(cache_node) != CE_None) {
-                delete m_cache;
-                m_cache = NULL;
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
-                ret = CE_Failure;
-            }
-        }
-    }
-    
-    if (ret == CE_None) {
-    	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
-    	if (v == -1) {
-	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
-	    ret = CE_Failure;
-	} else {
-	    m_unsafeSsl = v;
-	}
-    }
-
-    if (ret == CE_None) {
-        /* If we dont have projection already set ask mini-driver. */
-        if (!m_projection.size()) {
-            const char *proj = m_mini_driver->GetProjectionInWKT();
-            if (proj != NULL) {
-                m_projection = proj;
-            }
-        }
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, int pixel_space, int line_space, int band_space) {
-    CPLErr ret;
-
-    if (rw != GF_Read) return CE_Failure;
-    if (buffer == NULL) return CE_Failure;
-    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
-
-    m_hint.m_x0 = x0;
-    m_hint.m_y0 = y0;
-    m_hint.m_sx = sx;
-    m_hint.m_sy = sy;
-    m_hint.m_overview = -1;
-    m_hint.m_valid = true;
-    //	printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
-    ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
-    m_hint.m_valid = false;
-
-    return ret;
-}
-
-const char *GDALWMSDataset::GetProjectionRef() {
-    return m_projection.c_str();
-}
-
-CPLErr GDALWMSDataset::SetProjection(const char *proj) {
-    return CE_Failure;
-}
-
-CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
-    gt[0] = m_data_window.m_x0;
-    gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
-    gt[2] = 0.0;
-    gt[3] = m_data_window.m_y0;
-    gt[4] = 0.0;
-    gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
-    return CE_None;
-}
-
-CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
-    return CE_Failure;
-}
-
-const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
-    return &m_data_window;
-}
-
-void GDALWMSDataset::WMSSetBlockSize(int x, int y) {
-    m_block_size_x=x;
-    m_block_size_y=y;
-}
-
-void GDALWMSDataset::WMSSetRasterSize(int x, int y) {
-    nRasterXSize=x;
-    nRasterYSize=y;
-}
-
-void GDALWMSDataset::WMSSetBandsCount(int count) {
-    nBands=count;
-}
-
-void GDALWMSDataset::WMSSetClamp(bool flag=true) {
-    m_clamp_requests=flag;
-}
-
-void GDALWMSDataset::WMSSetDataType(GDALDataType type) {
-    m_data_type=type;
-}
-
-void GDALWMSDataset::WMSSetDataWindow(GDALWMSDataWindow &window) {
-    m_data_window=window;
-}
-
-void GDALWMSDataset::WMSSetDefaultBlockSize(int x, int y) {
-    m_default_block_size_x=x;
-    m_default_block_size_y=y;
-}
-
-void GDALWMSDataset::WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1)
-{
-    m_default_data_window.m_x0 = x0;
-    m_default_data_window.m_y0 = y0;
-    m_default_data_window.m_x1 = x1;
-    m_default_data_window.m_y1 = y1;
-}
-
-void GDALWMSDataset::WMSSetDefaultTileCount(int tilecountx, int tilecounty)
-{
-    m_default_tile_count_x = tilecountx;
-    m_default_tile_count_y = tilecounty;
-}
-
-void GDALWMSDataset::WMSSetDefaultTileLevel(int tlevel)
-{
-    m_default_data_window.m_tlevel = tlevel;
-}
-
-void GDALWMSDataset::WMSSetDefaultOverviewCount(int overview_count)
-{
-    m_default_overview_count = overview_count;
-}
-
-void GDALWMSDataset::WMSSetNeedsDataWindow(int flag)
-{
-    m_bNeedsDataWindow = flag;
-}
-
-static void list2vec(std::vector<double> &v,const char *pszList)
-{
-    if ((pszList==NULL)||(pszList[0]==0)) return;
-    char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
-        CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
-    v.clear();
-    for (int i=0;i<CSLCount(papszTokens);i++)
-        v.push_back(CPLStrtod(papszTokens[i],NULL));
-    CSLDestroy(papszTokens);
-}
-
-void GDALWMSDataset::WMSSetNoDataValue(const char * pszNoData)
-{
-    list2vec(vNoData,pszNoData);
-}
-
-void GDALWMSDataset::WMSSetMinValue(const char * pszMin)
-{
-    list2vec(vMin,pszMin);
-}
-
-void GDALWMSDataset::WMSSetMaxValue(const char * pszMax)
-{
-    list2vec(vMax,pszMax);
-}
-
-CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) {
-//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
-    if (m_offline_mode || !m_use_advise_read) return CE_None;
-    if (m_cache == NULL) return CE_Failure;
-
-    GDALRasterBand *band = GetRasterBand(1);
-    if (band == NULL) return CE_Failure;
-    return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
-}
-
-const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
-                                             const char * pszDomain )
-{
-    if( pszName != NULL && EQUAL(pszName, "XML") &&
-        pszDomain != NULL && EQUAL(pszDomain, "WMS") )
-    {
-        return (m_osXML.size()) ? m_osXML.c_str() : NULL;
-    }
-
-    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
-}
diff --git a/frmts/wms/frmt_wms.html b/frmts/wms/frmt_wms.html
index f0a6959..540609b 100644
--- a/frmts/wms/frmt_wms.html
+++ b/frmts/wms/frmt_wms.html
@@ -164,7 +164,7 @@
 		</tr>
 		<tr>
 			<td class="xml">        <Path><span class="value">./gdalwmscache</span></Path></td>
-			<td class="desc">Location where to store cache files. It is safe to use same cache path for different data sources. (optional, defaults to ./gdalwmscache)</td>
+			<td class="desc">Location where to store cache files. It is safe to use same cache path for different data sources. (optional, defaults to ./gdalwmscache if GDAL_DEFAULT_WMS_CACHE_PATH configuration option is not specified)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <Depth><span class="value">2</span></Depth></td>
@@ -327,7 +327,7 @@ Report pixel="248595" line="191985">
   </ul>
 <p>
   A typical ServerURL might look like:<br />
-  <tt>http://labs.metacarta.com/wms-c/Basic.py/${version}/${layer}/${z}/${x}/${y}.${format}</tt><br />
+  <tt>http://tilecache.osgeo.org/wms-c/Basic.py/${version}/${layer}/${z}/${x}/${y}.${format}</tt><br />
   In order to better suit TMS users, any URL that does not contain "${" will automatically have the string above (after "Basic.py/") appended to their URL.
 </p> 
 <p>
diff --git a/frmts/wms/frmt_wms_metacarta_tms.xml b/frmts/wms/frmt_wms_metacarta_tms.xml
index ee7b4e4..81c50e7 100644
--- a/frmts/wms/frmt_wms_metacarta_tms.xml
+++ b/frmts/wms/frmt_wms_metacarta_tms.xml
@@ -1,6 +1,6 @@
 <GDAL_WMS>
     <Service name="TMS">
-        <ServerUrl>http://labs.metacarta.com/wms-c/Basic.py</ServerUrl>
+        <ServerUrl>http://tilecache.osgeo.org/wms-c/Basic.py</ServerUrl>
         <Layer>basic</Layer>
         <Format>png</Format>
     </Service>
diff --git a/frmts/wms/frmt_wms_metacarta_wmsc.xml b/frmts/wms/frmt_wms_metacarta_wmsc.xml
index c8ec384..ebb2736 100644
--- a/frmts/wms/frmt_wms_metacarta_wmsc.xml
+++ b/frmts/wms/frmt_wms_metacarta_wmsc.xml
@@ -1,7 +1,7 @@
 <GDAL_WMS>
     <Service name="WMS">
         <Version>1</Version>
-        <ServerUrl>http://labs.metacarta.com/wms-c/Basic.py?</ServerUrl>
+        <ServerUrl>http://tilecache.osgeo.org/wms-c/Basic.py?</ServerUrl>
         <Layers>basic</Layers>
     </Service>
     <DataWindow>
diff --git a/frmts/wms/gdalhttp.cpp b/frmts/wms/gdalhttp.cpp
index 2626055..71076c2 100644
--- a/frmts/wms/gdalhttp.cpp
+++ b/frmts/wms/gdalhttp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalhttp.cpp 25661 2013-02-22 11:35:12Z rouault $
+ * $Id: gdalhttp.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,7 +29,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
 
 void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
 
@@ -202,9 +203,12 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
         FD_ZERO(&fdwrite);
         FD_ZERO(&fdexcep);
         curl_multi_fdset(curl_multi, &fdread, &fdwrite, &fdexcep, &maxfd);
-        timeout.tv_sec = 0;
-        timeout.tv_usec = 100000;
-        select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+        if( maxfd >= 0 )
+        {
+            timeout.tv_sec = 0;
+            timeout.tv_usec = 100000;
+            select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+        }
         while (curl_multi_perform(curl_multi, &still_running) == CURLM_CALL_MULTI_PERFORM);
     }
 
diff --git a/frmts/wms/gdalwmscache.cpp b/frmts/wms/gdalwmscache.cpp
new file mode 100644
index 0000000..23c7858
--- /dev/null
+++ b/frmts/wms/gdalwmscache.cpp
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * $Id: gdalwmscache.cpp 26900 2014-01-29 21:55:45Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Implementation of Dataset and RasterBand classes for WMS
+ *           and other similar services.
+ * Author:   Adam Nowacki, nowak at xpam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Adam Nowacki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "wmsdriver.h"
+
+GDALWMSCache::GDALWMSCache() {
+    m_cache_path = "./gdalwmscache";
+    m_postfix = "";
+    m_cache_depth = 2;
+}
+
+GDALWMSCache::~GDALWMSCache() {
+}
+
+CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
+    const char *xmlcache_path = CPLGetXMLValue(config, "Path", NULL); 
+    const char *usercache_path = CPLGetConfigOption("GDAL_DEFAULT_WMS_CACHE_PATH", NULL); 
+    if(xmlcache_path) 
+    {
+        m_cache_path = xmlcache_path;
+    }
+    else
+    {
+        if(usercache_path)
+        {
+            m_cache_path = usercache_path;
+        }
+        else
+        {
+            m_cache_path = "./gdalwmscache"; 
+        }
+    }
+
+    const char *cache_path = CPLGetXMLValue(config, "Path", "./gdalwmscache");
+    m_cache_path = cache_path;
+
+    const char *cache_depth = CPLGetXMLValue(config, "Depth", "2");
+    m_cache_depth = atoi(cache_depth);
+
+    const char *cache_extension = CPLGetXMLValue(config, "Extension", "");
+    m_postfix = cache_extension;
+
+    return CE_None;
+}
+
+CPLErr GDALWMSCache::Write(const char *key, const CPLString &file_name) {
+    CPLString cache_file(KeyToCacheFile(key));
+    //	printf("GDALWMSCache::Write(%s, %s) -> %s\n", key, file_name.c_str());
+    if (CPLCopyFile(cache_file.c_str(), file_name.c_str()) != CE_None) {
+        MakeDirs(cache_file.c_str());
+        CPLCopyFile(cache_file.c_str(), file_name.c_str());
+    }
+
+    return CE_None;
+}
+
+CPLErr GDALWMSCache::Read(const char *key, CPLString *file_name) {
+    CPLErr ret = CE_Failure;
+    CPLString cache_file(KeyToCacheFile(key));
+    VSILFILE* fp = VSIFOpenL(cache_file.c_str(), "rb");
+    if (fp != NULL)
+    {
+        VSIFCloseL(fp);
+        *file_name = cache_file;
+        ret = CE_None;
+    }
+    //    printf("GDALWMSCache::Read(...) -> %s\n", cache_file.c_str());
+
+    return ret;
+}
+
+CPLString GDALWMSCache::KeyToCacheFile(const char *key) {
+    CPLString hash(MD5String(key));
+    CPLString cache_file(m_cache_path);
+
+    if (cache_file.size() && (cache_file[cache_file.size() - 1] != '/')) cache_file.append(1, '/');
+    for (int i = 0; i < m_cache_depth; ++i) {
+        cache_file.append(1, hash[i]);
+        cache_file.append(1, '/');
+    }
+    cache_file.append(hash);
+    cache_file.append(m_postfix);
+    return cache_file;
+}
diff --git a/frmts/wms/gdalwmsdataset.cpp b/frmts/wms/gdalwmsdataset.cpp
new file mode 100644
index 0000000..a7f0a5a
--- /dev/null
+++ b/frmts/wms/gdalwmsdataset.cpp
@@ -0,0 +1,635 @@
+/******************************************************************************
+ * $Id: gdalwmsdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Implementation of Dataset and RasterBand classes for WMS
+ *           and other similar services.
+ * Author:   Adam Nowacki, nowak at xpam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************
+ *
+ * dataset.cpp:
+ * Initialization of the GDALWMSdriver, parsing the XML configuration file, 
+ * instantiation of the minidrivers and accessors used by minidrivers
+ *
+ ***************************************************************************/ 
+
+
+#include "wmsdriver.h"
+
+#include "minidriver_wms.h"
+#include "minidriver_tileservice.h"
+#include "minidriver_worldwind.h"
+#include "minidriver_tms.h"
+#include "minidriver_tiled_wms.h"
+#include "minidriver_virtualearth.h"
+
+/************************************************************************/
+/*                           GDALWMSDataset()                           */
+/************************************************************************/
+GDALWMSDataset::GDALWMSDataset() {
+    m_mini_driver = 0;
+    m_cache = 0;
+    m_hint.m_valid = false;
+    m_data_type = GDT_Byte;
+    m_clamp_requests = true;
+    m_unsafeSsl = false;
+    m_data_window.m_sx = -1;
+    nBands = 0;
+    m_default_block_size_x = 1024;
+    m_default_block_size_y = 1024;
+    m_bNeedsDataWindow = TRUE;
+    m_default_tile_count_x = 1;
+    m_default_tile_count_y = 1;
+    m_default_overview_count = -1;
+    m_zeroblock_on_serverexceptions = 0;
+    m_poColorTable = NULL;
+}
+
+/************************************************************************/
+/*                          ~GDALWMSDataset()                           */
+/************************************************************************/
+GDALWMSDataset::~GDALWMSDataset() {
+    if (m_mini_driver) delete m_mini_driver;
+    if (m_cache) delete m_cache;
+    if (m_poColorTable) delete m_poColorTable;
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
+    CPLErr ret = CE_None;
+
+    char* pszXML = CPLSerializeXMLTree( config );
+    if (pszXML)
+    {
+        m_osXML = pszXML;
+        CPLFree(pszXML);
+    }
+
+    // Initialize the minidriver, which can set parameters for the dataset using member functions
+    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
+    if (service_node != NULL)
+    {
+        const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
+        if (!service_name.empty())
+        {
+            GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
+            GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
+            if (mdf != NULL)
+            {
+                m_mini_driver = mdf->New();
+                m_mini_driver->m_parent_dataset = this;
+                if (m_mini_driver->Initialize(service_node) == CE_None)
+                {
+                    m_mini_driver_caps.m_capabilities_version = -1;
+                    m_mini_driver->GetCapabilities(&m_mini_driver_caps);
+                    if (m_mini_driver_caps.m_capabilities_version == -1)
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
+                        ret = CE_Failure;
+                    }
+                }
+                else
+                {
+                    delete m_mini_driver;
+                    m_mini_driver = NULL;
+
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
+                    ret = CE_Failure;
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
+                ret = CE_Failure;
+            }
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
+            ret = CE_Failure;
+        }
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
+        ret = CE_Failure;
+    }
+
+
+    /*
+      Parameters that could be set by minidriver already, based on server side information.
+      If the size is set, minidriver has done this already
+      A "server" side minidriver needs to set at least:
+      - Blocksize (x and y)
+      - Clamp flag (defaults to true)
+      - DataWindow
+      - Band Count
+      - Data Type
+      It should also initialize and register the bands and overviews.
+    */
+
+    if (m_data_window.m_sx<1)
+    {
+        int nOverviews = 0;
+
+        if (ret == CE_None)
+        {
+            m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
+            m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
+            if (m_block_size_x <= 0 || m_block_size_y <= 0)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
+                ret = CE_Failure;
+            }
+        }
+
+        if (ret == CE_None)
+        {
+            m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
+            if (m_clamp_requests<0)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
+                ret = CE_Failure;
+            }
+        }
+
+        if (ret == CE_None)
+        {
+            CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
+            if (data_window_node == NULL && m_bNeedsDataWindow)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
+                ret = CE_Failure;
+            }
+            else
+            {
+                CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
+                CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
+                CPLString osDefaultOverviewCount;
+                osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
+                osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
+                osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
+                osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
+                osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
+                osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
+                if (m_default_data_window.m_tlevel >= 0)
+                    osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
+                if (m_default_overview_count >= 0)
+                    osDefaultOverviewCount.Printf("%d", m_default_overview_count);
+                const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
+                const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
+                const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
+                const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
+                const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
+                const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
+                const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
+                const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
+                const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
+                const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
+                const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
+                const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
+                const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
+
+                if (ret == CE_None)
+                {
+                    if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0'))
+                    {
+                        m_data_window.m_x0 = atof(ulx);
+                        m_data_window.m_y0 = atof(uly);
+                        m_data_window.m_x1 = atof(lrx);
+                        m_data_window.m_y1 = atof(lry);
+                    }
+                    else
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
+                        ret = CE_Failure;
+                    }
+                }
+
+                m_data_window.m_tlevel = atoi(tlevel);
+
+                if (ret == CE_None)
+                {
+                    if ((sx[0] != '\0') && (sy[0] != '\0'))
+                    {
+                        m_data_window.m_sx = atoi(sx);
+                        m_data_window.m_sy = atoi(sy);
+                    }
+                    else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0'))
+                    {
+                        int tile_count_x = atoi(str_tile_count_x);
+                        int tile_count_y = atoi(str_tile_count_y);
+                        m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
+                        m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
+                    }
+                    else
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
+                        ret = CE_Failure;
+                    }
+                }
+                if (ret == CE_None)
+                {
+                    if ((tx[0] != '\0') && (ty[0] != '\0'))
+                    {
+                        m_data_window.m_tx = atoi(tx);
+                        m_data_window.m_ty = atoi(ty);
+                    }
+                    else
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
+                        ret = CE_Failure;
+                    }
+                }
+
+                if (ret == CE_None)
+                {
+                    if (overview_count[0] != '\0')
+                    {
+                        nOverviews = atoi(overview_count);
+                    }
+                    else if (tlevel[0] != '\0')
+                    {
+                        nOverviews = m_data_window.m_tlevel;
+                    }
+                    else
+                    {
+                        const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
+                        double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
+                            - log(static_cast<double>(min_overview_size)) / log(2.0);
+                        nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
+                    }
+                }
+                if (ret == CE_None)
+                {
+                    CPLString y_origin_str = y_origin;
+                    if (y_origin_str == "top") {
+                        m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
+                    } else if (y_origin_str == "bottom") {
+                        m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
+                    } else if (y_origin_str == "default") {
+                        m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
+                    } else {
+                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to "
+                                 "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
+                        ret = CE_Failure;
+                    }
+                }
+            }
+        }
+
+        if (ret == CE_None)
+        {
+            if (nBands<1)
+                nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
+            if (nBands<1)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "GDALWMS: Bad number of bands.");
+                ret = CE_Failure;
+            }
+        }
+
+        if (ret == CE_None)
+        {
+            const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
+            m_data_type = GDALGetDataTypeByName( data_type );
+            if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
+                ret = CE_Failure;
+            }
+        }
+
+        // Initialize the bands and the overviews.  Assumes overviews are powers of two
+        if (ret == CE_None)
+        {
+            nRasterXSize = m_data_window.m_sx;
+            nRasterYSize = m_data_window.m_sy;
+
+            if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
+                !GDALCheckBandCount(nBands, TRUE))
+            {
+                return CE_Failure;
+            }
+
+            GDALColorInterp default_color_interp[4][4] = {
+                { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
+                { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
+                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
+                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
+            };
+            for (int i = 0; i < nBands; ++i)
+            {
+                GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
+                GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
+                band->m_color_interp = color_interp;
+                SetBand(i + 1, band);
+                double scale = 0.5;
+                for (int j = 0; j < nOverviews; ++j)
+                {
+                    band->AddOverview(scale);
+                    band->m_color_interp = color_interp;
+                    scale *= 0.5;
+                }
+            }
+        }
+    }
+    
+    // UserPwd 
+    const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
+    if (pszUserPwd[0] != '\0')
+        m_osUserPwd = pszUserPwd;
+
+    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
+    if (pszUserAgent[0] != '\0')
+        m_osUserAgent = pszUserAgent;
+    
+    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
+    if (pszReferer[0] != '\0')
+        m_osReferer = pszReferer;
+    
+    if (ret == CE_None) {
+        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
+        if(pszHttpZeroBlockCodes == '\0') {
+            m_http_zeroblock_codes.push_back(204);
+        } else {
+            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
+            int nCount = CSLCount(kv);
+            for(int i=0; i<nCount; i++) {
+                int code = atoi(kv[i]);
+                if(code <= 0) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
+                             kv[i]);
+                    ret = CE_Failure;
+                    break;
+                }
+                m_http_zeroblock_codes.push_back(code);
+            }
+            CSLDestroy(kv);
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
+        if(pszZeroExceptions[0] != '\0') {
+            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
+            if (m_zeroblock_on_serverexceptions == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
+                         pszZeroExceptions);
+                ret = CE_Failure;
+            }
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
+        if (max_conn[0] != '\0') {
+            m_http_max_conn = atoi(max_conn);
+        } else {
+            m_http_max_conn = 2;
+        }
+    }
+    if (ret == CE_None) {
+        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
+        if (timeout[0] != '\0') {
+            m_http_timeout = atoi(timeout);
+        } else {
+            m_http_timeout = 300;
+        }
+    }
+    if (ret == CE_None) {
+        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
+        if (offline_mode[0] != '\0') {
+            const int offline_mode_bool = StrToBool(offline_mode);
+            if (offline_mode_bool == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
+                ret = CE_Failure;
+            } else {
+                m_offline_mode = offline_mode_bool;
+            }
+        } else {
+            m_offline_mode = 0;
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
+        if (advise_read[0] != '\0') {
+            const int advise_read_bool = StrToBool(advise_read);
+            if (advise_read_bool == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
+                ret = CE_Failure;
+            } else {
+                m_use_advise_read = advise_read_bool;
+            }
+        } else {
+            m_use_advise_read = 0;
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
+        if (m_use_advise_read) {
+            if (verify_advise_read[0] != '\0') {
+                const int verify_advise_read_bool = StrToBool(verify_advise_read);
+                if (verify_advise_read_bool == -1) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
+                    ret = CE_Failure;
+                } else {
+                    m_verify_advise_read = verify_advise_read_bool;
+                }
+            } else {
+                m_verify_advise_read = 1;
+            }
+        }
+    }
+
+    // Let the local configuration override the minidriver supplied projection
+
+    if (ret == CE_None) {
+        const char *proj = CPLGetXMLValue(config, "Projection", "");
+        if (proj[0] != '\0') {
+            m_projection = ProjToWKT(proj);
+            if (m_projection.size() == 0) {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
+                ret = CE_Failure;
+            }
+        }
+    }
+
+    // Same for Min, Max and NoData, defined per band or per dataset
+    // If they are set as null strings, they clear the server declared values
+    if (ret == CE_None) {
+        // Data values are attributes, they include NoData Min and Max
+        // TODO: document those options
+        if (0!=CPLGetXMLNode(config,"DataValues")) {
+            const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
+            if (nodata!=NULL) WMSSetNoDataValue(nodata);
+            const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
+            if (min!=NULL) WMSSetMinValue(min);
+            const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
+            if (max!=NULL) WMSSetMaxValue(max);
+        }
+    }
+
+    if (ret == CE_None) {
+        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
+        if (cache_node != NULL) {
+            m_cache = new GDALWMSCache();
+            if (m_cache->Initialize(cache_node) != CE_None) {
+                delete m_cache;
+                m_cache = NULL;
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
+                ret = CE_Failure;
+            }
+        }
+    }
+    
+    if (ret == CE_None) {
+    	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
+    	if (v == -1) {
+	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
+	    ret = CE_Failure;
+	} else {
+	    m_unsafeSsl = v;
+	}
+    }
+
+    if (ret == CE_None) {
+        /* If we dont have projection already set ask mini-driver. */
+        if (!m_projection.size()) {
+            const char *proj = m_mini_driver->GetProjectionInWKT();
+            if (proj != NULL) {
+                m_projection = proj;
+            }
+        }
+    }
+
+    return ret;
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, int pixel_space, int line_space, int band_space) {
+    CPLErr ret;
+
+    if (rw != GF_Read) return CE_Failure;
+    if (buffer == NULL) return CE_Failure;
+    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
+
+    m_hint.m_x0 = x0;
+    m_hint.m_y0 = y0;
+    m_hint.m_sx = sx;
+    m_hint.m_sy = sy;
+    m_hint.m_overview = -1;
+    m_hint.m_valid = true;
+    //	printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
+    ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
+    m_hint.m_valid = false;
+
+    return ret;
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+const char *GDALWMSDataset::GetProjectionRef() {
+    return m_projection.c_str();
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+CPLErr GDALWMSDataset::SetProjection(const char *proj) {
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
+    gt[0] = m_data_window.m_x0;
+    gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
+    gt[2] = 0.0;
+    gt[3] = m_data_window.m_y0;
+    gt[4] = 0.0;
+    gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             AdviseRead()                             */
+/************************************************************************/
+CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) {
+//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
+    if (m_offline_mode || !m_use_advise_read) return CE_None;
+    if (m_cache == NULL) return CE_Failure;
+
+    GDALRasterBand *band = GetRasterBand(1);
+    if (band == NULL) return CE_Failure;
+    return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GDALWMSDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "WMS", NULL);
+}
+
+/************************************************************************/
+/*                          GetMetadataItem()                           */
+/************************************************************************/
+const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
+                                             const char * pszDomain )
+{
+    if( pszName != NULL && EQUAL(pszName, "XML") &&
+        pszDomain != NULL && EQUAL(pszDomain, "WMS") )
+    {
+        return (m_osXML.size()) ? m_osXML.c_str() : NULL;
+    }
+
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
diff --git a/frmts/wms/gdalwmsrasterband.cpp b/frmts/wms/gdalwmsrasterband.cpp
new file mode 100644
index 0000000..159ba63
--- /dev/null
+++ b/frmts/wms/gdalwmsrasterband.cpp
@@ -0,0 +1,867 @@
+/******************************************************************************
+ * $Id: gdalwmsrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  GDALWMSRasterBand implementation.
+ * Author:   Adam Nowacki, nowak at xpam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "wmsdriver.h"
+
+GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale) {
+    //	printf("[%p] GDALWMSRasterBand::GDALWMSRasterBand(%p, %d, %f)\n", this, parent_dataset, band, scale);
+    m_parent_dataset = parent_dataset;
+    m_scale = scale;
+    m_overview = -1;
+    m_color_interp = GCI_Undefined;
+
+    poDS = parent_dataset;
+    nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
+    nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
+    nBand = band;
+    eDataType = m_parent_dataset->m_data_type;
+    nBlockXSize = m_parent_dataset->m_block_size_x;
+    nBlockYSize = m_parent_dataset->m_block_size_y;
+}
+
+GDALWMSRasterBand::~GDALWMSRasterBand() {
+    for (std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin(); it != m_overviews.end(); ++it) {
+        GDALWMSRasterBand *p = *it;
+        delete p;
+    }
+}
+
+char** GDALWMSRasterBand::BuildHTTPRequestOpts()
+{
+    char **http_request_opts = NULL;
+    if (m_parent_dataset->m_http_timeout != -1) {
+        CPLString http_request_optstr;
+        http_request_optstr.Printf("TIMEOUT=%d", m_parent_dataset->m_http_timeout);
+        http_request_opts = CSLAddString(http_request_opts, http_request_optstr.c_str());
+    }
+
+    if (m_parent_dataset->m_osUserAgent.size() != 0)
+    {
+        CPLString osUserAgentOptStr("USERAGENT=");
+        osUserAgentOptStr += m_parent_dataset->m_osUserAgent;
+        http_request_opts = CSLAddString(http_request_opts, osUserAgentOptStr.c_str());
+    }
+    if (m_parent_dataset->m_osReferer.size() != 0)
+    {
+        CPLString osRefererOptStr("REFERER=");
+        osRefererOptStr += m_parent_dataset->m_osReferer;
+        http_request_opts = CSLAddString(http_request_opts, osRefererOptStr.c_str());
+    }
+    if (m_parent_dataset->m_unsafeSsl >= 1) {
+        http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
+    }
+    if (m_parent_dataset->m_osUserPwd.size() != 0) 
+    {
+        CPLString osUserPwdOptStr("USERPWD=");
+        osUserPwdOptStr += m_parent_dataset->m_osUserPwd;
+        http_request_opts = CSLAddString(http_request_opts, osUserPwdOptStr.c_str());
+    }
+
+   return http_request_opts;
+}
+
+CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
+    CPLErr ret = CE_None;
+    int i;
+
+    int max_request_count = (bx1 - bx0 + 1) * (by1 - by0 + 1);
+    int request_count = 0;
+    CPLHTTPRequest *download_requests = NULL;
+    GDALWMSCache *cache = m_parent_dataset->m_cache;
+    struct BlockXY {
+        int x, y;
+    } *download_blocks = NULL;
+    if (!m_parent_dataset->m_offline_mode) {
+        download_requests = new CPLHTTPRequest[max_request_count];
+        download_blocks = new BlockXY[max_request_count];
+    }
+
+    char **http_request_opts = BuildHTTPRequestOpts();
+
+    for (int iy = by0; iy <= by1; ++iy) {
+        for (int ix = bx0; ix <= bx1; ++ix) {
+            bool need_this_block = false;
+            if (!advise_read) {
+                for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+                    if ((ix == x) && (iy == y) && (ib == nBand)) {
+                        need_this_block = true;
+                    } else {
+                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                        if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
+                    }
+                }
+            } else {
+                need_this_block = true;
+            }
+            CPLString url;
+            if (need_this_block) {
+                CPLString file_name;
+                AskMiniDriverForBlock(&url, ix, iy);
+                if ((cache != NULL) && (cache->Read(url.c_str(), &file_name) == CE_None)) {
+                    if (advise_read) {
+                        need_this_block = false;
+                    } else {
+                        void *p = 0;
+                        if ((ix == x) && (iy == y)) p = buffer;
+                        if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
+                    }
+                }
+            }
+            if (need_this_block) {
+                if (m_parent_dataset->m_offline_mode) {
+                    if (!advise_read) {
+                        void *p = 0;
+                        if ((ix == x) && (iy == y)) p = buffer;
+                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                            ret = CE_Failure;
+                        }
+                    }
+                } else {
+                    CPLHTTPInitializeRequest(&download_requests[request_count], url.c_str(), http_request_opts);
+                    download_blocks[request_count].x = ix;
+                    download_blocks[request_count].y = iy;
+                    ++request_count;
+                }
+            }
+        }
+    }
+    if (http_request_opts != NULL) {
+        CSLDestroy(http_request_opts);
+    }
+
+    if (request_count > 0) {
+        char **opts = NULL;
+        CPLString optstr;
+        if (m_parent_dataset->m_http_max_conn != -1) {
+            optstr.Printf("MAXCONN=%d", m_parent_dataset->m_http_max_conn);
+            opts = CSLAddString(opts, optstr.c_str());
+        }
+        if (CPLHTTPFetchMulti(download_requests, request_count, opts) != CE_None) {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
+            ret = CE_Failure;
+        }
+        if (opts != NULL) {
+            CSLDestroy(opts);
+        }
+    }
+
+    for (i = 0; i < request_count; ++i) {
+        if (ret == CE_None) {
+            if ((download_requests[i].nStatus == 200) && (download_requests[i].pabyData != NULL) && (download_requests[i].nDataLen > 0)) {
+                CPLString file_name(BufferToVSIFile(download_requests[i].pabyData, download_requests[i].nDataLen));
+                if (file_name.size() > 0) {
+                    bool wms_exception = false;
+                    /* check for error xml */
+                    if (download_requests[i].nDataLen >= 20) {
+                        const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
+                        if (EQUALN(download_data, "<?xml ", 6) 
+                        || EQUALN(download_data, "<!DOCTYPE ", 10)
+                        || EQUALN(download_data, "<ServiceException", 17)) {
+                            if (ReportWMSException(file_name.c_str()) != CE_None) {
+                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
+                            }
+                            wms_exception = true;
+                            ret = CE_Failure;
+                        }
+                    }
+                    if (ret == CE_None) {
+                        if (advise_read && !m_parent_dataset->m_verify_advise_read) {
+                            if (cache != NULL) {
+                                cache->Write(download_requests[i].pszURL, file_name);
+                            }
+                        } else {
+                            void *p = 0;
+                            if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
+                            if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
+                                if (cache != NULL) {
+                                    cache->Write(download_requests[i].pszURL, file_name);
+                                }
+                            } else {
+                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ReadBlockFromFile (%s) failed.",
+                                         download_requests[i].pszURL);
+                                ret = CE_Failure;
+                            }
+                        }
+                    } else if( wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions ) {
+                         void *p = 0;
+                         if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
+                         if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
+                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                         } else {
+                             ret = CE_None;
+                         }
+
+                    }
+                    VSIUnlink(file_name.c_str());
+                }
+            } else {
+               std::vector<int>::iterator zero_it = std::find(
+                     m_parent_dataset->m_http_zeroblock_codes.begin(),
+                     m_parent_dataset->m_http_zeroblock_codes.end(),
+                     download_requests[i].nStatus);
+               if ( zero_it != m_parent_dataset->m_http_zeroblock_codes.end() ) {
+                    if (!advise_read) {
+                        void *p = 0;
+                        if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
+                        if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                            ret = CE_Failure;
+                        }
+                    }
+                } else {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.",
+                        download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus, 
+		    download_requests[i].pszError ? download_requests[i].pszError : "(null)");
+                    ret = CE_Failure;
+                }
+            }
+        }
+        CPLHTTPCleanupRequest(&download_requests[i]);
+    }
+    if (!m_parent_dataset->m_offline_mode) {
+        delete[] download_blocks;
+        delete[] download_requests;
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
+    int bx0 = x;
+    int by0 = y;
+    int bx1 = x;
+    int by1 = y;
+
+    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview)) {
+        int tbx0 = m_parent_dataset->m_hint.m_x0 / nBlockXSize;
+        int tby0 = m_parent_dataset->m_hint.m_y0 / nBlockYSize;
+        int tbx1 = (m_parent_dataset->m_hint.m_x0 + m_parent_dataset->m_hint.m_sx - 1) / nBlockXSize;
+        int tby1 = (m_parent_dataset->m_hint.m_y0 + m_parent_dataset->m_hint.m_sy - 1) / nBlockYSize;
+        if ((tbx0 <= bx0) && (tby0 <= by0) && (tbx1 >= bx1) && (tby1 >= by1)) {
+            bx0 = tbx0;
+            by0 = tby0;
+            bx1 = tbx1;
+            by1 = tby1;
+        }
+    }
+
+    CPLErr eErr = ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
+
+    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview))
+    {
+        m_parent_dataset->m_hint.m_valid = false;
+    }
+
+    return eErr;
+}
+
+CPLErr GDALWMSRasterBand::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int pixel_space, int line_space) {
+    CPLErr ret;
+
+    if (rw != GF_Read) return CE_Failure;
+    if (buffer == NULL) return CE_Failure;
+    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0)) return CE_None;
+
+    m_parent_dataset->m_hint.m_x0 = x0;
+    m_parent_dataset->m_hint.m_y0 = y0;
+    m_parent_dataset->m_hint.m_sx = sx;
+    m_parent_dataset->m_hint.m_sy = sy;
+    m_parent_dataset->m_hint.m_overview = m_overview;
+    m_parent_dataset->m_hint.m_valid = true;
+    ret = GDALRasterBand::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, pixel_space, line_space);
+    m_parent_dataset->m_hint.m_valid = false;
+
+    return ret;
+}
+
+int GDALWMSRasterBand::HasArbitraryOverviews() {
+//    return m_parent_dataset->m_mini_driver_caps.m_has_arb_overviews;
+    return 0; // not implemented yet
+}
+
+int GDALWMSRasterBand::GetOverviewCount() {
+    return m_overviews.size();
+}
+
+GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
+    if ((m_overviews.size() > 0) && (static_cast<size_t>(n) < m_overviews.size())) return m_overviews[n];
+    else return NULL;
+}
+
+void GDALWMSRasterBand::AddOverview(double scale) {
+    GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand, scale);
+    std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin();
+    for (; it != m_overviews.end(); ++it) {
+        GDALWMSRasterBand *p = *it;
+        if (p->m_scale < scale) break;
+    }
+    m_overviews.insert(it, overview);
+    it = m_overviews.begin();
+    for (int i = 0; it != m_overviews.end(); ++it, ++i) {
+        GDALWMSRasterBand *p = *it;
+        p->m_overview = i;
+    }
+}
+
+bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
+    bool ret = false;
+    GDALRasterBlock *b = TryGetLockedBlockRef(x, y);
+    if (b != NULL) {
+        ret = true;
+        b->DropLock();
+    }
+    return ret;
+}
+
+// This is the function that calculates the block coordinates for the fetch
+void GDALWMSRasterBand::AskMiniDriverForBlock(CPLString *url, int x, int y)
+{
+    GDALWMSImageRequestInfo iri;
+    GDALWMSTiledImageRequestInfo tiri;
+
+    ComputeRequestInfo(iri, tiri, x, y);
+
+    m_parent_dataset->m_mini_driver->TiledImageRequest(url, iri, tiri);
+}
+
+void GDALWMSRasterBand::ComputeRequestInfo(GDALWMSImageRequestInfo &iri,
+                                           GDALWMSTiledImageRequestInfo &tiri,
+                                           int x, int y)
+{
+    int x0 = MAX(0, x * nBlockXSize);
+    int y0 = MAX(0, y * nBlockYSize);
+    int x1 = MAX(0, (x + 1) * nBlockXSize);
+    int y1 = MAX(0, (y + 1) * nBlockYSize);
+    if (m_parent_dataset->m_clamp_requests) {
+	x0 = MIN(x0, nRasterXSize);
+	y0 = MIN(y0, nRasterYSize);
+	x1 = MIN(x1, nRasterXSize);
+	y1 = MIN(y1, nRasterYSize);
+    }
+    
+    const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
+    const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
+    /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
+    iri.m_x0 = x0 * rx + m_parent_dataset->m_data_window.m_x0;
+    iri.m_y0 = y0 * ry + m_parent_dataset->m_data_window.m_y0;
+    iri.m_x1 = m_parent_dataset->m_data_window.m_x1 - (nRasterXSize - x1) * rx;
+    iri.m_y1 = m_parent_dataset->m_data_window.m_y1 - (nRasterYSize - y1) * ry;
+    iri.m_sx = x1 - x0;
+    iri.m_sy = y1 - y0;
+
+    int level = m_overview + 1;
+    tiri.m_x = (m_parent_dataset->m_data_window.m_tx >> level) + x;
+    tiri.m_y = (m_parent_dataset->m_data_window.m_ty >> level) + y;
+    tiri.m_level = m_parent_dataset->m_data_window.m_tlevel - level;
+}
+
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GDALWMSRasterBand::GetMetadataDomainList()
+{
+    return CSLAddString(GDALPamRasterBand::GetMetadataDomainList(), "LocationInfo");
+}
+
+const char *GDALWMSRasterBand::GetMetadataItem( const char * pszName,
+                                                const char * pszDomain )
+{
+/* ==================================================================== */
+/*      LocationInfo handling.                                          */
+/* ==================================================================== */
+    if( pszDomain != NULL
+        && EQUAL(pszDomain,"LocationInfo")
+        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
+    {
+        int iPixel, iLine;
+
+/* -------------------------------------------------------------------- */
+/*      What pixel are we aiming at?                                    */
+/* -------------------------------------------------------------------- */
+        if( EQUALN(pszName,"Pixel_",6) )
+        {
+            if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
+                return NULL;
+        }
+        else if( EQUALN(pszName,"GeoPixel_",9) )
+        {
+            double adfGeoTransform[6];
+            double adfInvGeoTransform[6];
+            double dfGeoX, dfGeoY;
+
+            {
+                CPLLocaleC oLocaleEnforcer;
+                if( sscanf( pszName+9, "%lf_%lf", &dfGeoX, &dfGeoY ) != 2 )
+                    return NULL;
+            }
+
+            if( GetDataset() == NULL )
+                return NULL;
+
+            if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
+                return NULL;
+
+            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
+                return NULL;
+
+            iPixel = (int) floor(
+                adfInvGeoTransform[0]
+                + adfInvGeoTransform[1] * dfGeoX
+                + adfInvGeoTransform[2] * dfGeoY );
+            iLine = (int) floor(
+                adfInvGeoTransform[3]
+                + adfInvGeoTransform[4] * dfGeoX
+                + adfInvGeoTransform[5] * dfGeoY );
+
+            /* The GetDataset() for the WMS driver is always the main overview level, so rescale */
+            /* the values if we are an overview */
+            if (m_overview >= 0)
+            {
+                iPixel = (int) (1.0 * iPixel * GetXSize() / GetDataset()->GetRasterBand(1)->GetXSize());
+                iLine = (int) (1.0 * iLine * GetYSize() / GetDataset()->GetRasterBand(1)->GetYSize());
+            }
+        }
+        else
+            return NULL;
+
+        if( iPixel < 0 || iLine < 0
+            || iPixel >= GetXSize()
+            || iLine >= GetYSize() )
+            return NULL;
+
+        if (nBand != 1)
+        {
+            GDALRasterBand* poFirstBand = m_parent_dataset->GetRasterBand(1);
+            if (m_overview >= 0)
+                poFirstBand = poFirstBand->GetOverview(m_overview);
+            if (poFirstBand)
+                return poFirstBand->GetMetadataItem(pszName, pszDomain);
+        }
+
+        GDALWMSImageRequestInfo iri;
+        GDALWMSTiledImageRequestInfo tiri;
+        int nBlockXOff = iPixel / nBlockXSize;
+        int nBlockYOff = iLine / nBlockYSize;
+
+        ComputeRequestInfo(iri, tiri, nBlockXOff, nBlockYOff);
+
+        CPLString url;
+        m_parent_dataset->m_mini_driver->GetTiledImageInfo(&url,
+                                                           iri, tiri,
+                                                           iPixel % nBlockXSize,
+                                                           iLine % nBlockXSize);
+
+
+        char* pszRes = NULL;
+
+        if (url.size() != 0)
+        {
+            if (url == osMetadataItemURL)
+            {
+                return osMetadataItem.size() != 0 ? osMetadataItem.c_str() : NULL;
+            }
+            osMetadataItemURL = url;
+
+            char **http_request_opts = BuildHTTPRequestOpts();
+            CPLHTTPResult* psResult = CPLHTTPFetch( url.c_str(), http_request_opts);
+            if( psResult && psResult->pabyData )
+                pszRes = CPLStrdup((const char*) psResult->pabyData);
+            CPLHTTPDestroyResult(psResult);
+            CSLDestroy(http_request_opts);
+        }
+
+        if (pszRes)
+        {
+            osMetadataItem = "<LocationInfo>";
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            CPLXMLNode* psXML = CPLParseXMLString(pszRes);
+            CPLPopErrorHandler();
+            if (psXML != NULL && psXML->eType == CXT_Element)
+            {
+                if (strcmp(psXML->pszValue, "?xml") == 0)
+                {
+                    if (psXML->psNext)
+                    {
+                        char* pszXML = CPLSerializeXMLTree(psXML->psNext);
+                        osMetadataItem += pszXML;
+                        CPLFree(pszXML);
+                    }
+                }
+                else
+                {
+                    osMetadataItem += pszRes;
+                }
+            }
+            else
+            {
+                char* pszEscapedXML = CPLEscapeString(pszRes, -1, CPLES_XML_BUT_QUOTES);
+                osMetadataItem += pszEscapedXML;
+                CPLFree(pszEscapedXML);
+            }
+            if (psXML != NULL)
+                CPLDestroyXMLNode(psXML);
+
+            osMetadataItem += "</LocationInfo>";
+            CPLFree(pszRes);
+            return osMetadataItem.c_str();
+        }
+        else
+        {
+            osMetadataItem = "";
+            return NULL;
+        }
+    }
+
+    return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
+}
+
+CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
+    CPLErr ret = CE_None;
+    GDALDataset *ds = 0;
+    GByte *color_table = NULL;
+    int i;
+
+    //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);
+
+    /* expected size */
+    const int esx = MIN(MAX(0, (x + 1) * nBlockXSize), nRasterXSize) - MIN(MAX(0, x * nBlockXSize), nRasterXSize);
+    const int esy = MIN(MAX(0, (y + 1) * nBlockYSize), nRasterYSize) - MIN(MAX(0, y * nBlockYSize), nRasterYSize);
+    ds = reinterpret_cast<GDALDataset*>(GDALOpen(file_name, GA_ReadOnly));
+    if (ds != NULL) {
+        int sx = ds->GetRasterXSize();
+        int sy = ds->GetRasterYSize();
+        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3  
+        /* Allow bigger than expected so pre-tiled constant size images work on corners */
+        if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
+                sx, sy, esx, esy, nBlockXSize, nBlockYSize);
+            ret = CE_Failure;
+        }
+        if (ret == CE_None) {
+            int nDSRasterCount = ds->GetRasterCount();
+            if (nDSRasterCount != m_parent_dataset->nBands) {
+                /* Maybe its an image with color table */
+                bool accepted_as_ct = false;
+                if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
+                    GDALRasterBand *rb = ds->GetRasterBand(1);
+                    if (rb->GetRasterDataType() == GDT_Byte) {
+                        GDALColorTable *ct = rb->GetColorTable();
+                        if (ct != NULL) {
+                            accepted_as_ct = true;
+                            if (!advise_read) {
+                                color_table = new GByte[256 * 4];
+                                const int count = MIN(256, ct->GetColorEntryCount());
+                                for (i = 0; i < count; ++i) {
+                                    GDALColorEntry ce;
+                                    ct->GetColorEntryAsRGB(i, &ce);
+                                    color_table[i] = static_cast<GByte>(ce.c1);
+                                    color_table[i + 256] = static_cast<GByte>(ce.c2);
+                                    color_table[i + 512] = static_cast<GByte>(ce.c3);
+                                    color_table[i + 768] = static_cast<GByte>(ce.c4);
+                                }
+                                for (i = count; i < 256; ++i) {
+                                    color_table[i] = 0;
+                                    color_table[i + 256] = 0;
+                                    color_table[i + 512] = 0;
+                                    color_table[i + 768] = 0;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (nDSRasterCount == 4 && m_parent_dataset->nBands == 3)
+                {
+                    /* metacarta TMS service sometimes return a 4 band PNG instead of the expected 3 band... */
+                }
+                else if (!accepted_as_ct) {
+                   if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
+                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque" 
+                      accepted_as_no_alpha = true;
+                   }
+                   else
+                   {
+                      CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
+                         nDSRasterCount, m_parent_dataset->nBands);
+                      ret = CE_Failure;
+                   }
+                }
+            }
+        }
+        if (!advise_read) {
+            for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+                if (ret == CE_None) {
+                    void *p = NULL;
+                    GDALRasterBlock *b = NULL;
+                    if ((buffer != NULL) && (ib == to_buffer_band)) {
+                        p = buffer;
+                    } else {
+                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                        if (!band->IsBlockInCache(x, y)) {
+                            b = band->GetLockedBlockRef(x, y, true);
+                            if (b != NULL) {
+                                p = b->GetDataRef();
+                                if (p == NULL) {
+                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
+                                  ret = CE_Failure;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
+                        }
+                    }
+                    if (p != NULL) {
+                        int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
+                        int line_space = pixel_space * nBlockXSize;
+                        if (color_table == NULL) {
+                            if( ib <= ds->GetRasterCount()) {
+				GDALDataType dt=eDataType;
+				// Get the data from the PNG as stored instead of converting, if the server asks for that
+                                // TODO: This hack is from #3493 - not sure it really belongs here.
+				if ((GDT_Int16==dt)&&(GDT_UInt16==ds->GetRasterBand(ib)->GetRasterDataType()))
+				    dt=GDT_UInt16;
+				if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, dt, 1, &ib, pixel_space, line_space, 0) != CE_None) {
+				    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
+				    ret = CE_Failure;
+				}
+                            }
+                            else
+                            {  // parent expects 4 bands but file only has 3 so generate a all "opaque" 4th band
+                               if (accepted_as_no_alpha)
+                               {
+                                  // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
+                                  GByte *byte_buffer = reinterpret_cast<GByte *>(p);
+                                  for (int y = 0; y < sy; ++y) {
+                                     for (int x = 0; x < sx; ++x) {
+                                        const int offset = x + y * line_space;
+                                        byte_buffer[offset] = 255;  // fill with opaque
+                                     }
+                                  }
+                               }
+                               else
+                               {  // we should never get here because this case was caught above
+                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
+                                     ds->GetRasterCount(), m_parent_dataset->nBands);
+                                  ret = CE_Failure;
+                               }     
+                            }
+                        } else if (ib <= 4) {
+                            if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0) != CE_None) {
+                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
+                                ret = CE_Failure;
+                            }
+                            if (ret == CE_None) {
+                                GByte *band_color_table = color_table + 256 * (ib - 1);
+                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
+                                for (int y = 0; y < sy; ++y) {
+                                    for (int x = 0; x < sx; ++x) {
+                                        const int offset = x + y * line_space;
+                                        byte_buffer[offset] = band_color_table[byte_buffer[offset]];
+                                    }
+                                }
+                            }
+                        } else {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
+                            ret = CE_Failure;
+                        }
+                    }
+                    if (b != NULL) {
+                        b->DropLock();
+                    }
+                }
+            }
+        }
+        GDALClose(ds);
+    } else {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
+        ret = CE_Failure;
+    }
+
+    if (color_table != NULL) {
+        delete[] color_table;
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
+    CPLErr ret = CE_None;
+
+    for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+        if (ret == CE_None) {
+            void *p = NULL;
+            GDALRasterBlock *b = NULL;
+            if ((buffer != NULL) && (ib == to_buffer_band)) {
+                p = buffer;
+            } else {
+                GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                if (!band->IsBlockInCache(x, y)) {
+                    b = band->GetLockedBlockRef(x, y, true);
+                    if (b != NULL) {
+                        p = b->GetDataRef();
+                        if (p == NULL) {
+                          CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
+                          ret = CE_Failure;
+                        }
+                    }
+                }
+            }
+            if (p != NULL) {
+                unsigned char *b = reinterpret_cast<unsigned char *>(p);
+                int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
+                for (int i = 0; i < block_size; ++i) b[i] = 0;
+            }
+            if (b != NULL) {
+                b->DropLock();
+            }
+        }
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::ReportWMSException(const char *file_name) {
+    CPLErr ret = CE_None;
+    int reported_errors_count = 0;
+
+    CPLXMLNode *orig_root = CPLParseXMLFile(file_name);
+    CPLXMLNode *root = orig_root;
+    if (root != NULL) {
+        root = CPLGetXMLNode(root, "=ServiceExceptionReport");
+    }
+    if (root != NULL) {
+        CPLXMLNode *n = CPLGetXMLNode(root, "ServiceException");
+        while (n != NULL) {
+            const char *exception = CPLGetXMLValue(n, "=ServiceException", "");
+            const char *exception_code = CPLGetXMLValue(n, "=ServiceException.code", "");
+            if (exception[0] != '\0') {
+                if (exception_code[0] != '\0') {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s': %s", exception_code, exception);
+                    ++reported_errors_count;
+                } else {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception: %s", exception);
+                    ++reported_errors_count;
+                }
+            } else if (exception_code[0] != '\0') {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s'.", exception_code);
+                ++reported_errors_count;
+            }
+
+            n = n->psNext;
+            if (n != NULL) {
+                n = CPLGetXMLNode(n, "=ServiceException");
+            }
+        }
+    } else {
+        ret = CE_Failure;
+    }
+    if (orig_root != NULL) {
+        CPLDestroyXMLNode(orig_root);
+    }
+
+    if (reported_errors_count == 0) {
+        ret = CE_Failure;
+    }
+
+    return ret;
+}
+
+
+CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options) {
+//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
+    if (m_parent_dataset->m_offline_mode || !m_parent_dataset->m_use_advise_read) return CE_None;
+    if (m_parent_dataset->m_cache == NULL) return CE_Failure;
+
+    int bx0 = x0 / nBlockXSize;
+    int by0 = y0 / nBlockYSize;
+    int bx1 = (x0 + sx - 1) / nBlockXSize;
+    int by1 = (y0 + sy - 1) / nBlockYSize;
+
+    return ReadBlocks(0, 0, NULL, bx0, by0, bx1, by1, 1);
+}
+
+GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
+    return m_color_interp;
+}
+
+CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
+{
+    m_color_interp = eNewInterp;
+    return CE_None;
+}
+
+// Utility function, returns a value from a vector corresponding to the band index
+// or the first entry
+static double getBandValue(std::vector<double> &v,size_t idx)
+{
+    idx--;
+    if (v.size()>idx) return v[idx];
+    return v[0];
+}
+
+double GDALWMSRasterBand::GetNoDataValue( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vNoData;
+    if (v.size()==0)
+        return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+double GDALWMSRasterBand::GetMinimum( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vMin;
+    if (v.size()==0)
+        return GDALPamRasterBand::GetMinimum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+double GDALWMSRasterBand::GetMaximum( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vMax;
+    if (v.size()==0)
+        return GDALPamRasterBand::GetMaximum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+GDALColorTable *GDALWMSRasterBand::GetColorTable()
+{
+    return m_parent_dataset->m_poColorTable;
+}
diff --git a/frmts/wms/makefile.vc b/frmts/wms/makefile.vc
index 620f2eb..d42fd77 100644
--- a/frmts/wms/makefile.vc
+++ b/frmts/wms/makefile.vc
@@ -1,7 +1,10 @@
 
-OBJ	=	cache.obj dataset.obj gdalhttp.obj md5.obj minidriver.obj rasterband.obj stuff.obj wmsdriver.obj \
-		minidriver_wms.obj minidriver_tileservice.obj minidriver_worldwind.obj minidriver_tms.obj minidriver_tiled_wms.obj \
-		wmsmetadataset.obj minidriver_virtualearth.obj
+OBJ	= \
+	gdalwmscache.obj gdalwmsdataset.obj gdalwmsrasterband.obj wmsutils.obj \
+	gdalhttp.obj md5.obj minidriver.obj  wmsdriver.obj \
+	minidriver_wms.obj minidriver_tileservice.obj \
+	minidriver_worldwind.obj minidriver_tms.obj minidriver_tiled_wms.obj \
+	wmsmetadataset.obj minidriver_virtualearth.obj
 
 EXTRAFLAGS = -DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC)
 
diff --git a/frmts/wms/minidriver.cpp b/frmts/wms/minidriver.cpp
index 8ae2f8d..aa79f6c 100644
--- a/frmts/wms/minidriver.cpp
+++ b/frmts/wms/minidriver.cpp
@@ -1,9 +1,8 @@
 /******************************************************************************
- * $Id: minidriver.cpp 23722 2012-01-07 22:15:29Z rouault $
+ * $Id: minidriver.cpp 26079 2013-06-13 01:31:48Z warmerdam $
  *
  * Project:  WMS Client Driver
- * Purpose:  Implementation of Dataset and RasterBand classes for WMS
- *           and other similar services.
+ * Purpose:  GDALWMSMiniDriver base class implementation.
  * Author:   Adam Nowacki, nowak at xpam.de
  *
  ******************************************************************************
@@ -28,7 +27,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
 
 static volatile GDALWMSMiniDriverManager *g_mini_driver_manager = NULL;
 static void *g_mini_driver_manager_mutex = NULL;
diff --git a/frmts/wms/minidriver_tiled_wms.cpp b/frmts/wms/minidriver_tiled_wms.cpp
index 6403142..13500ce 100644
--- a/frmts/wms/minidriver_tiled_wms.cpp
+++ b/frmts/wms/minidriver_tiled_wms.cpp
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,7 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_tiled_wms.h"
 
 CPP_GDALWMSMiniDriverFactory(TiledWMS)
 
diff --git a/frmts/wms/minidriver_tileservice.cpp b/frmts/wms/minidriver_tileservice.cpp
index e1723a9..da342aa 100644
--- a/frmts/wms/minidriver_tileservice.cpp
+++ b/frmts/wms/minidriver_tileservice.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_tileservice.cpp 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: minidriver_tileservice.cpp 26079 2013-06-13 01:31:48Z warmerdam $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,7 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_tileservice.h"
 
 CPP_GDALWMSMiniDriverFactory(TileService)
 
diff --git a/frmts/wms/minidriver_tms.cpp b/frmts/wms/minidriver_tms.cpp
index 22264ab..13105d1 100644
--- a/frmts/wms/minidriver_tms.cpp
+++ b/frmts/wms/minidriver_tms.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_tms.cpp 22021 2011-03-23 21:51:19Z rouault $
+ * $Id: minidriver_tms.cpp 26079 2013-06-13 01:31:48Z warmerdam $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,7 +28,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_tms.h"
+
 
 CPP_GDALWMSMiniDriverFactory(TMS)
 
diff --git a/frmts/wms/minidriver_virtualearth.cpp b/frmts/wms/minidriver_virtualearth.cpp
index 55775fb..ff86064 100644
--- a/frmts/wms/minidriver_virtualearth.cpp
+++ b/frmts/wms/minidriver_virtualearth.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_virtualearth.cpp 23033 2011-09-03 18:46:11Z rouault $
+ * $Id: minidriver_virtualearth.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -7,7 +7,7 @@
  * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,7 +28,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_virtualearth.h"
+
 
 CPP_GDALWMSMiniDriverFactory(VirtualEarth)
 
diff --git a/frmts/wms/minidriver_virtualearth.h b/frmts/wms/minidriver_virtualearth.h
index cedd5a7..208ded1 100644
--- a/frmts/wms/minidriver_virtualearth.h
+++ b/frmts/wms/minidriver_virtualearth.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_virtualearth.h 21948 2011-03-12 21:31:21Z rouault $
+ * $Id: minidriver_virtualearth.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -7,7 +7,7 @@
  * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/frmts/wms/minidriver_wms.cpp b/frmts/wms/minidriver_wms.cpp
index 3deca10..9b670b4 100644
--- a/frmts/wms/minidriver_wms.cpp
+++ b/frmts/wms/minidriver_wms.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_wms.cpp 23722 2012-01-07 22:15:29Z rouault $
+ * $Id: minidriver_wms.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,7 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_wms.h"
 
 CPP_GDALWMSMiniDriverFactory(WMS)
 
diff --git a/frmts/wms/minidriver_worldwind.cpp b/frmts/wms/minidriver_worldwind.cpp
index 718940a..86a468f 100644
--- a/frmts/wms/minidriver_worldwind.cpp
+++ b/frmts/wms/minidriver_worldwind.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_worldwind.cpp 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: minidriver_worldwind.cpp 26079 2013-06-13 01:31:48Z warmerdam $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,7 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
+#include "minidriver_worldwind.h"
 
 CPP_GDALWMSMiniDriverFactory(WorldWind)
 
diff --git a/frmts/wms/rasterband.cpp b/frmts/wms/rasterband.cpp
deleted file mode 100644
index f2b2575..0000000
--- a/frmts/wms/rasterband.cpp
+++ /dev/null
@@ -1,857 +0,0 @@
-/******************************************************************************
- * $Id: rasterband.cpp 25776 2013-03-20 20:46:48Z rouault $
- *
- * Project:  WMS Client Driver
- * Purpose:  Implementation of Dataset and RasterBand classes for WMS
- *           and other similar services.
- * Author:   Adam Nowacki, nowak at xpam.de
- *
- ******************************************************************************
- * Copyright (c) 2007, Adam Nowacki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "stdinc.h"
-
-GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale) {
-    //	printf("[%p] GDALWMSRasterBand::GDALWMSRasterBand(%p, %d, %f)\n", this, parent_dataset, band, scale);
-    m_parent_dataset = parent_dataset;
-    m_scale = scale;
-    m_overview = -1;
-    m_color_interp = GCI_Undefined;
-
-    poDS = parent_dataset;
-    nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
-    nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
-    nBand = band;
-    eDataType = m_parent_dataset->m_data_type;
-    nBlockXSize = m_parent_dataset->m_block_size_x;
-    nBlockYSize = m_parent_dataset->m_block_size_y;
-}
-
-GDALWMSRasterBand::~GDALWMSRasterBand() {
-    for (std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin(); it != m_overviews.end(); ++it) {
-        GDALWMSRasterBand *p = *it;
-        delete p;
-    }
-}
-
-char** GDALWMSRasterBand::BuildHTTPRequestOpts()
-{
-    char **http_request_opts = NULL;
-    if (m_parent_dataset->m_http_timeout != -1) {
-        CPLString http_request_optstr;
-        http_request_optstr.Printf("TIMEOUT=%d", m_parent_dataset->m_http_timeout);
-        http_request_opts = CSLAddString(http_request_opts, http_request_optstr.c_str());
-    }
-
-    if (m_parent_dataset->m_osUserAgent.size() != 0)
-    {
-        CPLString osUserAgentOptStr("USERAGENT=");
-        osUserAgentOptStr += m_parent_dataset->m_osUserAgent;
-        http_request_opts = CSLAddString(http_request_opts, osUserAgentOptStr.c_str());
-    }
-    if (m_parent_dataset->m_osReferer.size() != 0)
-    {
-        CPLString osRefererOptStr("REFERER=");
-        osRefererOptStr += m_parent_dataset->m_osReferer;
-        http_request_opts = CSLAddString(http_request_opts, osRefererOptStr.c_str());
-    }
-    if (m_parent_dataset->m_unsafeSsl >= 1) {
-        http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
-    }
-    if (m_parent_dataset->m_osUserPwd.size() != 0) 
-    {
-        CPLString osUserPwdOptStr("USERPWD=");
-        osUserPwdOptStr += m_parent_dataset->m_osUserPwd;
-        http_request_opts = CSLAddString(http_request_opts, osUserPwdOptStr.c_str());
-    }
-
-   return http_request_opts;
-}
-
-CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
-    CPLErr ret = CE_None;
-    int i;
-
-    int max_request_count = (bx1 - bx0 + 1) * (by1 - by0 + 1);
-    int request_count = 0;
-    CPLHTTPRequest *download_requests = NULL;
-    GDALWMSCache *cache = m_parent_dataset->m_cache;
-    struct BlockXY {
-        int x, y;
-    } *download_blocks = NULL;
-    if (!m_parent_dataset->m_offline_mode) {
-        download_requests = new CPLHTTPRequest[max_request_count];
-        download_blocks = new BlockXY[max_request_count];
-    }
-
-    char **http_request_opts = BuildHTTPRequestOpts();
-
-    for (int iy = by0; iy <= by1; ++iy) {
-        for (int ix = bx0; ix <= bx1; ++ix) {
-            bool need_this_block = false;
-            if (!advise_read) {
-                for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-                    if ((ix == x) && (iy == y) && (ib == nBand)) {
-                        need_this_block = true;
-                    } else {
-                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                        if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
-                    }
-                }
-            } else {
-                need_this_block = true;
-            }
-            CPLString url;
-            if (need_this_block) {
-                CPLString file_name;
-                AskMiniDriverForBlock(&url, ix, iy);
-                if ((cache != NULL) && (cache->Read(url.c_str(), &file_name) == CE_None)) {
-                    if (advise_read) {
-                        need_this_block = false;
-                    } else {
-                        void *p = 0;
-                        if ((ix == x) && (iy == y)) p = buffer;
-                        if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
-                    }
-                }
-            }
-            if (need_this_block) {
-                if (m_parent_dataset->m_offline_mode) {
-                    if (!advise_read) {
-                        void *p = 0;
-                        if ((ix == x) && (iy == y)) p = buffer;
-                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                            ret = CE_Failure;
-                        }
-                    }
-                } else {
-                    CPLHTTPInitializeRequest(&download_requests[request_count], url.c_str(), http_request_opts);
-                    download_blocks[request_count].x = ix;
-                    download_blocks[request_count].y = iy;
-                    ++request_count;
-                }
-            }
-        }
-    }
-    if (http_request_opts != NULL) {
-        CSLDestroy(http_request_opts);
-    }
-
-    if (request_count > 0) {
-        char **opts = NULL;
-        CPLString optstr;
-        if (m_parent_dataset->m_http_max_conn != -1) {
-            optstr.Printf("MAXCONN=%d", m_parent_dataset->m_http_max_conn);
-            opts = CSLAddString(opts, optstr.c_str());
-        }
-        if (CPLHTTPFetchMulti(download_requests, request_count, opts) != CE_None) {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
-            ret = CE_Failure;
-        }
-        if (opts != NULL) {
-            CSLDestroy(opts);
-        }
-    }
-
-    for (i = 0; i < request_count; ++i) {
-        if (ret == CE_None) {
-            if ((download_requests[i].nStatus == 200) && (download_requests[i].pabyData != NULL) && (download_requests[i].nDataLen > 0)) {
-                CPLString file_name(BufferToVSIFile(download_requests[i].pabyData, download_requests[i].nDataLen));
-                if (file_name.size() > 0) {
-                    bool wms_exception = false;
-                    /* check for error xml */
-                    if (download_requests[i].nDataLen >= 20) {
-                        const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
-                        if (EQUALN(download_data, "<?xml ", 6) 
-                        || EQUALN(download_data, "<!DOCTYPE ", 10)
-                        || EQUALN(download_data, "<ServiceException", 17)) {
-                            if (ReportWMSException(file_name.c_str()) != CE_None) {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
-                            }
-                            wms_exception = true;
-                            ret = CE_Failure;
-                        }
-                    }
-                    if (ret == CE_None) {
-                        if (advise_read && !m_parent_dataset->m_verify_advise_read) {
-                            if (cache != NULL) {
-                                cache->Write(download_requests[i].pszURL, file_name);
-                            }
-                        } else {
-                            void *p = 0;
-                            if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                            if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
-                                if (cache != NULL) {
-                                    cache->Write(download_requests[i].pszURL, file_name);
-                                }
-                            } else {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ReadBlockFromFile (%s) failed.",
-                                         download_requests[i].pszURL);
-                                ret = CE_Failure;
-                            }
-                        }
-                    } else if( wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions ) {
-                         void *p = 0;
-                         if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                         if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
-                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                         } else {
-                             ret = CE_None;
-                         }
-
-                    }
-                    VSIUnlink(file_name.c_str());
-                }
-            } else {
-               std::vector<int>::iterator zero_it = std::find(
-                     m_parent_dataset->m_http_zeroblock_codes.begin(),
-                     m_parent_dataset->m_http_zeroblock_codes.end(),
-                     download_requests[i].nStatus);
-               if ( zero_it != m_parent_dataset->m_http_zeroblock_codes.end() ) {
-                    if (!advise_read) {
-                        void *p = 0;
-                        if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                        if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                            ret = CE_Failure;
-                        }
-                    }
-                } else {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.",
-                        download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus, 
-		    download_requests[i].pszError ? download_requests[i].pszError : "(null)");
-                    ret = CE_Failure;
-                }
-            }
-        }
-        CPLHTTPCleanupRequest(&download_requests[i]);
-    }
-    if (!m_parent_dataset->m_offline_mode) {
-        delete[] download_blocks;
-        delete[] download_requests;
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
-    int bx0 = x;
-    int by0 = y;
-    int bx1 = x;
-    int by1 = y;
-
-    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview)) {
-        int tbx0 = m_parent_dataset->m_hint.m_x0 / nBlockXSize;
-        int tby0 = m_parent_dataset->m_hint.m_y0 / nBlockYSize;
-        int tbx1 = (m_parent_dataset->m_hint.m_x0 + m_parent_dataset->m_hint.m_sx - 1) / nBlockXSize;
-        int tby1 = (m_parent_dataset->m_hint.m_y0 + m_parent_dataset->m_hint.m_sy - 1) / nBlockYSize;
-        if ((tbx0 <= bx0) && (tby0 <= by0) && (tbx1 >= bx1) && (tby1 >= by1)) {
-            bx0 = tbx0;
-            by0 = tby0;
-            bx1 = tbx1;
-            by1 = tby1;
-        }
-    }
-
-    CPLErr eErr = ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
-
-    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview))
-    {
-        m_parent_dataset->m_hint.m_valid = false;
-    }
-
-    return eErr;
-}
-
-CPLErr GDALWMSRasterBand::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int pixel_space, int line_space) {
-    CPLErr ret;
-
-    if (rw != GF_Read) return CE_Failure;
-    if (buffer == NULL) return CE_Failure;
-    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0)) return CE_None;
-
-    m_parent_dataset->m_hint.m_x0 = x0;
-    m_parent_dataset->m_hint.m_y0 = y0;
-    m_parent_dataset->m_hint.m_sx = sx;
-    m_parent_dataset->m_hint.m_sy = sy;
-    m_parent_dataset->m_hint.m_overview = m_overview;
-    m_parent_dataset->m_hint.m_valid = true;
-    ret = GDALRasterBand::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, pixel_space, line_space);
-    m_parent_dataset->m_hint.m_valid = false;
-
-    return ret;
-}
-
-int GDALWMSRasterBand::HasArbitraryOverviews() {
-//    return m_parent_dataset->m_mini_driver_caps.m_has_arb_overviews;
-    return 0; // not implemented yet
-}
-
-int GDALWMSRasterBand::GetOverviewCount() {
-    return m_overviews.size();
-}
-
-GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
-    if ((m_overviews.size() > 0) && (static_cast<size_t>(n) < m_overviews.size())) return m_overviews[n];
-    else return NULL;
-}
-
-void GDALWMSRasterBand::AddOverview(double scale) {
-    GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand, scale);
-    std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin();
-    for (; it != m_overviews.end(); ++it) {
-        GDALWMSRasterBand *p = *it;
-        if (p->m_scale < scale) break;
-    }
-    m_overviews.insert(it, overview);
-    it = m_overviews.begin();
-    for (int i = 0; it != m_overviews.end(); ++it, ++i) {
-        GDALWMSRasterBand *p = *it;
-        p->m_overview = i;
-    }
-}
-
-bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
-    bool ret = false;
-    GDALRasterBlock *b = TryGetLockedBlockRef(x, y);
-    if (b != NULL) {
-        ret = true;
-        b->DropLock();
-    }
-    return ret;
-}
-
-// This is the function that calculates the block coordinates for the fetch
-void GDALWMSRasterBand::AskMiniDriverForBlock(CPLString *url, int x, int y)
-{
-    GDALWMSImageRequestInfo iri;
-    GDALWMSTiledImageRequestInfo tiri;
-
-    ComputeRequestInfo(iri, tiri, x, y);
-
-    m_parent_dataset->m_mini_driver->TiledImageRequest(url, iri, tiri);
-}
-
-void GDALWMSRasterBand::ComputeRequestInfo(GDALWMSImageRequestInfo &iri,
-                                           GDALWMSTiledImageRequestInfo &tiri,
-                                           int x, int y)
-{
-    int x0 = MAX(0, x * nBlockXSize);
-    int y0 = MAX(0, y * nBlockYSize);
-    int x1 = MAX(0, (x + 1) * nBlockXSize);
-    int y1 = MAX(0, (y + 1) * nBlockYSize);
-    if (m_parent_dataset->m_clamp_requests) {
-	x0 = MIN(x0, nRasterXSize);
-	y0 = MIN(y0, nRasterYSize);
-	x1 = MIN(x1, nRasterXSize);
-	y1 = MIN(y1, nRasterYSize);
-    }
-    
-    const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
-    const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
-    /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
-    iri.m_x0 = x0 * rx + m_parent_dataset->m_data_window.m_x0;
-    iri.m_y0 = y0 * ry + m_parent_dataset->m_data_window.m_y0;
-    iri.m_x1 = m_parent_dataset->m_data_window.m_x1 - (nRasterXSize - x1) * rx;
-    iri.m_y1 = m_parent_dataset->m_data_window.m_y1 - (nRasterYSize - y1) * ry;
-    iri.m_sx = x1 - x0;
-    iri.m_sy = y1 - y0;
-
-    int level = m_overview + 1;
-    tiri.m_x = (m_parent_dataset->m_data_window.m_tx >> level) + x;
-    tiri.m_y = (m_parent_dataset->m_data_window.m_ty >> level) + y;
-    tiri.m_level = m_parent_dataset->m_data_window.m_tlevel - level;
-}
-
-const char *GDALWMSRasterBand::GetMetadataItem( const char * pszName,
-                                                const char * pszDomain )
-{
-/* ==================================================================== */
-/*      LocationInfo handling.                                          */
-/* ==================================================================== */
-    if( pszDomain != NULL
-        && EQUAL(pszDomain,"LocationInfo")
-        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
-    {
-        int iPixel, iLine;
-
-/* -------------------------------------------------------------------- */
-/*      What pixel are we aiming at?                                    */
-/* -------------------------------------------------------------------- */
-        if( EQUALN(pszName,"Pixel_",6) )
-        {
-            if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
-                return NULL;
-        }
-        else if( EQUALN(pszName,"GeoPixel_",9) )
-        {
-            double adfGeoTransform[6];
-            double adfInvGeoTransform[6];
-            double dfGeoX, dfGeoY;
-
-            {
-                CPLLocaleC oLocaleEnforcer;
-                if( sscanf( pszName+9, "%lf_%lf", &dfGeoX, &dfGeoY ) != 2 )
-                    return NULL;
-            }
-
-            if( GetDataset() == NULL )
-                return NULL;
-
-            if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
-                return NULL;
-
-            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
-                return NULL;
-
-            iPixel = (int) floor(
-                adfInvGeoTransform[0]
-                + adfInvGeoTransform[1] * dfGeoX
-                + adfInvGeoTransform[2] * dfGeoY );
-            iLine = (int) floor(
-                adfInvGeoTransform[3]
-                + adfInvGeoTransform[4] * dfGeoX
-                + adfInvGeoTransform[5] * dfGeoY );
-
-            /* The GetDataset() for the WMS driver is always the main overview level, so rescale */
-            /* the values if we are an overview */
-            if (m_overview >= 0)
-            {
-                iPixel = (int) (1.0 * iPixel * GetXSize() / GetDataset()->GetRasterBand(1)->GetXSize());
-                iLine = (int) (1.0 * iLine * GetYSize() / GetDataset()->GetRasterBand(1)->GetYSize());
-            }
-        }
-        else
-            return NULL;
-
-        if( iPixel < 0 || iLine < 0
-            || iPixel >= GetXSize()
-            || iLine >= GetYSize() )
-            return NULL;
-
-        if (nBand != 1)
-        {
-            GDALRasterBand* poFirstBand = m_parent_dataset->GetRasterBand(1);
-            if (m_overview >= 0)
-                poFirstBand = poFirstBand->GetOverview(m_overview);
-            if (poFirstBand)
-                return poFirstBand->GetMetadataItem(pszName, pszDomain);
-        }
-
-        GDALWMSImageRequestInfo iri;
-        GDALWMSTiledImageRequestInfo tiri;
-        int nBlockXOff = iPixel / nBlockXSize;
-        int nBlockYOff = iLine / nBlockYSize;
-
-        ComputeRequestInfo(iri, tiri, nBlockXOff, nBlockYOff);
-
-        CPLString url;
-        m_parent_dataset->m_mini_driver->GetTiledImageInfo(&url,
-                                                           iri, tiri,
-                                                           iPixel % nBlockXSize,
-                                                           iLine % nBlockXSize);
-
-
-        char* pszRes = NULL;
-
-        if (url.size() != 0)
-        {
-            if (url == osMetadataItemURL)
-            {
-                return osMetadataItem.size() != 0 ? osMetadataItem.c_str() : NULL;
-            }
-            osMetadataItemURL = url;
-
-            char **http_request_opts = BuildHTTPRequestOpts();
-            CPLHTTPResult* psResult = CPLHTTPFetch( url.c_str(), http_request_opts);
-            if( psResult && psResult->pabyData )
-                pszRes = CPLStrdup((const char*) psResult->pabyData);
-            CPLHTTPDestroyResult(psResult);
-            CSLDestroy(http_request_opts);
-        }
-
-        if (pszRes)
-        {
-            osMetadataItem = "<LocationInfo>";
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            CPLXMLNode* psXML = CPLParseXMLString(pszRes);
-            CPLPopErrorHandler();
-            if (psXML != NULL && psXML->eType == CXT_Element)
-            {
-                if (strcmp(psXML->pszValue, "?xml") == 0)
-                {
-                    if (psXML->psNext)
-                    {
-                        char* pszXML = CPLSerializeXMLTree(psXML->psNext);
-                        osMetadataItem += pszXML;
-                        CPLFree(pszXML);
-                    }
-                }
-                else
-                {
-                    osMetadataItem += pszRes;
-                }
-            }
-            else
-            {
-                char* pszEscapedXML = CPLEscapeString(pszRes, -1, CPLES_XML_BUT_QUOTES);
-                osMetadataItem += pszEscapedXML;
-                CPLFree(pszEscapedXML);
-            }
-            if (psXML != NULL)
-                CPLDestroyXMLNode(psXML);
-
-            osMetadataItem += "</LocationInfo>";
-            CPLFree(pszRes);
-            return osMetadataItem.c_str();
-        }
-        else
-        {
-            osMetadataItem = "";
-            return NULL;
-        }
-    }
-
-    return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
-}
-
-CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
-    CPLErr ret = CE_None;
-    GDALDataset *ds = 0;
-    GByte *color_table = NULL;
-    int i;
-
-    //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);
-
-    /* expected size */
-    const int esx = MIN(MAX(0, (x + 1) * nBlockXSize), nRasterXSize) - MIN(MAX(0, x * nBlockXSize), nRasterXSize);
-    const int esy = MIN(MAX(0, (y + 1) * nBlockYSize), nRasterYSize) - MIN(MAX(0, y * nBlockYSize), nRasterYSize);
-    ds = reinterpret_cast<GDALDataset*>(GDALOpen(file_name, GA_ReadOnly));
-    if (ds != NULL) {
-        int sx = ds->GetRasterXSize();
-        int sy = ds->GetRasterYSize();
-        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3  
-        /* Allow bigger than expected so pre-tiled constant size images work on corners */
-        if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
-                sx, sy, esx, esy, nBlockXSize, nBlockYSize);
-            ret = CE_Failure;
-        }
-        if (ret == CE_None) {
-            int nDSRasterCount = ds->GetRasterCount();
-            if (nDSRasterCount != m_parent_dataset->nBands) {
-                /* Maybe its an image with color table */
-                bool accepted_as_ct = false;
-                if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
-                    GDALRasterBand *rb = ds->GetRasterBand(1);
-                    if (rb->GetRasterDataType() == GDT_Byte) {
-                        GDALColorTable *ct = rb->GetColorTable();
-                        if (ct != NULL) {
-                            accepted_as_ct = true;
-                            if (!advise_read) {
-                                color_table = new GByte[256 * 4];
-                                const int count = MIN(256, ct->GetColorEntryCount());
-                                for (i = 0; i < count; ++i) {
-                                    GDALColorEntry ce;
-                                    ct->GetColorEntryAsRGB(i, &ce);
-                                    color_table[i] = static_cast<GByte>(ce.c1);
-                                    color_table[i + 256] = static_cast<GByte>(ce.c2);
-                                    color_table[i + 512] = static_cast<GByte>(ce.c3);
-                                    color_table[i + 768] = static_cast<GByte>(ce.c4);
-                                }
-                                for (i = count; i < 256; ++i) {
-                                    color_table[i] = 0;
-                                    color_table[i + 256] = 0;
-                                    color_table[i + 512] = 0;
-                                    color_table[i + 768] = 0;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                if (nDSRasterCount == 4 && m_parent_dataset->nBands == 3)
-                {
-                    /* metacarta TMS service sometimes return a 4 band PNG instead of the expected 3 band... */
-                }
-                else if (!accepted_as_ct) {
-                   if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
-                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque" 
-                      accepted_as_no_alpha = true;
-                   }
-                   else
-                   {
-                      CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
-                         nDSRasterCount, m_parent_dataset->nBands);
-                      ret = CE_Failure;
-                   }
-                }
-            }
-        }
-        if (!advise_read) {
-            for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-                if (ret == CE_None) {
-                    void *p = NULL;
-                    GDALRasterBlock *b = NULL;
-                    if ((buffer != NULL) && (ib == to_buffer_band)) {
-                        p = buffer;
-                    } else {
-                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                        if (!band->IsBlockInCache(x, y)) {
-                            b = band->GetLockedBlockRef(x, y, true);
-                            if (b != NULL) {
-                                p = b->GetDataRef();
-                                if (p == NULL) {
-                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
-                                  ret = CE_Failure;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
-                        }
-                    }
-                    if (p != NULL) {
-                        int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
-                        int line_space = pixel_space * nBlockXSize;
-                        if (color_table == NULL) {
-                            if( ib <= ds->GetRasterCount()) {
-				GDALDataType dt=eDataType;
-				// Get the data from the PNG as stored instead of converting, if the server asks for that
-                                // TODO: This hack is from #3493 - not sure it really belongs here.
-				if ((GDT_Int16==dt)&&(GDT_UInt16==ds->GetRasterBand(ib)->GetRasterDataType()))
-				    dt=GDT_UInt16;
-				if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, dt, 1, &ib, pixel_space, line_space, 0) != CE_None) {
-				    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
-				    ret = CE_Failure;
-				}
-                            }
-                            else
-                            {  // parent expects 4 bands but file only has 3 so generate a all "opaque" 4th band
-                               if (accepted_as_no_alpha)
-                               {
-                                  // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
-                                  GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                  for (int y = 0; y < sy; ++y) {
-                                     for (int x = 0; x < sx; ++x) {
-                                        const int offset = x + y * line_space;
-                                        byte_buffer[offset] = 255;  // fill with opaque
-                                     }
-                                  }
-                               }
-                               else
-                               {  // we should never get here because this case was caught above
-                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
-                                     ds->GetRasterCount(), m_parent_dataset->nBands);
-                                  ret = CE_Failure;
-                               }     
-                            }
-                        } else if (ib <= 4) {
-                            if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0) != CE_None) {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
-                                ret = CE_Failure;
-                            }
-                            if (ret == CE_None) {
-                                GByte *band_color_table = color_table + 256 * (ib - 1);
-                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                for (int y = 0; y < sy; ++y) {
-                                    for (int x = 0; x < sx; ++x) {
-                                        const int offset = x + y * line_space;
-                                        byte_buffer[offset] = band_color_table[byte_buffer[offset]];
-                                    }
-                                }
-                            }
-                        } else {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
-                            ret = CE_Failure;
-                        }
-                    }
-                    if (b != NULL) {
-                        b->DropLock();
-                    }
-                }
-            }
-        }
-        GDALClose(ds);
-    } else {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
-        ret = CE_Failure;
-    }
-
-    if (color_table != NULL) {
-        delete[] color_table;
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
-    CPLErr ret = CE_None;
-
-    for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-        if (ret == CE_None) {
-            void *p = NULL;
-            GDALRasterBlock *b = NULL;
-            if ((buffer != NULL) && (ib == to_buffer_band)) {
-                p = buffer;
-            } else {
-                GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                if (!band->IsBlockInCache(x, y)) {
-                    b = band->GetLockedBlockRef(x, y, true);
-                    if (b != NULL) {
-                        p = b->GetDataRef();
-                        if (p == NULL) {
-                          CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
-                          ret = CE_Failure;
-                        }
-                    }
-                }
-            }
-            if (p != NULL) {
-                unsigned char *b = reinterpret_cast<unsigned char *>(p);
-                int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
-                for (int i = 0; i < block_size; ++i) b[i] = 0;
-            }
-            if (b != NULL) {
-                b->DropLock();
-            }
-        }
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::ReportWMSException(const char *file_name) {
-    CPLErr ret = CE_None;
-    int reported_errors_count = 0;
-
-    CPLXMLNode *orig_root = CPLParseXMLFile(file_name);
-    CPLXMLNode *root = orig_root;
-    if (root != NULL) {
-        root = CPLGetXMLNode(root, "=ServiceExceptionReport");
-    }
-    if (root != NULL) {
-        CPLXMLNode *n = CPLGetXMLNode(root, "ServiceException");
-        while (n != NULL) {
-            const char *exception = CPLGetXMLValue(n, "=ServiceException", "");
-            const char *exception_code = CPLGetXMLValue(n, "=ServiceException.code", "");
-            if (exception[0] != '\0') {
-                if (exception_code[0] != '\0') {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s': %s", exception_code, exception);
-                    ++reported_errors_count;
-                } else {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception: %s", exception);
-                    ++reported_errors_count;
-                }
-            } else if (exception_code[0] != '\0') {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s'.", exception_code);
-                ++reported_errors_count;
-            }
-
-            n = n->psNext;
-            if (n != NULL) {
-                n = CPLGetXMLNode(n, "=ServiceException");
-            }
-        }
-    } else {
-        ret = CE_Failure;
-    }
-    if (orig_root != NULL) {
-        CPLDestroyXMLNode(orig_root);
-    }
-
-    if (reported_errors_count == 0) {
-        ret = CE_Failure;
-    }
-
-    return ret;
-}
-
-
-CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options) {
-//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
-    if (m_parent_dataset->m_offline_mode || !m_parent_dataset->m_use_advise_read) return CE_None;
-    if (m_parent_dataset->m_cache == NULL) return CE_Failure;
-
-    int bx0 = x0 / nBlockXSize;
-    int by0 = y0 / nBlockYSize;
-    int bx1 = (x0 + sx - 1) / nBlockXSize;
-    int by1 = (y0 + sy - 1) / nBlockYSize;
-
-    return ReadBlocks(0, 0, NULL, bx0, by0, bx1, by1, 1);
-}
-
-GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
-    return m_color_interp;
-}
-
-CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
-{
-    m_color_interp = eNewInterp;
-    return CE_None;
-}
-
-// Utility function, returns a value from a vector corresponding to the band index
-// or the first entry
-static double getBandValue(std::vector<double> &v,size_t idx)
-{
-    idx--;
-    if (v.size()>idx) return v[idx];
-    return v[0];
-}
-
-double GDALWMSRasterBand::GetNoDataValue( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vNoData;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetNoDataValue(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-double GDALWMSRasterBand::GetMinimum( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vMin;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetMinimum(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-double GDALWMSRasterBand::GetMaximum( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vMax;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetMaximum(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-GDALColorTable *GDALWMSRasterBand::GetColorTable()
-{
-    return m_parent_dataset->m_poColorTable;
-}
diff --git a/frmts/wms/stdinc.h b/frmts/wms/stdinc.h
deleted file mode 100644
index 5ad33c2..0000000
--- a/frmts/wms/stdinc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <math.h>
-#include <vector>
-#include <list>
-#include <algorithm>
-#include <curl/curl.h>
-#include <gdal.h>
-#include <gdalwarper.h>
-#include <gdal_alg.h>
-#include <ogr_srs_api.h>
-#include <ogr_spatialref.h>
-#include <cpl_string.h>
-#include <gdal_priv.h>
-#include <gdal_pam.h>
-#include <cpl_multiproc.h>
-#include <cpl_http.h>
-
-#include "md5.h"
-#include "gdalhttp.h"
-#include "wmsdriver.h"
-#include "minidriver_wms.h"
-#include "minidriver_tileservice.h"
-#include "minidriver_worldwind.h"
-#include "minidriver_tms.h"
-#include "minidriver_tiled_wms.h"
-#include "minidriver_virtualearth.h"
diff --git a/frmts/wms/stuff.cpp b/frmts/wms/stuff.cpp
deleted file mode 100644
index ddd34a8..0000000
--- a/frmts/wms/stuff.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/******************************************************************************
- * $Id: stuff.cpp 22177 2011-04-16 19:45:11Z rouault $
- *
- * Project:  WMS Client Driver
- * Purpose:  Implementation of Dataset and RasterBand classes for WMS
- *           and other similar services.
- * Author:   Adam Nowacki, nowak at xpam.de
- *
- ******************************************************************************
- * Copyright (c) 2007, Adam Nowacki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "stdinc.h"
-
-CPLString MD5String(const char *s) {
-    unsigned char hash[16];
-    char hhash[33];
-    const char *tohex = "0123456789abcdef";
-    struct cvs_MD5Context context;
-    cvs_MD5Init(&context);
-    cvs_MD5Update(&context, reinterpret_cast<unsigned char const *>(s), strlen(s));
-    cvs_MD5Final(hash, &context);
-    for (int i = 0; i < 16; ++i) {
-        hhash[i * 2] = tohex[(hash[i] >> 4) & 0xf];
-        hhash[i * 2 + 1] = tohex[hash[i] & 0xf];
-    }
-    hhash[32] = '\0';
-    return CPLString(hhash);
-}
-
-CPLString ProjToWKT(const CPLString &proj) {
-    char* wkt = NULL;
-    OGRSpatialReference sr;
-    CPLString srs;
-
-    /* We could of course recognize OSGEO:41001 to SetFromUserInput(), but this hackish SRS */
-    /* is almost only used in the context of WMS */
-    if (strcmp(proj.c_str(),"OSGEO:41001") == 0)
-    {
-        if (sr.SetFromUserInput("EPSG:3857") != OGRERR_NONE) return srs;
-    }
-    else if (EQUAL(proj.c_str(),"EPSG:NONE"))
-    {
-        return srs;
-    }
-    else
-    {
-        if (sr.SetFromUserInput(proj.c_str()) != OGRERR_NONE) return srs;
-    }
-    sr.exportToWkt(&wkt);
-    srs = wkt;
-    OGRFree(wkt);
-    return srs;
-}
-
-void URLAppend(CPLString *url, const char *s) {
-    if ((s == NULL) || (s[0] == '\0')) return;
-    if (s[0] == '&') {
-        if (url->find('?') == std::string::npos) url->append(1, '?');
-        if (((*url)[url->size() - 1] == '?') || ((*url)[url->size() - 1] == '&')) url->append(s + 1);
-        else url->append(s);
-    } else url->append(s);
-}
-
-void URLAppendF(CPLString *url, const char *s, ...) {
-    CPLString tmp;
-    va_list args;
-
-    va_start(args, s);
-    tmp.vPrintf(s, args);
-    va_end(args);
-
-    URLAppend(url, tmp.c_str());
-}
-
-void URLAppend(CPLString *url, const CPLString &s) {
-    URLAppend(url, s.c_str());
-}
-
-CPLString BufferToVSIFile(GByte *buffer, size_t size) {
-    CPLString file_name;
-
-    file_name.Printf("/vsimem/wms/%p/wmsresult.dat", buffer);
-    VSILFILE *f = VSIFileFromMemBuffer(file_name.c_str(), buffer, size, false);
-    if (f == NULL) return CPLString();
-    VSIFCloseL(f);
-    return file_name;
-}
-
-CPLErr MakeDirs(const char *path) {
-    char *p = CPLStrdup(CPLGetDirname(path));
-    if (strlen(p) >= 2) {
-        MakeDirs(p);
-    }
-    VSIMkdir(p, 0744);
-    CPLFree(p);
-    return CE_None;
-}
-
-int VersionStringToInt(const char *version) {
-    if (version == NULL) return -1;
-    const char *p = version;
-    int v = 0;
-    for (int i = 3; i >= 0; --i) {
-        v += (1 << (i * 8)) * atoi(p);
-        for (; (*p != '\0') && (*p != '.'); ++p);
-        if (*p != '\0') ++p;
-    }
-    return v;
-}
-
-int StrToBool(const char *p) {
-    if (p == NULL) return -1;
-    if (EQUAL(p, "1") || EQUAL(p, "true") || EQUAL(p, "yes") || EQUAL(p, "enable") || EQUAL(p, "enabled") || EQUAL(p, "on")) return 1;
-    if (EQUAL(p, "0") || EQUAL(p, "false") || EQUAL(p, "no") || EQUAL(p, "disable") || EQUAL(p, "disabled") || EQUAL(p, "off")) return 0;
-    return -1;
-}
-
-int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, ...) {
-    CPLString tmp;
-    va_list args;
-
-    size_t start = base->find(search);
-    if (start == std::string::npos) {
-        return -1;
-    }
-
-    va_start(args, fmt);
-    tmp.vPrintf(fmt, args);
-    va_end(args);
-
-    base->replace(start, strlen(search), tmp);
-    return start;
-}
diff --git a/frmts/wms/wmsdriver.cpp b/frmts/wms/wmsdriver.cpp
index a6c6c40..b8a3fa0 100644
--- a/frmts/wms/wmsdriver.cpp
+++ b/frmts/wms/wmsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.cpp 25494 2013-01-13 12:55:17Z etourigny $
+ * $Id: wmsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,9 +29,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "stdinc.h"
+#include "wmsdriver.h"
 #include "wmsmetadataset.h"
 
+#include "minidriver_wms.h"
+#include "minidriver_tileservice.h"
+#include "minidriver_worldwind.h"
+#include "minidriver_tms.h"
+#include "minidriver_tiled_wms.h"
+#include "minidriver_virtualearth.h"
+
 /************************************************************************/
 /*              GDALWMSDatasetGetConfigFromURL()                        */
 /************************************************************************/
@@ -427,6 +435,22 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML)
 }
 
 /************************************************************************/
+/*                             GetJSonValue()                           */
+/************************************************************************/
+
+static const char* GetJSonValue(const char* pszLine, const char* pszKey)
+{
+    const char* pszJSonKey = CPLSPrintf("\"%s\" : ", pszKey);
+    const char* pszPtr;
+    if( (pszPtr = strstr(pszLine, pszJSonKey)) != NULL )
+        return pszPtr + strlen(pszJSonKey);
+    pszJSonKey = CPLSPrintf("\"%s\": ", pszKey);
+    if( (pszPtr = strstr(pszLine, pszJSonKey)) != NULL )
+        return pszPtr + strlen(pszJSonKey);
+    return NULL;
+}
+
+/************************************************************************/
 /*             GDALWMSDatasetGetConfigFromArcGISJSON()                  */
 /************************************************************************/
 
@@ -448,14 +472,14 @@ static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
     double dfBaseResolution = 0;
     while((pszLine = CPLReadLine2L(fp, 4096, NULL)) != NULL)
     {
-        const char* pszPtr;
-        if ((pszPtr = strstr(pszLine, "\"rows\" : ")) != NULL)
-            nTileHeight = atoi(pszPtr + strlen("\"rows\" : "));
-        else if ((pszPtr = strstr(pszLine, "\"cols\" : ")) != NULL)
-            nTileWidth = atoi(pszPtr + strlen("\"cols\" : "));
-        else if ((pszPtr = strstr(pszLine, "\"wkid\" : ")) != NULL)
+        const char* pszVal;
+        if ((pszVal = GetJSonValue(pszLine, "rows")) != NULL)
+            nTileHeight = atoi(pszVal);
+        else if ((pszVal = GetJSonValue(pszLine, "cols")) != NULL)
+            nTileWidth = atoi(pszVal);
+        else if ((pszVal = GetJSonValue(pszLine, "wkid")) != NULL)
         {
-            int nVal = atoi(pszPtr + strlen("\"wkid\" : "));
+            int nVal = atoi(pszVal);
             if (nWKID < 0)
                 nWKID = nVal;
             else if (nWKID != nVal)
@@ -465,19 +489,19 @@ static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
                 return NULL;
             }
         }
-        else if ((pszPtr = strstr(pszLine, "\"x\" : ")) != NULL)
+        else if ((pszVal = GetJSonValue(pszLine, "x")) != NULL)
         {
             bHasMinX = TRUE;
-            dfMinX = CPLAtofM(pszPtr + strlen("\"x\" : "));
+            dfMinX = CPLAtofM(pszVal);
         }
-        else if ((pszPtr = strstr(pszLine, "\"y\" : ")) != NULL)
+        else if ((pszVal = GetJSonValue(pszLine, "y")) != NULL)
         {
             bHasMaxY = TRUE;
-            dfMaxY = CPLAtofM(pszPtr + strlen("\"y\" : "));
+            dfMaxY = CPLAtofM(pszVal);
         }
-        else if ((pszPtr = strstr(pszLine, "\"level\" : ")) != NULL)
+        else if ((pszVal = GetJSonValue(pszLine, "level")) != NULL)
         {
-            int nLevel = atoi(pszPtr + strlen("\"level\" : "));
+            int nLevel = atoi(pszVal);
             if (nLevel != nExpectedLevel)
             {
                 CPLDebug("WMS", "Expected level : %d, got : %d", nExpectedLevel, nLevel);
@@ -485,9 +509,17 @@ static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
                 return NULL;
             }
 
-            if ((pszPtr = strstr(pszLine, "\"resolution\" : ")) != NULL)
+            pszVal = GetJSonValue(pszLine, "resolution");
+            if( pszVal == NULL )
+            {
+                pszLine = CPLReadLine2L(fp, 4096, NULL);
+                if( pszLine == NULL )
+                    break;
+                pszVal = GetJSonValue(pszLine, "resolution");
+            }
+            if (pszVal != NULL)
             {
-                double dfResolution = CPLAtofM(pszPtr + strlen("\"resolution\" : "));
+                double dfResolution = CPLAtofM(pszVal);
                 if (nLevel == 0)
                     dfBaseResolution = dfResolution;
             }
diff --git a/frmts/wms/wmsdriver.h b/frmts/wms/wmsdriver.h
index f299d82..28478c8 100644
--- a/frmts/wms/wmsdriver.h
+++ b/frmts/wms/wmsdriver.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.h 25776 2013-03-20 20:46:48Z rouault $
+ * $Id: wmsdriver.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,9 +29,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef WMSDRIVER_H_INCLUDED
+#define WMSDRIVER_H_INCLUDED
+
+#include <math.h>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <curl/curl.h>
+
+#include "cpl_conv.h"
+#include "cpl_http.h"
+#include "cpl_multiproc.h"
+#include "gdal_pam.h"
+#include "ogr_spatialref.h"
+#include "gdalwarper.h"
+#include "gdal_alg.h"
+
+#include "md5.h"
+#include "gdalhttp.h"
+
 class GDALWMSDataset;
 class GDALWMSRasterBand;
 
+/* -------------------------------------------------------------------- */
+/*      Helper functions.                                               */
+/* -------------------------------------------------------------------- */
 CPLString MD5String(const char *s);
 CPLString ProjToWKT(const CPLString &proj);
 void URLAppend(CPLString *url, const char *s);
@@ -72,6 +96,10 @@ public:
     int m_level;
 };
 
+/************************************************************************/
+/*                         Mini Driver Related                          */
+/************************************************************************/
+
 class GDALWMSRasterIOHint {
 public:
     int m_x0, m_y0;
@@ -179,6 +207,10 @@ public: \
     delete instance; \
 }
 
+/************************************************************************/
+/*                            GDALWMSCache                              */
+/************************************************************************/
+
 class GDALWMSCache {
 public:
     GDALWMSCache();
@@ -198,6 +230,10 @@ protected:
     int m_cache_depth;
 };
 
+/************************************************************************/
+/*                            GDALWMSDataset                            */
+/************************************************************************/
+
 class GDALWMSDataset : public GDALPamDataset {
     friend class GDALWMSRasterBand;
 
@@ -210,32 +246,96 @@ public:
     virtual CPLErr GetGeoTransform(double *gt);
     virtual CPLErr SetGeoTransform(double *gt);
     virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options);
+    
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
 
-    const GDALWMSDataWindow *WMSGetDataWindow() const;
-    void WMSSetClamp(bool flag);
-    void WMSSetBlockSize(int x, int y);
-    void WMSSetRasterSize(int x, int y);
-    void WMSSetDataType(GDALDataType type);
-    void WMSSetDataWindow(GDALWMSDataWindow &window);
-    void WMSSetBandsCount(int count);
     void SetColorTable(GDALColorTable *pct) { m_poColorTable=pct; }
 
-    void WMSSetNoDataValue(const char * pszNoData);
-    void WMSSetMinValue(const char* pszMin);
-    void WMSSetMaxValue(const char* pszMax);
-
     void mSetBand(int i, GDALRasterBand *band) { SetBand(i,band); };
     GDALWMSRasterBand *mGetBand(int i) { return reinterpret_cast<GDALWMSRasterBand *>(GetRasterBand(i)); };
 
+    const GDALWMSDataWindow *WMSGetDataWindow() const {
+        return &m_data_window;
+    }
 
-    void WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1);
-    void WMSSetDefaultTileLevel(int tlevel);
-    void WMSSetDefaultTileCount(int tilecountx, int tilecounty);
-    void WMSSetDefaultBlockSize(int x, int y);
-    void WMSSetDefaultOverviewCount(int overview_count);
-    void WMSSetNeedsDataWindow(int flag);
+    void WMSSetBlockSize(int x, int y) {
+        m_block_size_x=x;
+        m_block_size_y=y;
+    }
+
+    void WMSSetRasterSize(int x, int y) {
+        nRasterXSize=x;
+        nRasterYSize=y;
+    }
+
+    void WMSSetBandsCount(int count) {
+        nBands=count;
+    }
+
+    void WMSSetClamp(bool flag=true) {
+        m_clamp_requests=flag;
+    }
+
+    void WMSSetDataType(GDALDataType type) {
+        m_data_type=type;
+    }
+
+    void WMSSetDataWindow(GDALWMSDataWindow &window) {
+        m_data_window=window;
+    }
+
+    void WMSSetDefaultBlockSize(int x, int y) {
+        m_default_block_size_x=x;
+        m_default_block_size_y=y;
+    }
+
+    void WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1) {
+        m_default_data_window.m_x0 = x0;
+        m_default_data_window.m_y0 = y0;
+        m_default_data_window.m_x1 = x1;
+        m_default_data_window.m_y1 = y1;
+    }
+
+    void WMSSetDefaultTileCount(int tilecountx, int tilecounty) {
+        m_default_tile_count_x = tilecountx;
+        m_default_tile_count_y = tilecounty;
+    }
+
+    void WMSSetDefaultTileLevel(int tlevel) {
+        m_default_data_window.m_tlevel = tlevel;
+    }
+
+    void WMSSetDefaultOverviewCount(int overview_count) {
+        m_default_overview_count = overview_count;
+    }
+
+    void WMSSetNeedsDataWindow(int flag) {
+        m_bNeedsDataWindow = flag;
+    }
+    
+    static void list2vec(std::vector<double> &v,const char *pszList) {
+        if ((pszList==NULL)||(pszList[0]==0)) return;
+        char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
+                                              CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+        v.clear();
+        for (int i=0;i<CSLCount(papszTokens);i++)
+            v.push_back(CPLStrtod(papszTokens[i],NULL));
+        CSLDestroy(papszTokens);
+    }
+
+    void WMSSetNoDataValue(const char * pszNoData) {
+        list2vec(vNoData,pszNoData);
+    }
+
+    void WMSSetMinValue(const char * pszMin) {
+        list2vec(vMin,pszMin);
+    }
+
+    void WMSSetMaxValue(const char * pszMax) {
+        list2vec(vMax,pszMax);
+    }
 
     static GDALDataset* Open(GDALOpenInfo *poOpenInfo);
     static int Identify(GDALOpenInfo *poOpenInfo);
@@ -282,6 +382,10 @@ protected:
     CPLString m_osXML;
 };
 
+/************************************************************************/
+/*                            GDALWMSRasterBand                         */
+/************************************************************************/
+
 class GDALWMSRasterBand : public GDALPamRasterBand {
     friend class GDALWMSDataset;
 
@@ -311,6 +415,7 @@ public:
     virtual int GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int n);
 
+    virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
 
@@ -332,3 +437,5 @@ protected:
 
 GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager();
 void DestroyWMSMiniDriverManager(void);
+
+#endif /* notdef WMSDRIVER_H_INCLUDED */
diff --git a/frmts/wms/wmsmetadataset.cpp b/frmts/wms/wmsmetadataset.cpp
index dc35664..b35c8e9 100644
--- a/frmts/wms/wmsmetadataset.cpp
+++ b/frmts/wms/wmsmetadataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: wmsmetadataset.cpp 22576 2011-06-24 13:14:21Z warmerdam $
+ * $Id: wmsmetadataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Definition of GDALWMSMetaDataset class
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -80,6 +80,9 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInf
     CPLString osFormat = CPLURLGetValue(pszURL, "FORMAT");
     CPLString osTransparent = CPLURLGetValue(pszURL, "TRANSPARENT");
     CPLString osVersion = CPLURLGetValue(pszURL, "VERSION");
+    CPLString osPreferredSRS = CPLURLGetValue(pszURL, "SRS");
+    if( osPreferredSRS.size() == 0 )
+        osPreferredSRS = CPLURLGetValue(pszURL, "CRS");
 
     if (osVersion.size() == 0)
         osVersion = "1.1.1";
@@ -130,7 +133,7 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInf
         return NULL;
     }
 
-    GDALDataset* poRet = AnalyzeGetCapabilities(psXML, osFormat, osTransparent);
+    GDALDataset* poRet = AnalyzeGetCapabilities(psXML, osFormat, osTransparent, osPreferredSRS);
 
     CPLHTTPDestroyResult(psResult);
     CPLDestroyXMLNode( psXML );
@@ -202,6 +205,18 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetTileService(GDALOpenInfo *poOpenInfo
 
     return poRet;
 }
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GDALWMSMetaDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
 /************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
@@ -352,6 +367,7 @@ void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
 void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
                                       CPLString osFormat,
                                       CPLString osTransparent,
+                                      CPLString osPreferredSRS,
                                       const char* pszSRS,
                                       const char* pszMinX,
                                       const char* pszMinY,
@@ -362,6 +378,7 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
     const char* pszTitle = CPLGetXMLValue(psXML, "Title", NULL);
     const char* pszAbstract = CPLGetXMLValue(psXML, "Abstract", NULL);
 
+    CPLXMLNode* psSRS = NULL;
     const char* pszSRSLocal = NULL;
     const char* pszMinXLocal = NULL;
     const char* pszMinYLocal = NULL;
@@ -374,7 +391,24 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
     /* Use local bounding box if available, otherwise use the one */
     /* that comes from an upper layer */
     /* such as in http://neowms.sci.gsfc.nasa.gov/wms/wms */
-    CPLXMLNode* psSRS = CPLGetXMLNode( psXML, "BoundingBox" );
+    CPLXMLNode* psIter = psXML->psChild;
+    while( psIter != NULL )
+    {
+        if( psIter->eType == CXT_Element &&
+            strcmp(psIter->pszValue, "BoundingBox") == 0 )
+        {
+            psSRS = psIter;
+            pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
+            if( osPreferredSRS.size() == 0 || pszSRSLocal == NULL )
+                break;
+            if( EQUAL(osPreferredSRS, pszSRSLocal) )
+                break;
+            psSRS = NULL;
+            pszSRSLocal = NULL;
+        }
+        psIter = psIter->psNext;
+    }
+
     if (psSRS == NULL)
     {
         psSRS = CPLGetXMLNode( psXML, "LatLonBoundingBox" );
@@ -382,8 +416,7 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
         if (pszSRSLocal == NULL)
             pszSRSLocal = "EPSG:4326";
     }
-    else
-        pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
+
 
     if (pszSRSLocal != NULL && psSRS != NULL)
     {
@@ -426,13 +459,13 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
         }
     }
 
-    CPLXMLNode* psIter = psXML->psChild;
+    psIter = psXML->psChild;
     for(; psIter != NULL; psIter = psIter->psNext)
     {
         if (psIter->eType == CXT_Element)
         {
             if (EQUAL(psIter->pszValue, "Layer"))
-                ExploreLayer(psIter, osFormat, osTransparent,
+                ExploreLayer(psIter, osFormat, osTransparent, osPreferredSRS,
                              pszSRS, pszMinX, pszMinY, pszMaxX, pszMaxY);
         }
     }
@@ -547,7 +580,8 @@ void GDALWMSMetaDataset::ParseWMSCTileSets(CPLXMLNode* psXML)
 
 GDALDataset* GDALWMSMetaDataset::AnalyzeGetCapabilities(CPLXMLNode* psXML,
                                                           CPLString osFormat,
-                                                          CPLString osTransparent)
+                                                          CPLString osTransparent,
+                                                          CPLString osPreferredSRS)
 {
     const char* pszEncoding = NULL;
     if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
@@ -588,7 +622,7 @@ GDALDataset* GDALWMSMetaDataset::AnalyzeGetCapabilities(CPLXMLNode* psXML,
     poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
     if (psVendorSpecificCapabilities)
         poDS->ParseWMSCTileSets(psVendorSpecificCapabilities);
-    poDS->ExploreLayer(psLayer, osFormat, osTransparent);
+    poDS->ExploreLayer(psLayer, osFormat, osTransparent, osPreferredSRS);
 
     return poDS;
 }
diff --git a/frmts/wms/wmsmetadataset.h b/frmts/wms/wmsmetadataset.h
index c6de71e..24f2634 100644
--- a/frmts/wms/wmsmetadataset.h
+++ b/frmts/wms/wmsmetadataset.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: wmsmetadataset.h 22557 2011-06-22 15:56:00Z rouault $
+ * $Id: wmsmetadataset.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Declaration of GDALWMSMetaDataset class
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -83,6 +83,7 @@ class GDALWMSMetaDataset : public GDALPamDataset
     void                ExploreLayer(CPLXMLNode* psXML,
                                      CPLString osFormat,
                                      CPLString osTransparent,
+                                     CPLString osPreferredSRS,
                                      const char* pszSRS = NULL,
                                      const char* pszMinX = NULL,
                                      const char* pszMinY = NULL,
@@ -104,11 +105,13 @@ class GDALWMSMetaDataset : public GDALPamDataset
         GDALWMSMetaDataset();
        ~GDALWMSMetaDataset();
 
+    virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
 
     static GDALDataset* AnalyzeGetCapabilities(CPLXMLNode* psXML,
                                                CPLString osFormat = "",
-                                               CPLString osTransparent = "");
+                                               CPLString osTransparent = "",
+                                               CPLString osPreferredSRS = "");
     static GDALDataset* AnalyzeGetTileService(CPLXMLNode* psXML);
     static GDALDataset* AnalyzeTileMapService(CPLXMLNode* psXML);
 
diff --git a/frmts/wms/wmsutils.cpp b/frmts/wms/wmsutils.cpp
new file mode 100644
index 0000000..73d901a
--- /dev/null
+++ b/frmts/wms/wmsutils.cpp
@@ -0,0 +1,151 @@
+/******************************************************************************
+ * $Id: wmsutils.cpp 26079 2013-06-13 01:31:48Z warmerdam $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Supporting utility functions for GDAL WMS driver.
+ * Author:   Adam Nowacki, nowak at xpam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Adam Nowacki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "wmsdriver.h"
+
+CPLString MD5String(const char *s) {
+    unsigned char hash[16];
+    char hhash[33];
+    const char *tohex = "0123456789abcdef";
+    struct cvs_MD5Context context;
+    cvs_MD5Init(&context);
+    cvs_MD5Update(&context, reinterpret_cast<unsigned char const *>(s), strlen(s));
+    cvs_MD5Final(hash, &context);
+    for (int i = 0; i < 16; ++i) {
+        hhash[i * 2] = tohex[(hash[i] >> 4) & 0xf];
+        hhash[i * 2 + 1] = tohex[hash[i] & 0xf];
+    }
+    hhash[32] = '\0';
+    return CPLString(hhash);
+}
+
+CPLString ProjToWKT(const CPLString &proj) {
+    char* wkt = NULL;
+    OGRSpatialReference sr;
+    CPLString srs;
+
+    /* We could of course recognize OSGEO:41001 to SetFromUserInput(), but this hackish SRS */
+    /* is almost only used in the context of WMS */
+    if (strcmp(proj.c_str(),"OSGEO:41001") == 0)
+    {
+        if (sr.SetFromUserInput("EPSG:3857") != OGRERR_NONE) return srs;
+    }
+    else if (EQUAL(proj.c_str(),"EPSG:NONE"))
+    {
+        return srs;
+    }
+    else
+    {
+        if (sr.SetFromUserInput(proj.c_str()) != OGRERR_NONE) return srs;
+    }
+    sr.exportToWkt(&wkt);
+    srs = wkt;
+    OGRFree(wkt);
+    return srs;
+}
+
+void URLAppend(CPLString *url, const char *s) {
+    if ((s == NULL) || (s[0] == '\0')) return;
+    if (s[0] == '&') {
+        if (url->find('?') == std::string::npos) url->append(1, '?');
+        if (((*url)[url->size() - 1] == '?') || ((*url)[url->size() - 1] == '&')) url->append(s + 1);
+        else url->append(s);
+    } else url->append(s);
+}
+
+void URLAppendF(CPLString *url, const char *s, ...) {
+    CPLString tmp;
+    va_list args;
+
+    va_start(args, s);
+    tmp.vPrintf(s, args);
+    va_end(args);
+
+    URLAppend(url, tmp.c_str());
+}
+
+void URLAppend(CPLString *url, const CPLString &s) {
+    URLAppend(url, s.c_str());
+}
+
+CPLString BufferToVSIFile(GByte *buffer, size_t size) {
+    CPLString file_name;
+
+    file_name.Printf("/vsimem/wms/%p/wmsresult.dat", buffer);
+    VSILFILE *f = VSIFileFromMemBuffer(file_name.c_str(), buffer, size, false);
+    if (f == NULL) return CPLString();
+    VSIFCloseL(f);
+    return file_name;
+}
+
+CPLErr MakeDirs(const char *path) {
+    char *p = CPLStrdup(CPLGetDirname(path));
+    if (strlen(p) >= 2) {
+        MakeDirs(p);
+    }
+    VSIMkdir(p, 0744);
+    CPLFree(p);
+    return CE_None;
+}
+
+int VersionStringToInt(const char *version) {
+    if (version == NULL) return -1;
+    const char *p = version;
+    int v = 0;
+    for (int i = 3; i >= 0; --i) {
+        v += (1 << (i * 8)) * atoi(p);
+        for (; (*p != '\0') && (*p != '.'); ++p);
+        if (*p != '\0') ++p;
+    }
+    return v;
+}
+
+int StrToBool(const char *p) {
+    if (p == NULL) return -1;
+    if (EQUAL(p, "1") || EQUAL(p, "true") || EQUAL(p, "yes") || EQUAL(p, "enable") || EQUAL(p, "enabled") || EQUAL(p, "on")) return 1;
+    if (EQUAL(p, "0") || EQUAL(p, "false") || EQUAL(p, "no") || EQUAL(p, "disable") || EQUAL(p, "disabled") || EQUAL(p, "off")) return 0;
+    return -1;
+}
+
+int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, ...) {
+    CPLString tmp;
+    va_list args;
+
+    size_t start = base->find(search);
+    if (start == std::string::npos) {
+        return -1;
+    }
+
+    va_start(args, fmt);
+    tmp.vPrintf(fmt, args);
+    va_end(args);
+
+    base->replace(start, strlen(search), tmp);
+    return start;
+}
diff --git a/frmts/xpm/xpmdataset.cpp b/frmts/xpm/xpmdataset.cpp
index f1611ca..9c06d36 100644
--- a/frmts/xpm/xpmdataset.cpp
+++ b/frmts/xpm/xpmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xpmdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
+ * $Id: xpmdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XPM Driver
  * Purpose:  Implement GDAL XPM Support
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "gdal_frmts.h"						      
 
 
-CPL_CVSID("$Id: xpmdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
+CPL_CVSID("$Id: xpmdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static unsigned char *ParseXPM( const char *pszInput,
                                 int *pnXSize, int *pnYSize, 
diff --git a/frmts/xyz/xyzdataset.cpp b/frmts/xyz/xyzdataset.cpp
index dddf9c2..b823be8 100644
--- a/frmts/xyz/xyzdataset.cpp
+++ b/frmts/xyz/xyzdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: xyzdataset.cpp 24593 2012-06-16 18:58:42Z rouault $
+ * $Id: xyzdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XYZ driver
  * Purpose:  GDALDataset driver for XYZ dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: xyzdataset.cpp 24593 2012-06-16 18:58:42Z rouault $");
+CPL_CVSID("$Id: xyzdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_XYZ(void);
@@ -52,6 +52,7 @@ class XYZDataset : public GDALPamDataset
     VSILFILE   *fp;
     int         bHasHeaderLine;
     int         nCommentLineCount;
+    char        chDecimalSep;
     int         nXIndex;
     int         nYIndex;
     int         nZIndex;
@@ -59,7 +60,10 @@ class XYZDataset : public GDALPamDataset
     int         nLineNum;     /* any line */
     int         nDataLineNum; /* line with values (header line and empty lines ignored) */
     double      adfGeoTransform[6];
-    
+    int         bSameNumberOfValuesPerLine;
+    double      dfMinZ;
+    double      dfMaxZ;
+
     static int          IdentifyEx( GDALOpenInfo *, int&, int& nCommentLineCount );
 
   public:
@@ -85,11 +89,16 @@ class XYZRasterBand : public GDALPamRasterBand
 {
     friend class XYZDataset;
 
+    int          nLastYOff;
+
   public:
 
                 XYZRasterBand( XYZDataset *, int, GDALDataType );
 
     virtual CPLErr IReadBlock( int, int, void * );
+    virtual double GetMinimum( int *pbSuccess = NULL );
+    virtual double GetMaximum( int *pbSuccess = NULL );
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
 };
 
 
@@ -107,6 +116,8 @@ XYZRasterBand::XYZRasterBand( XYZDataset *poDS, int nBand, GDALDataType eDT )
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
+
+    nLastYOff = -1;
 }
 
 /************************************************************************/
@@ -122,8 +133,20 @@ CPLErr XYZRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if (poGDS->fp == NULL)
         return CE_Failure;
 
-    int nLineInFile = nBlockYOff * nBlockXSize;
-    if (poGDS->nDataLineNum > nLineInFile)
+    if( pImage )
+    {
+        int bSuccess = FALSE;
+        double dfNoDataValue = GetNoDataValue(&bSuccess);
+        if( !bSuccess )
+            dfNoDataValue = 0.0;
+        GDALCopyWords(&dfNoDataValue, GDT_Float64, 0,
+                      pImage, eDataType, GDALGetDataTypeSize(eDataType) / 8,
+                      nRasterXSize);
+    }
+
+    int nLineInFile = nBlockYOff * nBlockXSize; // only valid if bSameNumberOfValuesPerLine
+    if ( (poGDS->bSameNumberOfValuesPerLine && poGDS->nDataLineNum > nLineInFile) ||
+         (!poGDS->bSameNumberOfValuesPerLine && (nLastYOff == -1 || nBlockYOff != nLastYOff + 1)) )
     {
         poGDS->nDataLineNum = 0;
         VSIFSeekL(poGDS->fp, 0, SEEK_SET);
@@ -135,62 +158,95 @@ CPLErr XYZRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
             if (pszLine == NULL)
-            {
-                memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
                 return CE_Failure;
-            }
             poGDS->nLineNum ++;
         }
     }
 
-    while(poGDS->nDataLineNum < nLineInFile)
+    if( !poGDS->bSameNumberOfValuesPerLine && nBlockYOff != nLastYOff + 1 )
     {
-        const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
-        if (pszLine == NULL)
+        int iY;
+        if( nBlockYOff < nLastYOff )
         {
-            memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
-            return CE_Failure;
+            nLastYOff = -1;
+            for(iY = 0; iY < nBlockYOff; iY++)
+            {
+                if( IReadBlock(0, iY, NULL) != CE_None )
+                    return CE_Failure;
+            }
         }
-        poGDS->nLineNum ++;
-
-        const char* pszPtr = pszLine;
-        char ch;
-        int nCol = 0;
-        int bLastWasSep = TRUE;
-        while((ch = *pszPtr) != '\0')
+        else
         {
-            if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
+            for(iY = nLastYOff + 1; iY < nBlockYOff; iY++)
             {
-                if (!bLastWasSep)
-                    nCol ++;
-                bLastWasSep = TRUE;
+                if( IReadBlock(0, iY, NULL) != CE_None )
+                    return CE_Failure;
             }
-            else
+        }
+    }
+    else if( poGDS->bSameNumberOfValuesPerLine )
+    {
+        while(poGDS->nDataLineNum < nLineInFile)
+        {
+            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
+            if (pszLine == NULL)
+                return CE_Failure;
+            poGDS->nLineNum ++;
+
+            const char* pszPtr = pszLine;
+            char ch;
+            int nCol = 0;
+            int bLastWasSep = TRUE;
+            while((ch = *pszPtr) != '\0')
             {
-                bLastWasSep = FALSE;
+                if (ch == ' ')
+                {
+                    if (!bLastWasSep)
+                        nCol ++;
+                    bLastWasSep = TRUE;
+                }
+                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
+                {
+                    nCol ++;
+                    bLastWasSep = TRUE;
+                }
+                else
+                {
+                    bLastWasSep = FALSE;
+                }
+                pszPtr ++;
             }
-            pszPtr ++;
-        }
 
-        /* Skip empty line */
-        if (nCol == 0 && bLastWasSep)
-            continue;
+            /* Skip empty line */
+            if (nCol == 0 && bLastWasSep)
+                continue;
 
-        poGDS->nDataLineNum ++;
+            poGDS->nDataLineNum ++;
+        }
     }
 
-    int i;
-    for(i=0;i<nBlockXSize;i++)
+    double dfExpectedY = poGDS->adfGeoTransform[3] + (0.5 + nBlockYOff) * poGDS->adfGeoTransform[5];
+    int idx = -1;
+    while(TRUE)
     {
         int nCol;
         int bLastWasSep;
         do
         {
+            vsi_l_offset nOffsetBefore = VSIFTellL(poGDS->fp);
             const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
             if (pszLine == NULL)
             {
-                memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
-                return CE_Failure;
+                if( poGDS->bSameNumberOfValuesPerLine )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot read line %d", poGDS->nLineNum + 1);
+                    return CE_Failure;
+                }
+                else
+                {
+                    nLastYOff = nBlockYOff;
+                    return CE_None;
+                }
             }
             poGDS->nLineNum ++;
 
@@ -198,59 +254,160 @@ CPLErr XYZRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             char ch;
             nCol = 0;
             bLastWasSep = TRUE;
+            double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+            int bUsefulColsFound = 0;
             while((ch = *pszPtr) != '\0')
             {
-                if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
+                if (ch == ' ')
                 {
                     if (!bLastWasSep)
                         nCol ++;
                     bLastWasSep = TRUE;
                 }
+                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
+                {
+                    nCol ++;
+                    bLastWasSep = TRUE;
+                }
                 else
                 {
-                    if (bLastWasSep && nCol == poGDS->nZIndex)
+                    if (bLastWasSep)
                     {
-                        double dfZ = CPLAtofM(pszPtr);
-                        if (eDataType == GDT_Float32)
-                        {
-                            ((float*)pImage)[i] = (float)dfZ;
-                        }
-                        else if (eDataType == GDT_Int32)
+                        if (nCol == poGDS->nXIndex)
                         {
-                            ((GInt32*)pImage)[i] = (GInt32)dfZ;
+                            bUsefulColsFound ++;
+                            if( !poGDS->bSameNumberOfValuesPerLine )
+                                dfX = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
-                        else if (eDataType == GDT_Int16)
+                        else if (nCol == poGDS->nYIndex)
                         {
-                            ((GInt16*)pImage)[i] = (GInt16)dfZ;
+                            bUsefulColsFound ++;
+                            if( !poGDS->bSameNumberOfValuesPerLine )
+                                dfY = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
-                        else
+                        else if( nCol == poGDS->nZIndex)
                         {
-                            ((GByte*)pImage)[i] = (GByte)dfZ;
+                            bUsefulColsFound ++;
+                            dfZ = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
                     }
                     bLastWasSep = FALSE;
                 }
                 pszPtr ++;
             }
+            nCol ++;
 
+            if( bUsefulColsFound == 3 )
+            {
+                if( poGDS->bSameNumberOfValuesPerLine )
+                {
+                    idx ++;
+                }
+                else
+                {
+                    if( fabs(dfY - dfExpectedY) > 1e-8 )
+                    {
+                        if( idx < 0 )
+                        {
+                            CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %f instead of %f for nBlockYOff = %d",
+                                    poGDS->nLineNum, dfY, dfExpectedY, nBlockYOff);
+                            return CE_Failure;
+                        }
+                        VSIFSeekL(poGDS->fp, nOffsetBefore, SEEK_SET);
+                        nLastYOff = nBlockYOff;
+                        poGDS->nLineNum --;
+                        return CE_None;
+                    }
+
+                    idx = (int)((dfX - 0.5 * poGDS->adfGeoTransform[1] - poGDS->adfGeoTransform[0]) / poGDS->adfGeoTransform[1] + 0.5);
+                }
+                CPLAssert(idx >= 0 && idx < nRasterXSize);
+
+                if( pImage )
+                {
+                    if (eDataType == GDT_Float32)
+                    {
+                        ((float*)pImage)[idx] = (float)dfZ;
+                    }
+                    else if (eDataType == GDT_Int32)
+                    {
+                        ((GInt32*)pImage)[idx] = (GInt32)dfZ;
+                    }
+                    else if (eDataType == GDT_Int16)
+                    {
+                        ((GInt16*)pImage)[idx] = (GInt16)dfZ;
+                    }
+                    else
+                    {
+                        ((GByte*)pImage)[idx] = (GByte)dfZ;
+                    }
+                }
+            }
             /* Skip empty line */
         }
-        while (nCol == 0 && bLastWasSep);
+        while (nCol == 1 && bLastWasSep);
 
         poGDS->nDataLineNum ++;
-        nCol ++;
         if (nCol < poGDS->nMinTokens)
-        {
-            memset(pImage, 0, nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8));
             return CE_Failure;
-        }
+
+        if( idx + 1 == nRasterXSize )
+            break;
     }
-    CPLAssert(poGDS->nDataLineNum == (nBlockYOff + 1) * nBlockXSize);
+    
+    if( poGDS->bSameNumberOfValuesPerLine )
+        CPLAssert(poGDS->nDataLineNum == (nBlockYOff + 1) * nBlockXSize);
+
+    nLastYOff = nBlockYOff;
 
     return CE_None;
 }
 
 /************************************************************************/
+/*                            GetMinimum()                              */
+/************************************************************************/
+
+double XYZRasterBand::GetMinimum(int *pbSuccess)
+{
+    XYZDataset *poGDS = (XYZDataset *) poDS;
+    if( pbSuccess ) *pbSuccess = TRUE;
+    return poGDS->dfMinZ;
+}
+
+/************************************************************************/
+/*                            GetMaximum()                              */
+/************************************************************************/
+
+double XYZRasterBand::GetMaximum(int *pbSuccess)
+{
+    XYZDataset *poGDS = (XYZDataset *) poDS;
+    if( pbSuccess ) *pbSuccess = TRUE;
+    return poGDS->dfMaxZ;
+}
+
+/************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+double XYZRasterBand::GetNoDataValue(int *pbSuccess)
+{
+    XYZDataset *poGDS = (XYZDataset *) poDS;
+    if( !poGDS->bSameNumberOfValuesPerLine && 
+        poGDS->dfMinZ > -32768 && eDataType != GDT_Byte )
+    {
+        if( pbSuccess ) *pbSuccess = TRUE;
+        return (poGDS->dfMinZ > 0) ? 0 : -32768;
+    }
+    else if ( !poGDS->bSameNumberOfValuesPerLine && 
+              poGDS->dfMinZ > 0 && eDataType == GDT_Byte )
+    {
+        if( pbSuccess ) *pbSuccess = TRUE;
+        return 0;
+    }
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+}
+
+/************************************************************************/
 /*                            ~XYZDataset()                            */
 /************************************************************************/
 
@@ -260,6 +417,7 @@ XYZDataset::XYZDataset()
     nDataLineNum = INT_MAX;
     nLineNum = 0;
     nCommentLineCount = 0;
+    chDecimalSep = 0;
     bHasHeaderLine = FALSE;
     nXIndex = -1;
     nYIndex = -1;
@@ -271,6 +429,9 @@ XYZDataset::XYZDataset()
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
+    bSameNumberOfValuesPerLine = TRUE;
+    dfMinZ = 0;
+    dfMaxZ = 0;
 }
 
 /************************************************************************/
@@ -471,7 +632,6 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     int nXIndex = -1, nYIndex = -1, nZIndex = -1;
     int nMinTokens = 0;
 
-
     for(i=0;i<nCommentLineCount;i++)
         CPLReadLine2L(fp, 100, NULL);
 
@@ -541,12 +701,14 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     int nXSize = 0, nYSize = 0;
     int nLineNum = 0;
     int nDataLineNum = 0;
-    double dfFirstX = 0;
     double dfX = 0, dfY = 0, dfZ = 0;
     double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
+    double dfMinZ = 0, dfMaxZ = 0;
     double dfLastX = 0, dfLastY = 0;
     double dfStepX = 0, dfStepY = 0;
     GDALDataType eDT = GDT_Byte;
+    int bSameNumberOfValuesPerLine = TRUE;
+    char chDecimalSep = '\0';
     while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL)
     {
         nLineNum ++;
@@ -555,25 +717,81 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         char ch;
         int nCol = 0;
         int bLastWasSep = TRUE;
+        if( chDecimalSep == '\0' )
+        {
+            int nCountComma = 0;
+            int nCountFieldSep = 0;
+            while((ch = *pszPtr) != '\0')
+            {
+                if( ch == '.' )
+                {
+                    chDecimalSep = '.';
+                    break;
+                }
+                else if( ch == ',' )
+                {
+                    nCountComma ++;
+                    bLastWasSep = FALSE;
+                }
+                else if( ch == ' ' )
+                {
+                    if (!bLastWasSep)
+                        nCountFieldSep ++;
+                    bLastWasSep = TRUE;
+                }
+                else if( ch == '\t' || ch == ';' )
+                {
+                    nCountFieldSep ++;
+                    bLastWasSep = TRUE;
+                }
+                else
+                    bLastWasSep = FALSE;
+                pszPtr ++;
+            }
+            if( chDecimalSep == '\0' )
+            {
+                /* 1,2,3 */
+                if( nCountComma >= 2 && nCountFieldSep == 0 )
+                    chDecimalSep = '.';
+                /* 23,5;33;45 */
+                else if ( nCountComma > 0 && nCountFieldSep > 0 )
+                    chDecimalSep = ',';
+            }
+            pszPtr = pszLine;
+            bLastWasSep = TRUE;
+        }
+
+        char chLocalDecimalSep = chDecimalSep ? chDecimalSep : '.';
         while((ch = *pszPtr) != '\0')
         {
-            if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
+            if (ch == ' ')
             {
                 if (!bLastWasSep)
                     nCol ++;
                 bLastWasSep = TRUE;
             }
+            else if ((ch == ',' && chLocalDecimalSep != ',') || ch == '\t' || ch == ';')
+            {
+                nCol ++;
+                bLastWasSep = TRUE;
+            }
             else
             {
                 if (bLastWasSep)
                 {
                     if (nCol == nXIndex)
-                        dfX = CPLAtofM(pszPtr);
+                        dfX = CPLAtofDelim(pszPtr, chLocalDecimalSep);
                     else if (nCol == nYIndex)
-                        dfY = CPLAtofM(pszPtr);
+                        dfY = CPLAtofDelim(pszPtr, chLocalDecimalSep);
                     else if (nCol == nZIndex && eDT != GDT_Float32)
                     {
-                        dfZ = CPLAtofM(pszPtr);
+                        dfZ = CPLAtofDelim(pszPtr, chLocalDecimalSep);
+                        if( nDataLineNum == 0 )
+                            dfMinZ = dfMaxZ = dfZ;
+                        else if( dfZ < dfMinZ )
+                            dfMinZ = dfZ;
+                        else if( dfZ > dfMaxZ )
+                            dfMaxZ = dfZ;
                         int nZ = (int)dfZ;
                         if ((double)nZ != dfZ)
                         {
@@ -608,18 +826,6 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
 
-        if (nDataLineNum == 1)
-        {
-            dfFirstX = dfMinX = dfMaxX = dfX;
-            dfMinY = dfMaxY = dfY;
-        }
-        else
-        {
-            if (dfX < dfMinX) dfMinX = dfX;
-            if (dfX > dfMaxX) dfMaxX = dfX;
-            if (dfY < dfMinY) dfMinY = dfY;
-            if (dfY > dfMaxY) dfMaxY = dfY;
-        }
         if (nDataLineNum == 2)
         {
             dfStepX = dfX - dfLastX;
@@ -634,7 +840,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if (nDataLineNum > 2)
         {
-            double dfNewStepX = dfX - dfLastX;
+            //double dfNewStepX = dfX - dfLastX;
             double dfNewStepY = dfY - dfLastY;
             if (dfNewStepY != 0)
             {
@@ -649,21 +855,41 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                     }
                     dfStepX = dfAdjustedStepX;
                 }
-                if (dfStepY != 0 && fabs(dfX - dfFirstX) > 1e-8)
+                if (fabs(dfX - dfMinX) > 1e-8)
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Ungridded dataset: At line %d, X is %f, where as %f was expected",
-                             nLineNum, dfX, dfFirstX);
-                    VSIFCloseL(fp);
-                    return NULL;
+                    if( dfX < dfMinX && fmod(dfMinX - dfX, dfStepX) < 1e-8 )
+                    {
+                        bSameNumberOfValuesPerLine = FALSE;
+                        //CPLDebug("XYZ", "Adjusting minx to %f", dfX);
+                        dfMinX = dfX;
+                        nXSize = 1 + (int)((dfMaxX - dfMinX) / dfStepX + 1e-5 );
+                    }
+                    else if( !(dfX > dfMinX && fmod(dfX - dfMinX, dfStepX) < 1e-8) )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                "Ungridded dataset: At line %d, X is %f, where as %f was expected (1)",
+                                nLineNum, dfX, dfMinX);
+                        VSIFCloseL(fp);
+                        return NULL;
+                    }
                 }
-                if (dfStepY != 0 && fabs(dfLastX - dfMaxX) > 1e-8)
+                if (fabs(dfLastX - dfMaxX) > 1e-8)
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Ungridded dataset: At line %d, X is %f, where as %f was expected",
-                             nLineNum - 1, dfLastX, dfMaxX);
-                    VSIFCloseL(fp);
-                    return NULL;
+                    if( dfLastX > dfMaxX && fmod(dfLastX - dfMaxX, dfStepX) < 1e-8 )
+                    {
+                        bSameNumberOfValuesPerLine = FALSE;
+                        //CPLDebug("XYZ", "Adjusting maxx to %f", dfLastX);
+                        dfMaxX = dfLastX;
+                        nXSize = 1 + (int)((dfMaxX - dfMinX) / dfStepX + 1e-5 );
+                    }
+                    else if( !(dfLastX < dfMaxX && fmod(dfMaxX - dfLastX, dfStepX) < 1e-8) )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                "Ungridded dataset: At line %d, X is %f, where as %f was expected (2)",
+                                nLineNum - 1, dfLastX, dfMaxX);
+                        VSIFCloseL(fp);
+                        return NULL;
+                    }
                 }
                 /*if (dfStepY != 0 && fabs(dfNewStepY - dfStepY) > 1e-8)
                 {
@@ -675,8 +901,8 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 }*/
                 dfStepY = dfNewStepY;
             }
-            else if (dfNewStepX != 0)
-            {
+            //else if (dfNewStepX != 0)
+            //{
                 /*if (dfStepX != 0 && fabs(dfNewStepX - dfStepX) > 1e-8)
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
@@ -685,8 +911,22 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                     VSIFCloseL(fp);
                     return NULL;
                 }*/
-            }
+            //}
         }
+
+        if (nDataLineNum == 1)
+        {
+            dfMinX = dfMaxX = dfX;
+            dfMinY = dfMaxY = dfY;
+        }
+        else
+        {
+            if (dfStepY == 0 && dfX < dfMinX) dfMinX = dfX;
+            if (dfStepY == 0 && dfX > dfMaxX) dfMaxX = dfX;
+            if (dfY < dfMinY) dfMinY = dfY;
+            if (dfY > dfMaxY) dfMaxY = dfY;
+        }
+
         dfLastX = dfX;
         dfLastY = dfY;
     }
@@ -716,7 +956,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     //CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX);
     //CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY);
 
-    if (nDataLineNum != nXSize * nYSize)
+    if (bSameNumberOfValuesPerLine && nDataLineNum != nXSize * nYSize)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Found %d lines. Expected %d",
                  nDataLineNum,nXSize * nYSize);
@@ -742,6 +982,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->fp = fp;
     poDS->bHasHeaderLine = bHasHeaderLine;
     poDS->nCommentLineCount = nCommentLineCount;
+    poDS->chDecimalSep = chDecimalSep ? chDecimalSep : '.';
     poDS->nXIndex = nXIndex;
     poDS->nYIndex = nYIndex;
     poDS->nZIndex = nZIndex;
@@ -753,6 +994,10 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->adfGeoTransform[3] = (dfStepY < 0) ? dfMaxY - dfStepY / 2 :
                                                dfMinY - dfStepY / 2;
     poDS->adfGeoTransform[5] = dfStepY;
+    poDS->bSameNumberOfValuesPerLine = bSameNumberOfValuesPerLine;
+    poDS->dfMinZ = dfMinZ;
+    poDS->dfMaxZ = dfMaxZ;
+    //CPLDebug("XYZ", "bSameNumberOfValuesPerLine = %d", bSameNumberOfValuesPerLine);
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
@@ -930,7 +1175,7 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     poXYZ_DS->SetBand( 1, new XYZRasterBand( poXYZ_DS, 1, eReqDT ) );
     /* If outputing to stdout, we can't reopen it --> silence warning */
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    poXYZ_DS->fp = VSIFOpenL( pszFilename, "r" );
+    poXYZ_DS->fp = VSIFOpenL( pszFilename, "rb" );
     CPLPopErrorHandler();
     memcpy( &(poXYZ_DS->adfGeoTransform), adfGeoTransform, sizeof(double)*6 );
     poXYZ_DS->nXIndex = 0;
diff --git a/frmts/zlib/inflate.c b/frmts/zlib/inflate.c
index 792fdee..a6c40dd 100644
--- a/frmts/zlib/inflate.c
+++ b/frmts/zlib/inflate.c
@@ -113,7 +113,9 @@ z_streamp strm;
     state->mode = HEAD;
     state->last = 0;
     state->havedict = 0;
+    state->flags = 0;
     state->dmax = 32768U;
+    state->check = 0;
     state->head = Z_NULL;
     state->wsize = 0;
     state->whave = 0;
diff --git a/frmts/zmap/zmapdataset.cpp b/frmts/zmap/zmapdataset.cpp
index 940d023..a82fc32 100644
--- a/frmts/zmap/zmapdataset.cpp
+++ b/frmts/zmap/zmapdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: zmapdataset.cpp 24593 2012-06-16 18:58:42Z rouault $
+ * $Id: zmapdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ZMap driver
  * Purpose:  GDALDataset driver for ZMap dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: zmapdataset.cpp 24593 2012-06-16 18:58:42Z rouault $");
+CPL_CVSID("$Id: zmapdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void    GDALRegister_ZMap(void);
diff --git a/gcore/GNUmakefile b/gcore/GNUmakefile
index b4877a7..a5e19b6 100644
--- a/gcore/GNUmakefile
+++ b/gcore/GNUmakefile
@@ -9,7 +9,8 @@ OBJ	=	gdalopeninfo.o gdaldrivermanager.o gdaldriver.o gdaldataset.o \
 		gdal_rat.o gdalgmlcoverage.o gdalpamproxydb.o \
 		gdalallvalidmaskband.o gdalnodatamaskband.o gdal_rpcimdio.o \
  		gdalproxydataset.o gdalproxypool.o gdaldefaultasync.o \
-		gdalnodatavaluesmaskband.o gdaldllmain.o gdalexif.o gdalclientserver.o
+		gdalnodatavaluesmaskband.o gdaldllmain.o gdalexif.o gdalclientserver.o \
+		gdalgeorefpamdataset.o gdaljp2abstractdataset.o gdalvirtualmem.o
 
 # Enable the following if you want to use MITAB's code to convert
 # .tab coordinate systems into well known text.  But beware that linking
@@ -42,3 +43,8 @@ gdaldrivermanager.$(OBJ_EXT):	gdaldrivermanager.cpp ../GDALmake.opt
 
 install:
 	for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done
+
+# Small test tool using gdaljp2box.cpp to read jpeg2000 boxes.  Not normally
+# built or installed.
+jp2dump:	jp2dump.o
+	$(CXX) $(CXXFLAGS) jp2dump.o $(CONFIG_LIBS) -o jp2dump
diff --git a/gcore/gdal.h b/gcore/gdal.h
index 6f4c276..3a55ec0 100644
--- a/gcore/gdal.h
+++ b/gcore/gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.h 25545 2013-01-25 17:55:47Z warmerdam $
+ * $Id: gdal.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C/Public declarations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2002 Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,6 +42,7 @@
 #include "cpl_port.h"
 #include "cpl_error.h"
 #include "cpl_progress.h"
+#include "cpl_virtualmem.h"
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -279,17 +281,21 @@ GDAL_GCP CPL_DLL * CPL_STDCALL GDALDuplicateGCPs( int, const GDAL_GCP * );
 
 int CPL_DLL CPL_STDCALL
 GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs, 
-                        double *padfGeoTransform, int bApproxOK ); 
+                        double *padfGeoTransform, int bApproxOK )  CPL_WARN_UNUSED_RESULT; 
 int CPL_DLL CPL_STDCALL
 GDALInvGeoTransform( double *padfGeoTransformIn, 
-                     double *padfInvGeoTransformOut );
+                     double *padfInvGeoTransformOut ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL GDALApplyGeoTransform( double *, double, double, 
                                                 double *, double * );
+void CPL_DLL GDALComposeGeoTransforms(const double *padfGeoTransform1,
+                                      const double *padfGeoTransform2,
+                                      double *padfGeoTransformOut);
 
 /* ==================================================================== */
 /*      major objects (dataset, and, driver, drivermanager).            */
 /* ==================================================================== */
 
+char CPL_DLL  ** CPL_STDCALL GDALGetMetadataDomainList( GDALMajorObjectH hObject );
 char CPL_DLL  ** CPL_STDCALL GDALGetMetadata( GDALMajorObjectH, const char * );
 CPLErr CPL_DLL CPL_STDCALL GDALSetMetadata( GDALMajorObjectH, char **,
                                             const char * );
@@ -723,6 +729,16 @@ void CPL_DLL CPL_STDCALL GDALRATSetValueAsInt( GDALRasterAttributeTableH, int, i
                                                int );
 void CPL_DLL CPL_STDCALL GDALRATSetValueAsDouble( GDALRasterAttributeTableH, int, int,
                                                   double );
+
+int CPL_DLL CPL_STDCALL GDALRATChangesAreWrittenToFile( GDALRasterAttributeTableH hRAT );
+
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, double *pdfData );
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, int *pnData);
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, char **papszStrList);
+
 void CPL_DLL CPL_STDCALL GDALRATSetRowCount( GDALRasterAttributeTableH, 
                                              int );
 CPLErr CPL_DLL CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH, 
@@ -758,6 +774,77 @@ GIntBig CPL_DLL CPL_STDCALL GDALGetCacheUsed64(void);
 
 int CPL_DLL CPL_STDCALL GDALFlushCacheBlock(void);
 
+/* ==================================================================== */
+/*      GDAL virtual memory                                             */
+/* ==================================================================== */
+
+CPLVirtualMem CPL_DLL* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
+                                                 GDALRWFlag eRWFlag,
+                                                 int nXOff, int nYOff,
+                                                 int nXSize, int nYSize,
+                                                 int nBufXSize, int nBufYSize,
+                                                 GDALDataType eBufType,
+                                                 int nBandCount, int* panBandMap,
+                                                 int nPixelSpace,
+                                                 GIntBig nLineSpace,
+                                                 GIntBig nBandSpace,
+                                                 size_t nCacheSize,
+                                                 size_t nPageSizeHint,
+                                                 int bSingleThreadUsage,
+                                                 char **papszOptions );
+
+CPLVirtualMem CPL_DLL* GDALRasterBandGetVirtualMem( GDALRasterBandH hBand,
+                                         GDALRWFlag eRWFlag,
+                                         int nXOff, int nYOff,
+                                         int nXSize, int nYSize,
+                                         int nBufXSize, int nBufYSize,
+                                         GDALDataType eBufType,
+                                         int nPixelSpace,
+                                         GIntBig nLineSpace,
+                                         size_t nCacheSize,
+                                         size_t nPageSizeHint,
+                                         int bSingleThreadUsage,
+                                         char **papszOptions );
+
+CPLVirtualMem CPL_DLL* GDALGetVirtualMemAuto( GDALRasterBandH hBand,
+                                              GDALRWFlag eRWFlag,
+                                              int *pnPixelSpace,
+                                              GIntBig *pnLineSpace,
+                                              char **papszOptions );
+
+typedef enum
+{
+    /*! Tile Interleaved by Pixel: tile (0,0) with internal band interleaved by pixel organization, tile (1, 0), ...  */
+    GTO_TIP,
+    /*! Band Interleaved by Tile : tile (0,0) of first band, tile (0,0) of second band, ... tile (1,0) of fisrt band, tile (1,0) of second band, ... */
+    GTO_BIT,
+    /*! Band SeQuential : all the tiles of first band, all the tiles of following band... */
+    GTO_BSQ
+} GDALTileOrganization;
+
+CPLVirtualMem CPL_DLL* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
+                                                      GDALRWFlag eRWFlag,
+                                                      int nXOff, int nYOff,
+                                                      int nXSize, int nYSize,
+                                                      int nTileXSize, int nTileYSize,
+                                                      GDALDataType eBufType,
+                                                      int nBandCount, int* panBandMap,
+                                                      GDALTileOrganization eTileOrganization,
+                                                      size_t nCacheSize,
+                                                      int bSingleThreadUsage,
+                                                      char **papszOptions );
+
+CPLVirtualMem CPL_DLL* GDALRasterBandGetTiledVirtualMem( GDALRasterBandH hBand,
+                                                         GDALRWFlag eRWFlag,
+                                                         int nXOff, int nYOff,
+                                                         int nXSize, int nYSize,
+                                                         int nTileXSize, int nTileYSize,
+                                                         GDALDataType eBufType,
+                                                         size_t nCacheSize,
+                                                         int bSingleThreadUsage,
+                                                         char **papszOptions );
+
+
 CPL_C_END
 
 #endif /* ndef GDAL_H_INCLUDED */
diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h
index 87633f8..2a3526b 100644
--- a/gcore/gdal_frmts.h
+++ b/gcore/gdal_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_frmts.h 25798 2013-03-25 14:42:33Z aboudreault $
+ * $Id: gdal_frmts.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Prototypes for all format specific driver initializations.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -176,6 +177,7 @@ void CPL_DLL GDALRegister_NGSGEOID(void);
 void CPL_DLL GDALRegister_MBTiles(void);
 void CPL_DLL GDALRegister_ARG(void);
 void CPL_DLL GDALRegister_IRIS(void);
+void CPL_DLL GDALRegister_KRO(void);
 CPL_C_END
 
 #endif /* ndef GDAL_FRMTS_H_INCLUDED */
diff --git a/gcore/gdal_misc.cpp b/gcore/gdal_misc.cpp
index 395e499..3e1a91c 100644
--- a/gcore/gdal_misc.cpp
+++ b/gcore/gdal_misc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_misc.cpp 25545 2013-01-25 17:55:47Z warmerdam $
+ * $Id: gdal_misc.cpp 27121 2014-04-03 22:08:55Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Free standing functions for GDAL.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include <ctype.h>
 #include <string>
 
-CPL_CVSID("$Id: gdal_misc.cpp 25545 2013-01-25 17:55:47Z warmerdam $");
+CPL_CVSID("$Id: gdal_misc.cpp 27121 2014-04-03 22:08:55Z rouault $");
 
 #include "ogr_spatialref.h"
 
@@ -1992,6 +1993,56 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Compute source and destination ranges so we can normalize       */
+/*      the values to make the least squares computation more stable.   */
+/* -------------------------------------------------------------------- */
+    double min_pixel = pasGCPs[0].dfGCPPixel;
+    double max_pixel = pasGCPs[0].dfGCPPixel;
+    double min_line = pasGCPs[0].dfGCPLine;
+    double max_line = pasGCPs[0].dfGCPLine;
+    double min_geox = pasGCPs[0].dfGCPX;
+    double max_geox = pasGCPs[0].dfGCPX;
+    double min_geoy = pasGCPs[0].dfGCPY;
+    double max_geoy = pasGCPs[0].dfGCPY;
+
+    for (i = 1; i < nGCPCount; ++i) {
+        min_pixel = MIN(min_pixel, pasGCPs[i].dfGCPPixel);
+        max_pixel = MAX(max_pixel, pasGCPs[i].dfGCPPixel);
+        min_line = MIN(min_line, pasGCPs[i].dfGCPLine);
+        max_line = MAX(max_line, pasGCPs[i].dfGCPLine);
+        min_geox = MIN(min_geox, pasGCPs[i].dfGCPX);
+        max_geox = MAX(max_geox, pasGCPs[i].dfGCPX);
+        min_geoy = MIN(min_geoy, pasGCPs[i].dfGCPY);
+        max_geoy = MAX(max_geoy, pasGCPs[i].dfGCPY);
+    }
+
+    double EPS = 1.0e-12;
+
+    if( ABS(max_pixel - min_pixel) < EPS
+        || ABS(max_line - min_line) < EPS
+        || ABS(max_geox - min_geox) < EPS
+        || ABS(max_geoy - min_geoy) < EPS) 
+    {
+        return FALSE;  // degenerate in at least one dimension.
+    }
+
+    double pl_normalize[6], geo_normalize[6];
+    
+    pl_normalize[0] = -min_pixel / (max_pixel - min_pixel);
+    pl_normalize[1] = 1.0 / (max_pixel - min_pixel);
+    pl_normalize[2] = 0.0;
+    pl_normalize[3] = -min_line / (max_line - min_line);
+    pl_normalize[4] = 0.0;
+    pl_normalize[5] = 1.0 / (max_line - min_line);
+
+    geo_normalize[0] = -min_geox / (max_geox - min_geox);
+    geo_normalize[1] = 1.0 / (max_geox - min_geox);
+    geo_normalize[2] = 0.0;
+    geo_normalize[3] = -min_geoy / (max_geoy - min_geoy);
+    geo_normalize[4] = 0.0;
+    geo_normalize[5] = 1.0 / (max_geoy - min_geoy);
+
+/* -------------------------------------------------------------------- */
 /* In the general case, do a least squares error approximation by       */
 /* solving the equation Sum[(A - B*x + C*y - Lon)^2] = minimum		*/
 /* -------------------------------------------------------------------- */
@@ -2002,17 +2053,28 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     double divisor;
 
     for (i = 0; i < nGCPCount; ++i) {
-        sum_x += pasGCPs[i].dfGCPPixel;
-        sum_y += pasGCPs[i].dfGCPLine;
-        sum_xy += pasGCPs[i].dfGCPPixel * pasGCPs[i].dfGCPLine;
-        sum_xx += pasGCPs[i].dfGCPPixel * pasGCPs[i].dfGCPPixel;
-        sum_yy += pasGCPs[i].dfGCPLine * pasGCPs[i].dfGCPLine;
-        sum_Lon += pasGCPs[i].dfGCPX;
-        sum_Lonx += pasGCPs[i].dfGCPX * pasGCPs[i].dfGCPPixel;
-        sum_Lony += pasGCPs[i].dfGCPX * pasGCPs[i].dfGCPLine;
-        sum_Lat += pasGCPs[i].dfGCPY;
-        sum_Latx += pasGCPs[i].dfGCPY * pasGCPs[i].dfGCPPixel;
-        sum_Laty += pasGCPs[i].dfGCPY * pasGCPs[i].dfGCPLine;
+        double pixel, line, geox, geoy;
+
+        GDALApplyGeoTransform(pl_normalize, 
+                              pasGCPs[i].dfGCPPixel,
+                              pasGCPs[i].dfGCPLine,
+                              &pixel, &line);
+        GDALApplyGeoTransform(geo_normalize, 
+                              pasGCPs[i].dfGCPX,
+                              pasGCPs[i].dfGCPY,
+                              &geox, &geoy);
+
+        sum_x += pixel;
+        sum_y += line;
+        sum_xy += pixel * line;
+        sum_xx += pixel * pixel;
+        sum_yy += line * line;
+        sum_Lon += geox;
+        sum_Lonx += geox * pixel;
+        sum_Lony += geox * line;
+        sum_Lat += geoy;
+        sum_Latx += geoy * pixel;
+        sum_Laty += geoy * line;
     }
 
     divisor = nGCPCount * (sum_xx * sum_yy - sum_xy * sum_xy)
@@ -2028,44 +2090,55 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /* -------------------------------------------------------------------- */
 /*      Compute top/left origin.                                        */
 /* -------------------------------------------------------------------- */
-
-    padfGeoTransform[0] = (sum_Lon * (sum_xx * sum_yy - sum_xy * sum_xy)
-                           + sum_Lonx * (sum_y * sum_xy - sum_x *  sum_yy)
-                           + sum_Lony * (sum_x * sum_xy - sum_y * sum_xx))
+    double gt_normalized[6];
+    gt_normalized[0] = (sum_Lon * (sum_xx * sum_yy - sum_xy * sum_xy)
+                  + sum_Lonx * (sum_y * sum_xy - sum_x *  sum_yy)
+                  + sum_Lony * (sum_x * sum_xy - sum_y * sum_xx))
         / divisor;
 
-    padfGeoTransform[3] = (sum_Lat * (sum_xx * sum_yy - sum_xy * sum_xy)
-                           + sum_Latx * (sum_y * sum_xy - sum_x *  sum_yy)
-                           + sum_Laty * (sum_x * sum_xy - sum_y * sum_xx)) 
+    gt_normalized[3] = (sum_Lat * (sum_xx * sum_yy - sum_xy * sum_xy)
+                  + sum_Latx * (sum_y * sum_xy - sum_x *  sum_yy)
+                  + sum_Laty * (sum_x * sum_xy - sum_y * sum_xx)) 
         / divisor;
 
 /* -------------------------------------------------------------------- */
 /*      Compute X related coefficients.                                 */
 /* -------------------------------------------------------------------- */
-    padfGeoTransform[1] = (sum_Lon * (sum_y * sum_xy - sum_x * sum_yy)
-                           + sum_Lonx * (nGCPCount * sum_yy - sum_y * sum_y)
-                           + sum_Lony * (sum_x * sum_y - sum_xy * nGCPCount))
+    gt_normalized[1] = (sum_Lon * (sum_y * sum_xy - sum_x * sum_yy)
+                  + sum_Lonx * (nGCPCount * sum_yy - sum_y * sum_y)
+                  + sum_Lony * (sum_x * sum_y - sum_xy * nGCPCount))
         / divisor;
 
-    padfGeoTransform[2] = (sum_Lon * (sum_x * sum_xy - sum_y * sum_xx)
-                           + sum_Lonx * (sum_x * sum_y - nGCPCount * sum_xy)
-                           + sum_Lony * (nGCPCount * sum_xx - sum_x * sum_x))
+    gt_normalized[2] = (sum_Lon * (sum_x * sum_xy - sum_y * sum_xx)
+                  + sum_Lonx * (sum_x * sum_y - nGCPCount * sum_xy)
+                  + sum_Lony * (nGCPCount * sum_xx - sum_x * sum_x))
         / divisor;
 
 /* -------------------------------------------------------------------- */
 /*      Compute Y related coefficients.                                 */
 /* -------------------------------------------------------------------- */
-    padfGeoTransform[4] = (sum_Lat * (sum_y * sum_xy - sum_x * sum_yy)
-                           + sum_Latx * (nGCPCount * sum_yy - sum_y * sum_y)
-                           + sum_Laty * (sum_x * sum_y - sum_xy * nGCPCount))
+    gt_normalized[4] = (sum_Lat * (sum_y * sum_xy - sum_x * sum_yy)
+                  + sum_Latx * (nGCPCount * sum_yy - sum_y * sum_y)
+                  + sum_Laty * (sum_x * sum_y - sum_xy * nGCPCount))
         / divisor;
 
-    padfGeoTransform[5] = (sum_Lat * (sum_x * sum_xy - sum_y * sum_xx)
-                           + sum_Latx * (sum_x * sum_y - nGCPCount * sum_xy)
-                           + sum_Laty * (nGCPCount * sum_xx - sum_x * sum_x))
+    gt_normalized[5] = (sum_Lat * (sum_x * sum_xy - sum_y * sum_xx)
+                  + sum_Latx * (sum_x * sum_y - nGCPCount * sum_xy)
+                  + sum_Laty * (nGCPCount * sum_xx - sum_x * sum_x))
         / divisor;
 
 /* -------------------------------------------------------------------- */
+/*      Compose the resulting transformation with the normalization     */
+/*      geotransformations.                                             */
+/* -------------------------------------------------------------------- */
+    double gt1p2[6], inv_geo_normalize[6];
+    if( !GDALInvGeoTransform(geo_normalize, inv_geo_normalize))
+        return FALSE;
+
+    GDALComposeGeoTransforms(pl_normalize, gt_normalized, gt1p2);
+    GDALComposeGeoTransforms(gt1p2, inv_geo_normalize, padfGeoTransform);
+    
+/* -------------------------------------------------------------------- */
 /*      Now check if any of the input points fit this poorly.           */
 /* -------------------------------------------------------------------- */
     if( !bApproxOK )
@@ -2100,6 +2173,64 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 }
 
 /************************************************************************/
+/*                      GDALComposeGeoTransforms()                      */
+/************************************************************************/
+
+/**
+ * \brief Compose two geotransforms.
+ *
+ * The resulting geotransform is the equivelent to padfGT1 and then padfGT2
+ * being applied to a point.
+ * 
+ * @param padfGT1 the first geotransform, six values.
+ * @param padfGT2 the second geotransform, six values.
+ * @param padfGTOut the output geotransform, six values, may safely be the same
+ * array as padfGT1 or padfGT2.
+ */
+
+void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2, 
+                              double *padfGTOut)
+
+{
+    double gtwrk[6];
+    // We need to think of the geotransform in a more normal form to do
+    // the matrix multiple:
+    //
+    //  __                     __ 
+    //  | gt[1]   gt[2]   gt[0] |
+    //  | gt[4]   gt[5]   gt[3] |
+    //  |  0.0     0.0     1.0  |
+    //  --                     --
+    // 
+    // Then we can use normal matrix multiplication to produce the 
+    // composed transformation.  I don't actually reform the matrix 
+    // explicitly which is why the following may seem kind of spagettish.
+
+    gtwrk[1] = 
+        padfGT2[1] * padfGT1[1]
+        + padfGT2[2] * padfGT1[4];
+    gtwrk[2] = 
+        padfGT2[1] * padfGT1[2]
+        + padfGT2[2] * padfGT1[5];
+    gtwrk[0] = 
+        padfGT2[1] * padfGT1[0]
+        + padfGT2[2] * padfGT1[3]
+        + padfGT2[0] * 1.0;
+
+    gtwrk[4] = 
+        padfGT2[4] * padfGT1[1]
+        + padfGT2[5] * padfGT1[4];
+    gtwrk[5] = 
+        padfGT2[4] * padfGT1[2]
+        + padfGT2[5] * padfGT1[5];
+    gtwrk[3] = 
+        padfGT2[4] * padfGT1[0]
+        + padfGT2[5] * padfGT1[3]
+        + padfGT2[3] * 1.0;
+    memcpy(padfGTOut, gtwrk, sizeof(double) * 6);
+}
+
+/************************************************************************/
 /*                    GDALGeneralCmdLineProcessor()                     */
 /************************************************************************/
 
@@ -2477,7 +2608,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
         {
-            setlocale( LC_ALL, papszArgv[++iArg] );
+            CPLsetlocale( LC_ALL, papszArgv[++iArg] );
         }
 
 /* -------------------------------------------------------------------- */
@@ -2907,3 +3038,132 @@ int GDALCheckBandCount( int nBands, int bIsZeroAllowed )
 }
 
 CPL_C_END
+
+
+/************************************************************************/
+/*                     GDALSerializeGCPListToXML()                      */
+/************************************************************************/
+
+void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
+                                GDAL_GCP* pasGCPList,
+                                int nGCPCount,
+                                const char* pszGCPProjection )
+{
+    CPLString oFmt;
+
+    CPLXMLNode *psPamGCPList = CPLCreateXMLNode( psParentNode, CXT_Element, 
+                                                 "GCPList" );
+
+    CPLXMLNode* psLastChild = NULL;
+
+    if( pszGCPProjection != NULL 
+        && strlen(pszGCPProjection) > 0 )
+    {
+        CPLSetXMLValue( psPamGCPList, "#Projection", 
+                        pszGCPProjection );
+        psLastChild = psPamGCPList->psChild;
+    }
+
+    for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
+    {
+        CPLXMLNode *psXMLGCP;
+        GDAL_GCP *psGCP = pasGCPList + iGCP;
+
+        psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
+
+        if( psLastChild == NULL )
+            psPamGCPList->psChild = psXMLGCP;
+        else
+            psLastChild->psNext = psXMLGCP;
+        psLastChild = psXMLGCP;
+
+        CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
+
+        if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
+            CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
+
+        CPLSetXMLValue( psXMLGCP, "#Pixel", 
+                        oFmt.Printf( "%.4f", psGCP->dfGCPPixel ) );
+
+        CPLSetXMLValue( psXMLGCP, "#Line", 
+                        oFmt.Printf( "%.4f", psGCP->dfGCPLine ) );
+
+        CPLSetXMLValue( psXMLGCP, "#X", 
+                        oFmt.Printf( "%.12E", psGCP->dfGCPX ) );
+
+        CPLSetXMLValue( psXMLGCP, "#Y", 
+                        oFmt.Printf( "%.12E", psGCP->dfGCPY ) );
+
+        /* Note: GDAL 1.10.1 and older generated #GCPZ, but could not read it back */
+        if( psGCP->dfGCPZ != 0.0 )
+            CPLSetXMLValue( psXMLGCP, "#Z", 
+                            oFmt.Printf( "%.12E", psGCP->dfGCPZ ) );
+    }
+}
+
+/************************************************************************/
+/*                     GDALDeserializeGCPListFromXML()                  */
+/************************************************************************/
+
+void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
+                                    GDAL_GCP** ppasGCPList,
+                                    int* pnGCPCount,
+                                    char** ppszGCPProjection )
+{
+    CPLXMLNode *psXMLGCP;
+    OGRSpatialReference oSRS;
+
+    if( ppszGCPProjection )
+    {
+        const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
+
+        if( strlen(pszRawProj) > 0 
+            && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
+            oSRS.exportToWkt( ppszGCPProjection );
+        else
+            *ppszGCPProjection = CPLStrdup("");
+    }
+
+    // Count GCPs.
+    int  nGCPMax = 0;
+
+    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
+         psXMLGCP = psXMLGCP->psNext )
+        nGCPMax++;
+
+    *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
+    *pnGCPCount = 0;
+
+    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
+         psXMLGCP = psXMLGCP->psNext )
+    {
+        GDAL_GCP *psGCP = *ppasGCPList + *pnGCPCount;
+
+        if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
+            psXMLGCP->eType != CXT_Element )
+            continue;
+
+        GDALInitGCPs( 1, psGCP );
+
+        CPLFree( psGCP->pszId );
+        psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
+
+        CPLFree( psGCP->pszInfo );
+        psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
+
+        psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
+        psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
+
+        psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
+        psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
+        const char* pszZ = CPLGetXMLValue(psXMLGCP,"Z",NULL);
+        if( pszZ == NULL )
+        {
+            /* Note: GDAL 1.10.1 and older generated #GCPZ, but could not read it back */
+            pszZ = CPLGetXMLValue(psXMLGCP,"GCPZ","0.0");
+        }
+        psGCP->dfGCPZ = atof(pszZ);
+
+        (*pnGCPCount) ++;
+    }
+}
diff --git a/gcore/gdal_pam.h b/gcore/gdal_pam.h
index 4c07008..3f0580e 100644
--- a/gcore/gdal_pam.h
+++ b/gcore/gdal_pam.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_pam.h 22920 2011-08-10 21:08:07Z rouault $
+ * $Id: gdal_pam.h 26117 2013-06-29 20:22:34Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Declaration for Peristable Auxilary Metadata classes.
@@ -281,7 +281,7 @@ class CPL_DLL GDALPamRasterBand : public GDALRasterBand
                                          const char * pszValue,
                                          const char * pszDomain = "" );
 
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
     // new in GDALPamRasterBand. 
diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h
index b3c78eb..2802e92 100644
--- a/gcore/gdal_priv.h
+++ b/gcore/gdal_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_priv.h 25615 2013-02-08 22:24:32Z rouault $
+ * $Id: gdal_priv.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     gdal_priv.h
  * Project:  GDAL Core
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -112,6 +113,8 @@ class CPL_DLL GDALMajorObject
     CPLString           sDescription;
     GDALMultiDomainMetadata oMDMD;
     
+    char               **BuildMetadataDomainList(char** papszList, int bCheckNonEmpty, ...) CPL_NULL_TERMINATED;
+    
   public:
                         GDALMajorObject();
     virtual            ~GDALMajorObject();
@@ -122,6 +125,8 @@ class CPL_DLL GDALMajorObject
     virtual const char *GetDescription() const;
     virtual void        SetDescription( const char * );
 
+    virtual char      **GetMetadataDomainList();
+    
     virtual char      **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr      SetMetadata( char ** papszMetadata,
                                      const char * pszDomain = "" );
@@ -294,6 +299,13 @@ class CPL_DLL GDALDataset : public GDALMajorObject
                                int, int *, int, int, int );
     void   BlockBasedFlushCache();
 
+    CPLErr ValidateRasterIOOrAdviseReadParameters(
+                               const char* pszCallingFunc,
+                               int* pbStopProcessingOnCENone,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               int nBufXSize, int nBufYSize, 
+                               int nBandCount, int *panBandMap);
+
     virtual int         CloseDependentDatasets();
 
     friend class GDALRasterBand;
@@ -421,6 +433,9 @@ class CPL_DLL GDALRasterBlock
     static void Verify();
 
     static int  SafeLockBlock( GDALRasterBlock ** );
+    
+    /* Should only be called by GDALDestroyDriverManager() */
+    static void DestroyRBMutex();
 };
 
 /* ******************************************************************** */
@@ -597,13 +612,18 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
                                         int nBuckets, int *panHistogram );
 
-    virtual const GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
     virtual CPLErr          CreateMaskBand( int nFlags );
 
+    virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                               int *pnPixelSpace,
+                                               GIntBig *pnLineSpace,
+                                               char **papszOptions );
+
     void ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 };
 
@@ -952,4 +972,17 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 // (minimum value, maximum value, etc.)
 #define GDALSTAT_APPROX_NUMSAMPLES 2500
 
+CPL_C_START
+/* Caution: for technical reason this declaration is duplicated in gdal_crs.c */
+/* so any signature change should be reflected there too */
+void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
+                                GDAL_GCP* pasGCPList,
+                                int nGCPCount,
+                                const char* pszGCPProjection );
+void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
+                                    GDAL_GCP** ppasGCPList,
+                                    int* pnGCPCount,
+                                    char** ppszGCPProjection );
+CPL_C_END
+
 #endif /* ndef GDAL_PRIV_H_INCLUDED */
diff --git a/gcore/gdal_proxy.h b/gcore/gdal_proxy.h
index aba69f7..cb0351f 100644
--- a/gcore/gdal_proxy.h
+++ b/gcore/gdal_proxy.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gdal_proxy.h 20962 2010-10-25 23:00:16Z rouault $
+ * $Id: gdal_proxy.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C++/Private declarations
  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -54,6 +54,7 @@ class CPL_DLL GDALProxyDataset : public GDALDataset
                                 int, int *, int, int, int );
     public:
 
+        virtual char      **GetMetadataDomainList();
         virtual char      **GetMetadata( const char * pszDomain  );
         virtual CPLErr      SetMetadata( char ** papszMetadata,
                                         const char * pszDomain  );
@@ -109,6 +110,7 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
 
     public:
 
+        virtual char      **GetMetadataDomainList();
         virtual char      **GetMetadata( const char * pszDomain  );
         virtual CPLErr      SetMetadata( char ** papszMetadata,
                                         const char * pszDomain  );
@@ -171,13 +173,17 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
         virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
                                             int nBuckets, int *panHistogram );
 
-        virtual const GDALRasterAttributeTable *GetDefaultRAT();
+        virtual GDALRasterAttributeTable *GetDefaultRAT();
         virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
         virtual GDALRasterBand *GetMaskBand();
         virtual int             GetMaskFlags();
         virtual CPLErr          CreateMaskBand( int nFlags );
 
+        virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                                int *pnPixelSpace,
+                                                GIntBig *pnLineSpace,
+                                                char **papszOptions );
 };
 
 
diff --git a/gcore/gdal_rat.cpp b/gcore/gdal_rat.cpp
index 149de81..1846e88 100644
--- a/gcore/gdal_rat.cpp
+++ b/gcore/gdal_rat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.cpp 23156 2011-10-01 15:34:16Z rouault $
+ * $Id: gdal_rat.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdal_priv.h"
 #include "gdal_rat.h"
 
-CPL_CVSID("$Id: gdal_rat.cpp 23156 2011-10-01 15:34:16Z rouault $");
+CPL_CVSID("$Id: gdal_rat.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /**
  * \class GDALRasterAttributeTable
@@ -68,1602 +69,1738 @@ CPL_CVSID("$Id: gdal_rat.cpp 23156 2011-10-01 15:34:16Z rouault $");
  */
 
 /************************************************************************/
-/*                      GDALRasterAttributeTable()                      */
+/*                  ~GDALRasterAttributeTable()                         */
 /*                                                                      */
-/*      Simple initialization constructor.                              */
+/*                      Virtual Destructor                              */
 /************************************************************************/
 
-//! Construct empty table.
-
-GDALRasterAttributeTable::GDALRasterAttributeTable()
-
+GDALRasterAttributeTable::~GDALRasterAttributeTable()
 {
-    bColumnsAnalysed = FALSE;
-    nMinCol = -1;
-    nMaxCol = -1;
-    bLinearBinning = FALSE;
-    dfRow0Min = -0.5;
-    dfBinSize = 1.0;
-    nRowCount = 0;
+
 }
 
 /************************************************************************/
-/*                   GDALCreateRasterAttributeTable()                   */
+/*                              ValuesIO()                              */
+/*                                                                      */
+/*                      Default Implementations                         */
 /************************************************************************/
 
 /**
- * \brief Construct empty table.
+ * \brief Read or Write a block of doubles to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GDALRasterAttributeTable()
+ * This method is the same as the C function GDALRATValuesIOAsDouble().
+ *
+ * @param eRWFlag Either GF_Read or GF_Write
+ * @param iField column of the Attribute Table
+ * @param iStartRow start row to start reading/writing (zero based)
+ * @param iLength number of rows to read or write
+ * @param pdfData pointer to array of doubles to read/write. Should be at least iLength long.
+ *
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
  */
-GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
 
+CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
 {
-    return (GDALRasterAttributeTableH) (new GDALRasterAttributeTable());
-}
-
-/************************************************************************/
-/*                      GDALRasterAttributeTable()                      */
-/************************************************************************/
-
-//! Copy constructor.
+    int iIndex;
 
-GDALRasterAttributeTable::GDALRasterAttributeTable( 
-    const GDALRasterAttributeTable &oOther )
+    if( (iStartRow + iLength) > GetRowCount() ) 
+    {
+        return CE_Failure;
+    }
 
-{
-    // We have tried to be careful to allow wholesale assignment
-    *this = oOther;
+    if( eRWFlag == GF_Read )
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            pdfData[iIndex] = GetValueAsDouble(iIndex, iField);
+        }
+    }
+    else
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            SetValue(iIndex, iField, pdfData[iIndex]);
+        }
+    }
+    return CE_None;
 }
 
 /************************************************************************/
-/*                     ~GDALRasterAttributeTable()                      */
-/*                                                                      */
-/*      All magic done by magic by the container destructors.           */
+/*                       GDALRATValuesIOAsDouble()                      */
 /************************************************************************/
 
-GDALRasterAttributeTable::~GDALRasterAttributeTable()
+/**
+ * \brief Read or Write a block of doubles to/from the Attribute Table.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
+ */
+CPLErr CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, double *pdfData )
 
 {
-}
+    VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsDouble", CE_Failure );
 
-/************************************************************************/
-/*                  GDALDestroyRasterAttributeTable()                   */
-/************************************************************************/
+    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pdfData);
+}
 
 /**
- * \brief Destroys a RAT.
+ * \brief Read or Write a block of integers to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::~GDALRasterAttributeTable()
+ * This method is the same as the C function GDALRATValuesIOAsInteger().
+ *
+ * @param eRWFlag Either GF_Read or GF_Write
+ * @param iField column of the Attribute Table
+ * @param iStartRow start row to start reading/writing (zero based)
+ * @param iLength number of rows to read or write
+ * @param pnData pointer to array of ints to read/write. Should be at least iLength long.
+ *
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
  */
-void CPL_STDCALL 
-GDALDestroyRasterAttributeTable( GDALRasterAttributeTableH hRAT )
 
+CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
 {
-    if( hRAT != NULL )
-        delete static_cast<GDALRasterAttributeTable *>(hRAT);
+    int iIndex;
+
+    if( (iStartRow + iLength) > GetRowCount() ) 
+    {
+        return CE_Failure;
+    }
+
+    if( eRWFlag == GF_Read )
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            pnData[iIndex] = GetValueAsInt(iIndex, iField);
+        }
+    }
+    else
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            SetValue(iIndex, iField, pnData[iIndex]);
+        }
+    }
+    return CE_None;
 }
 
 /************************************************************************/
-/*                           AnalyseColumns()                           */
-/*                                                                      */
-/*      Internal method to work out which column to use for various     */
-/*      tasks.                                                          */
+/*                       GDALRATValuesIOAsInteger()                     */
 /************************************************************************/
 
-void GDALRasterAttributeTable::AnalyseColumns()
+/**
+ * \brief Read or Write a block of ints to/from the Attribute Table.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
+ */
+CPLErr CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, int *pnData)
 
 {
-    bColumnsAnalysed = TRUE;
-
-    nMinCol = GetColOfUsage( GFU_Min );
-    if( nMinCol == -1 )
-        nMinCol = GetColOfUsage( GFU_MinMax );
+    VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsInteger", CE_Failure );
 
-    nMaxCol = GetColOfUsage( GFU_Max );
-    if( nMaxCol == -1 )
-        nMaxCol = GetColOfUsage( GFU_MinMax );
+    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pnData);
 }
 
-/************************************************************************/
-/*                           GetColumnCount()                           */
-/************************************************************************/
-
 /**
- * \brief Fetch table column count.
+ * \brief Read or Write a block of strings to/from the Attribute Table.
+ *
+ * This method is the same as the C function GDALRATValuesIOAsString().
+ * When reading, papszStrList must be already allocated to the correct size.
+ * The caller is expected to call CPLFree on each read string.
  *
- * This method is the same as the C function GDALRATGetColumnCount().
+ * @param eRWFlag Either GF_Read or GF_Write
+ * @param iField column of the Attribute Table
+ * @param iStartRow start row to start reading/writing (zero based)
+ * @param iLength number of rows to read or write
+ * @param papszStrList pointer to array of strings to read/write. Should be at least iLength long.
  *
- * @return the number of columns.
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
  */
 
-int GDALRasterAttributeTable::GetColumnCount() const
-
+CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList)
 {
-    return aoFields.size();
+    int iIndex;
+
+    if( (iStartRow + iLength) > GetRowCount() ) 
+    {
+        return CE_Failure;
+    }
+
+    if( eRWFlag == GF_Read )
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            papszStrList[iIndex] = VSIStrdup(GetValueAsString(iIndex, iField));
+        }
+    }
+    else
+    {
+        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        {
+            SetValue(iIndex, iField, papszStrList[iIndex]);
+        }
+    }
+    return CE_None;
 }
 
 /************************************************************************/
-/*                       GDALRATGetColumnCount()                        */
+/*                       GDALRATValuesIOAsString()                      */
 /************************************************************************/
 
 /**
- * \brief Fetch table column count.
+ * \brief Read or Write a block of strings to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetColumnCount()
+ * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
  */
-int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
+CPLErr CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+                                        int iField, int iStartRow, int iLength, char **papszStrList)
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetColumnCount", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsString", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetColumnCount();
+    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, papszStrList);
 }
 
 /************************************************************************/
-/*                            GetNameOfCol()                            */
+/*                            SetRowCount()                             */
 /************************************************************************/
 
 /**
- * \brief Fetch name of indicated column.
+ * \brief Set row count.
  *
- * This method is the same as the C function GDALRATGetNameOfCol().
+ * Resizes the table to include the indicated number of rows.  Newly created
+ * rows will be initialized to their default values - "" for strings, 
+ * and zero for numeric fields. 
  *
- * @param iCol the column index (zero based). 
+ * This method is the same as the C function GDALRATSetRowCount().
  *
- * @return the column name or an empty string for invalid column numbers.
+ * @param nNewCount the new number of rows.
  */
 
-const char *GDALRasterAttributeTable::GetNameOfCol( int iCol ) const
-
+void GDALRasterAttributeTable::SetRowCount( int nNewCount )
 {
-    if( iCol < 0 || iCol >= (int) aoFields.size() )
-        return "";
-
-    else
-        return aoFields[iCol].sName;
 }
 
 /************************************************************************/
-/*                        GDALRATGetNameOfCol()                         */
+/*                         GDALRATSetRowCount()                         */
 /************************************************************************/
 
 /**
- * \brief Fetch name of indicated column.
+ * \brief Set row count.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetNameOfCol()
+ * This function is the same as the C++ method GDALRasterAttributeTable::SetRowCount()
  */
-const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
-                                             int iCol )
+void CPL_STDCALL 
+GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetNameOfCol", NULL );
-
-    // we don't just wrap the normal operator because we don't want to
-    // return a temporary string, we want to return a pointer to the
-    // internal column name. 
-
-    GDALRasterAttributeTable *poRAT = (GDALRasterAttributeTable *) hRAT;
-
-    if( iCol < 0 || iCol >= (int) poRAT->aoFields.size() )
-        return "";
+    VALIDATE_POINTER0( hRAT, "GDALRATSetRowCount" );
 
-    else
-        return poRAT->aoFields[iCol].sName.c_str();
+    ((GDALRasterAttributeTable *) hRAT)->SetRowCount( nNewCount );
 }
 
 /************************************************************************/
-/*                           GetUsageOfCol()                            */
+/*                           GetRowOfValue()                            */
 /************************************************************************/
 
 /**
- * \brief Fetch column usage value. 
+ * \brief Get row for pixel value.
+ *
+ * Given a raw pixel value, the raster attribute table is scanned to 
+ * determine which row in the table applies to the pixel value.  The
+ * row index is returned. 
  *
- * This method is the same as the C function GDALRATGetUsageOfCol().
+ * This method is the same as the C function GDALRATGetRowOfValue().
  *
- * @param iCol the column index (zero based).
+ * @param dfValue the pixel value. 
  *
- * @return the column usage, or GFU_Generic for improper column numbers.
+ * @return the row index or -1 if no row is appropriate. 
  */
 
-GDALRATFieldUsage GDALRasterAttributeTable::GetUsageOfCol( int iCol ) const
-
+int GDALRasterAttributeTable::GetRowOfValue( double dfValue ) const
 {
-    if( iCol < 0 || iCol >= (int) aoFields.size() )
-        return GFU_Generic;
-
-    else
-        return aoFields[iCol].eUsage;
+    return -1;
 }
 
 /************************************************************************/
-/*                        GDALRATGetUsageOfCol()                        */
+/*                        GDALRATGetRowOfValue()                        */
 /************************************************************************/
 
 /**
- * \brief Fetch column usage value. 
+ * \brief Get row for pixel value.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetRowOfValue()
  */
-GDALRATFieldUsage CPL_STDCALL 
-GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
+int CPL_STDCALL 
+GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetUsageOfCol", GFU_Generic );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetRowOfValue", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetUsageOfCol( iCol );
+    return ((GDALRasterAttributeTable *) hRAT)->GetRowOfValue( dfValue );
 }
 
 /************************************************************************/
-/*                            GetTypeOfCol()                            */
+/*                           GetRowOfValue()                            */
+/*                                                                      */
+/*      Int arg for now just converted to double.  Perhaps we will      */
+/*      handle this in a special way some day?                          */
+/************************************************************************/
+
+int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
+
+{
+    return GetRowOfValue( (double) nValue );
+}
+
+/************************************************************************/
+/*                            CreateColumn()                            */
 /************************************************************************/
 
 /**
- * \brief Fetch column type.
+ * \brief Create new column.
  *
- * This method is the same as the C function GDALRATGetTypeOfCol().
+ * If the table already has rows, all row values for the new column will
+ * be initialized to the default value ("", or zero).  The new column is
+ * always created as the last column, can will be column (field) 
+ * "GetColumnCount()-1" after CreateColumn() has completed successfully.
+ * 
+ * This method is the same as the C function GDALRATCreateColumn().
  *
- * @param iCol the column index (zero based).
+ * @param pszFieldName the name of the field to create.
+ * @param eFieldType the field type (integer, double or string).
+ * @param eFieldUsage the field usage, GFU_Generic if not known.
  *
- * @return column type or GFT_Integer if the column index is illegal.
+ * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
-GDALRATFieldType GDALRasterAttributeTable::GetTypeOfCol( int iCol ) const
+CPLErr GDALRasterAttributeTable::CreateColumn( const char *pszFieldName, 
+                                               GDALRATFieldType eFieldType,
+                                               GDALRATFieldUsage eFieldUsage )
 
 {
-    if( iCol < 0 || iCol >= (int) aoFields.size() )
-        return GFT_Integer;
-
-    else
-        return aoFields[iCol].eType;
+    return CE_Failure;
 }
 
 /************************************************************************/
-/*                        GDALRATGetTypeOfCol()                         */
+/*                        GDALRATCreateColumn()                         */
 /************************************************************************/
 
 /**
- * \brief Fetch column type.
+ * \brief Create new column.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetTypeOfCol()
+ * This function is the same as the C++ method GDALRasterAttributeTable::CreateColumn()
  */
-GDALRATFieldType CPL_STDCALL 
-GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
+CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT, 
+                                        const char *pszFieldName, 
+                                        GDALRATFieldType eFieldType,
+                                        GDALRATFieldUsage eFieldUsage )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetTypeOfCol", GFT_Integer );
+    VALIDATE_POINTER1( hRAT, "GDALRATCreateColumn", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetTypeOfCol( iCol );
+    return ((GDALRasterAttributeTable *) hRAT)->CreateColumn( pszFieldName, 
+                                                              eFieldType,
+                                                              eFieldUsage );
 }
 
 /************************************************************************/
-/*                           GetColOfUsage()                            */
+/*                          SetLinearBinning()                          */
 /************************************************************************/
 
 /**
- * \brief Fetch column index for given usage.
+ * \brief Set linear binning information.
  *
- * Returns the index of the first column of the requested usage type, or -1 
- * if no match is found. 
+ * For RATs with equal sized categories (in pixel value space) that are
+ * evenly spaced, this method may be used to associate the linear binning
+ * information with the table.
  *
- * This method is the same as the C function GDALRATGetUsageOfCol().
+ * This method is the same as the C function GDALRATSetLinearBinning().
  *
- * @param eUsage usage type to search for.
+ * @param dfRow0MinIn the lower bound (pixel value) of the first category.
+ * @param dfBinSizeIn the width of each category (in pixel value units). 
  *
- * @return column index, or -1 on failure. 
+ * @return CE_None on success or CE_Failure on failure.
  */
 
-int GDALRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
+CPLErr GDALRasterAttributeTable::SetLinearBinning( double dfRow0MinIn, 
+                                                   double dfBinSizeIn )
 
 {
-    unsigned int i;
-
-    for( i = 0; i < aoFields.size(); i++ )
-    {
-        if( aoFields[i].eUsage == eUsage )
-            return i;
-    }
-
-    return -1;
-}
+    return CE_Failure;
+}
 
 /************************************************************************/
-/*                        GDALRATGetColOfUsage()                        */
+/*                      GDALRATSetLinearBinning()                       */
 /************************************************************************/
 
 /**
- * \brief Fetch column index for given usage.
+ * \brief Set linear binning information.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetColOfUsage()
+ * This function is the same as the C++ method GDALRasterAttributeTable::SetLinearBinning()
  */
-int CPL_STDCALL 
-GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT, 
-                      GDALRATFieldUsage eUsage )
+CPLErr CPL_STDCALL 
+GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT, 
+                         double dfRow0Min, double dfBinSize )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetColOfUsage", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATSetLinearBinning", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetColOfUsage( eUsage );
+    return ((GDALRasterAttributeTable *) hRAT)->SetLinearBinning(
+        dfRow0Min, dfBinSize );
 }
 
 /************************************************************************/
-/*                            GetRowCount()                             */
+/*                          GetLinearBinning()                          */
 /************************************************************************/
 
 /**
- * \brief Fetch row count.
- * 
- * This method is the same as the C function GDALRATGetRowCount().
+ * \brief Get linear binning information.
+ *
+ * Returns linear binning information if any is associated with the RAT.
+ *
+ * This method is the same as the C function GDALRATGetLinearBinning().
+ *
+ * @param pdfRow0Min (out) the lower bound (pixel value) of the first category.
+ * @param pdfBinSize (out) the width of each category (in pixel value units).
  *
- * @return the number of rows. 
+ * @return TRUE if linear binning information exists or FALSE if there is none.
  */
 
-int GDALRasterAttributeTable::GetRowCount() const
-
+int GDALRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
+                                                double *pdfBinSize ) const
 {
-    return (int) nRowCount;
+    return FALSE;
 }
 
 /************************************************************************/
-/*                        GDALRATGetUsageOfCol()                        */
+/*                      GDALRATGetLinearBinning()                       */
 /************************************************************************/
+
 /**
- * \brief Fetch row count.
+ * \brief Get linear binning information.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetRowCount()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetLinearBinning()
  */
 int CPL_STDCALL 
-GDALRATGetRowCount( GDALRasterAttributeTableH hRAT )
+GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT, 
+                         double *pdfRow0Min, double *pdfBinSize )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetRowCount", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetLinearBinning", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetRowCount();
+    return ((GDALRasterAttributeTable *) hRAT)->GetLinearBinning(
+        pdfRow0Min, pdfBinSize );
 }
 
 /************************************************************************/
-/*                          GetValueAsString()                          */
+/*                             Serialize()                              */
 /************************************************************************/
 
-/**
- * \brief Fetch field value as a string.
- *
- * The value of the requested column in the requested row is returned
- * as a string.  If the field is numeric, it is formatted as a string
- * using default rules, so some precision may be lost.
- *
- * This method is the same as the C function GDALRATGetValueAsString().
- *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * 
- * @return field value
- */
-
-const char *
-GDALRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
+CPLXMLNode *GDALRasterAttributeTable::Serialize() const
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+    CPLXMLNode *psTree = NULL;
+    CPLXMLNode *psRow = NULL;
 
-        return "";
-    }
+    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) ) 
+ 	    return NULL;
 
-    if( iRow < 0 || iRow >= nRowCount )
+    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
+
+/* -------------------------------------------------------------------- */
+/*      Add attributes with regular binning info if appropriate.        */
+/* -------------------------------------------------------------------- */
+    char szValue[128];
+    double dfRow0Min, dfBinSize;
+
+    if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+        sprintf( szValue, "%.16g", dfRow0Min );
+        CPLCreateXMLNode( 
+            CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ), 
+            CXT_Text, szValue );
 
-        return "";
+        sprintf( szValue, "%.16g", dfBinSize );
+        CPLCreateXMLNode( 
+            CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ), 
+            CXT_Text, szValue );
     }
 
-    switch( aoFields[iField].eType )
+/* -------------------------------------------------------------------- */
+/*      Define each column.                                             */
+/* -------------------------------------------------------------------- */
+    int iCol;
+    int iColCount = GetColumnCount();
+
+    for( iCol = 0; iCol < iColCount; iCol++ )
     {
-      case GFT_Integer:
-      {
-          ((GDALRasterAttributeTable *) this)->
-              osWorkingResult.Printf( "%d", aoFields[iField].anValues[iRow] );
-          return osWorkingResult;
-      }
+        CPLXMLNode *psCol;
 
-      case GFT_Real:
-      {
-          ((GDALRasterAttributeTable *) this)->
-              osWorkingResult.Printf( "%.16g", aoFields[iField].adfValues[iRow]);
-          return osWorkingResult;
-      }
+        psCol = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
+        
+        sprintf( szValue, "%d", iCol );
+        CPLCreateXMLNode( 
+            CPLCreateXMLNode( psCol, CXT_Attribute, "index" ), 
+            CXT_Text, szValue );
 
-      case GFT_String:
-      {
-          return aoFields[iField].aosValues[iRow];
-      }
+        CPLCreateXMLElementAndValue( psCol, "Name", 
+                                     GetNameOfCol(iCol) );
+
+        sprintf( szValue, "%d", (int) GetTypeOfCol(iCol) );
+        CPLCreateXMLElementAndValue( psCol, "Type", szValue );
+
+        sprintf( szValue, "%d", (int) GetUsageOfCol(iCol) );
+        CPLCreateXMLElementAndValue( psCol, "Usage", szValue );
     }
 
-    return "";
-}
+/* -------------------------------------------------------------------- */
+/*      Write out each row.                                             */
+/* -------------------------------------------------------------------- */
+    int iRow;
+    int iRowCount = GetRowCount();
+    CPLXMLNode *psTail = NULL;
 
-/************************************************************************/
-/*                      GDALRATGetValueAsString()                       */
-/************************************************************************/
-/**
- * \brief Fetch field value as a string.
- *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsString()
- */
-const char * CPL_STDCALL 
-GDALRATGetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField )
+    for( iRow = 0; iRow < iRowCount; iRow++ )
+    {
+        psRow = CPLCreateXMLNode( NULL, CXT_Element, "Row" );
+        if( psTail == NULL )
+            CPLAddXMLChild( psTree, psRow );
+        else
+            psTail->psNext = psRow;
+        psTail = psRow;
 
-{
-    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsString", NULL );
+        sprintf( szValue, "%d", iRow );
+        CPLCreateXMLNode( 
+            CPLCreateXMLNode( psRow, CXT_Attribute, "index" ), 
+            CXT_Text, szValue );
 
-    GDALRasterAttributeTable *poRAT = (GDALRasterAttributeTable *) hRAT;
+        for( iCol = 0; iCol < iColCount; iCol++ )
+        {
+            const char *pszValue = szValue;
 
-    poRAT->osWorkingResult = poRAT->GetValueAsString( iRow, iField );
-    
-    return poRAT->osWorkingResult.c_str();
+            if( GetTypeOfCol(iCol) == GFT_Integer )
+                sprintf( szValue, "%d", GetValueAsInt(iRow, iCol) );
+            else if( GetTypeOfCol(iCol) == GFT_Real )
+                sprintf( szValue, "%.16g", GetValueAsDouble(iRow, iCol) );
+            else
+                pszValue = GetValueAsString(iRow, iCol);
+
+            CPLCreateXMLElementAndValue( psRow, "F", pszValue );
+        }
+    }
+
+    return psTree;
 }
 
 /************************************************************************/
-/*                           GetValueAsInt()                            */
+/*                              XMLInit()                               */
 /************************************************************************/
 
-/**
- * \brief Fetch field value as a integer.
- *
- * The value of the requested column in the requested row is returned
- * as an integer.  Non-integer fields will be converted to integer with
- * the possibility of data loss.
- *
- * This method is the same as the C function GDALRATGetValueAsInt().
- *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * 
- * @return field value
- */
-
-int 
-GDALRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
+CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree, 
+                                          const char * /*pszVRTPath*/ )
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
+    CPLAssert( GetRowCount() == 0 && GetColumnCount() == 0 );
+    
+/* -------------------------------------------------------------------- */
+/*      Linear binning.                                                 */
+/* -------------------------------------------------------------------- */
+    if( CPLGetXMLValue( psTree, "Row0Min", NULL ) 
+        && CPLGetXMLValue( psTree, "BinSize", NULL ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
-
-        return 0;
+        SetLinearBinning( atof(CPLGetXMLValue( psTree, "Row0Min","" )), 
+                          atof(CPLGetXMLValue( psTree, "BinSize","" )) );
     }
 
-    if( iRow < 0 || iRow >= nRowCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+/* -------------------------------------------------------------------- */
+/*      Column definitions                                              */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psChild;
 
-        return 0;
+    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
+    {
+        if( psChild->eType == CXT_Element 
+            && EQUAL(psChild->pszValue,"FieldDefn") )
+        {
+            CreateColumn( 
+              CPLGetXMLValue( psChild, "Name", "" ), 
+              (GDALRATFieldType) atoi(CPLGetXMLValue( psChild, "Type", "1" )),
+              (GDALRATFieldUsage) atoi(CPLGetXMLValue( psChild, "Usage","0")));
+        }
     }
-
-    switch( aoFields[iField].eType )
+    
+/* -------------------------------------------------------------------- */
+/*      Row data.                                                       */
+/* -------------------------------------------------------------------- */
+    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
     {
-      case GFT_Integer:
-        return aoFields[iField].anValues[iRow];
+        if( psChild->eType == CXT_Element 
+            && EQUAL(psChild->pszValue,"Row") )
+        {
+            int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
+            int iField = 0;
+            CPLXMLNode *psF;
 
-      case GFT_Real:
-        return (int)  aoFields[iField].adfValues[iRow];
+            for( psF = psChild->psChild; psF != NULL; psF = psF->psNext )
+            {
+                if( psF->eType != CXT_Element || !EQUAL(psF->pszValue,"F") )
+                    continue;
 
-      case GFT_String:
-        return atoi( aoFields[iField].aosValues[iRow].c_str() );
+                if( psF->psChild != NULL && psF->psChild->eType == CXT_Text )
+                    SetValue( iRow, iField++, psF->psChild->pszValue );
+                else
+                    SetValue( iRow, iField++, "" );
+            }
+        }
     }
 
-    return 0;
+    return CE_None;
 }
 
+
 /************************************************************************/
-/*                        GDALRATGetValueAsInt()                        */
+/*                      InitializeFromColorTable()                      */
 /************************************************************************/
 
 /**
- * \brief Fetch field value as a integer.
+ * \brief Initialize from color table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsInt()
- */
-int CPL_STDCALL 
-GDALRATGetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField )
-
-{
-    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsInt", 0 );
-
-    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsInt( iRow, iField );
-}
-
-/************************************************************************/
-/*                          GetValueAsDouble()                          */
-/************************************************************************/
-
-/**
- * \brief Fetch field value as a double.
- *
- * The value of the requested column in the requested row is returned
- * as a double.   Non double fields will be converted to double with
- * the possibility of data loss.
+ * This method will setup a whole raster attribute table based on the
+ * contents of the passed color table.  The Value (GFU_MinMax), 
+ * Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
+ * fields are created, and a row is set for each entry in the color table. 
  * 
- * This method is the same as the C function GDALRATGetValueAsDouble().
+ * The raster attribute table must be empty before calling 
+ * InitializeFromColorTable(). 
  *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * 
- * @return field value
+ * The Value fields are set based on the implicit assumption with color
+ * tables that entry 0 applies to pixel value 0, 1 to 1, etc. 
+ *
+ * This method is the same as the C function GDALRATInitializeFromColorTable().
+ *
+ * @param poTable the color table to copy from.
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
-double
-GDALRasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
+CPLErr GDALRasterAttributeTable::InitializeFromColorTable( 
+    const GDALColorTable *poTable )
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+    int iRow;
 
-        return 0;
+    if( GetRowCount() > 0 || GetColumnCount() > 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Raster Attribute Table not empty in InitializeFromColorTable()" );
+        return CE_Failure;
     }
 
-    if( iRow < 0 || iRow >= nRowCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+    SetLinearBinning( 0.0, 1.0 );
+    CreateColumn( "Value", GFT_Integer, GFU_MinMax );
+    CreateColumn( "Red", GFT_Integer, GFU_Red );
+    CreateColumn( "Green", GFT_Integer, GFU_Green );
+    CreateColumn( "Blue", GFT_Integer, GFU_Blue );
+    CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
 
-        return 0;
-    }
+    SetRowCount( poTable->GetColorEntryCount() );
 
-    switch( aoFields[iField].eType )
+    for( iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
     {
-      case GFT_Integer:
-        return aoFields[iField].anValues[iRow];
+        GDALColorEntry sEntry;
 
-      case GFT_Real:
-        return aoFields[iField].adfValues[iRow];
+        poTable->GetColorEntryAsRGB( iRow, &sEntry );
 
-      case GFT_String:
-        return atof( aoFields[iField].aosValues[iRow].c_str() );
+        SetValue( iRow, 0, iRow );
+        SetValue( iRow, 1, sEntry.c1 );
+        SetValue( iRow, 2, sEntry.c2 );
+        SetValue( iRow, 3, sEntry.c3 );
+        SetValue( iRow, 4, sEntry.c4 );
     }
 
-    return 0;
+    return CE_None;
 }
 
 /************************************************************************/
-/*                      GDALRATGetValueAsDouble()                       */
+/*                  GDALRATInitializeFromColorTable()                   */
 /************************************************************************/
 
 /**
- * \brief Fetch field value as a double.
+ * \brief Initialize from color table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsDouble()
+ * This function is the same as the C++ method GDALRasterAttributeTable::InitializeFromColorTable()
  */
-double CPL_STDCALL 
-GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
+CPLErr CPL_STDCALL 
+GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
+                                 GDALColorTableH hCT )
+                                 
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsDouble", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATInitializeFromColorTable", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsDouble(iRow,iField);
+    return ((GDALRasterAttributeTable *) hRAT)->
+        InitializeFromColorTable( (GDALColorTable *) hCT );
 }
 
 /************************************************************************/
-/*                            SetRowCount()                             */
+/*                       TranslateToColorTable()                        */
 /************************************************************************/
 
 /**
- * \brief Set row count.
+ * \brief Translate to a color table.
  *
- * Resizes the table to include the indicated number of rows.  Newly created
- * rows will be initialized to their default values - "" for strings, 
- * and zero for numeric fields. 
+ * This method will attempt to create a corresponding GDALColorTable from
+ * this raster attribute table. 
+ * 
+ * This method is the same as the C function GDALRATTranslateToColorTable().
  *
- * This method is the same as the C function GDALRATSetRowCount().
+ * @param nEntryCount The number of entries to produce (0 to nEntryCount-1), or -1 to auto-determine the number of entries.
  *
- * @param nNewCount the new number of rows.
+ * @return the generated color table or NULL on failure.
  */
 
-void GDALRasterAttributeTable::SetRowCount( int nNewCount )
+GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable( 
+    int nEntryCount )
 
 {
-    if( nNewCount == nRowCount )
-        return;
+/* -------------------------------------------------------------------- */
+/*      Establish which fields are red, green, blue and alpha.          */
+/* -------------------------------------------------------------------- */
+    int iRed, iGreen, iBlue, iAlpha;
 
-    unsigned int iField;
-    for( iField = 0; iField < aoFields.size(); iField++ )
+    iRed = GetColOfUsage( GFU_Red );
+    iGreen = GetColOfUsage( GFU_Green );
+    iBlue = GetColOfUsage( GFU_Blue );
+    iAlpha = GetColOfUsage( GFU_Alpha );
+
+    if( iRed == -1 || iGreen == -1 || iBlue == -1 )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If we aren't given an explicit number of values to scan for,    */
+/*      search for the maximum "max" value.                             */
+/* -------------------------------------------------------------------- */
+    if( nEntryCount == -1 )
     {
-        switch( aoFields[iField].eType )
-        {
-          case GFT_Integer:
-            aoFields[iField].anValues.resize( nNewCount );
-            break;
+        int  iRow;
+        int  iMaxCol;
 
-          case GFT_Real:
-            aoFields[iField].adfValues.resize( nNewCount );
-            break;
+        iMaxCol = GetColOfUsage( GFU_Max );
+        if( iMaxCol == -1 )
+            iMaxCol = GetColOfUsage( GFU_MinMax );
 
-          case GFT_String:
-            aoFields[iField].aosValues.resize( nNewCount );
-            break;
+        if( iMaxCol == -1 || GetRowCount() == 0 )
+            return NULL;
+    
+        for( iRow = 0; iRow < GetRowCount(); iRow++ )
+            nEntryCount = MAX(nEntryCount,GetValueAsInt(iRow,iMaxCol)+1);
+
+        if( nEntryCount < 0 )
+            return NULL;
+
+        // restrict our number of entries to something vaguely sensible
+        nEntryCount = MIN(65535,nEntryCount);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Assign values to color table.                                   */
+/* -------------------------------------------------------------------- */
+    GDALColorTable *poCT = new GDALColorTable();
+    int iEntry;
+
+    for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
+    {
+        GDALColorEntry sColor;
+        int iRow = GetRowOfValue( iEntry );
+
+        if( iRow == -1 )
+        {
+            sColor.c1 = sColor.c2 = sColor.c3 = sColor.c4 = 0;
+        }
+        else
+        {
+            sColor.c1 = (short) GetValueAsInt( iRow, iRed );
+            sColor.c2 = (short) GetValueAsInt( iRow, iGreen );
+            sColor.c3 = (short) GetValueAsInt( iRow, iBlue );
+            if( iAlpha == -1 )
+                sColor.c4 = 255;
+            else
+                sColor.c4 = (short) GetValueAsInt( iRow, iAlpha );
         }
+        
+        poCT->SetColorEntry( iEntry, &sColor );
     }
 
-    nRowCount = nNewCount;
+    return poCT;
 }
 
 /************************************************************************/
-/*                         GDALRATSetRowCount()                         */
+/*                  GDALRATInitializeFromColorTable()                   */
 /************************************************************************/
 
 /**
- * \brief Set row count.
+ * \brief Translate to a color table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetRowCount()
+ * This function is the same as the C++ method GDALRasterAttributeTable::TranslateToColorTable()
  */
-void CPL_STDCALL 
-GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
+GDALColorTableH CPL_STDCALL 
+GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
+                              int nEntryCount )
+                                 
 
 {
-    VALIDATE_POINTER0( hRAT, "GDALRATSetRowCount" );
+    VALIDATE_POINTER1( hRAT, "GDALRATTranslateToColorTable", NULL );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetRowCount( nNewCount );
+    return ((GDALRasterAttributeTable *) hRAT)->
+        TranslateToColorTable( nEntryCount );
 }
 
+
 /************************************************************************/
-/*                              SetValue()                              */
+/*                            DumpReadable()                            */
 /************************************************************************/
 
 /**
- * \brief Set field value from string.
+ * \brief Dump RAT in readable form.
  *
- * The indicated field (column) on the indicated row is set from the
- * passed value.  The value will be automatically converted for other field
- * types, with a possible loss of precision.
+ * Currently the readable form is the XML encoding ... only barely 
+ * readable. 
  *
- * This method is the same as the C function GDALRATSetValueAsString().
+ * This method is the same as the C function GDALRATDumpReadable().
  *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * @param pszValue the value to assign.
+ * @param fp file to dump to or NULL for stdout. 
  */
 
-void GDALRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         const char *pszValue )
+void GDALRasterAttributeTable::DumpReadable( FILE * fp )
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+    CPLXMLNode *psTree = Serialize();
+    char *pszXMLText = CPLSerializeXMLTree( psTree );
 
-        return;
-    }
+    CPLDestroyXMLNode( psTree );
 
-    if( iRow == nRowCount )
-        SetRowCount( nRowCount+1 );
-    
-    if( iRow < 0 || iRow >= nRowCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+    if( fp == NULL )
+        fp = stdout;
 
-        return;
-    }
+    fprintf( fp, "%s\n", pszXMLText );
 
-    switch( aoFields[iField].eType )
-    {
-      case GFT_Integer:
-        aoFields[iField].anValues[iRow] = atoi(pszValue);
-        break;
-        
-      case GFT_Real:
-        aoFields[iField].adfValues[iRow] = atof(pszValue);
-        break;
-        
-      case GFT_String:
-        aoFields[iField].aosValues[iRow] = pszValue;
-        break;
-    }
+    CPLFree( pszXMLText );
 }
 
 /************************************************************************/
-/*                      GDALRATSetValueAsString()                       */
+/*                        GDALRATDumpReadable()                         */
 /************************************************************************/
 
 /**
- * \brief Set field value from string.
+ * \brief Dump RAT in readable form.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method GDALRasterAttributeTable::DumpReadable()
  */
 void CPL_STDCALL 
-GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
-                         const char *pszValue )
+GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
 
 {
-    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsString" );
+    VALIDATE_POINTER0( hRAT, "GDALRATDumpReadable" );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, pszValue );
+    ((GDALRasterAttributeTable *) hRAT)->DumpReadable( fp );
 }
 
-/************************************************************************/
-/*                              SetValue()                              */
-/************************************************************************/
 
-/**
- * \brief Set field value from integer.
- *
- * The indicated field (column) on the indicated row is set from the
- * passed value.  The value will be automatically converted for other field
- * types, with a possible loss of precision.
- *
- * This method is the same as the C function GDALRATSetValueAsInteger().
- *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * @param nValue the value to assign.
+/* \class GDALDefaultRasterAttributeTable
+ * 
+ * An implementation of GDALRasterAttributeTable that keeps
+ * all data in memory. This is the same as the implementation
+ * of GDALRasterAttributeTable in GDAL <= 1.10.
  */
 
-void GDALRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         int nValue )
-
-{
-    if( iField < 0 || iField >= (int) aoFields.size() )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
-
-        return;
-    }
-
-    if( iRow == nRowCount )
-        SetRowCount( nRowCount+1 );
-    
-    if( iRow < 0 || iRow >= nRowCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+/************************************************************************/
+/*                  GDALDefaultRasterAttributeTable()                   */
+/*                                                                      */
+/*      Simple initialization constructor.                              */
+/************************************************************************/
 
-        return;
-    }
+//! Construct empty table.
 
-    switch( aoFields[iField].eType )
-    {
-      case GFT_Integer:
-        aoFields[iField].anValues[iRow] = nValue;
-        break;
-        
-      case GFT_Real:
-        aoFields[iField].adfValues[iRow] = nValue;
-        break;
-        
-      case GFT_String:
-      {
-          char szValue[100];
+GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
 
-          sprintf( szValue, "%d", nValue );
-          aoFields[iField].aosValues[iRow] = szValue;
-      }
-      break;
-    }
+{
+    bColumnsAnalysed = FALSE;
+    nMinCol = -1;
+    nMaxCol = -1;
+    bLinearBinning = FALSE;
+    dfRow0Min = -0.5;
+    dfBinSize = 1.0;
+    nRowCount = 0;
 }
 
 /************************************************************************/
-/*                        GDALRATSetValueAsInt()                        */
+/*                   GDALCreateRasterAttributeTable()                   */
 /************************************************************************/
 
 /**
- * \brief Set field value from integer.
+ * \brief Construct empty table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
  */
-void CPL_STDCALL 
-GDALRATSetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField,
-                      int nValue )
+GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
 
 {
-    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsInt" );
-
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, nValue);
+    return (GDALRasterAttributeTableH) (new GDALDefaultRasterAttributeTable());
 }
 
 /************************************************************************/
-/*                              SetValue()                              */
+/*                  GDALDefaultRasterAttributeTable()                   */
 /************************************************************************/
 
-/**
- * \brief Set field value from double.
- *
- * The indicated field (column) on the indicated row is set from the
- * passed value.  The value will be automatically converted for other field
- * types, with a possible loss of precision.
- *
- * This method is the same as the C function GDALRATSetValueAsDouble().
- *
- * @param iRow row to fetch (zero based).
- * @param iField column to fetch (zero based).
- * @param dfValue the value to assign.
- */
+//! Copy constructor.
 
-void GDALRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         double dfValue )
+GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable( 
+    const GDALDefaultRasterAttributeTable &oOther )
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
-
-        return;
-    }
-
-    if( iRow == nRowCount )
-        SetRowCount( nRowCount+1 );
-    
-    if( iRow < 0 || iRow >= nRowCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iRow (%d) out of range.", iRow );
+    // We have tried to be careful to allow wholesale assignment
+    *this = oOther;
+}
 
-        return;
-    }
+/************************************************************************/
+/*                 ~GDALDefaultRasterAttributeTable()                   */
+/*                                                                      */
+/*      All magic done by magic by the container destructors.           */
+/************************************************************************/
 
-    switch( aoFields[iField].eType )
-    {
-      case GFT_Integer:
-        aoFields[iField].anValues[iRow] = (int) dfValue;
-        break;
-        
-      case GFT_Real:
-        aoFields[iField].adfValues[iRow] = dfValue;
-        break;
-        
-      case GFT_String:
-      {
-          char szValue[100];
+GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable()
 
-          sprintf( szValue, "%.15g", dfValue );
-          aoFields[iField].aosValues[iRow] = szValue;
-      }
-      break;
-    }
+{
 }
 
 /************************************************************************/
-/*                      GDALRATSetValueAsDouble()                       */
+/*                  GDALDestroyRasterAttributeTable()                   */
 /************************************************************************/
 
 /**
- * \brief Set field value from double.
+ * \brief Destroys a RAT.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method GDALRasterAttributeTable::~GDALRasterAttributeTable()
  */
 void CPL_STDCALL 
-GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
-                         double dfValue )
+GDALDestroyRasterAttributeTable( GDALRasterAttributeTableH hRAT )
 
 {
-    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsDouble" );
-
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, dfValue );
+    if( hRAT != NULL )
+        delete static_cast<GDALRasterAttributeTable *>(hRAT);
 }
 
 /************************************************************************/
-/*                           GetRowOfValue()                            */
+/*                           AnalyseColumns()                           */
+/*                                                                      */
+/*      Internal method to work out which column to use for various     */
+/*      tasks.                                                          */
 /************************************************************************/
 
-/**
- * \brief Get row for pixel value.
- *
- * Given a raw pixel value, the raster attribute table is scanned to 
- * determine which row in the table applies to the pixel value.  The
- * row index is returned. 
- *
- * This method is the same as the C function GDALRATGetRowOfValue().
- *
- * @param dfValue the pixel value. 
- *
- * @return the row index or -1 if no row is appropriate. 
- */
-
-int GDALRasterAttributeTable::GetRowOfValue( double dfValue ) const
+void GDALDefaultRasterAttributeTable::AnalyseColumns()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Handle case of regular binning.                                 */
-/* -------------------------------------------------------------------- */
-    if( bLinearBinning )
-    {
-        int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
-        if( iBin < 0 || iBin >= nRowCount )
-            return -1;
-        else
-            return iBin;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have any information?                                     */
-/* -------------------------------------------------------------------- */
-    const GDALRasterAttributeField *poMin, *poMax;
-
-    if( !bColumnsAnalysed )
-        ((GDALRasterAttributeTable *) this)->AnalyseColumns();
-
-    if( nMinCol == -1 && nMaxCol == -1 )
-        return -1;
-
-    if( nMinCol != -1 )
-        poMin = &(aoFields[nMinCol]);
-    else
-        poMin = NULL;
-    
-    if( nMaxCol != -1 )
-        poMax = &(aoFields[nMaxCol]);
-    else
-        poMax = NULL;
-    
-/* -------------------------------------------------------------------- */
-/*      Search through rows for match.                                  */
-/* -------------------------------------------------------------------- */
-    int   iRow;
-
-    for( iRow = 0; iRow < nRowCount; iRow++ )
-    {
-        if( poMin != NULL )
-        {
-            if( poMin->eType == GFT_Integer )
-            {
-                while( iRow < nRowCount && dfValue < poMin->anValues[iRow] ) 
-                    iRow++;
-            }
-            else if( poMin->eType == GFT_Real )
-            {
-                while( iRow < nRowCount && dfValue < poMin->adfValues[iRow] )
-                    iRow++;
-            }
-
-            if( iRow == nRowCount )
-                break;
-        }
-
-        if( poMax != NULL )
-        {
-            if( (poMax->eType == GFT_Integer 
-                 && dfValue > poMax->anValues[iRow] ) 
-                || (poMax->eType == GFT_Real 
-                    && dfValue > poMax->adfValues[iRow] ) )
-                continue;
-        }
+    bColumnsAnalysed = TRUE;
 
-        return iRow;
-    }
+    nMinCol = GetColOfUsage( GFU_Min );
+    if( nMinCol == -1 )
+        nMinCol = GetColOfUsage( GFU_MinMax );
 
-    return -1;
+    nMaxCol = GetColOfUsage( GFU_Max );
+    if( nMaxCol == -1 )
+        nMaxCol = GetColOfUsage( GFU_MinMax );
 }
 
 /************************************************************************/
-/*                           GetRowOfValue()                            */
-/*                                                                      */
-/*      Int arg for now just converted to double.  Perhaps we will      */
-/*      handle this in a special way some day?                          */
+/*                           GetColumnCount()                           */
 /************************************************************************/
 
-int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
+int GDALDefaultRasterAttributeTable::GetColumnCount() const
 
 {
-    return GetRowOfValue( (double) nValue );
+    return aoFields.size();
 }
 
 /************************************************************************/
-/*                        GDALRATGetRowOfValue()                        */
+/*                       GDALRATGetColumnCount()                        */
 /************************************************************************/
 
 /**
- * \brief Get row for pixel value.
+ * \brief Fetch table column count.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetRowOfValue()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetColumnCount()
  */
-int CPL_STDCALL 
-GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
+int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetRowOfValue", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetColumnCount", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetRowOfValue( dfValue );
+    return ((GDALRasterAttributeTable *) hRAT)->GetColumnCount();
 }
 
 /************************************************************************/
-/*                          SetLinearBinning()                          */
+/*                            GetNameOfCol()                            */
 /************************************************************************/
 
-/**
- * \brief Set linear binning information.
- *
- * For RATs with equal sized categories (in pixel value space) that are
- * evenly spaced, this method may be used to associate the linear binning
- * information with the table.
- *
- * This method is the same as the C function GDALRATSetLinearBinning().
- *
- * @param dfRow0MinIn the lower bound (pixel value) of the first category.
- * @param dfBinSizeIn the width of each category (in pixel value units). 
- *
- * @return CE_None on success or CE_Failure on failure.
- */
-
-CPLErr GDALRasterAttributeTable::SetLinearBinning( double dfRow0MinIn, 
-                                                   double dfBinSizeIn )
+const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
 
 {
-    bLinearBinning = TRUE;
-    dfRow0Min = dfRow0MinIn;
-    dfBinSize = dfBinSizeIn;
+    if( iCol < 0 || iCol >= (int) aoFields.size() )
+        return "";
 
-    return CE_None;
+    else
+        return aoFields[iCol].sName;
 }
 
 /************************************************************************/
-/*                      GDALRATSetLinearBinning()                       */
+/*                        GDALRATGetNameOfCol()                         */
 /************************************************************************/
 
 /**
- * \brief Set linear binning information.
+ * \brief Fetch name of indicated column.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetLinearBinning()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetNameOfCol()
  */
-CPLErr CPL_STDCALL 
-GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT, 
-                         double dfRow0Min, double dfBinSize )
+const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
+                                             int iCol )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATSetLinearBinning", CE_Failure );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetNameOfCol", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->SetLinearBinning(
-        dfRow0Min, dfBinSize );
+    return ((GDALRasterAttributeTable *) hRAT)->GetNameOfCol( iCol );
 }
 
 /************************************************************************/
-/*                          GetLinearBinning()                          */
+/*                           GetUsageOfCol()                            */
 /************************************************************************/
 
-/**
- * \brief Get linear binning information.
- *
- * Returns linear binning information if any is associated with the RAT.
- *
- * This method is the same as the C function GDALRATGetLinearBinning().
- *
- * @param pdfRow0Min (out) the lower bound (pixel value) of the first category.
- * @param pdfBinSize (out) the width of each category (in pixel value units).
- *
- * @return TRUE if linear binning information exists or FALSE if there is none.
- */
-
-int GDALRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
-                                                double *pdfBinSize ) const
+GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol( int iCol ) const
 
 {
-    if( !bLinearBinning )
-        return FALSE;
-
-    *pdfRow0Min = dfRow0Min;
-    *pdfBinSize = dfBinSize;
+    if( iCol < 0 || iCol >= (int) aoFields.size() )
+        return GFU_Generic;
 
-    return TRUE;
+    else
+        return aoFields[iCol].eUsage;
 }
 
 /************************************************************************/
-/*                      GDALRATGetLinearBinning()                       */
+/*                        GDALRATGetUsageOfCol()                        */
 /************************************************************************/
 
 /**
- * \brief Get linear binning information.
+ * \brief Fetch column usage value. 
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetLinearBinning()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
  */
-int CPL_STDCALL 
-GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT, 
-                         double *pdfRow0Min, double *pdfBinSize )
+GDALRATFieldUsage CPL_STDCALL 
+GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATGetLinearBinning", 0 );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetUsageOfCol", GFU_Generic );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetLinearBinning(
-        pdfRow0Min, pdfBinSize );
+    return ((GDALRasterAttributeTable *) hRAT)->GetUsageOfCol( iCol );
 }
 
 /************************************************************************/
-/*                            CreateColumn()                            */
+/*                            GetTypeOfCol()                            */
 /************************************************************************/
 
-/**
- * \brief Create new column.
- *
- * If the table already has rows, all row values for the new column will
- * be initialized to the default value ("", or zero).  The new column is
- * always created as the last column, can will be column (field) 
- * "GetColumnCount()-1" after CreateColumn() has completed successfully.
- * 
- * This method is the same as the C function GDALRATCreateColumn().
- *
- * @param pszFieldName the name of the field to create.
- * @param eFieldType the field type (integer, double or string).
- * @param eFieldUsage the field usage, GFU_Generic if not known.
- *
- * @return CE_None on success or CE_Failure if something goes wrong.
- */
-
-CPLErr GDALRasterAttributeTable::CreateColumn( const char *pszFieldName, 
-                                               GDALRATFieldType eFieldType,
-                                               GDALRATFieldUsage eFieldUsage )
+GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
 
 {
-    int iNewField = aoFields.size();
-
-    aoFields.resize( iNewField+1 );
-
-    aoFields[iNewField].sName = pszFieldName;
-    aoFields[iNewField].eType = eFieldType;
-    aoFields[iNewField].eUsage = eFieldUsage;
-
-    if( eFieldType == GFT_Integer )
-        aoFields[iNewField].anValues.resize( nRowCount );
-    else if( eFieldType == GFT_Real )
-        aoFields[iNewField].adfValues.resize( nRowCount );
-    else if( eFieldType == GFT_String )
-        aoFields[iNewField].aosValues.resize( nRowCount );
+    if( iCol < 0 || iCol >= (int) aoFields.size() )
+        return GFT_Integer;
 
-    return CE_None;
+    else
+        return aoFields[iCol].eType;
 }
 
 /************************************************************************/
-/*                        GDALRATCreateColumn()                         */
+/*                        GDALRATGetTypeOfCol()                         */
 /************************************************************************/
 
 /**
- * \brief Create new column.
+ * \brief Fetch column type.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::CreateColumn()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetTypeOfCol()
  */
-CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT, 
-                                        const char *pszFieldName, 
-                                        GDALRATFieldType eFieldType,
-                                        GDALRATFieldUsage eFieldUsage )
+GDALRATFieldType CPL_STDCALL 
+GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATCreateColumn", CE_Failure );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetTypeOfCol", GFT_Integer );
 
-    return ((GDALRasterAttributeTable *) hRAT)->CreateColumn( pszFieldName, 
-                                                              eFieldType,
-                                                              eFieldUsage );
+    return ((GDALRasterAttributeTable *) hRAT)->GetTypeOfCol( iCol );
 }
 
 /************************************************************************/
-/*                      InitializeFromColorTable()                      */
+/*                           GetColOfUsage()                            */
 /************************************************************************/
 
-/**
- * \brief Initialize from color table.
- *
- * This method will setup a whole raster attribute table based on the
- * contents of the passed color table.  The Value (GFU_MinMax), 
- * Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
- * fields are created, and a row is set for each entry in the color table. 
- * 
- * The raster attribute table must be empty before calling 
- * InitializeFromColorTable(). 
- *
- * The Value fields are set based on the implicit assumption with color
- * tables that entry 0 applies to pixel value 0, 1 to 1, etc. 
- *
- * This method is the same as the C function GDALRATInitializeFromColorTable().
- *
- * @param poTable the color table to copy from.
- *
- * @return CE_None on success or CE_Failure if something goes wrong.
- */
-
-CPLErr GDALRasterAttributeTable::InitializeFromColorTable( 
-    const GDALColorTable *poTable )
+int GDALDefaultRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
 
 {
-    int iRow;
-
-    if( GetRowCount() > 0 || GetColumnCount() > 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Raster Attribute Table not empty in InitializeFromColorTable()" );
-        return CE_Failure;
-    }
-
-    SetLinearBinning( 0.0, 1.0 );
-    CreateColumn( "Value", GFT_Integer, GFU_MinMax );
-    CreateColumn( "Red", GFT_Integer, GFU_Red );
-    CreateColumn( "Green", GFT_Integer, GFU_Green );
-    CreateColumn( "Blue", GFT_Integer, GFU_Blue );
-    CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
-
-    SetRowCount( poTable->GetColorEntryCount() );
+    unsigned int i;
 
-    for( iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
+    for( i = 0; i < aoFields.size(); i++ )
     {
-        GDALColorEntry sEntry;
-
-        poTable->GetColorEntryAsRGB( iRow, &sEntry );
-
-        SetValue( iRow, 0, iRow );
-        SetValue( iRow, 1, sEntry.c1 );
-        SetValue( iRow, 2, sEntry.c2 );
-        SetValue( iRow, 3, sEntry.c3 );
-        SetValue( iRow, 4, sEntry.c4 );
+        if( aoFields[i].eUsage == eUsage )
+            return i;
     }
 
-    return CE_None;
+    return -1;
 }
 
 /************************************************************************/
-/*                  GDALRATInitializeFromColorTable()                   */
+/*                        GDALRATGetColOfUsage()                        */
 /************************************************************************/
 
 /**
- * \brief Initialize from color table.
+ * \brief Fetch column index for given usage.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::InitializeFromColorTable()
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetColOfUsage()
  */
-CPLErr CPL_STDCALL 
-GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
-                                 GDALColorTableH hCT )
-                                 
+int CPL_STDCALL 
+GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT, 
+                      GDALRATFieldUsage eUsage )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATInitializeFromColorTable", CE_Failure );
+    VALIDATE_POINTER1( hRAT, "GDALRATGetColOfUsage", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->
-        InitializeFromColorTable( (GDALColorTable *) hCT );
+    return ((GDALRasterAttributeTable *) hRAT)->GetColOfUsage( eUsage );
 }
 
 /************************************************************************/
-/*                       TranslateToColorTable()                        */
+/*                            GetRowCount()                             */
 /************************************************************************/
 
+int GDALDefaultRasterAttributeTable::GetRowCount() const
+
+{
+    return (int) nRowCount;
+}
+
+/************************************************************************/
+/*                        GDALRATGetUsageOfCol()                        */
+/************************************************************************/
 /**
- * \brief Translate to a color table.
- *
- * This method will attempt to create a corresponding GDALColorTable from
- * this raster attribute table. 
- * 
- * This method is the same as the C function GDALRATTranslateToColorTable().
- *
- * @param nEntryCount The number of entries to produce (0 to nEntryCount-1), or -1 to auto-determine the number of entries.
+ * \brief Fetch row count.
  *
- * @return the generated color table or NULL on failure.
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetRowCount()
  */
-
-GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable( 
-    int nEntryCount )
+int CPL_STDCALL 
+GDALRATGetRowCount( GDALRasterAttributeTableH hRAT )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Establish which fields are red, green, blue and alpha.          */
-/* -------------------------------------------------------------------- */
-    int iRed, iGreen, iBlue, iAlpha;
+    VALIDATE_POINTER1( hRAT, "GDALRATGetRowCount", 0 );
 
-    iRed = GetColOfUsage( GFU_Red );
-    iGreen = GetColOfUsage( GFU_Green );
-    iBlue = GetColOfUsage( GFU_Blue );
-    iAlpha = GetColOfUsage( GFU_Alpha );
+    return ((GDALRasterAttributeTable *) hRAT)->GetRowCount();
+}
 
-    if( iRed == -1 || iGreen == -1 || iBlue == -1 )
-        return NULL;
+/************************************************************************/
+/*                          GetValueAsString()                          */
+/************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*      If we aren't given an explicit number of values to scan for,    */
-/*      search for the maximum "max" value.                             */
-/* -------------------------------------------------------------------- */
-    if( nEntryCount == -1 )
+const char *
+GDALDefaultRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
     {
-        int  iRow;
-        int  iMaxCol;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
 
-        iMaxCol = GetColOfUsage( GFU_Max );
-        if( iMaxCol == -1 )
-            iMaxCol = GetColOfUsage( GFU_MinMax );
+        return "";
+    }
 
-        if( iMaxCol == -1 || nRowCount == 0 )
-            return NULL;
-    
-        for( iRow = 0; iRow < nRowCount; iRow++ )
-            nEntryCount = MAX(nEntryCount,GetValueAsInt(iRow,iMaxCol)+1);
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
 
-        if( nEntryCount < 0 )
-            return NULL;
+        return "";
+    }
 
-        // restrict our number of entries to something vaguely sensible
-        nEntryCount = MIN(65535,nEntryCount);
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+      {
+          ((GDALDefaultRasterAttributeTable *) this)->
+              osWorkingResult.Printf( "%d", aoFields[iField].anValues[iRow] );
+          return osWorkingResult;
+      }
+
+      case GFT_Real:
+      {
+          ((GDALDefaultRasterAttributeTable *) this)->
+             osWorkingResult.Printf( "%.16g", aoFields[iField].adfValues[iRow]);
+          return osWorkingResult;
+      }
+
+      case GFT_String:
+      {
+          return aoFields[iField].aosValues[iRow];
+      }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Assign values to color table.                                   */
-/* -------------------------------------------------------------------- */
-    GDALColorTable *poCT = new GDALColorTable();
-    int iEntry;
+    return "";
+}
 
-    for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
+/************************************************************************/
+/*                      GDALRATGetValueAsString()                       */
+/************************************************************************/
+/**
+ * \brief Fetch field value as a string.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsString()
+ */
+const char * CPL_STDCALL 
+GDALRATGetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField )
+
+{
+    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsString", NULL );
+
+    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsString(iRow, iField);
+}
+
+/************************************************************************/
+/*                           GetValueAsInt()                            */
+/************************************************************************/
+
+int 
+GDALDefaultRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
     {
-        GDALColorEntry sColor;
-        int iRow = GetRowOfValue( iEntry );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
 
-        if( iRow == -1 )
-        {
-            sColor.c1 = sColor.c2 = sColor.c3 = sColor.c4 = 0;
-        }
-        else
+        return 0;
+    }
+
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
+
+        return 0;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+        return aoFields[iField].anValues[iRow];
+
+      case GFT_Real:
+        return (int)  aoFields[iField].adfValues[iRow];
+
+      case GFT_String:
+        return atoi( aoFields[iField].aosValues[iRow].c_str() );
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                        GDALRATGetValueAsInt()                        */
+/************************************************************************/
+
+/**
+ * \brief Fetch field value as a integer.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsInt()
+ */
+int CPL_STDCALL 
+GDALRATGetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField )
+
+{
+    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsInt", 0 );
+
+    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsInt( iRow, iField );
+}
+
+/************************************************************************/
+/*                          GetValueAsDouble()                          */
+/************************************************************************/
+
+double
+GDALDefaultRasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return 0;
+    }
+
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
+
+        return 0;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+        return aoFields[iField].anValues[iRow];
+
+      case GFT_Real:
+        return aoFields[iField].adfValues[iRow];
+
+      case GFT_String:
+        return atof( aoFields[iField].aosValues[iRow].c_str() );
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                      GDALRATGetValueAsDouble()                       */
+/************************************************************************/
+
+/**
+ * \brief Fetch field value as a double.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsDouble()
+ */
+double CPL_STDCALL 
+GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
+
+{
+    VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsDouble", 0 );
+
+    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsDouble(iRow,iField);
+}
+
+/************************************************************************/
+/*                            SetRowCount()                             */
+/************************************************************************/
+
+void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
+
+{
+    if( nNewCount == nRowCount )
+        return;
+
+    unsigned int iField;
+    for( iField = 0; iField < aoFields.size(); iField++ )
+    {
+        switch( aoFields[iField].eType )
         {
-            sColor.c1 = (short) GetValueAsInt( iRow, iRed );
-            sColor.c2 = (short) GetValueAsInt( iRow, iGreen );
-            sColor.c3 = (short) GetValueAsInt( iRow, iBlue );
-            if( iAlpha == -1 )
-                sColor.c4 = 255;
-            else
-                sColor.c4 = (short) GetValueAsInt( iRow, iAlpha );
+          case GFT_Integer:
+            aoFields[iField].anValues.resize( nNewCount );
+            break;
+
+          case GFT_Real:
+            aoFields[iField].adfValues.resize( nNewCount );
+            break;
+
+          case GFT_String:
+            aoFields[iField].aosValues.resize( nNewCount );
+            break;
         }
+    }
+
+    nRowCount = nNewCount;
+}
+
+/************************************************************************/
+/*                              SetValue()                              */
+/************************************************************************/
+
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
+                                         const char *pszValue )
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return;
+    }
+
+    if( iRow == nRowCount )
+        SetRowCount( nRowCount+1 );
+    
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
+
+        return;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+        aoFields[iField].anValues[iRow] = atoi(pszValue);
+        break;
         
-        poCT->SetColorEntry( iEntry, &sColor );
+      case GFT_Real:
+        aoFields[iField].adfValues[iRow] = atof(pszValue);
+        break;
+        
+      case GFT_String:
+        aoFields[iField].aosValues[iRow] = pszValue;
+        break;
     }
+}
 
-    return poCT;
+/************************************************************************/
+/*                      GDALRATSetValueAsString()                       */
+/************************************************************************/
+
+/**
+ * \brief Set field value from string.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ */
+void CPL_STDCALL 
+GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
+                         const char *pszValue )
+
+{
+    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsString" );
+
+    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, pszValue );
 }
 
 /************************************************************************/
-/*                  GDALRATInitializeFromColorTable()                   */
+/*                              SetValue()                              */
+/************************************************************************/
+
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
+                                         int nValue )
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return;
+    }
+
+    if( iRow == nRowCount )
+        SetRowCount( nRowCount+1 );
+    
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
+
+        return;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+        aoFields[iField].anValues[iRow] = nValue;
+        break;
+        
+      case GFT_Real:
+        aoFields[iField].adfValues[iRow] = nValue;
+        break;
+        
+      case GFT_String:
+      {
+          char szValue[100];
+
+          sprintf( szValue, "%d", nValue );
+          aoFields[iField].aosValues[iRow] = szValue;
+      }
+      break;
+    }
+}
+
+/************************************************************************/
+/*                        GDALRATSetValueAsInt()                        */
 /************************************************************************/
 
 /**
- * \brief Translate to a color table.
+ * \brief Set field value from integer.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::TranslateToColorTable()
+ * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
  */
-GDALColorTableH CPL_STDCALL 
-GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
-                              int nEntryCount )
-                                 
+void CPL_STDCALL 
+GDALRATSetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField,
+                      int nValue )
 
 {
-    VALIDATE_POINTER1( hRAT, "GDALRATTranslateToColorTable", NULL );
+    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsInt" );
+
+    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, nValue);
+}
+
+/************************************************************************/
+/*                              SetValue()                              */
+/************************************************************************/
+
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
+                                         double dfValue )
+
+{
+    if( iField < 0 || iField >= (int) aoFields.size() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iField (%d) out of range.", iField );
+
+        return;
+    }
+
+    if( iRow == nRowCount )
+        SetRowCount( nRowCount+1 );
+    
+    if( iRow < 0 || iRow >= nRowCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "iRow (%d) out of range.", iRow );
+
+        return;
+    }
+
+    switch( aoFields[iField].eType )
+    {
+      case GFT_Integer:
+        aoFields[iField].anValues[iRow] = (int) dfValue;
+        break;
+        
+      case GFT_Real:
+        aoFields[iField].adfValues[iRow] = dfValue;
+        break;
+        
+      case GFT_String:
+      {
+          char szValue[100];
+
+          sprintf( szValue, "%.15g", dfValue );
+          aoFields[iField].aosValues[iRow] = szValue;
+      }
+      break;
+    }
+}
+
+/************************************************************************/
+/*                      GDALRATSetValueAsDouble()                       */
+/************************************************************************/
+
+/**
+ * \brief Set field value from double.
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ */
+void CPL_STDCALL 
+GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
+                         double dfValue )
+
+{
+    VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsDouble" );
 
-    return ((GDALRasterAttributeTable *) hRAT)->
-        TranslateToColorTable( nEntryCount );
+    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, dfValue );
 }
 
 /************************************************************************/
-/*                              XMLInit()                               */
+/*                       ChangesAreWrittenToFile()                      */
 /************************************************************************/
 
-CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree, 
-                                          const char * /*pszVRTPath*/ )
-
+int GDALDefaultRasterAttributeTable::ChangesAreWrittenToFile()
 {
-    CPLAssert( GetRowCount() == 0 && GetColumnCount() == 0 );
-    
-/* -------------------------------------------------------------------- */
-/*      Linear binning.                                                 */
-/* -------------------------------------------------------------------- */
-    if( CPLGetXMLValue( psTree, "Row0Min", NULL ) 
-        && CPLGetXMLValue( psTree, "BinSize", NULL ) )
-    {
-        SetLinearBinning( atof(CPLGetXMLValue( psTree, "Row0Min","" )), 
-                          atof(CPLGetXMLValue( psTree, "BinSize","" )) );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Column definitions                                              */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psChild;
-
-    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
-    {
-        if( psChild->eType == CXT_Element 
-            && EQUAL(psChild->pszValue,"FieldDefn") )
-        {
-            CreateColumn( 
-              CPLGetXMLValue( psChild, "Name", "" ), 
-              (GDALRATFieldType) atoi(CPLGetXMLValue( psChild, "Type", "1" )),
-              (GDALRATFieldUsage) atoi(CPLGetXMLValue( psChild, "Usage","0")));
-        }
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Row data.                                                       */
-/* -------------------------------------------------------------------- */
-    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
-    {
-        if( psChild->eType == CXT_Element 
-            && EQUAL(psChild->pszValue,"Row") )
-        {
-            int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
-            int iField = 0;
-            CPLXMLNode *psF;
+    // GDALRasterBand.SetDefaultRAT needs to be called on instances of 
+    // GDALDefaultRasterAttributeTable since changes are just in-memory
+    return FALSE;
+}
 
-            for( psF = psChild->psChild; psF != NULL; psF = psF->psNext )
-            {
-                if( psF->eType != CXT_Element || !EQUAL(psF->pszValue,"F") )
-                    continue;
+/************************************************************************/
+/*                   GDALRATChangesAreWrittenToFile()                   */
+/************************************************************************/
 
-                if( psF->psChild != NULL && psF->psChild->eType == CXT_Text )
-                    SetValue( iRow, iField++, psF->psChild->pszValue );
-                else
-                    SetValue( iRow, iField++, "" );
-            }
-        }
-    }
+/**
+ * \brief Determine whether changes made to this RAT are reflected directly in the dataset
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::ChangesAreWrittenToFile()
+ */
+int CPL_STDCALL
+GDALRATChangesAreWrittenToFile( GDALRasterAttributeTableH hRAT )
+{
+    VALIDATE_POINTER1( hRAT, "GDALRATChangesAreWrittenToFile", FALSE );
 
-    return CE_None;
+    return ((GDALRasterAttributeTable *) hRAT)->ChangesAreWrittenToFile();
 }
 
 /************************************************************************/
-/*                             Serialize()                              */
+/*                           GetRowOfValue()                            */
 /************************************************************************/
 
-CPLXMLNode *GDALRasterAttributeTable::Serialize() const
+int GDALDefaultRasterAttributeTable::GetRowOfValue( double dfValue ) const
 
 {
-    CPLXMLNode *psTree = NULL;
-    CPLXMLNode *psRow = NULL;
-
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
-
 /* -------------------------------------------------------------------- */
-/*      Add attributes with regular binning info if appropriate.        */
+/*      Handle case of regular binning.                                 */
 /* -------------------------------------------------------------------- */
-    char szValue[128];
-
     if( bLinearBinning )
     {
-        sprintf( szValue, "%.16g", dfRow0Min );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ), 
-            CXT_Text, szValue );
-
-        sprintf( szValue, "%.16g", dfBinSize );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ), 
-            CXT_Text, szValue );
+        int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
+        if( iBin < 0 || iBin >= nRowCount )
+            return -1;
+        else
+            return iBin;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Define each column.                                             */
+/*      Do we have any information?                                     */
 /* -------------------------------------------------------------------- */
-    int iCol;
-
-    for( iCol = 0; iCol < (int) aoFields.size(); iCol++ )
-    {
-        CPLXMLNode *psCol;
-
-        psCol = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
-        
-        sprintf( szValue, "%d", iCol );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psCol, CXT_Attribute, "index" ), 
-            CXT_Text, szValue );
-
-        CPLCreateXMLElementAndValue( psCol, "Name", 
-                                     aoFields[iCol].sName.c_str() );
+    const GDALRasterAttributeField *poMin, *poMax;
 
-        sprintf( szValue, "%d", (int) aoFields[iCol].eType );
-        CPLCreateXMLElementAndValue( psCol, "Type", szValue );
+    if( !bColumnsAnalysed )
+        ((GDALDefaultRasterAttributeTable *) this)->AnalyseColumns();
 
-        sprintf( szValue, "%d", (int) aoFields[iCol].eUsage );
-        CPLCreateXMLElementAndValue( psCol, "Usage", szValue );
-    }
+    if( nMinCol == -1 && nMaxCol == -1 )
+        return -1;
 
+    if( nMinCol != -1 )
+        poMin = &(aoFields[nMinCol]);
+    else
+        poMin = NULL;
+    
+    if( nMaxCol != -1 )
+        poMax = &(aoFields[nMaxCol]);
+    else
+        poMax = NULL;
+    
 /* -------------------------------------------------------------------- */
-/*      Write out each row.                                             */
+/*      Search through rows for match.                                  */
 /* -------------------------------------------------------------------- */
-    int iRow;
-    CPLXMLNode *psTail = NULL;
+    int   iRow;
 
     for( iRow = 0; iRow < nRowCount; iRow++ )
     {
-        psRow = CPLCreateXMLNode( NULL, CXT_Element, "Row" );
-        if( psTail == NULL )
-            CPLAddXMLChild( psTree, psRow );
-        else
-            psTail->psNext = psRow;
-        psTail = psRow;
-
-        sprintf( szValue, "%d", iRow );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psRow, CXT_Attribute, "index" ), 
-            CXT_Text, szValue );
-
-        for( iCol = 0; iCol < (int) aoFields.size(); iCol++ )
+        if( poMin != NULL )
         {
-            const char *pszValue = szValue;
+            if( poMin->eType == GFT_Integer )
+            {
+                while( iRow < nRowCount && dfValue < poMin->anValues[iRow] ) 
+                    iRow++;
+            }
+            else if( poMin->eType == GFT_Real )
+            {
+                while( iRow < nRowCount && dfValue < poMin->adfValues[iRow] )
+                    iRow++;
+            }
 
-            if( aoFields[iCol].eType == GFT_Integer )
-                sprintf( szValue, "%d", aoFields[iCol].anValues[iRow] );
-            else if( aoFields[iCol].eType == GFT_Real )
-                sprintf( szValue, "%.16g", aoFields[iCol].adfValues[iRow] );
-            else
-                pszValue = aoFields[iCol].aosValues[iRow].c_str();
+            if( iRow == nRowCount )
+                break;
+        }
 
-            CPLCreateXMLElementAndValue( psRow, "F", pszValue );
+        if( poMax != NULL )
+        {
+            if( (poMax->eType == GFT_Integer 
+                 && dfValue > poMax->anValues[iRow] ) 
+                || (poMax->eType == GFT_Real 
+                    && dfValue > poMax->adfValues[iRow] ) )
+                continue;
         }
+
+        return iRow;
     }
 
-    return psTree;
+    return -1;
 }
 
 /************************************************************************/
-/*                            DumpReadable()                            */
+/*                           GetRowOfValue()                            */
+/*                                                                      */
+/*      Int arg for now just converted to double.  Perhaps we will      */
+/*      handle this in a special way some day?                          */
 /************************************************************************/
 
-/**
- * \brief Dump RAT in readable form.
- *
- * Currently the readable form is the XML encoding ... only barely 
- * readable. 
- *
- * This method is the same as the C function GDALRATDumpReadable().
- *
- * @param fp file to dump to or NULL for stdout. 
- */
+int GDALDefaultRasterAttributeTable::GetRowOfValue( int nValue ) const
 
-void GDALRasterAttributeTable::DumpReadable( FILE * fp )
+{
+    return GetRowOfValue( (double) nValue );
+}
+
+/************************************************************************/
+/*                          SetLinearBinning()                          */
+/************************************************************************/
+
+CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning( double dfRow0MinIn, 
+                                                   double dfBinSizeIn )
 
 {
-    CPLXMLNode *psTree = Serialize();
-    char *pszXMLText = CPLSerializeXMLTree( psTree );
+    bLinearBinning = TRUE;
+    dfRow0Min = dfRow0MinIn;
+    dfBinSize = dfBinSizeIn;
 
-    CPLDestroyXMLNode( psTree );
+    return CE_None;
+}
 
-    if( fp == NULL )
-        fp = stdout;
+/************************************************************************/
+/*                          GetLinearBinning()                          */
+/************************************************************************/
 
-    fprintf( fp, "%s\n", pszXMLText );
+int GDALDefaultRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
+                                                double *pdfBinSize ) const
 
-    CPLFree( pszXMLText );
+{
+    if( !bLinearBinning )
+        return FALSE;
+
+    *pdfRow0Min = dfRow0Min;
+    *pdfBinSize = dfBinSize;
+
+    return TRUE;
 }
 
 /************************************************************************/
-/*                        GDALRATDumpReadable()                         */
+/*                            CreateColumn()                            */
 /************************************************************************/
 
-/**
- * \brief Dump RAT in readable form.
- *
- * This function is the same as the C++ method GDALRasterAttributeTable::DumpReadable()
- */
-void CPL_STDCALL 
-GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
+CPLErr GDALDefaultRasterAttributeTable::CreateColumn( const char *pszFieldName, 
+                                               GDALRATFieldType eFieldType,
+                                               GDALRATFieldUsage eFieldUsage )
 
 {
-    VALIDATE_POINTER0( hRAT, "GDALRATDumpReadable" );
+    int iNewField = aoFields.size();
 
-    ((GDALRasterAttributeTable *) hRAT)->DumpReadable( fp );
+    aoFields.resize( iNewField+1 );
+
+    aoFields[iNewField].sName = pszFieldName;
+
+    // color columns should be int 0..255 
+    if( ( eFieldUsage == GFU_Red ) || ( eFieldUsage == GFU_Green ) || 
+        ( eFieldUsage == GFU_Blue ) || ( eFieldUsage == GFU_Alpha ) )
+    {
+        eFieldType = GFT_Integer;
+    }
+    aoFields[iNewField].eType = eFieldType;
+    aoFields[iNewField].eUsage = eFieldUsage;
+
+    if( eFieldType == GFT_Integer )
+        aoFields[iNewField].anValues.resize( nRowCount );
+    else if( eFieldType == GFT_Real )
+        aoFields[iNewField].adfValues.resize( nRowCount );
+    else if( eFieldType == GFT_String )
+        aoFields[iNewField].aosValues.resize( nRowCount );
+
+    return CE_None;
 }
 
 /************************************************************************/
 /*                               Clone()                                */
 /************************************************************************/
 
-/**
- * \brief Copy Raster Attribute Table
- *
- * Creates a new copy of an existing raster attribute table.  The new copy
- * becomes the responsibility of the caller to destroy.
- *
- * This method is the same as the C function GDALRATClone().
- *
- * @return new copy of the RAT. 
- */
-
-GDALRasterAttributeTable *GDALRasterAttributeTable::Clone() const
+GDALDefaultRasterAttributeTable *GDALDefaultRasterAttributeTable::Clone() const
 
 {
-    return new GDALRasterAttributeTable( *this );
+    return new GDALDefaultRasterAttributeTable( *this );
 }
 
 /************************************************************************/
diff --git a/gcore/gdal_rat.h b/gcore/gdal_rat.h
index 267b5fc..f36939d 100644
--- a/gcore/gdal_rat.h
+++ b/gcore/gdal_rat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gdal_rat.h 26117 2013-06-29 20:22:34Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDALRasterAttributeTable class declarations.
@@ -32,6 +32,236 @@
 
 #include "cpl_minixml.h"
 
+// Clone and Serialize are allowed to fail if GetRowCount()*GetColCount() greater
+// than this number
+#define RAT_MAX_ELEM_FOR_CLONE  1000000
+
+/************************************************************************/
+/*                       GDALRasterAttributeTable                       */
+/************************************************************************/
+
+//! Raster Attribute Table interface.
+class GDALDefaultRasterAttributeTable;
+
+class CPL_DLL GDALRasterAttributeTable 
+{
+public:
+    virtual ~GDALRasterAttributeTable();
+    /**
+     * \brief Copy Raster Attribute Table
+     *
+     * Creates a new copy of an existing raster attribute table.  The new copy
+     * becomes the responsibility of the caller to destroy.
+     * May fail (return NULL) if the attribute table is too large to clone
+     * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
+     *
+     * This method is the same as the C function GDALRATClone().
+     *
+     * @return new copy of the RAT as an in-memory implementation.
+     */
+    virtual GDALDefaultRasterAttributeTable *Clone() const = 0;
+    
+    /**
+     * \brief Fetch table column count.
+     *
+     * This method is the same as the C function GDALRATGetColumnCount().
+     *
+     * @return the number of columns.
+     */
+    virtual int           GetColumnCount() const = 0;
+
+    /**
+     * \brief Fetch name of indicated column.
+     *
+     * This method is the same as the C function GDALRATGetNameOfCol().
+     *
+     * @param iCol the column index (zero based). 
+     *
+     * @return the column name or an empty string for invalid column numbers.
+     */
+    virtual const char   *GetNameOfCol( int ) const = 0;
+
+    /**
+     * \brief Fetch column usage value. 
+     *
+     * This method is the same as the C function GDALRATGetUsageOfCol().
+     *
+     * @param iCol the column index (zero based).
+     *
+     * @return the column usage, or GFU_Generic for improper column numbers.
+     */
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const = 0;
+
+    /**
+     * \brief Fetch column type.
+     *
+     * This method is the same as the C function GDALRATGetTypeOfCol().
+     *
+     * @param iCol the column index (zero based).
+     *
+     * @return column type or GFT_Integer if the column index is illegal.
+     */
+    virtual GDALRATFieldType GetTypeOfCol( int ) const = 0;
+    
+    /**
+     * \brief Fetch column index for given usage.
+     *
+     * Returns the index of the first column of the requested usage type, or -1 
+     * if no match is found. 
+     *
+     * This method is the same as the C function GDALRATGetUsageOfCol().
+     *
+     * @param eUsage usage type to search for.
+     *
+     * @return column index, or -1 on failure. 
+     */
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const = 0;
+
+    /**
+     * \brief Fetch row count.
+     * 
+     * This method is the same as the C function GDALRATGetRowCount().
+     *
+     * @return the number of rows. 
+     */
+    virtual int           GetRowCount() const = 0;
+
+    /**
+     * \brief Fetch field value as a string.
+     *
+     * The value of the requested column in the requested row is returned
+     * as a string.  If the field is numeric, it is formatted as a string
+     * using default rules, so some precision may be lost.
+     *
+     * The returned string is temporary and cannot be expected to be
+     * available after the next GDAL call.
+     * 
+     * This method is the same as the C function GDALRATGetValueAsString().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * 
+     * @return field value. 
+     */
+    virtual const char   *GetValueAsString( int iRow, int iField ) const = 0;
+
+    /**
+     * \brief Fetch field value as a integer.
+     *
+     * The value of the requested column in the requested row is returned
+     * as an integer.  Non-integer fields will be converted to integer with
+     * the possibility of data loss.
+     *
+     * This method is the same as the C function GDALRATGetValueAsInt().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * 
+     * @return field value
+     */
+    virtual int           GetValueAsInt( int iRow, int iField ) const = 0;
+
+    /**
+     * \brief Fetch field value as a double.
+     *
+     * The value of the requested column in the requested row is returned
+     * as a double.   Non double fields will be converted to double with
+     * the possibility of data loss.
+     * 
+     * This method is the same as the C function GDALRATGetValueAsDouble().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * 
+     * @return field value
+     */
+    virtual double        GetValueAsDouble( int iRow, int iField ) const = 0;
+
+    /**
+     * \brief Set field value from string.
+     *
+     * The indicated field (column) on the indicated row is set from the
+     * passed value.  The value will be automatically converted for other field
+     * types, with a possible loss of precision.
+     *
+     * This method is the same as the C function GDALRATSetValueAsString().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * @param pszValue the value to assign.
+     */
+    virtual void          SetValue( int iRow, int iField, const char *pszValue ) = 0;
+
+    /**
+     * \brief Set field value from integer.
+     *
+     * The indicated field (column) on the indicated row is set from the
+     * passed value.  The value will be automatically converted for other field
+     * types, with a possible loss of precision.
+     *
+     * This method is the same as the C function GDALRATSetValueAsInteger().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * @param nValue the value to assign.
+     */
+    virtual void          SetValue( int iRow, int iField, int nValue ) = 0;
+
+    /**
+     * \brief Set field value from double.
+     *
+     * The indicated field (column) on the indicated row is set from the
+     * passed value.  The value will be automatically converted for other field
+     * types, with a possible loss of precision.
+     *
+     * This method is the same as the C function GDALRATSetValueAsDouble().
+     *
+     * @param iRow row to fetch (zero based).
+     * @param iField column to fetch (zero based).
+     * @param dfValue the value to assign.
+     */
+    virtual void          SetValue( int iRow, int iField, double dfValue) = 0;
+
+    /**
+     * \brief Determine whether changes made to this RAT are reflected directly in the dataset
+     * 
+     * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be called. Otherwise
+     * this is unnecessary since changes to this object are reflected in the dataset.
+     *
+     * This method is the same as the C function GDALRATChangesAreWrittenToFile().
+     *
+     */
+    virtual int           ChangesAreWrittenToFile() = 0;
+
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData);
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList);
+
+    virtual void          SetRowCount( int iCount );
+    virtual int           GetRowOfValue( double dfValue ) const;
+    virtual int           GetRowOfValue( int nValue ) const;
+
+    virtual CPLErr        CreateColumn( const char *pszFieldName, 
+                                GDALRATFieldType eFieldType, 
+                                GDALRATFieldUsage eFieldUsage );
+    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
+    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
+
+    /**
+     * \brief Serialize
+     * 
+     * May fail (return NULL) if the attribute table is too large to serialize
+     * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
+     */
+    virtual CPLXMLNode   *Serialize() const;
+    virtual CPLErr        XMLInit( CPLXMLNode *, const char * );
+
+    virtual CPLErr        InitializeFromColorTable( const GDALColorTable * );
+    virtual GDALColorTable *TranslateToColorTable( int nEntryCount = -1 );
+    
+    virtual void          DumpReadable( FILE * = NULL );
+};
+
 /************************************************************************/
 /*                       GDALRasterAttributeField                       */
 /*                                                                      */
@@ -53,16 +283,13 @@ public:
 };
 
 /************************************************************************/
-/*                       GDALRasterAttributeTable                       */
+/*                    GDALDefaultRasterAttributeTable                   */
 /************************************************************************/
 
 //! Raster Attribute Table container.
 
-class CPL_DLL GDALRasterAttributeTable 
+class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
 {
-    friend const char * CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH, int );
-    friend const char * CPL_STDCALL GDALRATGetValueAsString( GDALRasterAttributeTableH, int, int );
-
 private:
     std::vector<GDALRasterAttributeField> aoFields;
 
@@ -77,54 +304,45 @@ private:
 
     int   nRowCount;
 
-    CPLString     osWorkingResult;
+    CPLString osWorkingResult;
 
 public:
-    GDALRasterAttributeTable();
-    GDALRasterAttributeTable(const GDALRasterAttributeTable&);
-    ~GDALRasterAttributeTable();
+    GDALDefaultRasterAttributeTable();
+    GDALDefaultRasterAttributeTable(const GDALDefaultRasterAttributeTable&);
+    ~GDALDefaultRasterAttributeTable();
 
-    GDALRasterAttributeTable *Clone() const;
+    GDALDefaultRasterAttributeTable *Clone() const;
     
-    int           GetColumnCount() const;
+    virtual int           GetColumnCount() const;
 
-    const char   *GetNameOfCol( int ) const;
-    GDALRATFieldUsage GetUsageOfCol( int ) const;
-    GDALRATFieldType GetTypeOfCol( int ) const;
+    virtual const char   *GetNameOfCol( int ) const;
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
+    virtual GDALRATFieldType GetTypeOfCol( int ) const;
     
-    int           GetColOfUsage( GDALRATFieldUsage ) const;
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
 
-    int           GetRowCount() const;
+    virtual int           GetRowCount() const;
 
-    const char   *GetValueAsString( int iRow, int iField ) const;
-    int           GetValueAsInt( int iRow, int iField ) const;
-    double        GetValueAsDouble( int iRow, int iField ) const;
+    virtual const char   *GetValueAsString( int iRow, int iField ) const;
+    virtual int           GetValueAsInt( int iRow, int iField ) const;
+    virtual double        GetValueAsDouble( int iRow, int iField ) const;
 
-    void          SetValue( int iRow, int iField, const char *pszValue );
-    void          SetValue( int iRow, int iField, double dfValue);
-    void          SetValue( int iRow, int iField, int nValue );
-    void          SetRowCount( int iCount );
+    virtual void          SetValue( int iRow, int iField, const char *pszValue );
+    virtual void          SetValue( int iRow, int iField, double dfValue);
+    virtual void          SetValue( int iRow, int iField, int nValue );
 
-    int           GetRowOfValue( double dfValue ) const;
-    int           GetRowOfValue( int nValue ) const;
-    int           GetColorOfValue( double dfValue, GDALColorEntry *psEntry ) const;
+    virtual int           ChangesAreWrittenToFile();
+    virtual void          SetRowCount( int iCount );
 
-    double        GetRowMin( int iRow ) const;
-    double        GetRowMax( int iRow ) const;
+    virtual int           GetRowOfValue( double dfValue ) const;
+    virtual int           GetRowOfValue( int nValue ) const;
 
-    CPLErr        CreateColumn( const char *pszFieldName, 
+    virtual CPLErr        CreateColumn( const char *pszFieldName, 
                                 GDALRATFieldType eFieldType, 
                                 GDALRATFieldUsage eFieldUsage );
-    CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
-    int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
+    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
+    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
 
-    CPLXMLNode   *Serialize() const;
-    CPLErr        XMLInit( CPLXMLNode *, const char * );
-
-    CPLErr        InitializeFromColorTable( const GDALColorTable * );
-    GDALColorTable *TranslateToColorTable( int nEntryCount = -1 );
-    
-    void          DumpReadable( FILE * = NULL );
 };
 
 #endif /* ndef GDAL_RAT_H_INCLUDED */
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index 6f5aacd..2fae310 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -5,8 +5,8 @@
 
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    1
-#  define GDAL_VERSION_MINOR    10
-#  define GDAL_VERSION_REV      1
+#  define GDAL_VERSION_MINOR    11
+#  define GDAL_VERSION_REV      0
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -22,8 +22,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20130826
+#  define GDAL_RELEASE_DATE     20140416
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "1.10.1"
+#  define GDAL_RELEASE_NAME     "1.11.0"
 #endif
diff --git a/gcore/gdalclientserver.cpp b/gcore/gdalclientserver.cpp
index ab9ff46..93949a9 100644
--- a/gcore/gdalclientserver.cpp
+++ b/gcore/gdalclientserver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gdalclientserver.cpp 25684 2013-02-25 15:40:26Z rouault $
+ * $Id: gdalclientserver.cpp 27142 2014-04-09 11:14:35Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Client/server dataset mechanism.
  * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2013, Even Rouault, <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,9 +30,10 @@
 #include "cpl_port.h"
 
 #ifdef WIN32
-  #ifndef _WIN32_WINNT
-    #define _WIN32_WINNT 0x0501
+  #ifdef _WIN32_WINNT
+    #undef _WIN32_WINNT
   #endif
+  #define _WIN32_WINNT 0x0501
   #include <winsock2.h>
   #include <ws2tcpip.h>
   typedef SOCKET CPL_SOCKET;
@@ -372,7 +373,7 @@ static void MyChdir(const char* pszCWD)
 #ifdef WIN32
     SetCurrentDirectory(pszCWD);
 #else
-    chdir(pszCWD);
+    CPLAssert(chdir(pszCWD) == 0);
 #endif
 }
 
@@ -385,7 +386,7 @@ static void MyChdirRootDirectory()
 #ifdef WIN32
     SetCurrentDirectory("C:\\");
 #else
-    chdir("/");
+    CPLAssert(chdir("/") == 0);
 #endif
 }
 
@@ -628,7 +629,7 @@ class GDALClientRasterBand : public GDALPamRasterBand
         virtual CPLErr BuildOverviews( const char *, int, int *,
                                        GDALProgressFunc, void * );
 
-        virtual const GDALRasterAttributeTable *GetDefaultRAT();
+        virtual GDALRasterAttributeTable *GetDefaultRAT();
         virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
@@ -984,7 +985,7 @@ static int GDALPipeRead(GDALPipe* p, GDALRasterAttributeTable** ppoRAT)
     if( poNode == NULL )
         return FALSE;
 
-    *ppoRAT = new GDALRasterAttributeTable();
+    *ppoRAT = new GDALDefaultRasterAttributeTable();
     if( (*ppoRAT)->XMLInit(poNode, NULL) != CE_None )
     {
         CPLDestroyXMLNode(poNode);
@@ -1884,6 +1885,8 @@ static int GDALServerLoop(GDALPipe* p,
                 CPLFree(pTemp);
             }
 
+            CPLFree(pszClientVersion);
+
             GDALPipeWrite(p, GDAL_RELEASE_NAME);
             GDALPipeWrite(p, GDAL_VERSION_MAJOR);
             GDALPipeWrite(p, GDAL_VERSION_MINOR);
@@ -1897,7 +1900,10 @@ static int GDALServerLoop(GDALPipe* p,
             char *pszKey = NULL, *pszValue = NULL;
             if( !GDALPipeRead(p, &pszKey) ||
                 !GDALPipeRead(p, &pszValue) )
+            {
+                CPLFree(pszKey);
                 break;
+            }
             CPLSetConfigOption(pszKey, pszValue);
             CPLFree(pszKey);
             CPLFree(pszValue);
@@ -2463,6 +2469,7 @@ static int GDALServerLoop(GDALPipe* p,
             int nBandCount;
             int *panBandList = NULL;
             char** papszOptions = NULL;
+            int nLength = 0;
             if( !GDALPipeRead(p, &nXOff) ||
                 !GDALPipeRead(p, &nYOff) ||
                 !GDALPipeRead(p, &nXSize) ||
@@ -2471,8 +2478,32 @@ static int GDALServerLoop(GDALPipe* p,
                 !GDALPipeRead(p, &nBufYSize) ||
                 !GDALPipeRead(p, &nDT) ||
                 !GDALPipeRead(p, &nBandCount) ||
-                !GDALPipeRead(p, nBandCount, &panBandList) ||
-                !GDALPipeRead(p, &papszOptions) )
+                !GDALPipeRead(p, &nLength) )
+            {
+                break;
+            }
+
+            /* panBandList can be NULL, hence the following test */
+            /* to check if we have band numbers to actually read */
+            if( nLength != 0 )
+            {
+                if( nLength != (int)sizeof(int) * nBandCount )
+                {
+                    break;
+                }
+
+                panBandList = (int*) VSIMalloc(nLength);
+                if( panBandList == NULL )
+                    break;
+
+                if( !GDALPipeRead_nolength(p, nLength, (void*)panBandList) )
+                {
+                    VSIFree(panBandList);
+                    break;
+                }
+            }
+
+            if (!GDALPipeRead(p, &papszOptions) )
             {
                 CPLFree(panBandList);
                 CSLDestroy(papszOptions);
@@ -3982,7 +4013,7 @@ CPLErr GDALClientDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSi
         !GDALPipeWrite(p, nBufYSize) ||
         !GDALPipeWrite(p, eDT) ||
         !GDALPipeWrite(p, nBandCount) ||
-        !GDALPipeWrite(p, nBandCount * sizeof(int), panBandList) ||
+        !GDALPipeWrite(p, panBandList ? nBandCount * sizeof(int) : 0, panBandList) ||
         !GDALPipeWrite(p, papszOptions) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
@@ -5332,7 +5363,7 @@ CPLErr GDALClientRasterBand::BuildOverviews( const char * pszResampling,
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *GDALClientRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *GDALClientRasterBand::GetDefaultRAT()
 {
     if( !SupportsInstr(INSTR_Band_GetDefaultRAT) )
         return GDALPamRasterBand::GetDefaultRAT();
diff --git a/gcore/gdalcolortable.cpp b/gcore/gdalcolortable.cpp
index 5384bf2..f88fc11 100644
--- a/gcore/gdalcolortable.cpp
+++ b/gcore/gdalcolortable.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalcolortable.cpp 16573 2009-03-14 12:34:17Z rouault $
+ * $Id: gdalcolortable.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Color table implementation.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalcolortable.cpp 16573 2009-03-14 12:34:17Z rouault $");
+CPL_CVSID("$Id: gdalcolortable.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           GDALColorTable()                           */
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 7b106d7..f5ed651 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 25868 2013-04-06 18:01:17Z rouault $
+ * $Id: gdaldataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for raster file formats.  
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2003, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_multiproc.h"
 #include <map>
 
-CPL_CVSID("$Id: gdaldataset.cpp 25868 2013-04-06 18:01:17Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -838,11 +839,6 @@ CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS, const char * pszProjecti
  * a CE_Failure error is returned, such as for formats that don't support
  * transformation to projection coordinates.
  *
- * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
- * OGC Grid Coverages pixel/line to projection transformation schemes.
- * Eventually this method will be depreciated in favour of a more general
- * scheme.
- *
  * This method does the same thing as the C GDALGetGeoTransform() function.
  *
  * @param padfTransform an existing six double buffer into which the
@@ -1470,7 +1466,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     CPLAssert( NULL != pData );
 
-    if (nXSize == nBufXSize && nYSize == nBufYSize &&
+    if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
         EQUAL(pszInterleave, "PIXEL"))
     {
@@ -1503,6 +1499,80 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
     return eErr;
 }
 
+/************************************************************************/
+/*               ValidateRasterIOOrAdviseReadParameters()               */
+/************************************************************************/
+
+CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
+                               const char* pszCallingFunc,
+                               int* pbStopProcessingOnCENone,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               int nBufXSize, int nBufYSize, 
+                               int nBandCount, int *panBandMap)
+{
+
+/* -------------------------------------------------------------------- */
+/*      Some size values are "noop".  Lets just return to avoid         */
+/*      stressing lower level functions.                                */
+/* -------------------------------------------------------------------- */
+    if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
+    {
+        CPLDebug( "GDAL", 
+                  "%s skipped for odd window or buffer size.\n"
+                  "  Window = (%d,%d)x%dx%d\n"
+                  "  Buffer = %dx%d\n",
+                  pszCallingFunc,
+                  nXOff, nYOff, nXSize, nYSize, 
+                  nBufXSize, nBufYSize );
+
+        *pbStopProcessingOnCENone = TRUE;
+        return CE_None;
+    }
+
+    CPLErr eErr = CE_None;
+    *pbStopProcessingOnCENone = FALSE;
+
+    if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
+        || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg,
+                  "Access window out of range in %s.  Requested\n"
+                  "(%d,%d) of size %dx%d on raster of %dx%d.",
+                  pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
+        eErr = CE_Failure;
+    }
+
+    if( panBandMap == NULL && nBandCount > GetRasterCount() )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg,
+                    "%s: nBandCount cannot be greater than %d",
+                    pszCallingFunc, GetRasterCount() );
+        eErr = CE_Failure;
+    }
+
+    for( int i = 0; i < nBandCount && eErr == CE_None; i++ )
+    {
+        int iBand = (panBandMap != NULL) ? panBandMap[i] : i + 1;
+        if( iBand < 1 || iBand > GetRasterCount() )
+        {
+            ReportError( CE_Failure, CPLE_IllegalArg,
+                      "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
+                      pszCallingFunc, i, iBand );
+            eErr = CE_Failure;
+        }
+
+        if( eErr == CE_None && GetRasterBand( iBand ) == NULL )
+        {
+            ReportError( CE_Failure, CPLE_IllegalArg,
+                      "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
+                      pszCallingFunc, i, iBand );
+            eErr = CE_Failure;
+        }
+    }
+
+    return eErr;
+}
+
 
 /************************************************************************/
 /*                              RasterIO()                              */
@@ -1596,25 +1666,29 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     {
         ReportError( CE_Failure, CPLE_AppDefined,
                   "The buffer into which the data should be read is null" );
-            return CE_Failure;
+        return CE_Failure;
     }
-
+    
 /* -------------------------------------------------------------------- */
-/*      Some size values are "noop".  Lets just return to avoid         */
-/*      stressing lower level functions.                                */
+/*      Do some validation of parameters.                               */
 /* -------------------------------------------------------------------- */
-    if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
-    {
-        CPLDebug( "GDAL", 
-                  "RasterIO() skipped for odd window or buffer size.\n"
-                  "  Window = (%d,%d)x%dx%d\n"
-                  "  Buffer = %dx%d\n",
-                  nXOff, nYOff, nXSize, nYSize, 
-                  nBufXSize, nBufYSize );
 
-        return CE_None;
+    if( eRWFlag != GF_Read && eRWFlag != GF_Write )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg,
+                  "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
+                  eRWFlag );
+        return CE_Failure;
     }
 
+    int bStopProcessing = FALSE;
+    eErr = ValidateRasterIOOrAdviseReadParameters( "RasterIO()", &bStopProcessing,
+                                                    nXOff, nYOff, nXSize, nYSize,
+                                                    nBufXSize, nBufYSize, 
+                                                    nBandCount, panBandMap);
+    if( eErr != CE_None || bStopProcessing )
+        return eErr;
+
 /* -------------------------------------------------------------------- */
 /*      If pixel and line spacing are defaulted assign reasonable      */
 /*      value assuming a packed buffer.                                 */
@@ -1649,13 +1723,6 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
     if( panBandMap == NULL )
     {
-        if (nBandCount > GetRasterCount())
-        {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "nBandCount cannot be greater than %d",
-                      GetRasterCount() );
-            return CE_Failure;
-        }
         panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
         if (panBandMap == NULL)
         {
@@ -1668,46 +1735,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
         bNeedToFreeBandMap = TRUE;
     }
-    
-/* -------------------------------------------------------------------- */
-/*      Do some validation of parameters.                               */
-/* -------------------------------------------------------------------- */
-    if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
-        || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
-    {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Access window out of range in RasterIO().  Requested\n"
-                  "(%d,%d) of size %dx%d on raster of %dx%d.",
-                  nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
-        eErr = CE_Failure;
-    }
 
-    if( eRWFlag != GF_Read && eRWFlag != GF_Write )
-    {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
-                  eRWFlag );
-        eErr = CE_Failure;
-    }
-
-    for( i = 0; i < nBandCount && eErr == CE_None; i++ )
-    {
-        if( panBandMap[i] < 1 || panBandMap[i] > GetRasterCount() )
-        {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "panBandMap[%d] = %d, this band does not exist on dataset.",
-                      i, panBandMap[i] );
-            eErr = CE_Failure;
-        }
-
-        if( eErr == CE_None && GetRasterBand( panBandMap[i] ) == NULL )
-        {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "panBandMap[%d]=%d, this band should exist but is NULL!",
-                      i, panBandMap[i] );
-            eErr = CE_Failure;
-        }
-    }
 
 /* -------------------------------------------------------------------- */
 /*      We are being forced to use cached IO instead of a driver        */
@@ -1930,6 +1958,17 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 {
     int iBand;
 
+/* -------------------------------------------------------------------- */
+/*      Do some validation of parameters.                               */
+/* -------------------------------------------------------------------- */
+    int bStopProcessing = FALSE;
+    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing,
+                                                    nXOff, nYOff, nXSize, nYSize,
+                                                    nBufXSize, nBufYSize, 
+                                                    nBandCount, panBandMap);
+    if( eErr != CE_None || bStopProcessing )
+        return eErr;
+
     for( iBand = 0; iBand < nBandCount; iBand++ )
     {
         CPLErr eErr;
diff --git a/gcore/gdaldefaultoverviews.cpp b/gcore/gdaldefaultoverviews.cpp
index 5fd1556..e164b5d 100644
--- a/gcore/gdaldefaultoverviews.cpp
+++ b/gcore/gdaldefaultoverviews.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldefaultoverviews.cpp 25358 2012-12-27 13:19:58Z rouault $
+ * $Id: gdaldefaultoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview and mask support for many 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, 2007, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaldefaultoverviews.cpp 25358 2012-12-27 13:19:58Z rouault $");
+CPL_CVSID("$Id: gdaldefaultoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        GDALDefaultOverviews()                        */
@@ -54,6 +55,7 @@ GDALDefaultOverviews::GDALDefaultOverviews()
 
     papszInitSiblingFiles = NULL;
     pszInitName = NULL;
+    bInitNameIsOVR = FALSE;
 }
 
 /************************************************************************/
@@ -1005,7 +1007,7 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /*      Are we even initialized?  If not, we apparently don't want      */
 /*      to support overviews and masks.                                 */
 /* -------------------------------------------------------------------- */
-    if( !IsInitialized() )
+    if( poDS == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
diff --git a/gcore/gdaldllmain.cpp b/gcore/gdaldllmain.cpp
index 57c7c9f..7efa1ca 100644
--- a/gcore/gdaldllmain.cpp
+++ b/gcore/gdaldllmain.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Mateusz Loskot <mateusz at loskot.net>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -77,9 +78,7 @@ static void GDALDestroy(void)
 
     CPLDebug("GDAL", "In GDALDestroy - unloading GDAL shared library.");
     bInGDALGlobalDestructor = TRUE;
-    CPLSetConfigOption("GDAL_CLOSE_JP2ECW_RESOURCE", "NO");
     GDALDestroyDriverManager();
-    CPLSetConfigOption("GDAL_CLOSE_JP2ECW_RESOURCE", NULL);
 
 #ifdef OGR_ENABLED
     OGRCleanupAll();
diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp
index cc359d1..a02300e 100644
--- a/gcore/gdaldriver.cpp
+++ b/gcore/gdaldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldriver.cpp 25606 2013-02-06 19:22:07Z rouault $
+ * $Id: gdaldriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriver class (and C wrappers)
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2000, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdaldriver.cpp 25606 2013-02-06 19:22:07Z rouault $");
+CPL_CVSID("$Id: gdaldriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 const char* GDALClientDatasetGetFilename(const char* pszFilename);
@@ -187,7 +188,8 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
                     poDstDS->poDriver = poAPIPROXYDriver;
             }
 
-            return poDstDS;
+            if( poDstDS != NULL || CPLGetLastErrorNo() != CPLE_NotSupported )
+                return poDstDS;
         }
     }
 
@@ -656,7 +658,8 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
             }
 
             CSLDestroy(papszOptionsDup);
-            return poDstDS;
+            if( poDstDS != NULL || CPLGetLastErrorNo() != CPLE_NotSupported )
+                return poDstDS;
         }
     }
 
@@ -665,9 +668,19 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      name.  But even if that seems to fail we will continue since    */
 /*      it might just be a corrupt file or something.                   */
 /* -------------------------------------------------------------------- */
-    if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
+    if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) &&
+        CSLFetchBoolean(papszOptions, "QUIET_DELETE_ON_CREATE_COPY", TRUE) )
         QuietDelete( pszFilename );
 
+    int iIdxQuietDeleteOnCreateCopy = 
+        CSLPartialFindString(papszOptions, "QUIET_DELETE_ON_CREATE_COPY=");
+    char** papszOptionsToDelete = NULL;
+    if( iIdxQuietDeleteOnCreateCopy >= 0 )
+    {
+        papszOptions = CSLRemoveStrings(CSLDuplicate(papszOptions), iIdxQuietDeleteOnCreateCopy, 1, NULL);
+        papszOptionsToDelete = papszOptions;
+    }
+    
 /* -------------------------------------------------------------------- */
 /*      Validate creation options.                                      */
 /* -------------------------------------------------------------------- */
@@ -679,10 +692,9 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      otherwise fallback to the internal implementation using the     */
 /*      Create() method.                                                */
 /* -------------------------------------------------------------------- */
-    if( pfnCreateCopy != NULL )
+    GDALDataset *poDstDS;
+    if( pfnCreateCopy != NULL && !CSLTestBoolean(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
     {
-        GDALDataset *poDstDS;
-
         poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
                                  pfnProgress, pProgressData );
         if( poDstDS != NULL )
@@ -694,12 +706,13 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
             if( poDstDS->poDriver == NULL )
                 poDstDS->poDriver = this;
         }
-
-        return poDstDS;
     }
     else
-        return DefaultCreateCopy( pszFilename, poSrcDS, bStrict, 
+        poDstDS = DefaultCreateCopy( pszFilename, poSrcDS, bStrict, 
                                   papszOptions, pfnProgress, pProgressData );
+
+    CSLDestroy(papszOptionsToDelete);
+    return poDstDS;
 }
 
 /************************************************************************/
diff --git a/gcore/gdaldrivermanager.cpp b/gcore/gdaldrivermanager.cpp
index 62b2ce9..72e4d97 100644
--- a/gcore/gdaldrivermanager.cpp
+++ b/gcore/gdaldrivermanager.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldrivermanager.cpp 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: gdaldrivermanager.cpp 27121 2014-04-03 22:08:55Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriverManager class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,7 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: gdaldrivermanager.cpp 25627 2013-02-10 10:17:19Z rouault $");
+CPL_CVSID("$Id: gdaldrivermanager.cpp 27121 2014-04-03 22:08:55Z rouault $");
 
 static const char *pszUpdatableINST_DATA = 
 "__INST_DATA_TARGET:                                                                                                                                      ";
@@ -188,8 +189,8 @@ GDALDriverManager::~GDALDriverManager()
     papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
     for(i=0;i<nDSCount;i++)
     {
-        CPLDebug( "GDAL", "force close of %s in GDALDriverManager cleanup.",
-                  papoDSList[i]->GetDescription() );
+        CPLDebug( "GDAL", "force close of %s (%p) in GDALDriverManager cleanup.",
+                  papoDSList[i]->GetDescription(), papoDSList[i] );
         /* Destroy with delete operator rather than GDALClose() to force deletion of */
         /* datasets with multiple reference count */
         /* We could also iterate while GetOpenDatasets() returns a non NULL list */
@@ -265,6 +266,11 @@ GDALDriverManager::~GDALDriverManager()
     } 
 
 /* -------------------------------------------------------------------- */
+/*      Cleanup raster block mutex                                      */
+/* -------------------------------------------------------------------- */
+    GDALRasterBlock::DestroyRBMutex();
+
+/* -------------------------------------------------------------------- */
 /*      Cleanup gdaltransformer.cpp mutex                               */
 /* -------------------------------------------------------------------- */
     GDALCleanupTransformDeserializerMutex();
@@ -275,6 +281,11 @@ GDALDriverManager::~GDALDriverManager()
     CPLCleanupErrorMutex();
 
 /* -------------------------------------------------------------------- */
+/*      Cleanup CPLsetlocale mutex                                      */
+/* -------------------------------------------------------------------- */
+    CPLCleanupSetlocaleMutex();
+
+/* -------------------------------------------------------------------- */
 /*      Cleanup the master CPL mutex, which governs the creation        */
 /*      of all other mutexes.                                           */ 
 /* -------------------------------------------------------------------- */
@@ -638,6 +649,9 @@ void GDALDriverManager::AutoSkipDrivers()
  * the /usr/local/lib/gdalplugins directory, and (if known) the
  * lib/gdalplugins subdirectory of the gdal home directory are searched on
  * UNIX and $(BINDIR)\gdalplugins on Windows.
+ *
+ * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
+ * config option to "disable".
  */
 
 void GDALDriverManager::AutoLoadDrivers()
@@ -648,6 +662,16 @@ void GDALDriverManager::AutoLoadDrivers()
         CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
 
 /* -------------------------------------------------------------------- */
+/*      Allow applications to completely disable this search by         */
+/*      setting the driver path to the special string "disable".        */
+/* -------------------------------------------------------------------- */
+    if( pszGDAL_DRIVER_PATH != NULL && EQUAL(pszGDAL_DRIVER_PATH,"disable")) 
+    {
+        CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() disabled." );
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Where should we look for stuff?                                 */
 /* -------------------------------------------------------------------- */
     if( pszGDAL_DRIVER_PATH != NULL )
diff --git a/gcore/gdalexif.cpp b/gcore/gdalexif.cpp
index 9122afa..c46e210 100644
--- a/gcore/gdalexif.cpp
+++ b/gcore/gdalexif.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalexif.cpp 24551 2012-06-09 20:19:04Z rouault $
+ * $Id: gdalexif.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements a EXIF directory reader
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Portions Copyright (c) Her majesty the Queen in right of Canada as
  * represented by the Minister of National Defence, 2006.
@@ -38,7 +39,7 @@
 
 #include "gdalexif.h"
 
-CPL_CVSID("$Id: gdalexif.cpp 24551 2012-06-09 20:19:04Z rouault $");
+CPL_CVSID("$Id: gdalexif.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         EXIFPrintData()                              */
diff --git a/gcore/gdalgeorefpamdataset.cpp b/gcore/gdalgeorefpamdataset.cpp
new file mode 100644
index 0000000..5d8c489
--- /dev/null
+++ b/gcore/gdalgeorefpamdataset.cpp
@@ -0,0 +1,158 @@
+/******************************************************************************
+ * $Id: gdalgeorefpamdataset.cpp 26571 2013-10-30 10:59:11Z rouault $
+ *
+ * Project:  GDAL 
+ * Purpose:  GDALPamDataset with internal storage for georeferencing, with
+ *           priority for PAM over internal georeferencing
+ * Author:   Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdalgeorefpamdataset.h"
+
+/************************************************************************/
+/*                       GDALGeorefPamDataset()                         */
+/************************************************************************/
+
+GDALGeorefPamDataset::GDALGeorefPamDataset()
+{
+    pszProjection = NULL;
+    nGCPCount = 0;
+    pasGCPList = NULL;
+    bGeoTransformValid = FALSE;
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                       ~GDALGeorefPamDataset()                        */
+/************************************************************************/
+
+GDALGeorefPamDataset::~GDALGeorefPamDataset()
+{
+    CPLFree( pszProjection );
+
+    if( nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
+    }
+}
+
+
+/************************************************************************/
+/*                            GetGCPCount()                             */
+/*                                                                      */
+/*      We let PAM coordinate system override the one stored inside     */
+/*      our file.                                                       */
+/************************************************************************/
+
+int GDALGeorefPamDataset::GetGCPCount()
+
+{
+    int nPamGCPCount = GDALPamDataset::GetGCPCount();
+    if( nGCPCount > 0 && nPamGCPCount == 0)
+        return nGCPCount;
+    else
+        return nPamGCPCount;
+}
+
+/************************************************************************/
+/*                          GetGCPProjection()                          */
+/*                                                                      */
+/*      We let PAM coordinate system override the one stored inside     */
+/*      our file.                                                       */
+/************************************************************************/
+
+const char *GDALGeorefPamDataset::GetGCPProjection()
+
+{
+    const char* pszPamPrj = GDALPamDataset::GetGCPProjection();
+    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
+        return pszProjection;
+    else
+        return pszPamPrj;
+}
+
+/************************************************************************/
+/*                               GetGCP()                               */
+/*                                                                      */
+/*      We let PAM coordinate system override the one stored inside     */
+/*      our file.                                                       */
+/************************************************************************/
+
+const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
+
+{
+    int nPamGCPCount = GDALPamDataset::GetGCPCount();
+    if( nGCPCount > 0 && nPamGCPCount == 0)
+        return pasGCPList;
+    else
+        return GDALPamDataset::GetGCPs();
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/*                                                                      */
+/*      We let PAM coordinate system override the one stored inside     */
+/*      our file.                                                       */
+/************************************************************************/
+
+const char *GDALGeorefPamDataset::GetProjectionRef() 
+
+{
+    const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
+
+    if( GetGCPCount() > 0 )
+        return "";
+
+    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
+        return pszProjection;
+    else
+        return pszPamPrj;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/*                                                                      */
+/*      Let the PAM geotransform override the native one if it is       */
+/*      available.                                                      */
+/************************************************************************/
+
+CPLErr GDALGeorefPamDataset::GetGeoTransform( double * padfTransform )
+
+{
+    CPLErr eErr = GDALPamDataset::GetGeoTransform( padfTransform );
+
+    if( eErr != CE_None && bGeoTransformValid )
+    {
+        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+        return( CE_None );
+    }
+    else
+        return eErr;
+}
diff --git a/gcore/gdalgeorefpamdataset.h b/gcore/gdalgeorefpamdataset.h
new file mode 100644
index 0000000..de1298e
--- /dev/null
+++ b/gcore/gdalgeorefpamdataset.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * $Id: gdalgeorefpamdataset.h 26571 2013-10-30 10:59:11Z rouault $
+ *
+ * Project:  GDAL 
+ * Purpose:  GDALPamDataset with internal storage for georeferencing, with
+ *           priority for PAM over internal georeferencing
+ * Author:   Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_GEOREF_PAM_DATASET_H_INCLUDED
+#define GDAL_GEOREF_PAM_DATASET_H_INCLUDED
+
+#include "gdal_pam.h"
+
+class CPL_DLL GDALGeorefPamDataset : public GDALPamDataset
+{
+  protected:
+    int         bGeoTransformValid;
+    double      adfGeoTransform[6];
+    char        *pszProjection;
+    int         nGCPCount;
+    GDAL_GCP    *pasGCPList;
+
+  public:
+        GDALGeorefPamDataset();
+        ~GDALGeorefPamDataset();
+
+    virtual CPLErr          GetGeoTransform( double * );
+    virtual const char     *GetProjectionRef();
+
+    virtual int             GetGCPCount();
+    virtual const char     *GetGCPProjection();
+    virtual const GDAL_GCP *GetGCPs();
+};
+
+#endif /* GDAL_GEOREF_PAM_DATASET_H_INCLUDED */
diff --git a/gcore/gdaljp2abstractdataset.cpp b/gcore/gdaljp2abstractdataset.cpp
new file mode 100644
index 0000000..7e33a3e
--- /dev/null
+++ b/gcore/gdaljp2abstractdataset.cpp
@@ -0,0 +1,142 @@
+/******************************************************************************
+ * $Id: gdaljp2abstractdataset.cpp 27181 2014-04-14 19:32:33Z rouault $
+ *
+ * Project:  GDAL 
+ * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
+ *           metadata from JP2Boxes
+ * Author:   Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdaljp2abstractdataset.h"
+#include "gdaljp2metadata.h"
+
+/************************************************************************/
+/*                     GDALJP2AbstractDataset()                         */
+/************************************************************************/
+
+GDALJP2AbstractDataset::GDALJP2AbstractDataset()
+{
+}
+
+/************************************************************************/
+/*                     ~GDALJP2AbstractDataset()                        */
+/************************************************************************/
+
+GDALJP2AbstractDataset::~GDALJP2AbstractDataset()
+{
+}
+
+/************************************************************************/
+/*                          LoadJP2Metadata()                           */
+/************************************************************************/
+
+void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
+                                             const char* pszOverideFilename)
+{
+    if( pszOverideFilename == NULL )
+        pszOverideFilename = poOpenInfo->pszFilename;
+
+/* -------------------------------------------------------------------- */
+/*      Check for georeferencing information.                           */
+/* -------------------------------------------------------------------- */
+    GDALJP2Metadata oJP2Geo;
+
+    if( oJP2Geo.ReadAndParse( pszOverideFilename ) )
+    {
+        CPLFree(pszProjection);
+        pszProjection = CPLStrdup(oJP2Geo.pszProjection);
+        bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
+        memcpy( adfGeoTransform, oJP2Geo.adfGeoTransform, 
+                sizeof(double) * 6 );
+        nGCPCount = oJP2Geo.nGCPCount;
+        pasGCPList =
+            GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
+
+        if( oJP2Geo.bPixelIsPoint )
+            GDALPamDataset::SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT);
+    }
+
+    if (oJP2Geo.pszXMPMetadata)
+    {
+        char *apszMDList[2];
+        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
+        apszMDList[1] = NULL;
+        GDALPamDataset::SetMetadata(apszMDList, "xml:XMP");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have any XML boxes we would like to treat as special      */
+/*      domain metadata?                                                */
+/* -------------------------------------------------------------------- */
+    int iBox;
+
+    for( iBox = 0; 
+            oJP2Geo.papszGMLMetadata
+                && oJP2Geo.papszGMLMetadata[iBox] != NULL; 
+            iBox++ )
+    {
+        char *pszName = NULL;
+        const char *pszXML = 
+            CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox], 
+                                &pszName );
+        CPLString osDomain;
+        char *apszMDList[2];
+
+        osDomain.Printf( "xml:%s", pszName );
+        apszMDList[0] = (char *) pszXML;
+        apszMDList[1] = NULL;
+
+        GDALPamDataset::SetMetadata( apszMDList, osDomain );
+
+        CPLFree( pszName );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have other misc metadata?                                 */
+/* -------------------------------------------------------------------- */
+    if( oJP2Geo.papszMetadata != NULL )
+    {
+        char **papszMD = CSLDuplicate(GDALPamDataset::GetMetadata());
+
+        papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
+        GDALPamDataset::SetMetadata( papszMD );
+
+        CSLDestroy( papszMD );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check for world file.                                           */
+/* -------------------------------------------------------------------- */
+    if( !bGeoTransformValid )
+    {
+        bGeoTransformValid |=
+            GDALReadWorldFile2( pszOverideFilename, NULL,
+                                adfGeoTransform,
+                                poOpenInfo->papszSiblingFiles, NULL )
+            || GDALReadWorldFile2( pszOverideFilename, ".wld",
+                                   adfGeoTransform,
+                                   poOpenInfo->papszSiblingFiles, NULL );
+    }
+}
diff --git a/gcore/gdaljp2abstractdataset.h b/gcore/gdaljp2abstractdataset.h
new file mode 100644
index 0000000..5e8debe
--- /dev/null
+++ b/gcore/gdaljp2abstractdataset.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * $Id: gdaljp2abstractdataset.h 26571 2013-10-30 10:59:11Z rouault $
+ *
+ * Project:  GDAL 
+ * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
+ *           metadata from JP2Boxes
+ * Author:   Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED
+#define GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED
+
+#include "gdalgeorefpamdataset.h"
+
+class CPL_DLL GDALJP2AbstractDataset: public GDALGeorefPamDataset
+{
+  public:
+        GDALJP2AbstractDataset();
+        ~GDALJP2AbstractDataset();
+
+        void LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
+                             const char* pszOverideFilename = NULL);
+};
+
+#endif /* GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED */
diff --git a/gcore/gdaljp2box.cpp b/gcore/gdaljp2box.cpp
index 102e6a2..c250db4 100644
--- a/gcore/gdaljp2box.cpp
+++ b/gcore/gdaljp2box.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2box.cpp 24227 2012-04-13 20:55:20Z rouault $
+ * $Id: gdaljp2box.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdaljp2metadata.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaljp2box.cpp 24227 2012-04-13 20:55:20Z rouault $");
+CPL_CVSID("$Id: gdaljp2box.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                             GDALJP2Box()                             */
diff --git a/gcore/gdaljp2metadata.cpp b/gcore/gdaljp2metadata.cpp
index e2753a2..0ad28f2 100644
--- a/gcore/gdaljp2metadata.cpp
+++ b/gcore/gdaljp2metadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: gdaljp2metadata.cpp 27182 2014-04-14 20:03:08Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "ogr_api.h"
 #include "gt_wkt_srs_for_gdal.h"
 
-CPL_CVSID("$Id: gdaljp2metadata.cpp 25727 2013-03-10 14:56:33Z rouault $");
+CPL_CVSID("$Id: gdaljp2metadata.cpp 27182 2014-04-14 20:03:08Z rouault $");
 
 static const unsigned char msi_uuid2[16] =
 {0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
@@ -49,6 +50,14 @@ static const unsigned char xmp_uuid[16] =
 { 0xBE,0x7A,0xCF,0xCB,0x97,0xA9,0x42,0xE8,
   0x9C,0x71,0x99,0x94,0x91,0xE3,0xAF,0xAC};
 
+struct _GDALJP2GeoTIFFBox
+{
+    int    nGeoTIFFSize;
+    GByte  *pabyGeoTIFFData;
+};
+
+#define MAX_JP2GEOTIFF_BOXES 2
+
 /************************************************************************/
 /*                          GDALJP2Metadata()                           */
 /************************************************************************/
@@ -64,8 +73,8 @@ GDALJP2Metadata::GDALJP2Metadata()
     papszGMLMetadata = NULL;
     papszMetadata = NULL;
 
-    nGeoTIFFSize = 0;
-    pabyGeoTIFFData = NULL;
+    nGeoTIFFBoxesCount = 0;
+    pasGeoTIFFBoxes = NULL;
 
     nMSIGSize = 0;
     pabyMSIGData = NULL;
@@ -79,6 +88,7 @@ GDALJP2Metadata::GDALJP2Metadata()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    bPixelIsPoint = FALSE;
 }
 
 /************************************************************************/
@@ -95,7 +105,11 @@ GDALJP2Metadata::~GDALJP2Metadata()
         CPLFree( pasGCPList );
     }
 
-    CPLFree( pabyGeoTIFFData );
+    for( int i=0; i < nGeoTIFFBoxesCount; i++ )
+    {
+        CPLFree( pasGeoTIFFBoxes[i].pabyGeoTIFFData );
+    }
+    CPLFree( pasGeoTIFFBoxes );
     CPLFree( pabyMSIGData );
     CSLDestroy( papszGMLMetadata );
     CSLDestroy( papszMetadata );
@@ -226,12 +240,30 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         if( EQUAL(oBox.GetType(),"uuid") 
             && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
         {
-            nGeoTIFFSize = (int) oBox.GetDataLength();
-            pabyGeoTIFFData = oBox.ReadBoxData();
-            if (pabyGeoTIFFData == NULL)
+            /* Erdas JPEG2000 files can in some conditions contain 2 GeoTIFF */
+            /* UUID boxes. One that is correct, another one that does not contain */
+            /* correct georeferencing. So let's fetch at most 2 of them */
+            /* for later analysis. */
+            if( nGeoTIFFBoxesCount == MAX_JP2GEOTIFF_BOXES )
+            {
+                CPLDebug("GDALJP2", "Too many UUID GeoTIFF boxes. Ignoring this one");
+            }
+            else
             {
-                CPLDebug("GDALJP2", "Cannot read data for UUID GeoTIFF box");
-                nGeoTIFFSize = 0;
+                int nGeoTIFFSize = (int) oBox.GetDataLength();
+                GByte* pabyGeoTIFFData = oBox.ReadBoxData();
+                if (pabyGeoTIFFData == NULL)
+                {
+                    CPLDebug("GDALJP2", "Cannot read data for UUID GeoTIFF box");
+                }
+                else
+                {
+                    pasGeoTIFFBoxes = (GDALJP2GeoTIFFBox*) CPLRealloc(
+                        pasGeoTIFFBoxes, sizeof(GDALJP2GeoTIFFBox) * (nGeoTIFFBoxesCount + 1) );
+                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].nGeoTIFFSize = nGeoTIFFSize;
+                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].pabyGeoTIFFData = pabyGeoTIFFData;
+                    nGeoTIFFBoxesCount ++;
+                }
             }
         }
 
@@ -241,16 +273,23 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         if( EQUAL(oBox.GetType(),"uuid") 
             && memcmp( oBox.GetUUID(), msig_uuid, 16 ) == 0 )
         {
-            nMSIGSize = (int) oBox.GetDataLength();
-            pabyMSIGData = oBox.ReadBoxData();
+            if( nMSIGSize == 0 )
+            {
+                nMSIGSize = (int) oBox.GetDataLength();
+                pabyMSIGData = oBox.ReadBoxData();
 
-            if( nMSIGSize < 70
-                || pabyMSIGData == NULL
-                || memcmp( pabyMSIGData, "MSIG/", 5 ) != 0 )
+                if( nMSIGSize < 70
+                    || pabyMSIGData == NULL
+                    || memcmp( pabyMSIGData, "MSIG/", 5 ) != 0 )
+                {
+                    CPLFree( pabyMSIGData );
+                    pabyMSIGData = NULL;
+                    nMSIGSize = 0;
+                }
+            }
+            else
             {
-                CPLFree( pabyMSIGData );
-                pabyMSIGData = NULL;
-                nMSIGSize = 0;
+                CPLDebug("GDALJP2", "Too many UUID MSIG boxes. Ignoring this one");
             }
         }
 
@@ -261,7 +300,14 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
             && memcmp( oBox.GetUUID(), xmp_uuid, 16 ) == 0 &&
             pszXMPMetadata == NULL )
         {
-            pszXMPMetadata = (char*) oBox.ReadBoxData();
+            if( pszXMPMetadata == NULL )
+            {
+                pszXMPMetadata = (char*) oBox.ReadBoxData();
+            }
+            else
+            {
+                CPLDebug("GDALJP2", "Too many UUID XMP boxes. Ignoring this one");
+            }
         }
 
 /* -------------------------------------------------------------------- */
@@ -372,38 +418,106 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
 int GDALJP2Metadata::ParseJP2GeoTIFF()
 
 {
-    if( nGeoTIFFSize < 1 )
-        return FALSE;
+    int abValidProjInfo[MAX_JP2GEOTIFF_BOXES] = { FALSE };
+    char* apszProjection[MAX_JP2GEOTIFF_BOXES] = { NULL };
+    double aadfGeoTransform[MAX_JP2GEOTIFF_BOXES][6];
+    int anGCPCount[MAX_JP2GEOTIFF_BOXES] = { 0 };
+    GDAL_GCP    *apasGCPList[MAX_JP2GEOTIFF_BOXES] = { NULL };
+    int abPixelIsPoint[MAX_JP2GEOTIFF_BOXES] = { 0 };
 
-/* -------------------------------------------------------------------- */
-/*      Convert raw data into projection and geotransform.              */
-/* -------------------------------------------------------------------- */
-    int bSuccess = TRUE;
+    int i;
+    int nMax = MIN(nGeoTIFFBoxesCount, MAX_JP2GEOTIFF_BOXES);
+    for(i=0; i < nMax; i++)
+    {
+    /* -------------------------------------------------------------------- */
+    /*      Convert raw data into projection and geotransform.              */
+    /* -------------------------------------------------------------------- */
+        aadfGeoTransform[i][0] = 0;
+        aadfGeoTransform[i][1] = 1;
+        aadfGeoTransform[i][2] = 0;
+        aadfGeoTransform[i][3] = 0;
+        aadfGeoTransform[i][4] = 0;
+        aadfGeoTransform[i][5] = 1;
+        if( GTIFWktFromMemBufEx( pasGeoTIFFBoxes[i].nGeoTIFFSize,
+                               pasGeoTIFFBoxes[i].pabyGeoTIFFData,
+                               &apszProjection[i], aadfGeoTransform[i],
+                               &anGCPCount[i], &apasGCPList[i], &abPixelIsPoint[i] ) == CE_None )
+        {
+            if( apszProjection[i] != NULL && strlen(apszProjection[i]) != 0 ) 
+                abValidProjInfo[i] = TRUE;
+        }
+    }
 
-    if( GTIFWktFromMemBuf( nGeoTIFFSize, pabyGeoTIFFData,
-                           &pszProjection, adfGeoTransform,
-                           &nGCPCount, &pasGCPList ) != CE_None )
+    /* Detect which box is the better one */
+    int iBestIndex = -1;
+    for(i=0; i < nMax; i++)
     {
-        bSuccess = FALSE;
+        if( abValidProjInfo[i] && iBestIndex < 0 )
+        {
+            iBestIndex = i;
+        }
+        else if( abValidProjInfo[i] && apszProjection[i] != NULL )
+        {
+            /* Anything else than a LOCAL_CS will probably be better */
+            if( EQUALN(apszProjection[iBestIndex], "LOCAL_CS", strlen("LOCAL_CS")) )
+                iBestIndex = i;
+        }
     }
 
-    if( pszProjection == NULL || strlen(pszProjection) == 0 )
-        bSuccess = FALSE;
+    if( iBestIndex < 0 )
+    {
+        for(i=0; i < nMax; i++)
+        {
+            if( aadfGeoTransform[i][0] != 0 
+                || aadfGeoTransform[i][1] != 1 
+                || aadfGeoTransform[i][2] != 0
+                || aadfGeoTransform[i][3] != 0 
+                || aadfGeoTransform[i][4] != 0
+                || aadfGeoTransform[i][5] != 1
+                || anGCPCount[i] > 0)
+            {
+                iBestIndex = i;
+            }
+        }
+    }
 
-    if( bSuccess )
-        CPLDebug( "GDALJP2Metadata", 
-                  "Got projection from GeoJP2 (geotiff) box: %s", 
-                 pszProjection );
+    if( iBestIndex >= 0 )
+    {
+        pszProjection = apszProjection[iBestIndex];
+        memcpy(adfGeoTransform, aadfGeoTransform[iBestIndex], 6 * sizeof(double));
+        nGCPCount = anGCPCount[iBestIndex];
+        pasGCPList = apasGCPList[iBestIndex];
+        bPixelIsPoint = abPixelIsPoint[iBestIndex];
+
+        if( adfGeoTransform[0] != 0 
+            || adfGeoTransform[1] != 1 
+            || adfGeoTransform[2] != 0
+            || adfGeoTransform[3] != 0 
+            || adfGeoTransform[4] != 0
+            || adfGeoTransform[5] != 1 )
+            bHaveGeoTransform = TRUE;
+
+        if( pszProjection )
+            CPLDebug( "GDALJP2Metadata", 
+                "Got projection from GeoJP2 (geotiff) box (%d): %s", 
+                iBestIndex, pszProjection );
+    }
 
-    if( adfGeoTransform[0] != 0 
-        || adfGeoTransform[1] != 1 
-        || adfGeoTransform[2] != 0
-        || adfGeoTransform[3] != 0 
-        || adfGeoTransform[4] != 0
-        || adfGeoTransform[5] != 1 )
-        bHaveGeoTransform = TRUE;
+    /* Cleanup unused boxes */
+    for(i=0; i < nMax; i++)
+    {
+        if( i != iBestIndex )
+        {
+            CPLFree( apszProjection[i] );
+            if( anGCPCount[i] > 0 )
+            {
+                GDALDeinitGCPs( anGCPCount[i], apasGCPList[i] );
+                CPLFree( apasGCPList[i] );
+            }
+        }
+    }
 
-    return bSuccess;;
+    return iBestIndex >= 0;
 }
 
 /************************************************************************/
@@ -473,7 +587,10 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     for( i = 0; pszLabel[i] != '#'; i++ )
     {
         if( pszLabel[i] == '\0' )
+        {
+            CPLFree(pszLabel);
             return NULL;
+        }
     }
 
     pszFragmentId = pszLabel + i + 1;
@@ -486,7 +603,10 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
         CSLFetchNameValue( papszGMLMetadata, pszLabel );
 
     if( pszDictionary == NULL )
+    {
+        CPLFree(pszLabel);
         return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try and parse the dictionary.                                   */
@@ -495,7 +615,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 
     if( psDictTree == NULL )
     {
-        CPLDestroyXMLNode( psDictTree );
+        CPLFree(pszLabel);
         return NULL;
     }
 
@@ -506,6 +626,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     if( psDictRoot == NULL )
     {
         CPLDestroyXMLNode( psDictTree );
+        CPLFree(pszLabel);
         return NULL;
     }
 
@@ -869,9 +990,9 @@ GDALJP2Box *GDALJP2Metadata::CreateJP2GeoTIFF()
     int         nGTBufSize = 0;
     unsigned char *pabyGTBuf = NULL;
 
-    if( GTIFMemBufFromWkt( pszProjection, adfGeoTransform, 
-                           nGCPCount, pasGCPList,
-                           &nGTBufSize, &pabyGTBuf ) != CE_None )
+    if( GTIFMemBufFromWktEx( pszProjection, adfGeoTransform, 
+                             nGCPCount, pasGCPList,
+                             &nGTBufSize, &pabyGTBuf, bPixelIsPoint ) != CE_None )
         return NULL;
 
     if( nGTBufSize == 0 )
diff --git a/gcore/gdaljp2metadata.h b/gcore/gdaljp2metadata.h
index 8678eec..6b90a50 100644
--- a/gcore/gdaljp2metadata.h
+++ b/gcore/gdaljp2metadata.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.h 24221 2012-04-12 20:02:38Z rouault $
+ * $Id: gdaljp2metadata.h 27181 2014-04-14 19:32:33Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  JP2 Box Reader (and GMLJP2 Interpreter)
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -98,6 +99,8 @@ public:
 /*                           GDALJP2Metadata                            */
 /************************************************************************/
 
+typedef struct _GDALJP2GeoTIFFBox GDALJP2GeoTIFFBox;
+
 class CPL_DLL GDALJP2Metadata
 
 {
@@ -105,8 +108,8 @@ private:
     void    CollectGMLData( GDALJP2Box * );
     int     GMLSRSLookup( const char *pszURN );
 
-    int    nGeoTIFFSize;
-    GByte  *pabyGeoTIFFData;
+    int    nGeoTIFFBoxesCount;
+    GDALJP2GeoTIFFBox  *pasGeoTIFFBoxes;
 
     int    nMSIGSize;
     GByte  *pabyMSIGData;
@@ -116,6 +119,7 @@ public:
     
     int     bHaveGeoTransform;
     double  adfGeoTransform[6];
+    int     bPixelIsPoint;
 
     char   *pszProjection;
 
diff --git a/gcore/gdalmajorobject.cpp b/gcore/gdalmajorobject.cpp
index f6f27a1..a94e6d9 100644
--- a/gcore/gdalmajorobject.cpp
+++ b/gcore/gdalmajorobject.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmajorobject.cpp 23156 2011-10-01 15:34:16Z rouault $
+ * $Id: gdalmajorobject.cpp 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for objects with metadata, etc.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalmajorobject.cpp 23156 2011-10-01 15:34:16Z rouault $");
+CPL_CVSID("$Id: gdalmajorobject.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 /************************************************************************/
 /*                          GDALMajorObject()                           */
@@ -137,6 +138,87 @@ void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject, const char *pszNe
 }
 
 /************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+/**
+ * \brief Fetch list of metadata domains.
+ *
+ * The returned string list is the list of (non-empty) metadata domains.
+ *
+ * This method does the same thing as the C function GDALGetMetadataDomainList().
+ * 
+ * @return NULL or a string list. Must be freed with CSLDestroy()
+ *
+ * @since GDAL 1.11
+ */
+
+char **GDALMajorObject::GetMetadataDomainList()
+{
+    return CSLDuplicate(oMDMD.GetDomainList());
+}
+
+/************************************************************************/
+/*                      BuildMetadataDomainList()                       */
+/************************************************************************/
+
+/**
+ * \brief Helper function for custom implementations of GetMetadataDomainList()
+ *
+ *
+ * @param papszList initial list of domains. May be NULL. Will become invalid
+ *                  after function call (use return value)
+ * @param bCheckNonEmpty if TRUE, each candidate domain will be tested to be non
+ *                       empty
+ * @param ... NULL terminated variadic list of candidate domains.
+ *
+ * @return NULL or a string list. Must be freed with CSLDestroy()
+ *
+ * @since GDAL 1.11
+ */
+
+char **GDALMajorObject::BuildMetadataDomainList(char** papszList, int bCheckNonEmpty, ...)
+{
+    va_list args;
+    const char* pszDomain;
+    va_start(args, bCheckNonEmpty);
+
+    while( (pszDomain = va_arg(args, const char*)) != NULL )
+    {
+        if( CSLFindString(papszList, pszDomain) < 0 &&
+            (!bCheckNonEmpty || GetMetadata(pszDomain) != NULL) )
+        {
+            papszList = CSLAddString(papszList, pszDomain);
+        }
+    }
+
+    va_end(args);
+
+    return papszList;
+}
+
+/************************************************************************/
+/*                    GDALGetMetadataDomainList()                       */
+/************************************************************************/
+
+/**
+ * \brief Fetch list of metadata domains.
+ *
+ * @see GDALMajorObject::GetMetadataDomainList()
+ *
+ * @since GDAL 1.11
+ */ 
+
+char ** CPL_STDCALL 
+GDALGetMetadataDomainList( GDALMajorObjectH hObject)
+
+{
+    VALIDATE_POINTER1( hObject, "GetMetadataDomainList", NULL );
+
+    return ((GDALMajorObject *) hObject)->GetMetadataDomainList();
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
diff --git a/gcore/gdalmultidomainmetadata.cpp b/gcore/gdalmultidomainmetadata.cpp
index ce4f558..5483bdc 100644
--- a/gcore/gdalmultidomainmetadata.cpp
+++ b/gcore/gdalmultidomainmetadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $
+ * $Id: gdalmultidomainmetadata.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALMultiDomainMetadata class.  This class
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include <map>
 
-CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $");
+CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      GDALMultiDomainMetadata()                       */
diff --git a/gcore/gdalnodatamaskband.cpp b/gcore/gdalnodatamaskband.cpp
index 81d8e9d..88c3c3f 100644
--- a/gcore/gdalnodatamaskband.cpp
+++ b/gcore/gdalnodatamaskband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalnodatamaskband.cpp 24299 2012-04-23 21:16:42Z rouault $
+ * $Id: gdalnodatamaskband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataMaskBand, a class implementing all
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatamaskband.cpp 24299 2012-04-23 21:16:42Z rouault $");
+CPL_CVSID("$Id: gdalnodatamaskband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        GDALNoDataMaskBand()                          */
diff --git a/gcore/gdalnodatavaluesmaskband.cpp b/gcore/gdalnodatavaluesmaskband.cpp
index c4bcb2a..4bf5fe1 100644
--- a/gcore/gdalnodatavaluesmaskband.cpp
+++ b/gcore/gdalnodatavaluesmaskband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalnodatavaluesmaskband.cpp 17757 2009-10-05 17:06:20Z rouault $
+ * $Id: gdalnodatavaluesmaskband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataValuesMaskBand, a class implementing 
@@ -9,7 +9,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot ogr>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 17757 2009-10-05 17:06:20Z rouault $");
+CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                   GDALNoDataValuesMaskBand()                         */
diff --git a/gcore/gdalopeninfo.cpp b/gcore/gdalopeninfo.cpp
index 1894689..92d5567 100644
--- a/gcore/gdalopeninfo.cpp
+++ b/gcore/gdalopeninfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalopeninfo.cpp 23717 2012-01-07 14:58:34Z rouault $
+ * $Id: gdalopeninfo.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALOpenInfo class.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include <unistd.h>
 #endif
 
-CPL_CVSID("$Id: gdalopeninfo.cpp 23717 2012-01-07 14:58:34Z rouault $");
+CPL_CVSID("$Id: gdalopeninfo.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/gcore/gdalpamdataset.cpp b/gcore/gdalpamdataset.cpp
index 17cfd4a..df3c4fb 100644
--- a/gcore/gdalpamdataset.cpp
+++ b/gcore/gdalpamdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamdataset.cpp 22922 2011-08-10 21:50:46Z rouault $
+ * $Id: gdalpamdataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamDataset, a dataset base class that 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalpamdataset.cpp 22922 2011-08-10 21:50:46Z rouault $");
+CPL_CVSID("$Id: gdalpamdataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           GDALPamDataset()                           */
@@ -219,53 +220,10 @@ CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 /* -------------------------------------------------------------------- */
     if( psPam->nGCPCount > 0 )
     {
-        CPLXMLNode *psPamGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
-                                                     "GCPList" );
-
-        CPLXMLNode* psLastChild = NULL;
-
-        if( psPam->pszGCPProjection != NULL 
-            && strlen(psPam->pszGCPProjection) > 0 )
-        {
-            CPLSetXMLValue( psPamGCPList, "#Projection", 
-                            psPam->pszGCPProjection );
-            psLastChild = psPamGCPList->psChild;
-        }
-
-        for( int iGCP = 0; iGCP < psPam->nGCPCount; iGCP++ )
-        {
-            CPLXMLNode *psXMLGCP;
-            GDAL_GCP *psGCP = psPam->pasGCPList + iGCP;
-
-            psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
-
-            if( psLastChild == NULL )
-                psPamGCPList->psChild = psXMLGCP;
-            else
-                psLastChild->psNext = psXMLGCP;
-            psLastChild = psXMLGCP;
-
-            CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
-
-            if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
-                CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
-
-            CPLSetXMLValue( psXMLGCP, "#Pixel", 
-                            oFmt.Printf( "%.4f", psGCP->dfGCPPixel ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Line", 
-                            oFmt.Printf( "%.4f", psGCP->dfGCPLine ) );
-
-            CPLSetXMLValue( psXMLGCP, "#X", 
-                            oFmt.Printf( "%.12E", psGCP->dfGCPX ) );
-
-            CPLSetXMLValue( psXMLGCP, "#Y", 
-                            oFmt.Printf( "%.12E", psGCP->dfGCPY ) );
-
-            if( psGCP->dfGCPZ != 0.0 )
-                CPLSetXMLValue( psXMLGCP, "#GCPZ", 
-                                oFmt.Printf( "%.12E", psGCP->dfGCPZ ) );
-        }
+        GDALSerializeGCPListToXML( psDSTree,
+                                   psPam->pasGCPList,
+                                   psPam->nGCPCount,
+                                   psPam->pszGCPProjection );
     }
 
 /* -------------------------------------------------------------------- */
@@ -427,25 +385,9 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
 
     if( psGCPList != NULL )
     {
-        CPLXMLNode *psXMLGCP;
-        OGRSpatialReference oSRS;
-        const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
-
         CPLFree( psPam->pszGCPProjection );
+        psPam->pszGCPProjection = NULL;
 
-        if( strlen(pszRawProj) > 0 
-            && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
-            oSRS.exportToWkt( &(psPam->pszGCPProjection) );
-        else
-            psPam->pszGCPProjection = CPLStrdup("");
-
-        // Count GCPs.
-        int  nGCPMax = 0;
-         
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-            nGCPMax++;
-        
         // Make sure any previous GCPs, perhaps from an .aux file, are cleared
         // if we have new ones.
         if( psPam->nGCPCount > 0 )
@@ -456,34 +398,10 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
             psPam->pasGCPList = 0;
         }
 
-        psPam->pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
-         
-        for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
-             psXMLGCP = psXMLGCP->psNext )
-        {
-            GDAL_GCP *psGCP = psPam->pasGCPList + psPam->nGCPCount;
-
-            if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
-                psXMLGCP->eType != CXT_Element )
-                continue;
-             
-            GDALInitGCPs( 1, psGCP );
-             
-            CPLFree( psGCP->pszId );
-            psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
-             
-            CPLFree( psGCP->pszInfo );
-            psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
-             
-            psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
-            psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
-             
-            psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
-            psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
-            psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
-
-            psPam->nGCPCount++;
-        }
+        GDALDeserializeGCPListFromXML( psGCPList,
+                                       &(psPam->pasGCPList),
+                                       &(psPam->nGCPCount),
+                                       &(psPam->pszGCPProjection) );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/gcore/gdalpamrasterband.cpp b/gcore/gdalpamrasterband.cpp
index 2e782d5..a28da5d 100644
--- a/gcore/gdalpamrasterband.cpp
+++ b/gcore/gdalpamrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamrasterband.cpp 25873 2013-04-07 11:06:58Z rouault $
+ * $Id: gdalpamrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamRasterBand, a raster band base class
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "gdal_rat.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalpamrasterband.cpp 25873 2013-04-07 11:06:58Z rouault $");
+CPL_CVSID("$Id: gdalpamrasterband.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         GDALPamRasterBand()                          */
@@ -458,7 +459,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
             delete psPam->poDefaultRAT;
             psPam->poDefaultRAT = NULL;
         }
-        psPam->poDefaultRAT = new GDALRasterAttributeTable();
+        psPam->poDefaultRAT = new GDALDefaultRasterAttributeTable();
         psPam->poDefaultRAT->XMLInit( psRAT, "" );
     }
 
@@ -1290,7 +1291,7 @@ GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-const GDALRasterAttributeTable *GDALPamRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *GDALPamRasterBand::GetDefaultRAT()
 
 {
     PamInitialize();
diff --git a/gcore/gdalproxydataset.cpp b/gcore/gdalproxydataset.cpp
index 610810a..700aab2 100644
--- a/gcore/gdalproxydataset.cpp
+++ b/gcore/gdalproxydataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxydataset.cpp 21866 2011-02-26 21:04:58Z rouault $
+ * $Id: gdalproxydataset.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that act as proxy for underlying
@@ -7,7 +7,7 @@
  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdalproxydataset.cpp 21866 2011-02-26 21:04:58Z rouault $");
+CPL_CVSID("$Id: gdalproxydataset.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* ******************************************************************** */
 /*                        GDALProxyDataset                              */
@@ -86,6 +86,7 @@ void  GDALProxyDataset::FlushCache()
     }
 }
 
+D_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadataDomainList, (), ())
 D_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadata, (const char * pszDomain), (pszDomain))
 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadata,
                         (char ** papszMetadata, const char * pszDomain),
@@ -189,6 +190,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
                                 pData, nBufXSize, nBufYSize, eBufType,
                                 nPixelSpace, nLineSpace ) )
 
+RB_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadataDomainList, (), ())
 RB_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadata, (const char * pszDomain), (pszDomain))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadata,
                         (char ** papszMetadata, const char * pszDomain),
@@ -279,7 +281,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetDefaultHistogram,
                         int nBuckets, int * panHistogram ),
                         (dfMin, dfMax, nBuckets, panHistogram))
 
-RB_PROXY_METHOD_WITH_RET(const GDALRasterAttributeTable *, NULL,
+RB_PROXY_METHOD_WITH_RET(GDALRasterAttributeTable *, NULL,
                         GetDefaultRAT, (), ())
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetDefaultRAT,
                         ( const GDALRasterAttributeTable * arg1), (arg1))
@@ -288,6 +290,10 @@ RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetMaskBand, (), ())
 RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlags ), (nFlags))
 
+RB_PROXY_METHOD_WITH_RET(CPLVirtualMem*, NULL, GetVirtualMemAuto,
+                         ( GDALRWFlag eRWFlag, int *pnPixelSpace, GIntBig *pnLineSpace, char **papszOptions ),
+                         (eRWFlag, pnPixelSpace, pnLineSpace, papszOptions) )
+
 /************************************************************************/
 /*                 UnrefUnderlyingRasterBand()                        */
 /************************************************************************/
diff --git a/gcore/gdalproxypool.cpp b/gcore/gdalproxypool.cpp
index 4315930..c6cb12a 100644
--- a/gcore/gdalproxypool.cpp
+++ b/gcore/gdalproxypool.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxypool.cpp 25615 2013-02-08 22:24:32Z rouault $
+ * $Id: gdalproxypool.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that differ the opening of the
@@ -7,7 +7,7 @@
  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "gdal_proxy.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalproxypool.cpp 25615 2013-02-08 22:24:32Z rouault $");
+CPL_CVSID("$Id: gdalproxypool.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* We *must* share the same mutex as the gdaldataset.cpp file, as we are */
 /* doing GDALOpen() calls that can indirectly call GDALOpenShared() on */
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index a3cecee..c68d3a6 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterband.cpp 26358 2013-08-21 20:12:38Z rouault $
+ * $Id: gdalrasterband.cpp 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for format specific band class implementation.  This
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #define TO_SUBBLOCK(x) ((x) >> 6)
 #define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
 
-CPL_CVSID("$Id: gdalrasterband.cpp 26358 2013-08-21 20:12:38Z rouault $");
+CPL_CVSID("$Id: gdalrasterband.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -566,6 +567,8 @@ CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
 /**
  * \brief Fetch the pixel data type for this band.
  *
+ * This method is the same as the C function GDALGetRasterDataType().
+ *
  * @return the data type of pixels for this band.
  */
   
@@ -614,6 +617,8 @@ GDALDataType CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH hBand )
  * evenly, meaning that right and bottom edge blocks may be incomplete.
  * See ReadBlock() for an example of code dealing with these issues.
  *
+ * This method is the same as the C function GDALGetBlockSize().
+ *
  * @param pnXSize integer to put the X block size into or NULL.
  *
  * @param pnYSize integer to put the Y block size into or NULL.
@@ -1280,7 +1285,9 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
  * to the underlying type before writing to the file. An optional
  * second argument allows the imaginary component of a complex
  * constant value to be specified.
- * 
+ *
+ * This method is the same as the C function GDALFillRaster().
+ *
  * @param dfRealValue Real component of fill value
  * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
  * 
@@ -1431,7 +1438,9 @@ GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
  * The returned stringlist should not be altered or freed by the application.
  * It may change on the next GDAL call, so please copy it if it is needed
  * for any period of time. 
- * 
+ *
+ * This method is the same as the C function GDALGetRasterCategoryNames().
+ *
  * @return list of names, or NULL if none.
  */
 
@@ -1836,6 +1845,8 @@ GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
 /**
  * \brief Set color interpretation of a band.
  *
+ * This method is the same as the C function GDALSetRasterColorInterpretation().
+ *
  * @param eColorInterp the new color interpretation to apply to this band.
  * 
  * @return CE_None on success or CE_Failure if method is unsupported by format.
@@ -2269,7 +2280,9 @@ double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
  *
  * Very few formats implement this method.   When not implemented it will
  * issue a CPLE_NotSupported error and return CE_Failure. 
- * 
+ *
+ * This method is the same as the C function GDALSetRasterOffset().
+ *
  * @param dfNewOffset the new offset.
  *
  * @return CE_None or success or CE_Failure on failure. 
@@ -2367,6 +2380,8 @@ double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
  *
  * Very few formats implement this method.   When not implemented it will
  * issue a CPLE_NotSupported error and return CE_Failure. 
+ *
+ * This method is the same as the C function GDALSetRasterScale().
  * 
  * @param dfNewScale the new scale.
  *
@@ -2620,7 +2635,7 @@ int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
  * Note that some GDALRasterBands are not considered to be a part of a dataset,
  * such as overviews or other "freestanding" bands. 
  *
- * This method is the same as the C function GDALGetBandDataset()
+ * This method is the same as the C function GDALGetBandDataset().
  *
  * @return the pointer to the GDALDataset to which this band belongs, or
  * NULL if this cannot be determined.
@@ -2677,6 +2692,8 @@ GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
  * in generating histogram based luts for instance.  Generally bApproxOK is
  * much faster than an exactly computed histogram.
  *
+ * This method is the same as the C function GDALGetRasterHistogram().
+ *
  * @param dfMin the lower bound of the histogram.
  * @param dfMax the upper bound of the histogram.
  * @param nBuckets the number of buckets in panHistogram.
@@ -2736,6 +2753,15 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
     dfScale = nBuckets / (dfMax - dfMin);
     memset( panHistogram, 0, sizeof(int) * nBuckets );
 
+    double dfNoDataValue;
+    int bGotNoDataValue;
+    dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
+    bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
+    /* Not advertized. May be removed at any time. Just as a provision if the */
+    /* old behaviour made sense somethimes... */
+    bGotNoDataValue = bGotNoDataValue &&
+        !CSLTestBoolean(CPLGetConfigOption("GDAL_NODATA_IN_HISTOGRAM", "NO"));
+
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
 
@@ -2859,6 +2885,9 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     CPLAssert( FALSE );
                 }
 
+                if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
+                    continue;
+
                 nIndex = (int) floor((dfValue - dfMin) * dfScale);
                 
                 if( nIndex < 0 )
@@ -2951,7 +2980,10 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                 GByte  *pabyData = (GByte *) pData;
                 
                 for( int i = 0; i < nPixels; i++ )
-                    panHistogram[pabyData[i]]++;
+                    if (! (bGotNoDataValue && (pabyData[i] == (GByte)dfNoDataValue)))
+                    {
+                        panHistogram[pabyData[i]]++;
+                    }
 
                 poBlock->DropLock();
                 continue; /* to next sample block */
@@ -3043,6 +3075,9 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                         return CE_Failure;
                     }
                     
+                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
+                        continue;
+
                     nIndex = (int) floor((dfValue - dfMin) * dfScale);
 
                     if( nIndex < 0 )
@@ -3111,6 +3146,8 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
  * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
  * that may be able to fetch efficiently an already stored histogram.
  *
+ * This method is the same as the C function GDALGetDefaultHistogram().
+ *
  * @param pdfMin pointer to double value that will contain the lower bound of the histogram.
  * @param pdfMax pointer to double value that will contain the upper bound of the histogram.
  * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
@@ -4258,6 +4295,8 @@ GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
 /* FIXME : add proper documentation */
 /**
  * \brief Set default histogram.
+ *
+ * This method is the same as the C function GDALSetDefaultHistogram().
  */
 CPLErr GDALRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
                                             int nBuckets, int *panHistogram )
@@ -4300,12 +4339,14 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
  *
  * A RAT will be returned if there is a default one associated with the
  * band, otherwise NULL is returned.  The returned RAT is owned by the
- * band and should not be deleted, or altered by the application. 
- * 
+ * band and should not be deleted by the application. 
+ *
+ * This method is the same as the C function GDALGetDefaultRAT().
+ *
  * @return NULL, or a pointer to an internal RAT owned by the band.
  */
 
-const GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
+GDALRasterAttributeTable *GDALRasterBand::GetDefaultRAT()
 
 {
     return NULL;
@@ -4341,6 +4382,8 @@ GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
  * format a CPLE_NotSupported error will be issued.  If successful a copy
  * of the RAT is made, the original remains owned by the caller.
  *
+ * This method is the same as the C function GDALSetDefaultRAT().
+ *
  * @param poRAT the RAT to assign to the band.
  *
  * @return CE_None on success or CE_Failure if unsupported or otherwise 
@@ -4406,7 +4449,9 @@ CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
  * </ul>
  *
  * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
- * an all 255 mask with the flags indicating GMF_ALL_VALID. 
+ * an all 255 mask with the flags indicating GMF_ALL_VALID.
+ *
+ * This method is the same as the C function GDALGetMaskBand().
  *
  * @return a valid mask band.
  *
@@ -4597,6 +4642,8 @@ GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
  *     The null flags will return GMF_ALL_VALID.</li>
  * </ul>
  *
+ * This method is the same as the C function GDALGetMaskFlags().
+ *
  * @since GDAL 1.5.0
  *
  * @return a valid mask band.
@@ -4654,6 +4701,8 @@ int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
  * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
  * again.
  *
+ * This method is the same as the C function GDALCreateMaskBand().
+ *
  * @since GDAL 1.5.0
  *
  * @return CE_None on success or CE_Failure on an error.
@@ -4906,3 +4955,118 @@ void GDALRasterBand::ReportError(CPLErr eErrClass, int err_no, const char *fmt,
     }
     va_end(args);
 }
+
+
+/************************************************************************/
+/*                           GetVirtualMemAuto()                        */
+/************************************************************************/
+
+/** \brief Create a CPLVirtualMem object from a GDAL raster band object.
+ *
+ * Only supported on Linux for now.
+ *
+ * This method allows creating a virtual memory object for a GDALRasterBand,
+ * that exposes the whole image data as a virtual array.
+ *
+ * The default implementation relies on GDALRasterBandGetVirtualMem(), but specialized
+ * implementation, such as for raw files, may also directly use mechanisms of the
+ * operating system to create a view of the underlying file into virtual memory
+ * ( CPLVirtualMemFileMapNew() )
+ *
+ * At the time of writing, the GeoTIFF driver and "raw" drivers (EHdr, ...) offer
+ * a specialized implementation with direct file mapping, provided that some
+ * requirements are met :
+ *   - for all drivers, the dataset must be backed by a "real" file in the file
+ *     system, and the byte ordering of multi-byte datatypes (Int16, etc.)
+ *     must match the native ordering of the CPU.
+ *   - in addition, for the GeoTIFF driver, the GeoTIFF file must be uncompressed, scanline
+ *     oriented (i.e. not tiled). Strips must be organized in the file in sequential
+ *     order, and be equally spaced (which is generally the case). Only power-of-two
+ *     bit depths are supported (8 for GDT_Bye, 16 for GDT_Int16/GDT_UInt16,
+ *     32 for GDT_Float32 and 64 for GDT_Float64)
+ *
+ * The pointer returned remains valid until CPLVirtualMemFree() is called.
+ * CPLVirtualMemFree() must be called before the raster band object is destroyed.
+ *
+ * If p is such a pointer and base_type the type matching GDALGetRasterDataType(),
+ * the element of image coordinates (x, y) can be accessed with
+ * *(base_type*) ((GByte*)p + x * *pnPixelSpace + y * *pnLineSpace)
+ *
+ * This method is the same as the C GDALGetVirtualMemAuto() function.
+ *
+ * @param eRWFlag Either GF_Read to read the band, or GF_Write to
+ * read/write the band.
+ *
+ * @param pnPixelSpace Output parameter giving the byte offset from the start of one pixel value in
+ * the buffer to the start of the next pixel value within a scanline.
+ *
+ * @param pnLineSpace Output parameter giving the byte offset from the start of one scanline in
+ * the buffer to the start of the next.
+ *
+ * @param papszOptions NULL terminated list of options.
+ *                     If a specialized implementation exists, defining USE_DEFAULT_IMPLEMENTATION=YES
+ *                     will cause the default implementation to be used.
+ *                     When requiring or falling back to the default implementation, the following
+ *                     options are available : CACHE_SIZE (in bytes, defaults to 40 MB),
+ *                     PAGE_SIZE_HINT (in bytes),
+ *                     SINGLE_THREAD ("FALSE" / "TRUE", defaults to FALSE)
+ *
+ * @return a virtual memory object that must be unreferenced by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 1.11
+ */
+
+CPLVirtualMem  *GDALRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                                   int *pnPixelSpace,
+                                                   GIntBig *pnLineSpace,
+                                                   char **papszOptions )
+{
+    int nPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
+    GIntBig nLineSpace = (GIntBig)nRasterXSize * nPixelSpace;
+    if( pnPixelSpace )
+        *pnPixelSpace = nPixelSpace;
+    if( pnLineSpace )
+        *pnLineSpace = nLineSpace;
+    size_t nCacheSize = atoi(CSLFetchNameValueDef(papszOptions,
+                                            "CACHE_SIZE", "40000000"));
+    size_t nPageSizeHint = atoi(CSLFetchNameValueDef(papszOptions,
+                                            "PAGE_SIZE_HINT", "0"));
+    int bSingleThreadUsage = CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
+                                            "SINGLE_THREAD", "FALSE"));
+    return GDALRasterBandGetVirtualMem( (GDALRasterBandH) this,
+                                        eRWFlag,
+                                        0, 0, nRasterXSize, nRasterYSize,
+                                        nRasterXSize, nRasterYSize,
+                                        eDataType,
+                                        nPixelSpace, nLineSpace,
+                                        nCacheSize,
+                                        nPageSizeHint,
+                                        bSingleThreadUsage,
+                                        papszOptions );
+}
+
+/************************************************************************/
+/*                         GDALGetVirtualMemAuto()                      */
+/************************************************************************/
+
+/**
+ * \brief Create a CPLVirtualMem object from a GDAL raster band object.
+ *
+ * @see GDALRasterBand::GetVirtualMemAuto()
+ */
+
+CPLVirtualMem * GDALGetVirtualMemAuto( GDALRasterBandH hBand,
+                                       GDALRWFlag eRWFlag,
+                                       int *pnPixelSpace,
+                                       GIntBig *pnLineSpace,
+                                       char **papszOptions )
+{
+    VALIDATE_POINTER1( hBand, "GDALGetVirtualMemAuto", NULL );
+
+    GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
+
+    return poBand->GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                     pnLineSpace, papszOptions);
+}
+
diff --git a/gcore/gdalrasterblock.cpp b/gcore/gdalrasterblock.cpp
index 3005c84..5e396ec 100644
--- a/gcore/gdalrasterblock.cpp
+++ b/gcore/gdalrasterblock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterblock.cpp 24412 2012-05-14 17:55:36Z rouault $
+ * $Id: gdalrasterblock.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterBlock class and related global 
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 1998, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "gdal_priv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalrasterblock.cpp 24412 2012-05-14 17:55:36Z rouault $");
+CPL_CVSID("$Id: gdalrasterblock.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int bCacheMaxInitialized = FALSE;
 static GIntBig nCacheMax = 40 * 1024*1024;
@@ -42,7 +43,6 @@ static volatile GDALRasterBlock *poNewest = NULL;    /* head */
 
 static void *hRBMutex = NULL;
 
-
 /************************************************************************/
 /*                          GDALSetCacheMax()                           */
 /************************************************************************/
@@ -702,3 +702,14 @@ int GDALRasterBlock::SafeLockBlock( GDALRasterBlock ** ppBlock )
     else
         return FALSE;
 }
+
+/************************************************************************/
+/*                          DestroyRBMutex()                           */
+/************************************************************************/
+
+void GDALRasterBlock::DestroyRBMutex()
+{
+    if( hRBMutex != NULL )
+        CPLDestroyMutex(hRBMutex);
+    hRBMutex = NULL;
+}
diff --git a/gcore/gdalvirtualmem.cpp b/gcore/gdalvirtualmem.cpp
new file mode 100644
index 0000000..d8aff4b
--- /dev/null
+++ b/gcore/gdalvirtualmem.cpp
@@ -0,0 +1,1541 @@
+/**********************************************************************
+ * $Id: gdalvirtualmem.cpp 27110 2014-03-28 21:29:20Z rouault $
+ *
+ * Name:     gdalvirtualmem.cpp
+ * Project:  GDAL
+ * Purpose:  Dataset and rasterband exposed as a virtual memory mapping.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "cpl_conv.h"
+#include "cpl_virtualmem.h"
+
+/************************************************************************/
+/*                            GDALVirtualMem                            */
+/************************************************************************/
+
+class GDALVirtualMem
+{
+    GDALDatasetH hDS;
+    GDALRasterBandH hBand;
+    int nXOff;
+    int nYOff;
+    /*int nXSize;
+    int nYSize;*/
+    int nBufXSize;
+    int nBufYSize;
+    GDALDataType eBufType;
+    int nBandCount;
+    int* panBandMap;
+    int nPixelSpace;
+    GIntBig nLineSpace;
+    GIntBig nBandSpace;
+
+    int     bIsCompact;
+    int     bIsBandSequential;
+
+    int  IsCompact() const { return bIsCompact; }
+    int  IsBandSequential() const { return bIsBandSequential; }
+
+    void GetXYBand( size_t nOffset, int& x, int& y, int& band ) const;
+    size_t GetOffset(int x, int y, int band) const;
+    int  GotoNextPixel(int& x, int& y, int& band) const;
+
+    void DoIOBandSequential( GDALRWFlag eRWFlag, size_t nOffset,
+                              void* pPage, size_t nBytes ) const;
+    void DoIOPixelInterleaved( GDALRWFlag eRWFlag, size_t nOffset,
+                               void* pPage, size_t nBytes ) const;
+
+public:
+             GDALVirtualMem( GDALDatasetH hDS,
+                             GDALRasterBandH hBand,
+                          int nXOff, int nYOff,
+                          int nXSize, int nYSize,
+                          int nBufXSize, int nBufYSize,
+                          GDALDataType eBufType,
+                          int nBandCount, const int* panBandMapIn,
+                          int nPixelSpace,
+                          GIntBig nLineSpace,
+                          GIntBig nBandSpace );
+            ~GDALVirtualMem();
+
+    static void FillCacheBandSequential(CPLVirtualMem* ctxt,  size_t nOffset,
+                                         void* pPageToFill,
+                                         size_t nToFill, void* pUserData);
+    static void SaveFromCacheBandSequential(CPLVirtualMem* ctxt,  size_t nOffset,
+                                             const void* pPageToBeEvicted,
+                                             size_t nToEvicted, void* pUserData);
+
+    static void FillCachePixelInterleaved(CPLVirtualMem* ctxt,  size_t nOffset,
+                                          void* pPageToFill,
+                                          size_t nToFill, void* pUserData);
+    static void SaveFromCachePixelInterleaved(CPLVirtualMem* ctxt,  size_t nOffset,
+                                              const void* pPageToBeEvicted,
+                                              size_t nToEvicted, void* pUserData);
+
+    static void Destroy(void* pUserData);
+};
+
+/************************************************************************/
+/*                             GDALVirtualMem()                         */
+/************************************************************************/
+
+GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDS,
+                                GDALRasterBandH hBand,
+                          int nXOff, int nYOff,
+                          int nXSize, int nYSize,
+                          int nBufXSize, int nBufYSize,
+                          GDALDataType eBufType,
+                          int nBandCount, const int* panBandMapIn,
+                          int nPixelSpace,
+                          GIntBig nLineSpace,
+                          GIntBig nBandSpace ) :
+    hDS(hDS), hBand(hBand), nXOff(nXOff), nYOff(nYOff), /*nXSize(nXSize), nYSize(nYSize),*/
+    nBufXSize(nBufXSize), nBufYSize(nBufYSize), eBufType(eBufType),
+    nBandCount(nBandCount), nPixelSpace(nPixelSpace), nLineSpace(nLineSpace),
+    nBandSpace(nBandSpace)
+{
+    if( hDS != NULL )
+    {
+        if( panBandMapIn )
+        {
+            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
+            memcpy(panBandMap, panBandMapIn, nBandCount * sizeof(int));
+        }
+        else
+        {
+            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
+            for(int i=0;i<nBandCount;i++)
+                panBandMap[i] = i + 1;
+        }
+    }
+    else
+    {
+        panBandMap = NULL;
+        nBandCount = 1;
+    }
+
+    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    if( nPixelSpace == nDataTypeSize &&
+        nLineSpace == (GIntBig)nBufXSize * nPixelSpace &&
+        nBandSpace == nBufYSize * nLineSpace )
+        bIsCompact = TRUE;
+    else if( nBandSpace == nDataTypeSize &&
+            nPixelSpace == nBandCount * nBandSpace &&
+            nLineSpace == (GIntBig)nBufXSize * nPixelSpace )
+        bIsCompact = TRUE;
+    else
+        bIsCompact = FALSE;
+
+    bIsBandSequential = ( nBandSpace >= nBufYSize * nLineSpace );
+}
+
+/************************************************************************/
+/*                            ~GDALVirtualMem()                         */
+/************************************************************************/
+
+GDALVirtualMem::~GDALVirtualMem()
+{
+    CPLFree(panBandMap);
+}
+
+/************************************************************************/
+/*                              GetXYBand()                             */
+/************************************************************************/
+
+void GDALVirtualMem::GetXYBand( size_t nOffset, int& x, int& y, int& band ) const
+{
+    if( IsBandSequential() )
+    {
+        if( nBandCount == 1 )
+            band = 0;
+        else
+            band = nOffset / nBandSpace;
+        y = (nOffset - band * nBandSpace) / nLineSpace;
+        x = (nOffset - band * nBandSpace - y * nLineSpace) / nPixelSpace;
+    }
+    else
+    {
+        y = nOffset / nLineSpace;
+        x = (nOffset - y * nLineSpace) / nPixelSpace;
+        if( nBandCount == 1 )
+            band = 0;
+        else
+            band = (nOffset - y * nLineSpace - x * nPixelSpace) / nBandSpace;
+    }
+}
+
+/************************************************************************/
+/*                            GotoNextPixel()                           */
+/************************************************************************/
+
+int GDALVirtualMem::GotoNextPixel(int& x, int& y, int& band) const
+{
+    if( IsBandSequential() )
+    {
+        x++;
+        if( x == nBufXSize )
+        {
+            x = 0;
+            y ++;
+        }
+        if( y == nBufYSize )
+        {
+            y = 0;
+            band ++;
+            if (band == nBandCount)
+                return FALSE;
+        }
+    }
+    else
+    {
+        band ++;
+        if( band == nBandCount )
+        {
+            band = 0;
+            x ++;
+        }
+        if( x == nBufXSize )
+        {
+            x = 0;
+            y ++;
+            if(y == nBufYSize)
+                return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              GetOffset()                             */
+/************************************************************************/
+
+size_t GDALVirtualMem::GetOffset(int x, int y, int band) const
+{
+    return x * nPixelSpace + y * nLineSpace + band * nBandSpace;
+}
+
+/************************************************************************/
+/*                          DoIOPixelInterleaved()                      */
+/************************************************************************/
+
+void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
+                        const size_t nOffset, void* pPage, size_t nBytes ) const
+{
+    int x, y, band;
+
+    GetXYBand(nOffset, x, y, band);
+    /*fprintf(stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",
+            eRWFlag, (int)nOffset, x, y, band);*/
+
+    if( eRWFlag == GF_Read && !IsCompact() )
+        memset(pPage, 0, nBytes);
+
+    if( band >= nBandCount )
+    {
+        band = nBandCount - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+    }
+    else if( x >= nBufXSize )
+    {
+        x = nBufXSize - 1;
+        band = nBandCount - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+    }
+
+    size_t nOffsetRecompute = GetOffset(x, y, band);
+    CPLAssert(nOffsetRecompute >= nOffset);
+    size_t nOffsetShift = nOffsetRecompute - nOffset;
+    if( nOffsetShift >= nBytes )
+        return;
+
+    // If we don't start at the first band for that given pixel, load/store
+    // the remaining bands
+    if( band > 0 )
+    {
+        size_t nEndOffsetEndOfPixel = GetOffset(x, y, nBandCount);
+        int bandEnd;
+        // Check that we have enough space to load/store until last band
+        // Should be always OK unless the number of bands is really huge
+        if( nEndOffsetEndOfPixel - nOffset > nBytes )
+        {
+            // Not enough space: find last possible band
+            int xEnd, yEnd;
+            GetXYBand(nOffset + nBytes, xEnd, yEnd, bandEnd);
+            CPLAssert(x == xEnd);
+            CPLAssert(y == yEnd);
+        }
+        else
+            bandEnd = nBandCount;
+
+        // Finish reading/writing the remaining bands for that pixel
+        GDALDatasetRasterIO( hDS, eRWFlag,
+                            nXOff + x, nYOff + y, 1, 1,
+                            (char*)pPage + nOffsetShift,
+                            1, 1, eBufType,
+                            bandEnd - band, panBandMap + band,
+                            nPixelSpace, nLineSpace, nBandSpace );
+
+        if( bandEnd < nBandCount )
+            return;
+
+        band = nBandCount - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+        nOffsetRecompute = GetOffset(x, y, 0);
+        nOffsetShift = nOffsetRecompute - nOffset;
+        if( nOffsetShift >= nBytes )
+            return;
+    }
+
+    // Is there enough place to store/load up to the end of current line ?
+    size_t nEndOffsetEndOfLine = GetOffset(nBufXSize-1, y, nBandCount);
+    if( nEndOffsetEndOfLine - nOffset > nBytes )
+    {
+        // No : read/write as many pixels on this line as possible
+        int xEnd, yEnd, bandEnd;
+        GetXYBand(nOffset + nBytes, xEnd, yEnd, bandEnd);
+        CPLAssert(y == yEnd);
+
+        if( x < xEnd )
+        {
+            GDALDatasetRasterIO( hDS, eRWFlag,
+                                nXOff + x, nYOff + y, xEnd - x, 1,
+                                (char*) pPage + nOffsetShift,
+                                xEnd - x, 1, eBufType,
+                                nBandCount, panBandMap,
+                                nPixelSpace, nLineSpace, nBandSpace );
+        }
+
+        // Are there partial bands to read/write for the last pixel ?
+        if( bandEnd > 0 )
+        {
+            x = xEnd;
+            nOffsetRecompute = GetOffset(x, y, 0);
+            nOffsetShift = nOffsetRecompute - nOffset;
+            if( nOffsetShift >= nBytes )
+                return;
+
+            if( bandEnd >= nBandCount )
+                bandEnd = nBandCount;
+
+            GDALDatasetRasterIO( hDS, eRWFlag,
+                                nXOff + x, nYOff + y, 1, 1,
+                                (char*) pPage + nOffsetShift,
+                                1, 1, eBufType,
+                                bandEnd, panBandMap,
+                                nPixelSpace, nLineSpace, nBandSpace );
+        }
+
+        return;
+    }
+
+    // Yes, enough place to read/write until end of line
+    if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
+    {
+        GDALDatasetRasterIO( hDS, eRWFlag,
+                    nXOff + x, nYOff + y, nBufXSize - x, 1,
+                    (char*)pPage + nOffsetShift,
+                    nBufXSize - x, 1, eBufType,
+                    nBandCount, panBandMap,
+                    nPixelSpace, nLineSpace, nBandSpace );
+
+        // Go to beginning of next line
+        x = nBufXSize - 1;
+        band = nBandCount - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+        nOffsetRecompute = GetOffset(x, y, 0);
+        nOffsetShift = nOffsetRecompute - nOffset;
+        if( nOffsetShift >= nBytes )
+            return;
+    }
+
+    // How many whole lines can we store/load ?
+    int nLineCount = (nBytes - nOffsetShift) / nLineSpace;
+    if( y + nLineCount > nBufYSize )
+        nLineCount = nBufYSize - y;
+    if( nLineCount > 0 )
+    {
+        GDALDatasetRasterIO( hDS, eRWFlag,
+                             nXOff + 0, nYOff + y, nBufXSize, nLineCount,
+                             (GByte*) pPage + nOffsetShift,
+                             nBufXSize, nLineCount, eBufType,
+                             nBandCount, panBandMap,
+                             nPixelSpace, nLineSpace, nBandSpace );
+        
+        y += nLineCount;
+        if( y == nBufYSize )
+            return;
+        nOffsetRecompute = GetOffset(x, y, 0);
+        nOffsetShift = nOffsetRecompute - nOffset;
+    }
+
+    if( nOffsetShift < nBytes )
+    {
+        DoIOPixelInterleaved( eRWFlag, nOffsetRecompute, 
+               (char*) pPage + nOffsetShift, nBytes - nOffsetShift );
+    }
+}
+
+/************************************************************************/
+/*                          DoIOPixelInterleaved()                      */
+/************************************************************************/
+
+void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
+                        const size_t nOffset, void* pPage, size_t nBytes ) const
+{
+    int x, y, band;
+
+    GetXYBand(nOffset, x, y, band);
+    /*fprintf(stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",
+            eRWFlag, (int)nOffset, x, y, band);*/
+
+    if( eRWFlag == GF_Read && !IsCompact() )
+        memset(pPage, 0, nBytes);
+
+    if( x >= nBufXSize )
+    {
+        x = nBufXSize - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+    }
+    else if( y >= nBufYSize )
+    {
+        x = nBufXSize - 1;
+        y = nBufYSize - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+    }
+
+    size_t nOffsetRecompute = GetOffset(x, y, band);
+    CPLAssert(nOffsetRecompute >= nOffset);
+    size_t nOffsetShift = nOffsetRecompute - nOffset;
+    if( nOffsetShift >= nBytes )
+        return;
+
+    // Is there enough place to store/load up to the end of current line ?
+    size_t nEndOffsetEndOfLine = GetOffset(nBufXSize, y, band);
+    if( nEndOffsetEndOfLine - nOffset > nBytes )
+    {
+        // No : read/write as many pixels on this line as possible
+        int xEnd, yEnd, bandEnd;
+        GetXYBand(nOffset + nBytes, xEnd, yEnd, bandEnd);
+        CPLAssert(y == yEnd);
+        CPLAssert(band == bandEnd);
+        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+                      nXOff + x, nYOff + y, xEnd - x, 1,
+                      (char*)pPage + nOffsetShift,
+                      xEnd - x, 1, eBufType,
+                      nPixelSpace, nLineSpace );
+
+        return;
+    }
+
+    // Yes, enough place to read/write until end of line
+    if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
+    {
+        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+                    nXOff + x, nYOff + y, nBufXSize - x, 1,
+                    (char*)pPage + nOffsetShift,
+                    nBufXSize - x, 1, eBufType,
+                    nPixelSpace, nLineSpace );
+
+        // Go to beginning of next line
+        x = nBufXSize - 1;
+        if( !GotoNextPixel(x, y, band) )
+            return;
+        nOffsetRecompute = GetOffset(x, y, band);
+        nOffsetShift = nOffsetRecompute - nOffset;
+        if( nOffsetShift >= nBytes )
+            return;
+    }
+
+    // How many whole lines can we store/load ?
+    int nLineCount = (nBytes - nOffsetShift) / nLineSpace;
+    if( y + nLineCount > nBufYSize )
+        nLineCount = nBufYSize - y;
+    if( nLineCount > 0 )
+    {
+        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+                    nXOff + 0, nYOff + y, nBufXSize, nLineCount,
+                    (GByte*) pPage + nOffsetShift,
+                    nBufXSize, nLineCount, eBufType,
+                    nPixelSpace, nLineSpace );
+
+        y += nLineCount;
+        if( y == nBufYSize )
+        {
+            y = 0;
+            band ++;
+            if( band == nBandCount )
+                return;
+        }
+        nOffsetRecompute = GetOffset(x, y, band);
+        nOffsetShift = nOffsetRecompute - nOffset;
+    }
+
+    if( nOffsetShift < nBytes )
+    {
+        DoIOBandSequential( eRWFlag, nOffsetRecompute, 
+               (char*) pPage + nOffsetShift, nBytes - nOffsetShift );
+    }
+}
+
+/************************************************************************/
+/*                    FillCacheBandSequential()                        */
+/************************************************************************/
+
+void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem* ctxt, 
+                  size_t nOffset,
+                  void* pPageToFill,
+                  size_t nToFill,
+                  void* pUserData)
+{
+    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIOBandSequential(GF_Read, nOffset, pPageToFill, nToFill);
+}
+
+/************************************************************************/
+/*                    SaveFromCacheBandSequential()                    */
+/************************************************************************/
+
+void GDALVirtualMem::SaveFromCacheBandSequential(CPLVirtualMem* ctxt, 
+                  size_t nOffset,
+                  const void* pPageToBeEvicted,
+                  size_t nToEvicted,
+                  void* pUserData)
+{
+    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIOBandSequential(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+}
+
+/************************************************************************/
+/*                     FillCachePixelInterleaved()                      */
+/************************************************************************/
+
+void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem* ctxt, 
+                  size_t nOffset,
+                  void* pPageToFill,
+                  size_t nToFill,
+                  void* pUserData)
+{
+    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIOPixelInterleaved(GF_Read, nOffset, pPageToFill, nToFill);
+}
+
+/************************************************************************/
+/*                     SaveFromCachePixelInterleaved()                  */
+/************************************************************************/
+
+void GDALVirtualMem::SaveFromCachePixelInterleaved(CPLVirtualMem* ctxt, 
+                  size_t nOffset,
+                  const void* pPageToBeEvicted,
+                  size_t nToEvicted,
+                  void* pUserData)
+{
+    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIOPixelInterleaved(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+}
+
+/************************************************************************/
+/*                                Destroy()                             */
+/************************************************************************/
+
+void GDALVirtualMem::Destroy(void* pUserData)
+{
+    GDALVirtualMem* psParams = (GDALVirtualMem*) pUserData;
+    delete psParams;
+}
+
+/************************************************************************/
+/*                      GDALCheckBandParameters()                       */
+/************************************************************************/
+
+static int GDALCheckBandParameters( GDALDatasetH hDS,
+                                    int nBandCount, int* panBandMap )
+{
+    if( nBandCount == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "nBandCount == 0");
+        return FALSE;
+    }
+
+    if( panBandMap != NULL )
+    {
+        for(int i=0;i<nBandCount;i++)
+        {
+            if( panBandMap[i] < 1 || panBandMap[i] > GDALGetRasterCount(hDS) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "panBandMap[%d]=%d",
+                        i, panBandMap[i]);
+                return FALSE;
+            }
+        }
+    }
+    else if( nBandCount > GDALGetRasterCount(hDS) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "nBandCount > GDALGetRasterCount(hDS)");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GDALGetVirtualMem()                         */
+/************************************************************************/
+
+static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
+                                         GDALRasterBandH hBand,
+                                         GDALRWFlag eRWFlag,
+                                         int nXOff, int nYOff,
+                                         int nXSize, int nYSize,
+                                         int nBufXSize, int nBufYSize,
+                                         GDALDataType eBufType,
+                                         int nBandCount, int* panBandMap,
+                                         int nPixelSpace,
+                                         GIntBig nLineSpace,
+                                         GIntBig nBandSpace,
+                                         size_t nCacheSize,
+                                         size_t nPageSizeHint,
+                                         int bSingleThreadUsage,
+                                         char **papszOptions )
+{
+    CPLVirtualMem* view;
+    GDALVirtualMem* psParams;
+    GUIntBig nReqMem;
+    (void) papszOptions;
+
+    if( nXSize != nBufXSize || nYSize != nBufYSize )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "nXSize != nBufXSize || nYSize != nBufYSize");
+        return NULL;
+    }
+    
+    int nRasterXSize = (hDS) ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
+    int nRasterYSize = (hDS) ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
+
+    if( nXOff < 0 || nYOff < 0 ||
+        nXSize == 0 || nYSize == 0 ||
+        nBufXSize < 0 || nBufYSize < 0 ||
+        nXOff + nXSize > nRasterXSize ||
+        nYOff + nYSize > nRasterYSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid window request");
+        return NULL;
+    }
+
+    if( nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0) 
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0");
+        return NULL;
+    }
+
+    if( hDS != NULL && !GDALCheckBandParameters(hDS, nBandCount, panBandMap ) )
+        return NULL;
+
+    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    if( nPixelSpace == 0 )
+        nPixelSpace = nDataTypeSize;
+    if( nLineSpace == 0 )
+        nLineSpace = (GIntBig)nBufXSize * nPixelSpace;
+    if( nBandSpace == 0 )
+        nBandSpace = (GIntBig)nBufYSize * nLineSpace;
+
+    // OFFSET = offset(x,y,band) = x * nPixelSpace + y * nLineSpace + band * nBandSpace
+    // where 0 <= x < nBufXSize and 0 <= y < nBufYSize and 0 <= band < nBandCount
+    // if nPixelSpace, nLineSpace and nBandSpace can have arbitrary values, there's
+    // no way of finding a unique(x,y,band) solution. We need to restrict the
+    // space of possibilities strongly.
+    // if nBandSpace >= nBufYSize * nLineSpace and nLineSpace >= nBufXSize * nPixelSpace,           INTERLEAVE = BAND
+    //      band = OFFSET / nBandSpace
+    //      y = (OFFSET - band * nBandSpace) / nLineSpace
+    //      x = (OFFSET - band * nBandSpace - y * nLineSpace) / nPixelSpace
+    // else if nPixelSpace >= nBandCount * nBandSpace and nLineSpace >= nBufXSize * nPixelSpace,    INTERLEAVE = PIXEL
+    //      y = OFFSET / nLineSpace
+    //      x = (OFFSET - y * nLineSpace) / nPixelSpace
+    //      band = (OFFSET - y * nLineSpace - x * nPixelSpace) / nBandSpace
+
+    if( nDataTypeSize == 0 || /* to please Coverity. not needed */
+        nLineSpace < (GIntBig)nBufXSize * nPixelSpace ||
+        (nBandCount > 1 &&
+        (nBandSpace == nPixelSpace ||
+        (nBandSpace < nPixelSpace && 
+         (nBandSpace < nDataTypeSize || nPixelSpace < nBandCount * nBandSpace)) ||
+        (nBandSpace > nPixelSpace &&
+         (nPixelSpace < nDataTypeSize || nBandSpace < nBufYSize * nLineSpace)))) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only pixel interleaving or band interleaving are supported");
+        return NULL;
+    }
+
+    /* Avoid odd spacings that would complicate I/O operations */
+    /* Ensuring they are multiple of nDataTypeSize should be fine, because */
+    /* the page size is a power of 2 that is also a multiple of nDataTypeSize */
+    if( (nPixelSpace % nDataTypeSize) != 0 ||
+        (nLineSpace % nDataTypeSize) != 0 ||
+        (nBandSpace % nDataTypeSize) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Unsupported spacing");
+        return NULL;
+    }
+
+    int bIsBandSequential = ( nBandSpace >= nBufYSize * nLineSpace );
+    if( bIsBandSequential )
+        nReqMem = nBandCount * nBandSpace;
+    else
+        nReqMem = nBufYSize * nLineSpace;
+    if( nReqMem != (GUIntBig)(size_t)nReqMem )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem);
+        return NULL;
+    }
+
+    psParams = new GDALVirtualMem(hDS, hBand, nXOff, nYOff,
+                               nXSize, nYSize,
+                               nBufXSize, nBufYSize,
+                               eBufType,
+                               nBandCount, panBandMap,
+                               nPixelSpace,
+                               nLineSpace,
+                               nBandSpace);
+
+    view = CPLVirtualMemNew((size_t)nReqMem,
+                         nCacheSize,
+                         nPageSizeHint,
+                         bSingleThreadUsage,
+                         (eRWFlag == GF_Read) ? VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
+                         (bIsBandSequential) ? GDALVirtualMem::FillCacheBandSequential :
+                                                GDALVirtualMem::FillCachePixelInterleaved,
+                         (bIsBandSequential) ? GDALVirtualMem::SaveFromCacheBandSequential :
+                                                GDALVirtualMem::SaveFromCachePixelInterleaved,
+                         GDALVirtualMem::Destroy,
+                         psParams);
+
+    if( view == NULL )
+    {
+        delete psParams;
+    }
+
+    return view;
+}
+
+/************************************************************************/
+/*                       GDALDatasetGetVirtualMem()                     */
+/************************************************************************/
+
+/** Create a CPLVirtualMem object from a GDAL dataset object.
+ *
+ * Only supported on Linux for now.
+ *
+ * This method allows creating a virtual memory object for a region of one
+ * or more GDALRasterBands from  this dataset. The content of the virtual
+ * memory object is automatically filled from dataset content when a virtual
+ * memory page is first accessed, and it is released (or flushed in case of a
+ * "dirty" page) when the cache size limit has been reached.
+ *
+ * The pointer to access the virtual memory object is obtained with
+ * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
+ * CPLVirtualMemFree() must be called before the dataset object is destroyed.
+ *
+ * If p is such a pointer and base_type the C type matching eBufType, for default
+ * values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) for band b can be accessed with
+ * ((base_type*)p)[x + y * nBufXSize + (b-1)*nBufXSize*nBufYSize].
+ *
+ * Note that the mechanism used to transparently fill memory pages when they are
+ * accessed is the same (but in a controlled way) than what occurs when a memory
+ * error occurs in a program. Debugging software will generally interrupt program
+ * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
+ * that by ensuring memory pages are allocated before being accessed.
+ *
+ * The size of the region that can be mapped as a virtual memory object depends
+ * on hardware and operating system limitations.
+ * On Linux AMD64 platforms, the maximum value is 128 TB.
+ * On Linux x86 platforms, the maximum value is 2 GB.
+ *
+ * Data type translation is automatically done if the data type
+ * (eBufType) of the buffer is different than
+ * that of the GDALRasterBand.
+ *
+ * Image decimation / replication is currently not supported, i.e. if the
+ * size of the region being accessed (nXSize x nYSize) is different from the
+ * buffer size (nBufXSize x nBufYSize).
+ *
+ * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
+ * writing from various organization of buffers. Arbitrary values for the spacing
+ * parameters are not supported. Those values must be multiple of the size of the
+ * buffer data type, and must be either band sequential organization (typically
+ * nPixelSpace = GDALGetDataTypeSize(eBufType) / 8, nLineSpace = nPixelSpace * nBufXSize,
+ * nBandSpace = nLineSpace * nBufYSize), or pixel-interleaved organization
+ * (typically nPixelSpace = nBandSpace * nBandCount, nLineSpace = nPixelSpace * nBufXSize,
+ * nBandSpace = GDALGetDataTypeSize(eBufType) / 8)
+ *
+ * @param hDS Dataset object
+ *
+ * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
+ * write a region of data.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param nBufXSize the width of the buffer image into which the desired region
+ * is to be read, or from which it is to be written.
+ *
+ * @param nBufYSize the height of the buffer image into which the desired
+ * region is to be read, or from which it is to be written.
+ *
+ * @param eBufType the type of the pixel values in the data buffer. The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nBandCount the number of bands being read or written. 
+ *
+ * @param panBandMap the list of nBandCount band numbers being read/written.
+ * Note band numbers are 1 based. This may be NULL to select the first 
+ * nBandCount bands.
+ *
+ * @param nPixelSpace The byte offset from the start of one pixel value in
+ * the buffer to the start of the next pixel value within a scanline. If defaulted
+ * (0) the size of the datatype eBufType is used.
+ *
+ * @param nLineSpace The byte offset from the start of one scanline in
+ * the buffer to the start of the next. If defaulted (0) the size of the datatype
+ * eBufType * nBufXSize is used.
+ *
+ * @param nBandSpace the byte offset from the start of one bands data to the
+ * start of the next. If defaulted (0) the value will be 
+ * nLineSpace * nBufYSize implying band sequential organization
+ * of the data buffer.
+ *
+ * @param nCacheSize   size in bytes of the maximum memory that will be really
+ *                     allocated (must ideally fit into RAM)
+ *
+ * @param nPageSizeHint hint for the page size. Must be a multiple of the
+ *                      system page size, returned by CPLGetPageSize().
+ *                      Minimum value is generally 4096. Might be set to 0 to
+ *                      let the function determine a default page size.
+ *
+ * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
+ *                           that will access the virtual memory mapping. This can
+ *                           optimize performance a bit. If set to FALSE,
+ *                           CPLVirtualMemDeclareThread() must be called.
+ *
+ * @param papszOptions NULL terminated list of options. Unused for now.
+ *
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 1.11
+ */
+
+CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
+                                         GDALRWFlag eRWFlag,
+                                         int nXOff, int nYOff,
+                                         int nXSize, int nYSize,
+                                         int nBufXSize, int nBufYSize,
+                                         GDALDataType eBufType,
+                                         int nBandCount, int* panBandMap,
+                                         int nPixelSpace,
+                                         GIntBig nLineSpace,
+                                         GIntBig nBandSpace,
+                                         size_t nCacheSize,
+                                         size_t nPageSizeHint,
+                                         int bSingleThreadUsage,
+                                         char **papszOptions )
+{
+    return GDALGetVirtualMem( hDS, NULL, eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                              nBufXSize, nBufYSize, eBufType,
+                              nBandCount, panBandMap,
+                              nPixelSpace, nLineSpace, nBandSpace,
+                              nCacheSize, nPageSizeHint, bSingleThreadUsage,
+                              papszOptions );
+}
+
+/************************************************************************/
+/*                     GDALRasterBandGetVirtualMem()                    */
+/************************************************************************/
+
+/** Create a CPLVirtualMem object from a GDAL raster band object.
+ *
+ * Only supported on Linux for now.
+ *
+ * This method allows creating a virtual memory object for a region of a
+ * GDALRasterBand. The content of the virtual
+ * memory object is automatically filled from dataset content when a virtual
+ * memory page is first accessed, and it is released (or flushed in case of a
+ * "dirty" page) when the cache size limit has been reached.
+ *
+ * The pointer to access the virtual memory object is obtained with
+ * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
+ * CPLVirtualMemFree() must be called before the raster band object is destroyed.
+ *
+ * If p is such a pointer and base_type the C type matching eBufType, for default
+ * values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) can be accessed with
+ * ((base_type*)p)[x + y * nBufXSize].
+ *
+ * Note that the mechanism used to transparently fill memory pages when they are
+ * accessed is the same (but in a controlled way) than what occurs when a memory
+ * error occurs in a program. Debugging software will generally interrupt program
+ * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
+ * that by ensuring memory pages are allocated before being accessed.
+ *
+ * The size of the region that can be mapped as a virtual memory object depends
+ * on hardware and operating system limitations.
+ * On Linux AMD64 platforms, the maximum value is 128 TB.
+ * On Linux x86 platforms, the maximum value is 2 GB.
+ *
+ * Data type translation is automatically done if the data type
+ * (eBufType) of the buffer is different than
+ * that of the GDALRasterBand.
+ *
+ * Image decimation / replication is currently not supported, i.e. if the
+ * size of the region being accessed (nXSize x nYSize) is different from the
+ * buffer size (nBufXSize x nBufYSize).
+ *
+ * The nPixelSpace and nLineSpace parameters allow reading into or
+ * writing from various organization of buffers. Arbitrary values for the spacing
+ * parameters are not supported. Those values must be multiple of the size of the
+ * buffer data type and must be such that nLineSpace >= nPixelSpace * nBufXSize.
+ *
+ * @param hBand Rasterband object
+ *
+ * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
+ * write a region of data.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param nBufXSize the width of the buffer image into which the desired region
+ * is to be read, or from which it is to be written.
+ *
+ * @param nBufYSize the height of the buffer image into which the desired
+ * region is to be read, or from which it is to be written.
+ *
+ * @param eBufType the type of the pixel values in the data buffer. The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nPixelSpace The byte offset from the start of one pixel value in
+ * the buffer to the start of the next pixel value within a scanline. If defaulted
+ * (0) the size of the datatype eBufType is used.
+ *
+ * @param nLineSpace The byte offset from the start of one scanline in
+ * the buffer to the start of the next. If defaulted (0) the size of the datatype
+ * eBufType * nBufXSize is used.
+ *
+ * @param nCacheSize   size in bytes of the maximum memory that will be really
+ *                     allocated (must ideally fit into RAM)
+ *
+ * @param nPageSizeHint hint for the page size. Must be a multiple of the
+ *                      system page size, returned by CPLGetPageSize().
+ *                      Minimum value is generally 4096. Might be set to 0 to
+ *                      let the function determine a default page size.
+ *
+ * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
+ *                           that will access the virtual memory mapping. This can
+ *                           optimize performance a bit. If set to FALSE,
+ *                           CPLVirtualMemDeclareThread() must be called.
+ *
+ * @param papszOptions NULL terminated list of options. Unused for now.
+ *
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 1.11
+ */
+
+CPLVirtualMem* GDALRasterBandGetVirtualMem( GDALRasterBandH hBand,
+                                         GDALRWFlag eRWFlag,
+                                         int nXOff, int nYOff,
+                                         int nXSize, int nYSize,
+                                         int nBufXSize, int nBufYSize,
+                                         GDALDataType eBufType,
+                                         int nPixelSpace,
+                                         GIntBig nLineSpace,
+                                         size_t nCacheSize,
+                                         size_t nPageSizeHint,
+                                         int bSingleThreadUsage,
+                                         char **papszOptions )
+{
+    return GDALGetVirtualMem( NULL, hBand, eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                              nBufXSize, nBufYSize, eBufType,
+                              1, NULL,
+                              nPixelSpace, nLineSpace, 0,
+                              nCacheSize, nPageSizeHint, bSingleThreadUsage,
+                              papszOptions );
+}
+
+/************************************************************************/
+/*                        GDALTiledVirtualMem                           */
+/************************************************************************/
+
+class GDALTiledVirtualMem
+{
+    GDALDatasetH hDS;
+    GDALRasterBandH hBand;
+    int nXOff;
+    int nYOff;
+    int nXSize;
+    int nYSize;
+    int nTileXSize;
+    int nTileYSize;
+    GDALDataType eBufType;
+    int nBandCount;
+    int* panBandMap;
+    GDALTileOrganization eTileOrganization;
+
+    void DoIO( GDALRWFlag eRWFlag, size_t nOffset,
+               void* pPage, size_t nBytes ) const;
+
+public:
+             GDALTiledVirtualMem( GDALDatasetH hDS,
+                                  GDALRasterBandH hBand,
+                                  int nXOff, int nYOff,
+                                  int nXSize, int nYSize,
+                                  int nTileXSize, int nTileYSize,
+                                  GDALDataType eBufType,
+                                  int nBandCount, const int* panBandMapIn,
+                                  GDALTileOrganization eTileOrganization );
+            ~GDALTiledVirtualMem();
+
+    static void FillCache(CPLVirtualMem* ctxt,  size_t nOffset,
+                                         void* pPageToFill,
+                                         size_t nPageSize, void* pUserData);
+    static void SaveFromCache(CPLVirtualMem* ctxt,  size_t nOffset,
+                                             const void* pPageToBeEvicted,
+                                             size_t nToEvicted, void* pUserData);
+
+    static void Destroy(void* pUserData);
+};
+
+/************************************************************************/
+/*                        GDALTiledVirtualMem()                         */
+/************************************************************************/
+
+GDALTiledVirtualMem::GDALTiledVirtualMem( GDALDatasetH hDS,
+                                          GDALRasterBandH hBand,
+                                  int nXOff, int nYOff,
+                                  int nXSize, int nYSize,
+                                  int nTileXSize, int nTileYSize,
+                                  GDALDataType eBufType,
+                                  int nBandCount, const int* panBandMapIn,
+                                  GDALTileOrganization eTileOrganization ):
+    hDS(hDS), hBand(hBand), nXOff(nXOff), nYOff(nYOff), nXSize(nXSize), nYSize(nYSize),
+    nTileXSize(nTileXSize), nTileYSize(nTileYSize), eBufType(eBufType),
+    nBandCount(nBandCount), eTileOrganization(eTileOrganization)
+{
+    if( hDS != NULL )
+    {
+        if( panBandMapIn )
+        {
+            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
+            memcpy(panBandMap, panBandMapIn, nBandCount * sizeof(int));
+        }
+        else
+        {
+            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
+            for(int i=0;i<nBandCount;i++)
+                panBandMap[i] = i + 1;
+        }
+    }
+    else
+    {
+        panBandMap = NULL;
+        nBandCount = 1;
+    }
+}
+
+/************************************************************************/
+/*                       ~GDALTiledVirtualMem()                         */
+/************************************************************************/
+
+GDALTiledVirtualMem::~GDALTiledVirtualMem()
+{
+    CPLFree(panBandMap);
+}
+
+/************************************************************************/
+/*                                DoIO()                                */
+/************************************************************************/
+
+void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
+                                void* pPage, size_t nBytes ) const
+{
+    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    int nTilesPerRow = (nXSize + nTileXSize - 1) / nTileXSize;
+    int nTilesPerCol = (nYSize + nTileYSize - 1) / nTileYSize;
+    size_t nPageSize = nTileXSize * nTileYSize * nDataTypeSize;
+    if( eTileOrganization != GTO_BSQ )
+        nPageSize *= nBandCount;
+    CPLAssert((nOffset % nPageSize) == 0);
+    CPLAssert(nBytes == nPageSize);
+    size_t nTile;
+    int band;
+    int nPixelSpace, nLineSpace, nBandSpace;
+    if( eTileOrganization == GTO_TIP )
+    {
+        nTile = nOffset / nPageSize;
+        band = 0;
+        nPixelSpace = nDataTypeSize * nBandCount;
+        nLineSpace = nPixelSpace * nTileXSize;
+        nBandSpace = nDataTypeSize;
+    }
+    else if( eTileOrganization == GTO_BIT )
+    {
+        nTile = nOffset / nPageSize;
+        band = 0;
+        nPixelSpace = nDataTypeSize;
+        nLineSpace = nPixelSpace * nTileXSize;
+        nBandSpace = nLineSpace * nTileYSize;
+    }
+    else
+    {
+        //offset = nPageSize * (band * nTilesPerRow * nTilesPerCol + nTile)
+        band = nOffset / (nPageSize * nTilesPerRow * nTilesPerCol);
+        nTile = nOffset / nPageSize - band * nTilesPerRow * nTilesPerCol;
+        nPixelSpace = nDataTypeSize;
+        nLineSpace = nPixelSpace * nTileXSize;
+        nBandSpace = 0;
+        band ++;
+    }
+    size_t nYTile = nTile / nTilesPerRow;
+    size_t nXTile = nTile - nYTile * nTilesPerRow;
+
+    int nReqXSize = MIN( nTileXSize, nXSize - (int)(nXTile * nTileXSize) );
+    int nReqYSize = MIN( nTileYSize, nYSize - (int)(nYTile * nTileYSize) );
+    if( eRWFlag == GF_Read && (nReqXSize < nTileXSize || nReqYSize < nTileYSize) )
+        memset(pPage, 0, nBytes);
+    if( hDS != NULL )
+    {
+        GDALDatasetRasterIO( hDS, eRWFlag,
+                            nXOff + nXTile * nTileXSize, nYOff + nYTile * nTileYSize,
+                            nReqXSize, nReqYSize,
+                            pPage,
+                            nReqXSize, nReqYSize,
+                            eBufType,
+                            ( eTileOrganization != GTO_BSQ ) ? nBandCount : 1,
+                            ( eTileOrganization != GTO_BSQ ) ? panBandMap : &band,
+                            nPixelSpace, nLineSpace, nBandSpace );
+    }
+    else
+    {
+        GDALRasterIO(hBand, eRWFlag,
+                     nXOff + nXTile * nTileXSize, nYOff + nYTile * nTileYSize,
+                     nReqXSize, nReqYSize,
+                     pPage,
+                     nReqXSize, nReqYSize,
+                     eBufType,
+                     nPixelSpace, nLineSpace );
+    }
+}
+
+/************************************************************************/
+/*                           FillCache()                                */
+/************************************************************************/
+
+void GDALTiledVirtualMem::FillCache(CPLVirtualMem* ctxt,  size_t nOffset,
+                                         void* pPageToFill,
+                                         size_t nToFill, void* pUserData)
+{
+    const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIO(GF_Read, nOffset, pPageToFill, nToFill);
+}
+
+/************************************************************************/
+/*                          SaveFromCache()                             */
+/************************************************************************/
+
+void GDALTiledVirtualMem::SaveFromCache(CPLVirtualMem* ctxt,  size_t nOffset,
+                                             const void* pPageToBeEvicted,
+                                             size_t nToEvicted, void* pUserData)
+{
+    const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
+    (void)ctxt;
+    psParms->DoIO(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+}
+
+/************************************************************************/
+/*                                Destroy()                             */
+/************************************************************************/
+
+void GDALTiledVirtualMem::Destroy(void* pUserData)
+{
+    GDALTiledVirtualMem* psParams = (GDALTiledVirtualMem*) pUserData;
+    delete psParams;
+}
+
+/************************************************************************/
+/*                      GDALGetTiledVirtualMem()                        */
+/************************************************************************/
+
+static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
+                                              GDALRasterBandH hBand,
+                                              GDALRWFlag eRWFlag,
+                                              int nXOff, int nYOff,
+                                              int nXSize, int nYSize,
+                                              int nTileXSize, int nTileYSize,
+                                              GDALDataType eBufType,
+                                              int nBandCount, int* panBandMap,
+                                              GDALTileOrganization eTileOrganization,
+                                              size_t nCacheSize,
+                                              int bSingleThreadUsage,
+                                              char **papszOptions )
+{
+    CPLVirtualMem* view;
+    GDALTiledVirtualMem* psParams;
+    (void) papszOptions;
+
+    int nRasterXSize = (hDS) ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
+    int nRasterYSize = (hDS) ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
+
+    if( nXOff < 0 || nYOff < 0 ||
+        nTileXSize <= 0 || nTileYSize <= 0 ||
+        nXOff + nXSize > nRasterXSize ||
+        nYOff + nYSize > nRasterYSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid window request");
+        return NULL;
+    }
+
+    if( hDS != NULL && !GDALCheckBandParameters(hDS, nBandCount, panBandMap ) )
+        return NULL;
+
+    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    int nTilesPerRow = (nXSize + nTileXSize - 1) / nTileXSize;
+    int nTilesPerCol = (nYSize + nTileYSize - 1) / nTileYSize;
+    GUIntBig nReqMem = (GUIntBig)nTilesPerRow * nTilesPerCol *
+                        nTileXSize * nTileYSize * nBandCount * nDataTypeSize;
+    if( nReqMem != (GUIntBig)(size_t)nReqMem )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem);
+        return NULL;
+    }
+
+    size_t nPageSizeHint = nTileXSize * nTileYSize * nDataTypeSize;
+    if( eTileOrganization != GTO_BSQ )
+        nPageSizeHint *= nBandCount;
+    if( (nPageSizeHint % CPLGetPageSize()) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Tile dimensions incompatible with page size");
+        return NULL;
+    }
+
+    psParams = new GDALTiledVirtualMem(hDS, hBand, nXOff, nYOff,
+                                       nXSize, nYSize,
+                                       nTileXSize, nTileYSize,
+                                       eBufType,
+                                       nBandCount, panBandMap,
+                                       eTileOrganization);
+
+    view = CPLVirtualMemNew((size_t)nReqMem,
+                         nCacheSize,
+                         nPageSizeHint,
+                         bSingleThreadUsage,
+                         (eRWFlag == GF_Read) ? VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
+                         GDALTiledVirtualMem::FillCache,
+                         GDALTiledVirtualMem::SaveFromCache,
+                         GDALTiledVirtualMem::Destroy,
+                         psParams);
+
+    if( view == NULL )
+    {
+        delete psParams;
+    }
+    else if( CPLVirtualMemGetPageSize(view) != nPageSizeHint )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Did not get expected page size : %d vs %d",
+                 (int)CPLVirtualMemGetPageSize(view), (int)nPageSizeHint);
+        CPLVirtualMemFree(view);
+        return NULL;
+    }
+
+    return view;
+}
+
+/************************************************************************/
+/*                   GDALDatasetGetTiledVirtualMem()                    */
+/************************************************************************/
+
+/** Create a CPLVirtualMem object from a GDAL dataset object, with tiling
+ * organization
+ *
+ * Only supported on Linux for now.
+ *
+ * This method allows creating a virtual memory object for a region of one
+ * or more GDALRasterBands from  this dataset. The content of the virtual
+ * memory object is automatically filled from dataset content when a virtual
+ * memory page is first accessed, and it is released (or flushed in case of a
+ * "dirty" page) when the cache size limit has been reached.
+ *
+ * Contrary to GDALDatasetGetVirtualMem(), pixels will be organized by tiles
+ * instead of scanlines. Different ways of organizing pixel within/accross tiles
+ * can be selected with the eTileOrganization parameter.
+ *
+ * If nXSize is not a multiple of nTileXSize or nYSize is not a multiple of
+ * nTileYSize, partial tiles will exists at the right and/or bottom of the region
+ * of interest. Those partial tiles will also have nTileXSize * nTileYSize dimension,
+ * with padding pixels.
+ *
+ * The pointer to access the virtual memory object is obtained with
+ * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
+ * CPLVirtualMemFree() must be called before the dataset object is destroyed.
+ *
+ * If p is such a pointer and base_type the C type matching eBufType, for default
+ * values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) for band b can be accessed with :
+ *  - for eTileOrganization = GTO_TIP, ((base_type*)p)[tile_number(x,y)*nBandCount*tile_size + offset_in_tile(x,y)*nBandCount + (b-1)].
+ *  - for eTileOrganization = GTO_BIT, ((base_type*)p)[(tile_number(x,y)*nBandCount + (b-1)) * tile_size + offset_in_tile(x,y)].
+ *  - for eTileOrganization = GTO_BSQ, ((base_type*)p)[(tile_number(x,y) + (b-1)*nTilesCount) * tile_size + offset_in_tile(x,y)].
+ *
+ * where nTilesPerRow = ceil(nXSize / nTileXSize)
+ *       nTilesPerCol = ceil(nYSize / nTileYSize)
+ *       nTilesCount = nTilesPerRow * nTilesPerCol
+ *       tile_number(x,y) = (y / nTileYSize) * nTilesPerRow + (x / nTileXSize)
+ *       offset_in_tile(x,y) = (y % nTileYSize) * nTileXSize  + (x % nTileXSize)
+ *       tile_size = nTileXSize * nTileYSize
+ *
+ * Note that for a single band request, all tile organizations are equivalent.
+ *
+ * Note that the mechanism used to transparently fill memory pages when they are
+ * accessed is the same (but in a controlled way) than what occurs when a memory
+ * error occurs in a program. Debugging software will generally interrupt program
+ * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
+ * that by ensuring memory pages are allocated before being accessed.
+ *
+ * The size of the region that can be mapped as a virtual memory object depends
+ * on hardware and operating system limitations.
+ * On Linux AMD64 platforms, the maximum value is 128 TB.
+ * On Linux x86 platforms, the maximum value is 2 GB.
+ *
+ * Data type translation is automatically done if the data type
+ * (eBufType) of the buffer is different than
+ * that of the GDALRasterBand.
+ *
+ * @param hDS Dataset object
+ *
+ * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
+ * write a region of data.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param nTileXSize the width of the tiles.
+ *
+ * @param nTileYSize the height of the tiles.
+ *
+ * @param eBufType the type of the pixel values in the data buffer. The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nBandCount the number of bands being read or written. 
+ *
+ * @param panBandMap the list of nBandCount band numbers being read/written.
+ * Note band numbers are 1 based. This may be NULL to select the first 
+ * nBandCount bands.
+ *
+ * @param eTileOrganization tile organization.
+ *
+ * @param nCacheSize   size in bytes of the maximum memory that will be really
+ *                     allocated (must ideally fit into RAM)
+ *
+ * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
+ *                           that will access the virtual memory mapping. This can
+ *                           optimize performance a bit. If set to FALSE,
+ *                           CPLVirtualMemDeclareThread() must be called.
+ *
+ * @param papszOptions NULL terminated list of options. Unused for now.
+ *
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 1.11
+ */
+
+CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
+                                              GDALRWFlag eRWFlag,
+                                              int nXOff, int nYOff,
+                                              int nXSize, int nYSize,
+                                              int nTileXSize, int nTileYSize,
+                                              GDALDataType eBufType,
+                                              int nBandCount, int* panBandMap,
+                                              GDALTileOrganization eTileOrganization,
+                                              size_t nCacheSize,
+                                              int bSingleThreadUsage,
+                                              char **papszOptions )
+{
+    return GDALGetTiledVirtualMem( hDS, NULL, eRWFlag, nXOff, nYOff,
+                                   nXSize, nYSize, nTileXSize, nTileYSize,
+                                   eBufType, nBandCount, panBandMap,
+                                   eTileOrganization,
+                                   nCacheSize, bSingleThreadUsage, papszOptions );
+}
+
+/************************************************************************/
+/*                   GDALRasterBandGetTiledVirtualMem()                 */
+/************************************************************************/
+
+/** Create a CPLVirtualMem object from a GDAL rasterband object, with tiling
+ * organization
+ *
+ * Only supported on Linux for now.
+ *
+ * This method allows creating a virtual memory object for a region of one
+ * GDALRasterBand. The content of the virtual
+ * memory object is automatically filled from dataset content when a virtual
+ * memory page is first accessed, and it is released (or flushed in case of a
+ * "dirty" page) when the cache size limit has been reached.
+ *
+ * Contrary to GDALDatasetGetVirtualMem(), pixels will be organized by tiles
+ * instead of scanlines.
+ *
+ * If nXSize is not a multiple of nTileXSize or nYSize is not a multiple of
+ * nTileYSize, partial tiles will exists at the right and/or bottom of the region
+ * of interest. Those partial tiles will also have nTileXSize * nTileYSize dimension,
+ * with padding pixels.
+ *
+ * The pointer to access the virtual memory object is obtained with
+ * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
+ * CPLVirtualMemFree() must be called before the raster band object is destroyed.
+ *
+ * If p is such a pointer and base_type the C type matching eBufType, for default
+ * values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) can be accessed with :
+ *  ((base_type*)p)[tile_number(x,y)*tile_size + offset_in_tile(x,y)].
+ *
+ * where nTilesPerRow = ceil(nXSize / nTileXSize)
+ *       nTilesCount = nTilesPerRow * nTilesPerCol
+ *       tile_number(x,y) = (y / nTileYSize) * nTilesPerRow + (x / nTileXSize)
+ *       offset_in_tile(x,y) = (y % nTileYSize) * nTileXSize  + (x % nTileXSize)
+ *       tile_size = nTileXSize * nTileYSize
+ *
+ * Note that the mechanism used to transparently fill memory pages when they are
+ * accessed is the same (but in a controlled way) than what occurs when a memory
+ * error occurs in a program. Debugging software will generally interrupt program
+ * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
+ * that by ensuring memory pages are allocated before being accessed.
+ *
+ * The size of the region that can be mapped as a virtual memory object depends
+ * on hardware and operating system limitations.
+ * On Linux AMD64 platforms, the maximum value is 128 TB.
+ * On Linux x86 platforms, the maximum value is 2 GB.
+ *
+ * Data type translation is automatically done if the data type
+ * (eBufType) of the buffer is different than
+ * that of the GDALRasterBand.
+ *
+ * @param hBand Rasterband object
+ *
+ * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
+ * write a region of data.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param nTileXSize the width of the tiles.
+ *
+ * @param nTileYSize the height of the tiles.
+ *
+ * @param eBufType the type of the pixel values in the data buffer. The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nCacheSize   size in bytes of the maximum memory that will be really
+ *                     allocated (must ideally fit into RAM)
+ *
+ * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
+ *                           that will access the virtual memory mapping. This can
+ *                           optimize performance a bit. If set to FALSE,
+ *                           CPLVirtualMemDeclareThread() must be called.
+ *
+ * @param papszOptions NULL terminated list of options. Unused for now.
+ *
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 1.11
+ */
+
+CPLVirtualMem* GDALRasterBandGetTiledVirtualMem( GDALRasterBandH hBand,
+                                              GDALRWFlag eRWFlag,
+                                              int nXOff, int nYOff,
+                                              int nXSize, int nYSize,
+                                              int nTileXSize, int nTileYSize,
+                                              GDALDataType eBufType,
+                                              size_t nCacheSize,
+                                              int bSingleThreadUsage,
+                                              char **papszOptions )
+{
+    return GDALGetTiledVirtualMem( NULL, hBand, eRWFlag, nXOff, nYOff,
+                                   nXSize, nYSize, nTileXSize, nTileYSize,
+                                   eBufType, 1, NULL,
+                                   GTO_BSQ,
+                                   nCacheSize, bSingleThreadUsage, papszOptions );
+}
diff --git a/gcore/jp2dump.cpp b/gcore/jp2dump.cpp
new file mode 100755
index 0000000..d6cdff5
--- /dev/null
+++ b/gcore/jp2dump.cpp
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL 
+ * Purpose:  Small test utility for dumping jpeg2000 boxes.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdaljp2metadata.h"
+
+int main( int argc, char ** argv )
+
+{
+    VSILFILE   *fp;
+
+    if( argc < 2 )
+    {
+        printf( "Usage: jp2dump <filename>\n" );
+        exit( 2 );
+    }
+
+    fp = VSIFOpenL( argv[1], "rb" );
+    if( fp == NULL )
+    {
+        perror( "open" );
+        exit( 1 );
+    }
+
+    GDALJP2Box oBox(fp);
+
+    oBox.ReadFirst();
+    do 
+    {
+        oBox.DumpReadable( stdout );
+    } while( oBox.ReadNext() );
+}
diff --git a/gcore/makefile.vc b/gcore/makefile.vc
index fdf9c2b..1ac9bde 100644
--- a/gcore/makefile.vc
+++ b/gcore/makefile.vc
@@ -9,7 +9,9 @@ OBJ	=	gdalopeninfo.obj gdaldrivermanager.obj gdaldriver.obj \
 		gdalallvalidmaskband.obj gdalnodatamaskband.obj \
 		gdal_rpcimdio.obj gdalproxydataset.obj gdalproxypool.obj \
 		gdalnodatavaluesmaskband.obj gdaldefaultasync.obj \
-        gdaldllmain.obj gdalexif.obj gdalclientserver.obj
+		gdaldllmain.obj gdalexif.obj gdalclientserver.obj \
+		gdalgeorefpamdataset.obj  gdaljp2abstractdataset.obj \
+		gdalvirtualmem.obj
 
 RES	=	Version.res
 
diff --git a/gcore/overview.cpp b/gcore/overview.cpp
index 98a9080..4a419c8 100644
--- a/gcore/overview.cpp
+++ b/gcore/overview.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: overview.cpp 21356 2010-12-31 16:35:02Z rouault $
+ * $Id: overview.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview support in different drivers.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: overview.cpp 21356 2010-12-31 16:35:02Z rouault $");
+CPL_CVSID("$Id: overview.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef CPLErr (*GDALDownsampleFunction)
                       ( int nSrcWidth, int nSrcHeight,
diff --git a/gcore/rasterio.cpp b/gcore/rasterio.cpp
index 02b6658..f53337c 100644
--- a/gcore/rasterio.cpp
+++ b/gcore/rasterio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterio.cpp 25225 2012-11-11 19:29:06Z rouault $
+ * $Id: rasterio.cpp 27119 2014-04-03 18:48:27Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -47,7 +48,7 @@
 #endif
 
 
-CPL_CVSID("$Id: rasterio.cpp 25225 2012-11-11 19:29:06Z rouault $");
+CPL_CVSID("$Id: rasterio.cpp 27119 2014-04-03 18:48:27Z rouault $");
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -69,7 +70,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     GByte       *pabySrcBlock = NULL;
     GDALRasterBlock *poBlock = NULL;
     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
-
+    
     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     {
         CPLError(eFlushBlockErr, CPLE_AppDefined,
@@ -192,6 +193,18 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                             nPixelSpace, nLineSpace );
         }
     }
+    
+    
+    if( eRWFlag == GF_Read &&
+        nBufXSize < nXSize / 100 && nBufYSize < nYSize / 100 &&
+        nPixelSpace == nBufDataSize &&
+        nLineSpace == nPixelSpace * nBufXSize &&
+        CSLTestBoolean(CPLGetConfigOption("GDAL_NO_COSTLY_OVERVIEW", "NO")) )
+    {
+        memset(pData, 0, nLineSpace * nBufYSize);
+        return CE_None;
+    }
+
 
 /* ==================================================================== */
 /*      The second case when we don't need subsample data but likely    */
@@ -825,16 +838,16 @@ inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
 /************************************************************************/
 /**
  * Template function, used to copy data from pSrcData into buffer
- * pDstData, with stride nSrcPixelOffset in the source data and
- * stride nDstPixelOffset in the destination data. This template can
+ * pDstData, with stride nSrcPixelStride in the source data and
+ * stride nDstPixelStride in the destination data. This template can
  * deal with the case where the input data type is real or complex and
  * the output is real.
  *
  * @param pSrcData the source data buffer
- * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
+ * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
  *                      of interest.
  * @param pDstData the destination buffer.
- * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
+ * @param nDstPixelStride the stride in the buffer pDstData for pixels of
  *                      interest.
  * @param nWordCount the total number of pixel words to copy
  *
@@ -850,8 +863,8 @@ inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
  */
 
 template <class Tin, class Tout>
-static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelOffset,
-                           Tout* const pDstData, int nDstPixelOffset,
+static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelStride,
+                           Tout* const pDstData, int nDstPixelStride,
                            int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
@@ -860,12 +873,12 @@ static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelOffset,
     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelOffset));
+        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
         Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
         CopyWord(tValue, *pOutPixel);
 
-        nDstOffset += nDstPixelOffset;
+        nDstOffset += nDstPixelStride;
     }
 }
 
@@ -874,22 +887,22 @@ static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelOffset,
 /************************************************************************/
 /**
  * Template function, used to copy data from pSrcData into buffer
- * pDstData, with stride nSrcPixelOffset in the source data and
- * stride nDstPixelOffset in the destination data. Deals with the 
+ * pDstData, with stride nSrcPixelStride in the source data and
+ * stride nDstPixelStride in the destination data. Deals with the 
  * complex case, where input is complex and output is complex.
  *
  * @param pSrcData the source data buffer
- * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
+ * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
  *                      of interest.
  * @param pDstData the destination buffer.
- * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
+ * @param nDstPixelStride the stride in the buffer pDstData for pixels of
  *                      interest.
  * @param nWordCount the total number of pixel words to copy
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelOffset,
-                                  Tout* const pDstData, int nDstPixelOffset,
+inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelStride,
+                                  Tout* const pDstData, int nDstPixelStride,
                                   int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
@@ -903,13 +916,13 @@ inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelOffset
 
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin* const pPixelIn = reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelOffset);
+        const Tin* const pPixelIn = reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
         CopyWord(pPixelIn[0], pPixelOut[0]);
         CopyWord(pPixelIn[1], pPixelOut[1]);
 
-        nDstOffset += nDstPixelOffset;
+        nDstOffset += nDstPixelStride;
     }
 }
 
@@ -918,22 +931,22 @@ inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelOffset
 /************************************************************************/
 /**
  * Template function, used to copy data from pSrcData into buffer
- * pDstData, with stride nSrcPixelOffset in the source data and
- * stride nDstPixelOffset in the destination data. Deals with the 
+ * pDstData, with stride nSrcPixelStride in the source data and
+ * stride nDstPixelStride in the destination data. Deals with the 
  * case where the value is real coming in, but complex going out.
  *
  * @param pSrcData the source data buffer
- * @param nSrcPixelOffset the stride, in the buffer pSrcData for pixels
+ * @param nSrcPixelStride the stride, in the buffer pSrcData for pixels
  *                      of interest, in bytes.
  * @param pDstData the destination buffer.
- * @param nDstPixelOffset the stride in the buffer pDstData for pixels of
+ * @param nDstPixelStride the stride in the buffer pDstData for pixels of
  *                      interest, in bytes.
  * @param nWordCount the total number of pixel words to copy
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelOffset,
-                                     Tout* const pDstData, int nDstPixelOffset,
+inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelStride,
+                                     Tout* const pDstData, int nDstPixelStride,
                                      int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
@@ -945,13 +958,13 @@ inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelOff
 
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin tValue = *reinterpret_cast<const Tin* const>(pSrcDataPtr + n * nSrcPixelOffset);
+        const Tin tValue = *reinterpret_cast<const Tin* const>(pSrcDataPtr + n * nSrcPixelStride);
         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
         CopyWord(tValue, *pPixelOut);
 
         pPixelOut[1] = tOutZero;
 
-        nDstOffset += nDstPixelOffset;
+        nDstOffset += nDstPixelStride;
     }
 }
 
@@ -964,108 +977,108 @@ inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelOff
  * never call this function directly (call GDALCopyWords instead).
  *
  * @param pSrcData source data buffer
- * @param nSrcPixelOffset pixel stride in input buffer, in pixel words
+ * @param nSrcPixelStride pixel stride in input buffer, in pixel words
  * @param bInComplex input is complex
  * @param pDstData destination data buffer
  * @param eDstType destination data type
- * @param nDstPixelOffset pixel stride in output buffer, in pixel words
+ * @param nDstPixelStride pixel stride in output buffer, in pixel words
  * @param nWordCount number of pixel words to be copied
  */
 template <class T>
-inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelOffset, bool bInComplex,
-                               void *pDstData, GDALDataType eDstType, int nDstPixelOffset,
+inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelStride, bool bInComplex,
+                               void *pDstData, GDALDataType eDstType, int nDstPixelStride,
                                int nWordCount)
 {
     switch (eDstType)
     {
     case GDT_Byte:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<unsigned char*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<unsigned char*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_UInt16:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<unsigned short*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<unsigned short*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_Int16:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<short*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<short*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_UInt32:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<unsigned int*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<unsigned int*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_Int32:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<int*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<int*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_Float32:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<float*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<float*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_Float64:
-        GDALCopyWordsT(pSrcData, nSrcPixelOffset,
-                       static_cast<double*>(pDstData), nDstPixelOffset,
+        GDALCopyWordsT(pSrcData, nSrcPixelStride,
+                       static_cast<double*>(pDstData), nDstPixelStride,
                        nWordCount);
         break;
     case GDT_CInt16:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
-                                  static_cast<short *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
+                                  static_cast<short *>(pDstData), nDstPixelStride,
                                   nWordCount);
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
-                                     static_cast<short *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
+                                     static_cast<short *>(pDstData), nDstPixelStride,
                                      nWordCount);
         }
         break;
     case GDT_CInt32:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
-                                  static_cast<int *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
+                                  static_cast<int *>(pDstData), nDstPixelStride,
                                   nWordCount);
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
-                                     static_cast<int *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
+                                     static_cast<int *>(pDstData), nDstPixelStride,
                                      nWordCount);
         }
         break;
     case GDT_CFloat32:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
-                                  static_cast<float *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
+                                  static_cast<float *>(pDstData), nDstPixelStride,
                                   nWordCount);
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
-                                     static_cast<float *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
+                                     static_cast<float *>(pDstData), nDstPixelStride,
                                      nWordCount);
         }
         break;
     case GDT_CFloat64:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelOffset,
-                                  static_cast<double *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
+                                  static_cast<double *>(pDstData), nDstPixelStride,
                                   nWordCount);
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelOffset,
-                                     static_cast<double *>(pDstData), nDstPixelOffset,
+            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
+                                     static_cast<double *>(pDstData), nDstPixelStride,
                                      nWordCount);
         }
         break;
@@ -1083,7 +1096,7 @@ inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelOffset, boo
 /************************************************************************/
 
 void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
-                       void *pDstData, GDALDataType eDstType, int nDstPixelOffset,
+                       void *pDstData, GDALDataType eDstType, int nDstPixelStride,
                        int nWordCount)
 {
 /* ----------------------------------------------------------------------- */
@@ -1094,19 +1107,19 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
     /* Let the general translation case do the necessary conversions */
     /* on the first destination element */
     GDALCopyWords(pSrcData, eSrcType, 0,
-                  pDstData, eDstType, nDstPixelOffset,
+                  pDstData, eDstType, nDstPixelStride,
                   1 );
 
     /* Now copy the first element to the nWordCount - 1 following destination */
     /* elements */
     nWordCount--;
-    GByte *pabyDstWord = ((GByte *)pDstData) + nDstPixelOffset;
+    GByte *pabyDstWord = ((GByte *)pDstData) + nDstPixelStride;
 
     switch (eDstType)
     {
         case GDT_Byte:
         {
-            if (nDstPixelOffset == 1)
+            if (nDstPixelStride == 1)
             {
                 if (nWordCount > 0)
                     memset(pabyDstWord, *(GByte*)pDstData, nWordCount);
@@ -1117,7 +1130,7 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
                 while(nWordCount--)
                 {
                     *pabyDstWord = valSet;
-                    pabyDstWord += nDstPixelOffset;
+                    pabyDstWord += nDstPixelStride;
                 }
             }
             break;
@@ -1130,7 +1143,7 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
             while(nWordCount--) \
             { \
                 *(c_type*)pabyDstWord = valSet; \
-                pabyDstWord += nDstPixelOffset; \
+                pabyDstWord += nDstPixelStride; \
             } \
             break; \
         }
@@ -1151,7 +1164,7 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
             { \
                 ((c_type*)pabyDstWord)[0] = valSet1; \
                 ((c_type*)pabyDstWord)[1] = valSet2; \
-                pabyDstWord += nDstPixelOffset; \
+                pabyDstWord += nDstPixelStride; \
             } \
             break; \
         }
@@ -1191,10 +1204,10 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
  *
  * @param pSrcData Pointer to source data to be converted.
  * @param eSrcType the source data type (see GDALDataType enum)
- * @param nSrcPixelOffset Source pixel offset, in bytes
+ * @param nSrcPixelStride Source pixel stride (i.e. distance between 2 words), in bytes
  * @param pDstData Pointer to buffer where destination data should go
  * @param eDstType the destination data type (see GDALDataType enum)
- * @param nDstPixelOffset Destination pixel offset, in bytes
+ * @param nDstPixelStride Destination pixel stride (i.e. distance between 2 words), in bytes
  * @param nWordCount number of words to be copied
  *
  * 
@@ -1212,16 +1225,16 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
  */
 
 void CPL_STDCALL
-GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
-               void * pDstData, GDALDataType eDstType, int nDstPixelOffset,
+GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
+               void * pDstData, GDALDataType eDstType, int nDstPixelStride,
                int nWordCount )
 
 {
     // Deal with the case where we're replicating a single word into the
     // provided buffer
-    if (nSrcPixelOffset == 0 && nWordCount > 1)
+    if (nSrcPixelStride == 0 && nWordCount > 1)
     {
-        GDALReplicateWord(pSrcData, eSrcType, pDstData, eDstType, nDstPixelOffset, nWordCount);
+        GDALReplicateWord(pSrcData, eSrcType, pDstData, eDstType, nDstPixelStride, nWordCount);
         return;
     }
 
@@ -1230,8 +1243,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
     int nSrcDataTypeSize = GDALGetDataTypeSize(eSrcType) / 8;
     // Let memcpy() handle the case where we're copying a packed buffer
     // of pixels.
-    if (eSrcType == eDstType && nSrcPixelOffset == nDstPixelOffset &&
-        nSrcPixelOffset == nSrcDataTypeSize)
+    if (eSrcType == eDstType && nSrcPixelStride == nDstPixelStride &&
+        nSrcPixelStride == nSrcDataTypeSize)
     {
         memcpy(pDstData, pSrcData, nWordCount * nSrcDataTypeSize);
         return;
@@ -1242,58 +1255,58 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
     switch (eSrcType)
     {
     case GDT_Byte:
-        GDALCopyWordsFromT<unsigned char>(static_cast<unsigned char *>(pSrcData), nSrcPixelOffset, false,
-                                 pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<unsigned char>(static_cast<unsigned char *>(pSrcData), nSrcPixelStride, false,
+                                 pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_UInt16:
-        GDALCopyWordsFromT<unsigned short>(static_cast<unsigned short *>(pSrcData), nSrcPixelOffset, false,
-                                           pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<unsigned short>(static_cast<unsigned short *>(pSrcData), nSrcPixelStride, false,
+                                           pDstData, eDstType, nDstPixelStride,
                                            nWordCount);
         break;
     case GDT_Int16:
-        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelOffset, false,
-                                  pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelStride, false,
+                                  pDstData, eDstType, nDstPixelStride,
                                   nWordCount);
         break;
     case GDT_UInt32:
-        GDALCopyWordsFromT<unsigned int>(static_cast<unsigned int *>(pSrcData), nSrcPixelOffset, false,
-                                         pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<unsigned int>(static_cast<unsigned int *>(pSrcData), nSrcPixelStride, false,
+                                         pDstData, eDstType, nDstPixelStride,
                                          nWordCount);
         break;
     case GDT_Int32:
-        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelOffset, false,
-                                pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelStride, false,
+                                pDstData, eDstType, nDstPixelStride,
                                 nWordCount);
         break;
     case GDT_Float32:
-        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelOffset, false,
-                                  pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelStride, false,
+                                  pDstData, eDstType, nDstPixelStride,
                                   nWordCount);
         break;
     case GDT_Float64:
-        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelOffset, false,
-                                   pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelStride, false,
+                                   pDstData, eDstType, nDstPixelStride,
                                    nWordCount);
         break;
     case GDT_CInt16:
-        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelOffset, true,
-                                 pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelStride, true,
+                                 pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CInt32:
-        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelOffset, true,
-                                 pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelStride, true,
+                                 pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CFloat32:
-        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelOffset, true,
-                                 pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelStride, true,
+                                 pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CFloat64:
-        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelOffset, true,
-                                 pDstData, eDstType, nDstPixelOffset,
+        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelStride, true,
+                                 pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_Unknown:
@@ -1311,9 +1324,9 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
         int     i;
 
         // contiguous blocks.
-        if( nWordSize == nSrcPixelOffset && nWordSize == nDstPixelOffset )
+        if( nWordSize == nSrcPixelStride && nWordSize == nDstPixelStride )
         {
-            memcpy( pDstData, pSrcData, nSrcPixelOffset * nWordCount );
+            memcpy( pDstData, pSrcData, nSrcPixelStride * nWordCount );
             return;
         }
 
@@ -1330,53 +1343,53 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
 /*     typical source and destination pixel spacing : we unroll the     */
 /*     loop.                                                            */
 /* ==================================================================== */
-#define ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, _k) \
-                 pabyDst[_nDstPixelOffset * _k] = pabySrc[_nSrcPixelOffset * _k]
-#define ASSIGN_LOOP(_nSrcPixelOffset, _nDstPixelOffset) \
+#define ASSIGN(_nSrcPixelStride, _nDstPixelStride, _k) \
+                 pabyDst[_nDstPixelStride * _k] = pabySrc[_nSrcPixelStride * _k]
+#define ASSIGN_LOOP(_nSrcPixelStride, _nDstPixelStride) \
                 for( i = nWordCount / 16 ; i != 0; i-- ) \
                 { \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 0); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 1); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 2); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 3); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 4); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 5); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 6); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 7); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 8); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 9); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 10); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 11); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 12); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 13); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 14); \
-                    ASSIGN(_nSrcPixelOffset, _nDstPixelOffset, 15); \
-                    pabyDst += _nDstPixelOffset * 16; \
-                    pabySrc += _nSrcPixelOffset * 16; \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 0); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 1); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 2); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 3); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 4); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 5); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 6); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 7); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 8); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 9); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 10); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 11); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 12); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 13); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 14); \
+                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 15); \
+                    pabyDst += _nDstPixelStride * 16; \
+                    pabySrc += _nSrcPixelStride * 16; \
                 } \
                 nWordCount = nWordCount % 16;
 
-                if (nSrcPixelOffset == 3 && nDstPixelOffset == 1)
+                if (nSrcPixelStride == 3 && nDstPixelStride == 1)
                 {
                     ASSIGN_LOOP(3, 1)
                 }
-                else if (nSrcPixelOffset == 1 && nDstPixelOffset == 3)
+                else if (nSrcPixelStride == 1 && nDstPixelStride == 3)
                 {
                     ASSIGN_LOOP(1, 3)
                 }
-                else if (nSrcPixelOffset == 4 && nDstPixelOffset == 1)
+                else if (nSrcPixelStride == 4 && nDstPixelStride == 1)
                 {
                     ASSIGN_LOOP(4, 1)
                 }
-                else if (nSrcPixelOffset == 1 && nDstPixelOffset == 4)
+                else if (nSrcPixelStride == 1 && nDstPixelStride == 4)
                 {
                     ASSIGN_LOOP(1, 4)
                 }
-                else if (nSrcPixelOffset == 3 && nDstPixelOffset == 4)
+                else if (nSrcPixelStride == 3 && nDstPixelStride == 4)
                 {
                     ASSIGN_LOOP(3, 4)
                 }
-                else if (nSrcPixelOffset == 4 && nDstPixelOffset == 3)
+                else if (nSrcPixelStride == 4 && nDstPixelStride == 3)
                 {
                     ASSIGN_LOOP(4, 3)
                 }
@@ -1385,8 +1398,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
             for( i = nWordCount; i != 0; i-- )
             {
                 *pabyDst = *pabySrc;
-                pabyDst += nDstPixelOffset;
-                pabySrc += nSrcPixelOffset;
+                pabyDst += nDstPixelStride;
+                pabySrc += nSrcPixelStride;
             }
         }
         else if (nWordSize == 2)
@@ -1394,8 +1407,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
             for( i = nWordCount; i != 0; i-- )
             {
                 *(short*)pabyDst = *(short*)pabySrc;
-                pabyDst += nDstPixelOffset;
-                pabySrc += nSrcPixelOffset;
+                pabyDst += nDstPixelStride;
+                pabySrc += nSrcPixelStride;
             }
         }
         else if (nWordSize == 4)
@@ -1403,8 +1416,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
             for( i = nWordCount; i != 0; i-- )
             {
                 *(int*)pabyDst = *(int*)pabySrc;
-                pabyDst += nDstPixelOffset;
-                pabySrc += nSrcPixelOffset;
+                pabyDst += nDstPixelStride;
+                pabySrc += nSrcPixelStride;
             }
         }
         else if (nWordSize == 8)
@@ -1413,8 +1426,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
             {
                 ((int*)pabyDst)[0] = ((int*)pabySrc)[0];
                 ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
-                pabyDst += nDstPixelOffset;
-                pabySrc += nSrcPixelOffset;
+                pabyDst += nDstPixelStride;
+                pabySrc += nSrcPixelStride;
             }
         }
         else if (nWordSize == 16)
@@ -1425,8 +1438,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
                 ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
                 ((int*)pabyDst)[2] = ((int*)pabySrc)[2];
                 ((int*)pabyDst)[3] = ((int*)pabySrc)[3];
-                pabyDst += nDstPixelOffset;
-                pabySrc += nSrcPixelOffset;
+                pabyDst += nDstPixelStride;
+                pabySrc += nSrcPixelStride;
             }
         }
         else
@@ -1445,8 +1458,8 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
         void   *pSrcWord, *pDstWord;
         double  dfPixelValue=0.0, dfPixelValueI=0.0;
 
-        pSrcWord = static_cast<GByte *>(pSrcData) + iWord * nSrcPixelOffset;
-        pDstWord = static_cast<GByte *>(pDstData) + iWord * nDstPixelOffset;
+        pSrcWord = static_cast<GByte *>(pSrcData) + iWord * nSrcPixelStride;
+        pDstWord = static_cast<GByte *>(pDstData) + iWord * nDstPixelStride;
 
 /* -------------------------------------------------------------------- */
 /*      Fetch source value based on data type.                          */
@@ -2661,15 +2674,37 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
 
     int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
     int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
-    
+
+    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
+    if( bInterleave)
+        nPixelSize *= nBandCount;
+
+    // aim for one row of blocks.  Do not settle for less.
+    int nSwathCols  = nXSize;
+    int nSwathLines = nBlockYSize;
+
 /* -------------------------------------------------------------------- */
 /*      What will our swath size be?                                    */
 /* -------------------------------------------------------------------- */
     /* When writing interleaved data in a compressed format, we want to be sure */
     /* that each block will only be written once, so the swath size must not be */
     /* greater than the block cache. */
-    /* So as the default cache size is 40 MB, 10 MB is a safe value */
-    int nTargetSwathSize = atoi(CPLGetConfigOption("GDAL_SWATH_SIZE", "10000000"));
+    const char* pszSwathSize = CPLGetConfigOption("GDAL_SWATH_SIZE", NULL);
+    int nTargetSwathSize;
+    if( pszSwathSize != NULL )
+        nTargetSwathSize = atoi(pszSwathSize);
+    else
+    {
+        /* As a default, take one 1/4 of the cache size */
+        nTargetSwathSize = MIN(INT_MAX, GDALGetCacheMax64() / 4);
+
+        /* but if the minimum idal swath buf size is less, then go for it to */
+        /* avoid unnecessarily abusing RAM usage */
+        GIntBig nIdealSwathBufSize = (GIntBig)nSwathCols * nSwathLines * nPixelSize;
+        if( nTargetSwathSize > nIdealSwathBufSize )
+            nTargetSwathSize = nIdealSwathBufSize;
+    }
+
     if (nTargetSwathSize < 1000000)
         nTargetSwathSize = 1000000;
 
@@ -2678,17 +2713,9 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "When translating into a compressed interleave format, the block cache size (" CPL_FRMT_GIB ") "
-                 "should be at least the size of the swath (%d)", GDALGetCacheMax64(), nTargetSwathSize);
+                 "should be at least the size of the swath (%d) (GDAL_SWATH_SIZE config. option)", GDALGetCacheMax64(), nTargetSwathSize);
     }
 
-    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
-    if( bInterleave)
-        nPixelSize *= nBandCount;
-
-    // aim for one row of blocks.  Do not settle for less.
-    int nSwathCols  = nXSize;
-    int nSwathLines = nBlockYSize;
-
 #define IS_MULTIPLE_OF(x,y) ((y)%(x) == 0)
 #define ROUND_TO(x,y) (((x)/(y))*(y))
 
@@ -2734,7 +2761,7 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
 
         CPLDebug( "GDAL",
               "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
-              "since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
+              "since requirement (%d * %d bytes) exceed target swath size (%d bytes) (GDAL_SWATH_SIZE config. option)",
               nSwathLines, nBlockYSize, nMemoryPerCol, nTargetSwathSize);
     }
     // If we are processing single scans, try to handle several at once.
diff --git a/gdal.pc.in b/gdal.pc.in
new file mode 100644
index 0000000..7f61932
--- /dev/null
+++ b/gdal.pc.in
@@ -0,0 +1,11 @@
+prefix=${CONFIG_INST_PREFIX}
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${exec_prefix}/include
+datadir=${CONFIG_INST_DATA}
+ 
+Name: libgdal
+Description: Geospatial Data Abstraction Library
+Version: ${CONFIG_VERSION}
+Libs: ${CONFIG_INST_LIBS}
+Cflags: ${CONFIG_INST_CFLAGS}
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index 0abeb55..1daa09c 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: acinclude.m4 24948 2012-09-22 10:52:03Z rouault $
+dnl $Id: acinclude.m4 26534 2013-10-16 12:10:05Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure extra local definitions.
@@ -432,6 +432,36 @@ AC_DEFUN([AC_LD_SHARED],
   AC_SUBST(SO_EXT,$SO_EXT)
 ])
 
+# --------------------------------------------------------
+dnl AC_CHECK_FW_FUNC(FRAMEWORK-BASENAME, FUNCTION,
+dnl              [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],
+dnl              [OTHER-LIBRARIES])
+dnl ------------------------------------------------------
+dnl
+dnl Duplicate of AC_CHECK_LIB, with small edit to handle -framework $1, i.e.:
+dnl   "-framework JavaVM" instead of "-ljvm"
+dnl See autoconf-src/lib/autoconf/libs.m4 for more information
+
+AC_DEFUN([AC_CHECK_FW_FUNC],
+[m4_ifval([$3], , [AH_CHECK_LIB([$1])])dnl
+AS_LITERAL_WORD_IF([$1],
+	      [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2])],
+	      [AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1''_$2])])dnl
+AC_CACHE_CHECK([for $2 in -framework $1], [ac_Lib],
+[ac_check_fw_func_save_LIBS=$LIBS
+LIBS="-framework $1 $5 $LIBS"
+AC_LINK_IFELSE([AC_LANG_CALL([], [$2])],
+	       [AS_VAR_SET([ac_Lib], [yes])],
+	       [AS_VAR_SET([ac_Lib], [no])])
+LIBS=$ac_check_fw_func_save_LIBS])
+AS_VAR_IF([ac_Lib], [yes],
+      [m4_default([$3], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1))
+  LIBS="-framework $1 $LIBS"
+])],
+      [$4])
+AS_VAR_POPDEF([ac_Lib])dnl
+])# AC_CHECK_FW_FUNC
+
 dnl ---------------------------------------------------------------------------
 dnl Message output
 dnl ---------------------------------------------------------------------------
diff --git a/makegdal10.sln b/makegdal10.sln
deleted file mode 100644
index b777ff4..0000000
--- a/makegdal10.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual Studio 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makegdal", "makegdal10.vcxproj", "{769DD10E-E284-46BE-9172-A35184250A3A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Release|Win32 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug|Win32.Build.0 = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release|Win32.ActiveCfg = Release|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release|Win32.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/makegdal10.vcxproj b/makegdal10.vcxproj
deleted file mode 100644
index e9008a6..0000000
--- a/makegdal10.vcxproj
+++ /dev/null
@@ -1,1595 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectName>makegdal</ProjectName>
-    <ProjectGuid>{769DD10E-E284-46BE-9172-A35184250A3A}</ProjectGuid>
-    <Keyword>MakeFileProj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.21006.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 install</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 clean && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 install</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 clean</NMakeCleanCommandLine>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">gdal17.dll</NMakeOutput>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 && nmake -f makefile.vc MSVC_VER=1500 install</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 clean && nmake -f makefile.vc MSVC_VER=1500 && nmake -f makefile.vc MSVC_VER=1500 install</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 clean</NMakeCleanCommandLine>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">gdal17.dll</NMakeOutput>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <None Include="makefile.vc" />
-    <None Include="nmake-wince.opt" />
-    <None Include="nmake.opt" />
-    <None Include="alg\makefile.vc" />
-    <None Include="apps\makefile.vc" />
-    <None Include="frmts\makefile.vc" />
-    <None Include="frmts\aaigrid\makefile.vc" />
-    <None Include="frmts\adrg\makefile.vc" />
-    <None Include="frmts\aigrid\makefile.vc" />
-    <None Include="frmts\airsar\makefile.vc" />
-    <None Include="frmts\blx\makefile.vc" />
-    <None Include="frmts\bmp\makefile.vc" />
-    <None Include="frmts\bsb\makefile.vc" />
-    <None Include="frmts\ceos\makefile.vc" />
-    <None Include="frmts\ceos2\makefile.vc" />
-    <None Include="frmts\coasp\makefile.vc" />
-    <None Include="frmts\cosar\makefile.vc" />
-    <None Include="frmts\dimap\makefile.vc" />
-    <None Include="frmts\dods\makefile.vc" />
-    <None Include="frmts\dted\makefile.vc" />
-    <None Include="frmts\ecw\makefile.vc" />
-    <None Include="frmts\elas\makefile.vc" />
-    <None Include="frmts\envisat\makefile.vc" />
-    <None Include="frmts\epsilon\makefile.vc" />
-    <None Include="frmts\ers\makefile.vc" />
-    <None Include="frmts\fit\makefile.vc" />
-    <None Include="frmts\fits\makefile.vc" />
-    <None Include="frmts\georaster\makefile.vc" />
-    <None Include="frmts\gff\makefile.vc" />
-    <None Include="frmts\gif\makefile.vc" />
-    <None Include="frmts\gif\giflib\makefile.vc" />
-    <None Include="frmts\grib\makefile.vc" />
-    <None Include="frmts\grib\degrib18\makefile.vc" />
-    <None Include="frmts\grib\degrib18\degrib\makefile.vc" />
-    <None Include="frmts\grib\degrib18\g2clib-1.0.4\makefile.vc" />
-    <None Include="frmts\gsg\makefile.vc" />
-    <None Include="frmts\gtiff\makefile.vc" />
-    <None Include="frmts\gtiff\libgeotiff\makefile.vc" />
-    <None Include="frmts\gtiff\libtiff\makefile.vc" />
-    <None Include="frmts\gxf\makefile.vc" />
-    <None Include="frmts\hdf4\makefile.vc" />
-    <None Include="frmts\hdf4\hdf-eos\makefile.vc" />
-    <None Include="frmts\hdf5\makefile.vc" />
-    <None Include="frmts\hfa\makefile.vc" />
-    <None Include="frmts\idrisi\makefile.vc" />
-    <None Include="frmts\ilwis\makefile.vc" />
-    <None Include="frmts\ingr\makefile.vc" />
-    <None Include="frmts\iso8211\makefile.vc" />
-    <None Include="frmts\jaxapalsar\makefile.vc" />
-    <None Include="frmts\jdem\makefile.vc" />
-    <None Include="frmts\jp2kak\makefile.vc" />
-    <None Include="frmts\jpeg\makefile.vc" />
-    <None Include="frmts\jpeg\libjpeg\makefile.vc" />
-    <None Include="frmts\jpeg\libjpeg12\makefile.vc" />
-    <None Include="frmts\jpeg2000\makefile.vc" />
-    <None Include="frmts\l1b\makefile.vc" />
-    <None Include="frmts\leveller\makefile.vc" />
-    <None Include="frmts\mem\makefile.vc" />
-    <None Include="frmts\mrsid\makefile.vc" />
-    <None Include="frmts\msg\makefile.vc" />
-    <None Include="frmts\msgn\makefile.vc" />
-    <None Include="frmts\netcdf\makefile.vc" />
-    <None Include="frmts\nitf\makefile.vc" />
-    <None Include="frmts\northwood\makefile.vc" />
-    <None Include="frmts\ogdi\makefile.vc" />
-    <None Include="frmts\pcidsk\makefile.vc" />
-    <None Include="frmts\pcidsk\sdk\Makefile.vc" />
-    <None Include="frmts\pcraster\makefile.vc" />
-    <None Include="frmts\pcraster\libcsf\makefile.vc" />
-    <None Include="frmts\pds\makefile.vc" />
-    <None Include="frmts\pgchip\makefile.vc" />
-    <None Include="frmts\png\makefile.vc" />
-    <None Include="frmts\png\libpng\makefile.vc" />
-    <None Include="frmts\r\makefile.vc" />
-    <None Include="frmts\rasterlite\makefile.vc" />
-    <None Include="frmts\raw\makefile.vc" />
-    <None Include="frmts\rik\makefile.vc" />
-    <None Include="frmts\rmf\makefile.vc" />
-    <None Include="frmts\rs2\makefile.vc" />
-    <None Include="frmts\saga\makefile.vc" />
-    <None Include="frmts\sde\makefile.vc" />
-    <None Include="frmts\sdts\makefile.vc" />
-    <None Include="frmts\sgi\makefile.vc" />
-    <None Include="frmts\srtmhgt\makefile.vc" />
-    <None Include="frmts\terragen\makefile.vc" />
-    <None Include="frmts\terralib\makefile.vc" />
-    <None Include="frmts\til\makefile.vc" />
-    <None Include="frmts\tsx\makefile.vc" />
-    <None Include="frmts\usgsdem\makefile.vc" />
-    <None Include="frmts\vrt\makefile.vc" />
-    <None Include="frmts\wcs\makefile.vc" />
-    <None Include="frmts\wktraster\makefile.vc" />
-    <None Include="frmts\wms\makefile.vc" />
-    <None Include="frmts\xpm\makefile.vc" />
-    <None Include="frmts\zlib\makefile.vc" />
-    <None Include="gcore\makefile.vc" />
-    <None Include="ogr\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\avc\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\bna\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\csv\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\dgn\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\dgn\dist\Makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\dods\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\dxf\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\fme\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\generic\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\geoconcept\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\geojson\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\geojson\jsonc\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\georss\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\gml\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\gmt\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\gpx\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\gtm\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\idb\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\ili\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\ili\iom\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\kml\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\mem\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\mitab\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\mysql\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\ntf\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\oci\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\odbc\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\ogdi\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\pcidsk\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\pg\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\pgeo\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\rec\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\s57\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\sde\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\sdts\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\shape\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\sqlite\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\tiger\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\vrt\makefile.vc" />
-    <None Include="ogr\ogrsf_frmts\xplane\makefile.vc" />
-    <None Include="ogr\wcts\makefile.vc" />
-    <None Include="port\cpl_config.h.vc" />
-    <None Include="port\makefile.vc" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="alg\gdalgrid.h" />
-    <ClInclude Include="alg\gdalwarper.h" />
-    <ClInclude Include="alg\gdal_alg.h" />
-    <ClInclude Include="alg\gdal_alg_priv.h" />
-    <ClInclude Include="alg\gvgcpfit.h" />
-    <ClInclude Include="alg\thinplatespline.h" />
-    <ClInclude Include="bridge\gdalbridge.h" />
-    <ClInclude Include="frmts\aigrid\aigrid.h" />
-    <ClInclude Include="frmts\blx\blx.h" />
-    <ClInclude Include="frmts\bsb\bsb_read.h" />
-    <ClInclude Include="frmts\ceos\ceosopen.h" />
-    <ClInclude Include="frmts\ceos2\ceos.h" />
-    <ClInclude Include="frmts\dted\dted_api.h" />
-    <ClInclude Include="frmts\ecw\jp2userbox.h" />
-    <ClInclude Include="frmts\ecw\vsiiostream.h" />
-    <ClInclude Include="frmts\envisat\EnvisatFile.h" />
-    <ClInclude Include="frmts\ers\ershdrnode.h" />
-    <ClInclude Include="frmts\fit\fit.h" />
-    <ClInclude Include="frmts\fit\gstEndian.h" />
-    <ClInclude Include="frmts\fit\gstTypes.h" />
-    <ClInclude Include="frmts\georaster\georaster_priv.h" />
-    <ClInclude Include="frmts\georaster\oci_wrapper.h" />
-    <ClInclude Include="frmts\gif\giflib\gif_hash.h" />
-    <ClInclude Include="frmts\gif\giflib\gif_lib.h" />
-    <ClInclude Include="frmts\gif\giflib\gif_lib_private.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\clock.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\datasource.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\degrib1.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\degrib2.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\engribapi.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\filedatasource.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\fileendian.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\grib2api.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\inventory.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\memendian.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\memorydatasource.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\meta.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\metaname.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\myassert.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\myerror.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\myutil.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\scan.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\tdlpack.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\type.h" />
-    <ClInclude Include="frmts\grib\degrib18\degrib\weather.h" />
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\drstemplates.h" />
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\grib2.h" />
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.h" />
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.h" />
-    <ClInclude Include="frmts\gtiff\gt_overview.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\cpl_serv.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geokeys.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geonames.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geotiff.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geotiffio.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geovalues.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_config.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_keyp.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_normalize.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_simpletags.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_tiffp.h" />
-    <ClInclude Include="frmts\gtiff\libgeotiff\xtiffio.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\t4.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tiff.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tiffconf.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tiffio.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tiffiop.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tiffvers.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tif_config.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tif_dir.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tif_fax3.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\tif_predict.h" />
-    <ClInclude Include="frmts\gtiff\libtiff\uvcode.h" />
-    <ClInclude Include="frmts\gxf\gxfopen.h" />
-    <ClInclude Include="frmts\hdf4\hdf4compat.h" />
-    <ClInclude Include="frmts\hdf4\hdf4dataset.h" />
-    <ClInclude Include="frmts\hdf4\hdf-eos\ease.h" />
-    <ClInclude Include="frmts\hdf4\hdf-eos\HdfEosDef.h" />
-    <ClInclude Include="frmts\hdf4\hdf-eos\HDFEOSVersion.h" />
-    <ClInclude Include="frmts\hdf5\gh5_convenience.h" />
-    <ClInclude Include="frmts\hdf5\hdf5dataset.h" />
-    <ClInclude Include="frmts\hfa\hfa.h" />
-    <ClInclude Include="frmts\hfa\hfa_p.h" />
-    <ClInclude Include="frmts\ilwis\ilwisdataset.h" />
-    <ClInclude Include="frmts\ingr\IngrTypes.h" />
-    <ClInclude Include="frmts\ingr\IntergraphBand.h" />
-    <ClInclude Include="frmts\ingr\IntergraphDataset.h" />
-    <ClInclude Include="frmts\ingr\JpegHelper.h" />
-    <ClInclude Include="frmts\iso8211\iso8211.h" />
-    <ClInclude Include="frmts\jp2kak\subfile_source.h" />
-    <ClInclude Include="frmts\jp2kak\vsil_target.h" />
-    <ClInclude Include="frmts\jpeg\gdalexif.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jchuff.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jconfig.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jdct.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jdhuff.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jerror.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jinclude.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jmemsys.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jmorecfg.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jpegint.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jpeglib.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg\jversion.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jchuff.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jconfig.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jdct.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jdhuff.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jerror.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jinclude.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jmemsys.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jmorecfg.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jpegint.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jpeglib.h" />
-    <ClInclude Include="frmts\jpeg\libjpeg12\jversion.h" />
-    <ClInclude Include="frmts\jpeg2000\jpeg2000_vsil_io.h" />
-    <ClInclude Include="frmts\mem\memdataset.h" />
-    <ClInclude Include="frmts\mrsid\mrsidstream.h" />
-    <ClInclude Include="frmts\msg\msgcommand.h" />
-    <ClInclude Include="frmts\msg\msgdataset.h" />
-    <ClInclude Include="frmts\msg\prologue.h" />
-    <ClInclude Include="frmts\msg\reflectancecalculator.h" />
-    <ClInclude Include="frmts\msg\xritheaderparser.h" />
-    <ClInclude Include="frmts\msgn\msg_basic_types.h" />
-    <ClInclude Include="frmts\msgn\msg_reader_core.h" />
-    <ClInclude Include="frmts\netcdf\netcdfdataset.h" />
-    <ClInclude Include="frmts\nitf\mgrs.h" />
-    <ClInclude Include="frmts\nitf\nitflib.h" />
-    <ClInclude Include="frmts\nitf\rpftoclib.h" />
-    <ClInclude Include="frmts\northwood\northwood.h" />
-    <ClInclude Include="frmts\pcidsk\gdal_pcidsk.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_buffer.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_channel.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_config.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_exception.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_file.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_georef.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_interfaces.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_io.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_mutex.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_pct.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_segment.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_shape.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_types.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_vectorsegment.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cbandinterleavedchannel.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cpcidskchannel.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\channel\ctiledchannel.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\cpcidskfile.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\metadataset.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\mutexholder.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\pcidsk_utils.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\protectedfile.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\core\sysvirtualfile.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskgeoref.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskpct.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidsksegment.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\metadatasegment.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\pcidskgeorefbuilder.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\segmentfactory.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\sysblockmap.h" />
-    <ClInclude Include="frmts\pcidsk\sdk\segment\uuid.h" />
-    <ClInclude Include="frmts\pcraster\pcrasterdataset.h" />
-    <ClInclude Include="frmts\pcraster\pcrasterrasterband.h" />
-    <ClInclude Include="frmts\pcraster\pcrasterutil.h" />
-    <ClInclude Include="frmts\pcraster\libcsf\csf.h" />
-    <ClInclude Include="frmts\pcraster\libcsf\csfattr.h" />
-    <ClInclude Include="frmts\pcraster\libcsf\csfimpl.h" />
-    <ClInclude Include="frmts\pcraster\libcsf\csftypes.h" />
-    <ClInclude Include="frmts\pcraster\libcsf\pcrtypes.h" />
-    <ClInclude Include="frmts\pds\nasakeywordhandler.h" />
-    <ClInclude Include="frmts\pgchip\pgchip.h" />
-    <ClInclude Include="frmts\png\libpng\png.h" />
-    <ClInclude Include="frmts\png\libpng\pngconf.h" />
-    <ClInclude Include="frmts\rasterlite\rasterlitedataset.h" />
-    <ClInclude Include="frmts\raw\atlsci_spheroid.h" />
-    <ClInclude Include="frmts\raw\rawdataset.h" />
-    <ClInclude Include="frmts\rmf\rmfdataset.h" />
-    <ClInclude Include="frmts\sde\gdal_sde.h" />
-    <ClInclude Include="frmts\sde\sdedataset.h" />
-    <ClInclude Include="frmts\sde\sdeerror.h" />
-    <ClInclude Include="frmts\sde\sderasterband.h" />
-    <ClInclude Include="frmts\sdts\sdts_al.h" />
-    <ClInclude Include="frmts\terralib\TerraLibDataset.h" />
-    <ClInclude Include="frmts\terralib\TerraLibRasterBand.h" />
-    <ClInclude Include="frmts\vrt\gdal_vrt.h" />
-    <ClInclude Include="frmts\vrt\vrtdataset.h" />
-    <ClInclude Include="frmts\wktraster\wktraster.h" />
-    <ClInclude Include="frmts\wms\gdalhttp.h" />
-    <ClInclude Include="frmts\wms\md5.h" />
-    <ClInclude Include="frmts\wms\minidriver_tileservice.h" />
-    <ClInclude Include="frmts\wms\minidriver_tms.h" />
-    <ClInclude Include="frmts\wms\minidriver_wms.h" />
-    <ClInclude Include="frmts\wms\minidriver_worldwind.h" />
-    <ClInclude Include="frmts\wms\stdinc.h" />
-    <ClInclude Include="frmts\wms\wmsdriver.h" />
-    <ClInclude Include="frmts\zlib\crc32.h" />
-    <ClInclude Include="frmts\zlib\deflate.h" />
-    <ClInclude Include="frmts\zlib\inffast.h" />
-    <ClInclude Include="frmts\zlib\inffixed.h" />
-    <ClInclude Include="frmts\zlib\inflate.h" />
-    <ClInclude Include="frmts\zlib\inftrees.h" />
-    <ClInclude Include="frmts\zlib\trees.h" />
-    <ClInclude Include="frmts\zlib\zconf.h" />
-    <ClInclude Include="frmts\zlib\zlib.h" />
-    <ClInclude Include="frmts\zlib\zutil.h" />
-    <ClInclude Include="gcore\gdal.h" />
-    <ClInclude Include="gcore\gdaljp2metadata.h" />
-    <ClInclude Include="gcore\gdal_frmts.h" />
-    <ClInclude Include="gcore\gdal_pam.h" />
-    <ClInclude Include="gcore\gdal_priv.h" />
-    <ClInclude Include="gcore\gdal_proxy.h" />
-    <ClInclude Include="gcore\gdal_rat.h" />
-    <ClInclude Include="gcore\gdal_version.h" />
-    <ClInclude Include="ogr\ogr_api.h" />
-    <ClInclude Include="ogr\ogr_core.h" />
-    <ClInclude Include="ogr\ogr_expat.h" />
-    <ClInclude Include="ogr\ogr_feature.h" />
-    <ClInclude Include="ogr\ogr_featurestyle.h" />
-    <ClInclude Include="ogr\ogr_geometry.h" />
-    <ClInclude Include="ogr\ogr_geos.h" />
-    <ClInclude Include="ogr\ogr_p.h" />
-    <ClInclude Include="ogr\ogr_spatialref.h" />
-    <ClInclude Include="ogr\ogr_srs_api.h" />
-    <ClInclude Include="ogr\ogr_srs_esri_names.h" />
-    <ClInclude Include="ogr\swq.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ogrsf_frmts.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ogr_attrind.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\avc\avc.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\avc\avc_mbyte.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\avc\dbfopen.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\avc\ogr_avc.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\bna\ogrbnaparser.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\bna\ogr_bna.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\csv\ogr_csv.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dgnlib.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dgnlibp.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\ogr_dgn.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dist\cpl_config.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dods\ogr_dods.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\dxf\ogr_dxf.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\fme\fme2ogr.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\generic\ogr_gensql.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\geoconcept.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonreader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonutils.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogr_geojson.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\arraylist.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\bits.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\config.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\debug.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_object.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_object_private.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_tokener.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_util.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\linkhash.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\printbuf.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\georss\ogr_georss.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gml\gmlreader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gml\gmlreaderp.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gml\ogr_gml.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gmt\ogr_gmt.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gpx\ogr_gpx.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\grass\ogrgrass.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gtm\gtm.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\gtm\ogr_gtm.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\idb\ogr_idb.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili1reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili1readerp.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili2reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili2readerp.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ilihelper.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iomhelper.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ogr_ili1.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ogr_ili2.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iom\iom.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iom\iom_p.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ingres\ogr_ingres.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kml.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlnode.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlutility.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlvector.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\kml\ogr_kml.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mem\ogr_mem.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_geometry.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_priv.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_utils.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\mysql\ogr_mysql.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ntf\ntf.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\oci\ogr_oci.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\odbc\ogr_odbc.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\ogdi\ogrogdi.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\pg\ogrpgutility.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\pg\ogr_pg.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\pgeo\ogr_pgeo.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\rec\ogr_rec.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\s57\ogr_s57.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\s57\s57.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\s57\s57tables.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\sde\ogr_sde.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\sdts\ogr_sdts.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\shape\ogrshape.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\shape\shapefil.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\sqlite\ogr_sqlite.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\tiger\ogr_tiger.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\vrt\ogr_vrt.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.h" />
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_reader.h" />
-    <ClInclude Include="port\cplkeywordparser.h" />
-    <ClInclude Include="port\cpl_atomic_ops.h" />
-    <ClInclude Include="port\cpl_config.h" />
-    <ClInclude Include="port\cpl_config_extras.h" />
-    <ClInclude Include="port\cpl_conv.h" />
-    <ClInclude Include="port\cpl_csv.h" />
-    <ClInclude Include="port\cpl_error.h" />
-    <ClInclude Include="port\cpl_hash_set.h" />
-    <ClInclude Include="port\cpl_http.h" />
-    <ClInclude Include="port\cpl_list.h" />
-    <ClInclude Include="port\cpl_minixml.h" />
-    <ClInclude Include="port\cpl_minizip_ioapi.h" />
-    <ClInclude Include="port\cpl_minizip_unzip.h" />
-    <ClInclude Include="port\cpl_multiproc.h" />
-    <ClInclude Include="port\cpl_odbc.h" />
-    <ClInclude Include="port\cpl_port.h" />
-    <ClInclude Include="port\cpl_quad_tree.h" />
-    <ClInclude Include="port\cpl_string.h" />
-    <ClInclude Include="port\cpl_time.h" />
-    <ClInclude Include="port\cpl_vsi.h" />
-    <ClInclude Include="port\cpl_vsi_virtual.h" />
-    <ClInclude Include="port\cpl_win32ce_api.h" />
-    <ClInclude Include="port\cpl_wince.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="alg\gdal_crs.c" />
-    <ClCompile Include="alg\gdal_nrgcrs.c" />
-    <ClCompile Include="alg\contour.cpp" />
-    <ClCompile Include="alg\gdalchecksum.cpp" />
-    <ClCompile Include="alg\gdalcutline.cpp" />
-    <ClCompile Include="alg\gdaldither.cpp" />
-    <ClCompile Include="alg\gdalgeoloc.cpp" />
-    <ClCompile Include="alg\gdalgrid.cpp" />
-    <ClCompile Include="alg\gdalmediancut.cpp" />
-    <ClCompile Include="alg\gdalproximity.cpp" />
-    <ClCompile Include="alg\gdalrasterize.cpp" />
-    <ClCompile Include="alg\gdalrasterpolygonenumerator.cpp" />
-    <ClCompile Include="alg\gdalsievefilter.cpp" />
-    <ClCompile Include="alg\gdalsimplewarp.cpp" />
-    <ClCompile Include="alg\gdaltransformer.cpp" />
-    <ClCompile Include="alg\gdalwarper.cpp" />
-    <ClCompile Include="alg\gdalwarpkernel.cpp" />
-    <ClCompile Include="alg\gdalwarpoperation.cpp" />
-    <ClCompile Include="alg\gdal_rpc.cpp" />
-    <ClCompile Include="alg\gdal_tps.cpp" />
-    <ClCompile Include="alg\llrasterize.cpp" />
-    <ClCompile Include="alg\polygonize.cpp" />
-    <ClCompile Include="alg\rasterfill.cpp" />
-    <ClCompile Include="alg\thinplatespline.cpp" />
-    <ClCompile Include="apps\gdal2ogr.c" />
-    <ClCompile Include="apps\gdalflattenmask.c" />
-    <ClCompile Include="apps\gdalinfo.c" />
-    <ClCompile Include="apps\gdaltindex.c" />
-    <ClCompile Include="apps\gdalwarpsimple.c" />
-    <ClCompile Include="apps\dumpoverviews.cpp" />
-    <ClCompile Include="apps\gdaladdo.cpp" />
-    <ClCompile Include="apps\gdalbuildvrt.cpp" />
-    <ClCompile Include="apps\gdaldem.cpp" />
-    <ClCompile Include="apps\gdalenhance.cpp" />
-    <ClCompile Include="apps\gdalmanage.cpp" />
-    <ClCompile Include="apps\gdaltorture.cpp" />
-    <ClCompile Include="apps\gdaltransform.cpp" />
-    <ClCompile Include="apps\gdalwarp.cpp" />
-    <ClCompile Include="apps\gdal_contour.cpp" />
-    <ClCompile Include="apps\gdal_grid.cpp" />
-    <ClCompile Include="apps\gdal_rasterize.cpp" />
-    <ClCompile Include="apps\gdal_translate.cpp" />
-    <ClCompile Include="apps\multireadtest.cpp" />
-    <ClCompile Include="apps\nearblack.cpp" />
-    <ClCompile Include="apps\ogr2ogr.cpp" />
-    <ClCompile Include="apps\ogrdissolve.cpp" />
-    <ClCompile Include="apps\ogrinfo.cpp" />
-    <ClCompile Include="apps\ogrtindex.cpp" />
-    <ClCompile Include="apps\testepsg.cpp" />
-    <ClCompile Include="apps\test_ogrsf.cpp" />
-    <ClCompile Include="bridge\bridge_test.cpp" />
-    <ClCompile Include="bridge\gbgetsymbol.cpp" />
-    <ClCompile Include="bridge\gdalbridge.cpp" />
-    <ClCompile Include="frmts\gdalallregister.cpp" />
-    <ClCompile Include="frmts\aaigrid\aaigriddataset.cpp" />
-    <ClCompile Include="frmts\adrg\adrgdataset.cpp" />
-    <ClCompile Include="frmts\adrg\srpdataset.cpp" />
-    <ClCompile Include="frmts\aigrid\aigccitt.c" />
-    <ClCompile Include="frmts\aigrid\aigopen.c" />
-    <ClCompile Include="frmts\aigrid\aitest.c" />
-    <ClCompile Include="frmts\aigrid\gridlib.c" />
-    <ClCompile Include="frmts\aigrid\aigdataset.cpp" />
-    <ClCompile Include="frmts\airsar\airsardataset.cpp" />
-    <ClCompile Include="frmts\blx\blx.c" />
-    <ClCompile Include="frmts\blx\blxdataset.cpp" />
-    <ClCompile Include="frmts\bmp\bmpdataset.cpp" />
-    <ClCompile Include="frmts\bsb\bsb2raw.c" />
-    <ClCompile Include="frmts\bsb\bsb_read.c" />
-    <ClCompile Include="frmts\bsb\bsbdataset.cpp" />
-    <ClCompile Include="frmts\ceos\ceosopen.c" />
-    <ClCompile Include="frmts\ceos\ceostest.c" />
-    <ClCompile Include="frmts\ceos\ceosdataset.cpp" />
-    <ClCompile Include="frmts\ceos2\ceos.c" />
-    <ClCompile Include="frmts\ceos2\ceosrecipe.c" />
-    <ClCompile Include="frmts\ceos2\ceossar.c" />
-    <ClCompile Include="frmts\ceos2\link.c" />
-    <ClCompile Include="frmts\ceos2\sar_ceosdataset.cpp" />
-    <ClCompile Include="frmts\coasp\coasp_dataset.cpp" />
-    <ClCompile Include="frmts\cosar\cosar_dataset.cpp" />
-    <ClCompile Include="frmts\dimap\dimapdataset.cpp" />
-    <ClCompile Include="frmts\dods\dodsdataset2.cpp" />
-    <ClCompile Include="frmts\dted\dted_api.c" />
-    <ClCompile Include="frmts\dted\dted_create.c" />
-    <ClCompile Include="frmts\dted\dted_ptstream.c" />
-    <ClCompile Include="frmts\dted\dted_test.c" />
-    <ClCompile Include="frmts\dted\dteddataset.cpp" />
-    <ClCompile Include="frmts\ecw\ecwcreatecopy.cpp" />
-    <ClCompile Include="frmts\ecw\ecwdataset.cpp" />
-    <ClCompile Include="frmts\ecw\jp2userbox.cpp" />
-    <ClCompile Include="frmts\elas\elasdataset.cpp" />
-    <ClCompile Include="frmts\envisat\dumpgeo.c" />
-    <ClCompile Include="frmts\envisat\EnvisatFile.c" />
-    <ClCompile Include="frmts\envisat\envisat_dump.c" />
-    <ClCompile Include="frmts\envisat\envisatdataset.cpp" />
-    <ClCompile Include="frmts\epsilon\epsilondataset.cpp" />
-    <ClCompile Include="frmts\ers\ersdataset.cpp" />
-    <ClCompile Include="frmts\ers\ershdrnode.cpp" />
-    <ClCompile Include="frmts\fit\fit.cpp" />
-    <ClCompile Include="frmts\fit\fitdataset.cpp" />
-    <ClCompile Include="frmts\fits\fitsdataset.cpp" />
-    <ClCompile Include="frmts\georaster\georaster_dataset.cpp" />
-    <ClCompile Include="frmts\georaster\georaster_driver.cpp" />
-    <ClCompile Include="frmts\georaster\georaster_rasterband.cpp" />
-    <ClCompile Include="frmts\georaster\georaster_wrapper.cpp" />
-    <ClCompile Include="frmts\georaster\oci_wrapper.cpp" />
-    <ClCompile Include="frmts\gff\gff_dataset.cpp" />
-    <ClCompile Include="frmts\gif\biggifdataset.cpp" />
-    <ClCompile Include="frmts\gif\gifdataset.cpp" />
-    <ClCompile Include="frmts\gif\giflib\dgif_lib.c" />
-    <ClCompile Include="frmts\gif\giflib\egif_lib.c" />
-    <ClCompile Include="frmts\gif\giflib\gifalloc.c" />
-    <ClCompile Include="frmts\gif\giflib\gif_err.c" />
-    <ClCompile Include="frmts\gif\giflib\gif_hash.c" />
-    <ClCompile Include="frmts\grass\grass57dataset.cpp" />
-    <ClCompile Include="frmts\grass\grassdataset.cpp" />
-    <ClCompile Include="frmts\grib\gribdataset.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\clock.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\engribapi.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\grib2api.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\memendian.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\myassert.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\myerror.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\myutil.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\scan.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\weather.c" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\degrib1.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\degrib2.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\filedatasource.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\fileendian.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\grib1tab.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\inventory.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\memorydatasource.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaname.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaparse.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaprint.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\degrib\tdlpack.cpp" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\cmplxpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\compack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\comunpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\dec_png.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\drstemplates.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\enc_jpeg2000.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\enc_png.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addfield.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addgrid.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addlocal.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_create.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_free.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_getfld.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_gribend.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_info.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_miss.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack1.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack2.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack3.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack4.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack5.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack6.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack7.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\gbits.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\getdim.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\getpoly.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\int_power.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\jpcpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\jpcunpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\misspack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\mkieee.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pack_gp.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pngpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pngunpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\rdieee.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\reduce.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\seekgb.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\simpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\simunpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\specpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\specunpack.c" />
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\dec_jpeg2000.cpp" />
-    <ClCompile Include="frmts\gsg\gs7bgdataset.cpp" />
-    <ClCompile Include="frmts\gsg\gsagdataset.cpp" />
-    <ClCompile Include="frmts\gsg\gsbgdataset.cpp" />
-    <ClCompile Include="frmts\gtiff\tif_float.c" />
-    <ClCompile Include="frmts\gtiff\geotiff.cpp" />
-    <ClCompile Include="frmts\gtiff\gt_citation.cpp" />
-    <ClCompile Include="frmts\gtiff\gt_overview.cpp" />
-    <ClCompile Include="frmts\gtiff\gt_wkt_srs.cpp" />
-    <ClCompile Include="frmts\gtiff\tifvsi.cpp" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geotiff_proj4.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_extra.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_free.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_get.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_names.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_new.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_normalize.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_print.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_set.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_simpletags.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_tiffp.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_trans.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_write.c" />
-    <ClCompile Include="frmts\gtiff\libgeotiff\xtiff.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_aux.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_close.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_codec.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_color.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_compress.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dir.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirinfo.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirread.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirwrite.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dumpmode.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_error.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_extension.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_fax3.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_fax3sm.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_flush.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_getimage.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_jpeg.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_jpeg_12.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_luv.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_lzw.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_next.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_ojpeg.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_open.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_packbits.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_pixarlog.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_predict.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_print.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_read.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_strip.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_swab.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_thunder.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_tile.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_version.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_vsi.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_warning.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_write.c" />
-    <ClCompile Include="frmts\gtiff\libtiff\tif_zip.c" />
-    <ClCompile Include="frmts\gxf\gxfopen.c" />
-    <ClCompile Include="frmts\gxf\gxf_ogcwkt.c" />
-    <ClCompile Include="frmts\gxf\gxf_proj4.c" />
-    <ClCompile Include="frmts\gxf\gxfdataset.cpp" />
-    <ClCompile Include="frmts\hdf4\hdf4dataset.cpp" />
-    <ClCompile Include="frmts\hdf4\hdf4imagedataset.cpp" />
-    <ClCompile Include="frmts\hdf4\hdf-eos\EHapi.c" />
-    <ClCompile Include="frmts\hdf4\hdf-eos\gctp_wrap.c" />
-    <ClCompile Include="frmts\hdf4\hdf-eos\GDapi.c" />
-    <ClCompile Include="frmts\hdf4\hdf-eos\SWapi.c" />
-    <ClCompile Include="frmts\hdf5\bagdataset.cpp" />
-    <ClCompile Include="frmts\hdf5\gh5_convenience.cpp" />
-    <ClCompile Include="frmts\hdf5\hdf5dataset.cpp" />
-    <ClCompile Include="frmts\hdf5\hdf5imagedataset.cpp" />
-    <ClCompile Include="frmts\hdf5\iso19115_srs.cpp" />
-    <ClCompile Include="frmts\hfa\hfaband.cpp" />
-    <ClCompile Include="frmts\hfa\hfacompress.cpp" />
-    <ClCompile Include="frmts\hfa\hfadataset.cpp" />
-    <ClCompile Include="frmts\hfa\hfadictionary.cpp" />
-    <ClCompile Include="frmts\hfa\hfaentry.cpp" />
-    <ClCompile Include="frmts\hfa\hfafield.cpp" />
-    <ClCompile Include="frmts\hfa\hfaopen.cpp" />
-    <ClCompile Include="frmts\hfa\hfatest.cpp" />
-    <ClCompile Include="frmts\hfa\hfatype.cpp" />
-    <ClCompile Include="frmts\hfa\hfa_overviews.cpp" />
-    <ClCompile Include="frmts\idrisi\IdrisiDataset.cpp" />
-    <ClCompile Include="frmts\ilwis\ilwiscoordinatesystem.cpp" />
-    <ClCompile Include="frmts\ilwis\ilwisdataset.cpp" />
-    <ClCompile Include="frmts\ingr\IngrTypes.cpp" />
-    <ClCompile Include="frmts\ingr\IntergraphBand.cpp" />
-    <ClCompile Include="frmts\ingr\IntergraphDataset.cpp" />
-    <ClCompile Include="frmts\ingr\JpegHelper.cpp" />
-    <ClCompile Include="frmts\iso8211\8211dump.cpp" />
-    <ClCompile Include="frmts\iso8211\8211view.cpp" />
-    <ClCompile Include="frmts\iso8211\ddffield.cpp" />
-    <ClCompile Include="frmts\iso8211\ddffielddefn.cpp" />
-    <ClCompile Include="frmts\iso8211\ddfmodule.cpp" />
-    <ClCompile Include="frmts\iso8211\ddfrecord.cpp" />
-    <ClCompile Include="frmts\iso8211\ddfsubfielddefn.cpp" />
-    <ClCompile Include="frmts\iso8211\ddfutils.cpp" />
-    <ClCompile Include="frmts\iso8211\mkcatalog.cpp" />
-    <ClCompile Include="frmts\iso8211\timetest.cpp" />
-    <ClCompile Include="frmts\jaxapalsar\jaxapalsardataset.cpp" />
-    <ClCompile Include="frmts\jdem\jdemdataset.cpp" />
-    <ClCompile Include="frmts\jp2kak\jp2kakdataset.cpp" />
-    <ClCompile Include="frmts\jpeg\jpgdataset.cpp" />
-    <ClCompile Include="frmts\jpeg\jpgdataset_12.cpp" />
-    <ClCompile Include="frmts\jpeg\vsidataio.cpp" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcapimin.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcapistd.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jccoefct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jccolor.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcdctmgr.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jchuff.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcinit.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmainct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmarker.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmaster.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcomapi.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcparam.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcphuff.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcprepct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jcsample.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jctrans.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdapimin.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdapistd.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdatadst.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdatasrc.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdcoefct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdcolor.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jddctmgr.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdhuff.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdinput.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmainct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmarker.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmaster.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmerge.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdphuff.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdpostct.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdsample.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jdtrans.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jerror.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctflt.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctfst.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctint.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctflt.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctfst.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctint.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctred.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jmemansi.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jmemmgr.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jquant1.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jquant2.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg\jutils.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcapimin12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcapistd12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jccoefct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jccolor12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcdctmgr12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jchuff12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcinit12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmainct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmarker12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmaster12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcomapi12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcparam12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcphuff12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcprepct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcsample12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jctrans12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdapimin12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdapistd12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdatadst12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdatasrc12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdcoefct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdcolor12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jddctmgr12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdhuff12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdinput12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmainct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmarker12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmaster12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmerge12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdphuff12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdpostct12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdsample12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdtrans12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jerror12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctflt12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctfst12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctint12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctflt12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctfst12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctint12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctred12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jmemansi12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jmemmgr12.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jquant112.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jquant212.c" />
-    <ClCompile Include="frmts\jpeg\libjpeg12\jutils12.c" />
-    <ClCompile Include="frmts\jpeg2000\jpeg2000dataset.cpp" />
-    <ClCompile Include="frmts\jpeg2000\jpeg2000_vsil_io.cpp" />
-    <ClCompile Include="frmts\l1b\l1bdataset.cpp" />
-    <ClCompile Include="frmts\leveller\levellerdataset.cpp" />
-    <ClCompile Include="frmts\mem\memdataset.cpp" />
-    <ClCompile Include="frmts\mrsid\mrsiddataset.cpp" />
-    <ClCompile Include="frmts\mrsid\mrsidstream.cpp" />
-    <ClCompile Include="frmts\msg\msgcommand.cpp" />
-    <ClCompile Include="frmts\msg\msgdataset.cpp" />
-    <ClCompile Include="frmts\msg\prologue.cpp" />
-    <ClCompile Include="frmts\msg\reflectancecalculator.cpp" />
-    <ClCompile Include="frmts\msg\xritheaderparser.cpp" />
-    <ClCompile Include="frmts\msgn\msgndataset.cpp" />
-    <ClCompile Include="frmts\msgn\msg_basic_types.cpp" />
-    <ClCompile Include="frmts\msgn\msg_reader_core.cpp" />
-    <ClCompile Include="frmts\netcdf\gmtdataset.cpp" />
-    <ClCompile Include="frmts\netcdf\netcdfdataset.cpp" />
-    <ClCompile Include="frmts\nitf\mgrs.c" />
-    <ClCompile Include="frmts\nitf\nitfdump.c" />
-    <ClCompile Include="frmts\nitf\nitffile.c" />
-    <ClCompile Include="frmts\nitf\nitfimage.c" />
-    <ClCompile Include="frmts\nitf\nitfaridpcm.cpp" />
-    <ClCompile Include="frmts\nitf\nitfbilevel.cpp" />
-    <ClCompile Include="frmts\nitf\nitfdataset.cpp" />
-    <ClCompile Include="frmts\nitf\nitfwritejpeg.cpp" />
-    <ClCompile Include="frmts\nitf\nitfwritejpeg_12.cpp" />
-    <ClCompile Include="frmts\nitf\rpftocdataset.cpp" />
-    <ClCompile Include="frmts\nitf\rpftocfile.cpp" />
-    <ClCompile Include="frmts\northwood\grcdataset.cpp" />
-    <ClCompile Include="frmts\northwood\grddataset.cpp" />
-    <ClCompile Include="frmts\northwood\northwood.cpp" />
-    <ClCompile Include="frmts\ogdi\ogdidataset.cpp" />
-    <ClCompile Include="frmts\pcidsk\pcidskdataset.cpp" />
-    <ClCompile Include="frmts\pcidsk\pcidskdataset2.cpp" />
-    <ClCompile Include="frmts\pcidsk\pcidsktiledrasterband.cpp" />
-    <ClCompile Include="frmts\pcidsk\vsi_pcidsk_io.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cbandinterleavedchannel.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cpcidskchannel.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\channel\ctiledchannel.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\cpcidskfile.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\libjpeg_io.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\metadataset_p.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskbuffer.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskcreate.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskexception.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskinterfaces.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskopen.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidsk_pubutils.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidsk_utils.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\core\sysvirtualfile.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\port\io_stdio.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\port\io_win32.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\port\pthread_mutex.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\port\win32_mutex.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskpct.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidsksegment.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\metadatasegment_p.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\segmentfactory.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\segment_loader.cpp" />
-    <ClCompile Include="frmts\pcidsk\sdk\segment\sysblockmap.cpp" />
-    <ClCompile Include="frmts\pcraster\pcrasterdataset.cpp" />
-    <ClCompile Include="frmts\pcraster\pcrastermisc.cpp" />
-    <ClCompile Include="frmts\pcraster\pcrasterrasterband.cpp" />
-    <ClCompile Include="frmts\pcraster\pcrasterutil.cpp" />
-    <ClCompile Include="frmts\pcraster\libcsf\angle.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\attravai.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\attrsize.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\cellsize.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\create2.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\csfglob.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\csfsup.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\delattr.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\dumconv.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\endian.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\filename.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gattrblk.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gattridx.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gcellrep.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gdattype.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\getattr.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\getx0.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gety0.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\ggisfid.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gmaxval.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gminval.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gnrcols.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gnrrows.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gproj.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gputproj.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gvalscal.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gvartype.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\gversion.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\ismv.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\kernlcsf.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\legend.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\mclose.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\mopen.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\moreattr.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\mperror.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\pgisfid.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\pmaxval.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\pminval.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\putallmv.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\putattr.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\putsomec.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\putx0.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\puty0.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\pvalscal.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rattrblk.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rcomp.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rcoords.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rdup2.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\reseterr.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rextend.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rmalloc.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\rrowcol.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\ruseas.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\setangle.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\setmv.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\setvtmv.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\strconst.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\strpad.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\swapio.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\trackmm.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\vs2.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\vsdef.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\vsis.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\vsvers.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\wattrblk.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\_getcell.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\_getrow.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\_gsomece.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\_putcell.c" />
-    <ClCompile Include="frmts\pcraster\libcsf\_rputrow.c" />
-    <ClCompile Include="frmts\pds\isis2dataset.cpp" />
-    <ClCompile Include="frmts\pds\isis3dataset.cpp" />
-    <ClCompile Include="frmts\pds\nasakeywordhandler.cpp" />
-    <ClCompile Include="frmts\pds\pdsdataset.cpp" />
-    <ClCompile Include="frmts\pgchip\pgchipdataset.cpp" />
-    <ClCompile Include="frmts\pgchip\pgchiprasterband.cpp" />
-    <ClCompile Include="frmts\pgchip\pgchiputilities.cpp" />
-    <ClCompile Include="frmts\png\pngdataset.cpp" />
-    <ClCompile Include="frmts\png\libpng\png.c" />
-    <ClCompile Include="frmts\png\libpng\pngerror.c" />
-    <ClCompile Include="frmts\png\libpng\pnggccrd.c" />
-    <ClCompile Include="frmts\png\libpng\pngget.c" />
-    <ClCompile Include="frmts\png\libpng\pngmem.c" />
-    <ClCompile Include="frmts\png\libpng\pngpread.c" />
-    <ClCompile Include="frmts\png\libpng\pngread.c" />
-    <ClCompile Include="frmts\png\libpng\pngrio.c" />
-    <ClCompile Include="frmts\png\libpng\pngrtran.c" />
-    <ClCompile Include="frmts\png\libpng\pngrutil.c" />
-    <ClCompile Include="frmts\png\libpng\pngset.c" />
-    <ClCompile Include="frmts\png\libpng\pngtrans.c" />
-    <ClCompile Include="frmts\png\libpng\pngvcrd.c" />
-    <ClCompile Include="frmts\png\libpng\pngwio.c" />
-    <ClCompile Include="frmts\png\libpng\pngwrite.c" />
-    <ClCompile Include="frmts\png\libpng\pngwtran.c" />
-    <ClCompile Include="frmts\png\libpng\pngwutil.c" />
-    <ClCompile Include="frmts\r\rcreatecopy.cpp" />
-    <ClCompile Include="frmts\r\rdataset.cpp" />
-    <ClCompile Include="frmts\rasterlite\rasterlitecreatecopy.cpp" />
-    <ClCompile Include="frmts\rasterlite\rasterlitedataset.cpp" />
-    <ClCompile Include="frmts\rasterlite\rasterliteoverviews.cpp" />
-    <ClCompile Include="frmts\raw\atlsci_spheroid.cpp" />
-    <ClCompile Include="frmts\raw\btdataset.cpp" />
-    <ClCompile Include="frmts\raw\cpgdataset.cpp" />
-    <ClCompile Include="frmts\raw\dipxdataset.cpp" />
-    <ClCompile Include="frmts\raw\doq1dataset.cpp" />
-    <ClCompile Include="frmts\raw\doq2dataset.cpp" />
-    <ClCompile Include="frmts\raw\ehdrdataset.cpp" />
-    <ClCompile Include="frmts\raw\eirdataset.cpp" />
-    <ClCompile Include="frmts\raw\envidataset.cpp" />
-    <ClCompile Include="frmts\raw\fastdataset.cpp" />
-    <ClCompile Include="frmts\raw\fujibasdataset.cpp" />
-    <ClCompile Include="frmts\raw\genbindataset.cpp" />
-    <ClCompile Include="frmts\raw\gscdataset.cpp" />
-    <ClCompile Include="frmts\raw\hkvdataset.cpp" />
-    <ClCompile Include="frmts\raw\idadataset.cpp" />
-    <ClCompile Include="frmts\raw\landataset.cpp" />
-    <ClCompile Include="frmts\raw\lcpdataset.cpp" />
-    <ClCompile Include="frmts\raw\mffdataset.cpp" />
-    <ClCompile Include="frmts\raw\ndfdataset.cpp" />
-    <ClCompile Include="frmts\raw\pauxdataset.cpp" />
-    <ClCompile Include="frmts\raw\pnmdataset.cpp" />
-    <ClCompile Include="frmts\raw\rawdataset.cpp" />
-    <ClCompile Include="frmts\rik\rikdataset.cpp" />
-    <ClCompile Include="frmts\rmf\rmfdataset.cpp" />
-    <ClCompile Include="frmts\rmf\rmflzw.cpp" />
-    <ClCompile Include="frmts\rs2\rs2dataset.cpp" />
-    <ClCompile Include="frmts\saga\sagadataset.cpp" />
-    <ClCompile Include="frmts\sde\sdedataset.cpp" />
-    <ClCompile Include="frmts\sde\sdeerror.cpp" />
-    <ClCompile Include="frmts\sde\sderasterband.cpp" />
-    <ClCompile Include="frmts\sdts\sdts2shp.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsattrreader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtscatd.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsdataset.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsindexedreader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsiref.cpp" />
-    <ClCompile Include="frmts\sdts\sdtslib.cpp" />
-    <ClCompile Include="frmts\sdts\sdtslinereader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtspointreader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtspolygonreader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsrasterreader.cpp" />
-    <ClCompile Include="frmts\sdts\sdtstransfer.cpp" />
-    <ClCompile Include="frmts\sdts\sdtsxref.cpp" />
-    <ClCompile Include="frmts\sgi\sgidataset.cpp" />
-    <ClCompile Include="frmts\srtmhgt\srtmhgtdataset.cpp" />
-    <ClCompile Include="frmts\terragen\terragendataset.cpp" />
-    <ClCompile Include="frmts\terralib\TerraLibDataset.cpp" />
-    <ClCompile Include="frmts\terralib\TerraLibRasterBand.cpp" />
-    <ClCompile Include="frmts\til\tildataset.cpp" />
-    <ClCompile Include="frmts\tsx\tsxdataset.cpp" />
-    <ClCompile Include="frmts\usgsdem\usgsdemdataset.cpp" />
-    <ClCompile Include="frmts\usgsdem\usgsdem_create.cpp" />
-    <ClCompile Include="frmts\vrt\vrtdataset.cpp" />
-    <ClCompile Include="frmts\vrt\vrtderivedrasterband.cpp" />
-    <ClCompile Include="frmts\vrt\vrtdriver.cpp" />
-    <ClCompile Include="frmts\vrt\vrtfilters.cpp" />
-    <ClCompile Include="frmts\vrt\vrtrasterband.cpp" />
-    <ClCompile Include="frmts\vrt\vrtrawrasterband.cpp" />
-    <ClCompile Include="frmts\vrt\vrtsourcedrasterband.cpp" />
-    <ClCompile Include="frmts\vrt\vrtsources.cpp" />
-    <ClCompile Include="frmts\vrt\vrtwarped.cpp" />
-    <ClCompile Include="frmts\wcs\httpdriver.cpp" />
-    <ClCompile Include="frmts\wcs\wcsdataset.cpp" />
-    <ClCompile Include="frmts\wktraster\wktrasterdataset.cpp" />
-    <ClCompile Include="frmts\wktraster\wktrasterrasterband.cpp" />
-    <ClCompile Include="frmts\wktraster\wktrasterwrapper.cpp" />
-    <ClCompile Include="frmts\wms\cache.cpp" />
-    <ClCompile Include="frmts\wms\dataset.cpp" />
-    <ClCompile Include="frmts\wms\gdalhttp.cpp" />
-    <ClCompile Include="frmts\wms\md5.cpp" />
-    <ClCompile Include="frmts\wms\minidriver.cpp" />
-    <ClCompile Include="frmts\wms\minidriver_tileservice.cpp" />
-    <ClCompile Include="frmts\wms\minidriver_tms.cpp" />
-    <ClCompile Include="frmts\wms\minidriver_wms.cpp" />
-    <ClCompile Include="frmts\wms\minidriver_worldwind.cpp" />
-    <ClCompile Include="frmts\wms\rasterband.cpp" />
-    <ClCompile Include="frmts\wms\stuff.cpp" />
-    <ClCompile Include="frmts\wms\wmsdriver.cpp" />
-    <ClCompile Include="frmts\xpm\xpmdataset.cpp" />
-    <ClCompile Include="frmts\zlib\adler32.c" />
-    <ClCompile Include="frmts\zlib\compress.c" />
-    <ClCompile Include="frmts\zlib\crc32.c" />
-    <ClCompile Include="frmts\zlib\deflate.c" />
-    <ClCompile Include="frmts\zlib\gzio.c" />
-    <ClCompile Include="frmts\zlib\infback.c" />
-    <ClCompile Include="frmts\zlib\inffast.c" />
-    <ClCompile Include="frmts\zlib\inflate.c" />
-    <ClCompile Include="frmts\zlib\inftrees.c" />
-    <ClCompile Include="frmts\zlib\trees.c" />
-    <ClCompile Include="frmts\zlib\uncompr.c" />
-    <ClCompile Include="frmts\zlib\zutil.c" />
-    <ClCompile Include="gcore\gdalallvalidmaskband.cpp" />
-    <ClCompile Include="gcore\gdalcolortable.cpp" />
-    <ClCompile Include="gcore\gdaldataset.cpp" />
-    <ClCompile Include="gcore\gdaldefaultoverviews.cpp" />
-    <ClCompile Include="gcore\gdaldriver.cpp" />
-    <ClCompile Include="gcore\gdaldrivermanager.cpp" />
-    <ClCompile Include="gcore\gdalgmlcoverage.cpp" />
-    <ClCompile Include="gcore\gdaljp2box.cpp" />
-    <ClCompile Include="gcore\gdaljp2metadata.cpp" />
-    <ClCompile Include="gcore\gdalmajorobject.cpp" />
-    <ClCompile Include="gcore\gdalmultidomainmetadata.cpp" />
-    <ClCompile Include="gcore\gdalnodatamaskband.cpp" />
-    <ClCompile Include="gcore\gdalnodatavaluesmaskband.cpp" />
-    <ClCompile Include="gcore\gdalopeninfo.cpp" />
-    <ClCompile Include="gcore\gdalpamdataset.cpp" />
-    <ClCompile Include="gcore\gdalpamproxydb.cpp" />
-    <ClCompile Include="gcore\gdalpamrasterband.cpp" />
-    <ClCompile Include="gcore\gdalproxydataset.cpp" />
-    <ClCompile Include="gcore\gdalproxypool.cpp" />
-    <ClCompile Include="gcore\gdalrasterband.cpp" />
-    <ClCompile Include="gcore\gdalrasterblock.cpp" />
-    <ClCompile Include="gcore\gdal_misc.cpp" />
-    <ClCompile Include="gcore\gdal_rat.cpp" />
-    <ClCompile Include="gcore\gdal_rpcimdio.cpp" />
-    <ClCompile Include="gcore\overview.cpp" />
-    <ClCompile Include="gcore\rasterio.cpp" />
-    <ClCompile Include="ogr\ogr_capi_test.c" />
-    <ClCompile Include="ogr\swq.c" />
-    <ClCompile Include="ogr\gml2ogrgeometry.cpp" />
-    <ClCompile Include="ogr\ogr2gmlgeometry.cpp" />
-    <ClCompile Include="ogr\ograssemblepolygon.cpp" />
-    <ClCompile Include="ogr\ogrct.cpp" />
-    <ClCompile Include="ogr\ogrcurve.cpp" />
-    <ClCompile Include="ogr\ogrfeature.cpp" />
-    <ClCompile Include="ogr\ogrfeaturedefn.cpp" />
-    <ClCompile Include="ogr\ogrfeaturequery.cpp" />
-    <ClCompile Include="ogr\ogrfeaturestyle.cpp" />
-    <ClCompile Include="ogr\ogrfielddefn.cpp" />
-    <ClCompile Include="ogr\ogrgeometry.cpp" />
-    <ClCompile Include="ogr\ogrgeometrycollection.cpp" />
-    <ClCompile Include="ogr\ogrgeometryfactory.cpp" />
-    <ClCompile Include="ogr\ogrlinearring.cpp" />
-    <ClCompile Include="ogr\ogrlinestring.cpp" />
-    <ClCompile Include="ogr\ogrmultilinestring.cpp" />
-    <ClCompile Include="ogr\ogrmultipoint.cpp" />
-    <ClCompile Include="ogr\ogrmultipolygon.cpp" />
-    <ClCompile Include="ogr\ogrpoint.cpp" />
-    <ClCompile Include="ogr\ogrpolygon.cpp" />
-    <ClCompile Include="ogr\ogrspatialreference.cpp" />
-    <ClCompile Include="ogr\ogrsurface.cpp" />
-    <ClCompile Include="ogr\ogrutils.cpp" />
-    <ClCompile Include="ogr\ogr_api.cpp" />
-    <ClCompile Include="ogr\ogr_expat.cpp" />
-    <ClCompile Include="ogr\ogr_fromepsg.cpp" />
-    <ClCompile Include="ogr\ogr_opt.cpp" />
-    <ClCompile Include="ogr\ogr_srsnode.cpp" />
-    <ClCompile Include="ogr\ogr_srs_dict.cpp" />
-    <ClCompile Include="ogr\ogr_srs_erm.cpp" />
-    <ClCompile Include="ogr\ogr_srs_esri.cpp" />
-    <ClCompile Include="ogr\ogr_srs_ozi.cpp" />
-    <ClCompile Include="ogr\ogr_srs_panorama.cpp" />
-    <ClCompile Include="ogr\ogr_srs_pci.cpp" />
-    <ClCompile Include="ogr\ogr_srs_proj4.cpp" />
-    <ClCompile Include="ogr\ogr_srs_usgs.cpp" />
-    <ClCompile Include="ogr\ogr_srs_validate.cpp" />
-    <ClCompile Include="ogr\ogr_srs_xml.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_bin.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_binwr.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00gen.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00parse.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00read.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00write.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_mbyte.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_misc.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_rawbin.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbindatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbindriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbinlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00datasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00driver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00layer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravclayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnadatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnadriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnalayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnaparser.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgndump.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnwritetest.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnfloat.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnhelp.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnopen.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnread.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnstroke.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnwrite.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgndatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgndriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgnlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsfielddefn.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsgrid.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxflayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfwriterds.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfwriterlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_blockmap.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_dimension.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_diskio.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmecacheindex.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmedatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmedriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayercached.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayerdb.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrregisterall.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrsfdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_attrind.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_gensql.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_miattrind.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\geoconcept.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsondatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsondriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonreader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonutils.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\arraylist.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\debug.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_object.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_tokener.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_util.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\linkhash.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\printbuf.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorssdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorssdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorsslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlfeature.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlfeatureclass.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlhandler.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlpropertydefn.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlreader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlreadstate.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmldatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmldriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmllayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\parsexsd.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\trstring.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gml\resolvexlinks.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrassdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrassdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrasslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtm.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtmtracklayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtmwaypointlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridblayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili1reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili2handler.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili2reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ilihelper.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iomhelper.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1datasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1driver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1layer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2datasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2driver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2layer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_attr.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_basket.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_error.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_file.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_iterator.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_object.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_utilities.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_value.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\tags.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\ustrings.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\writer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringreslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresresultlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresstatement.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringrestablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kml.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kmlnode.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kmlvector.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogr2kmlgeometry.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmldatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmldriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmllayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_bounds.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_datfile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_feature.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_geometry.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_idfile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_indfile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_miffile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabview.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_utils.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqllayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfdump.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntffilereader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfrecord.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfstroke.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_codelist.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_estlayers.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_generic.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_raster.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntfdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntfdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntffeatureclasslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntflayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\fastload.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ocitest.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\oci_utils.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocidatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocidriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocilayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociloaderlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociselectlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocisession.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistatement.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistringbuf.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistroke.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocitablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociwritablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbclayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcselectlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbctablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdidatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidskdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidskdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidsklayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdebug.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpglayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgresultlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgtablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeodriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeolayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeoselectlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeotablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ll_recio.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrrecdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrrecdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrreclayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ddfrecordindex.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57datasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57driver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57layer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57classregistrar.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57dump.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57featuredefns.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57filecollector.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57writer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdedatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdedriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtsdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\dbfopen.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shpopen.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shptree.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shp_vsi.c" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapedriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shape2ogr.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitedatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitedriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqliteselectlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeraltname.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerarealandmarks.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigercompletechain.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerentitynames.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerfeatureids.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerfilebase.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeridhistory.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerinfo.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerkeyfeatures.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerlandmarks.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeroverunder.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpip.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpoint.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolychainlink.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygon.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygoncorrections.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygoneconomic.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerspatialmetadata.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigertlidrange.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzerocellid.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtdatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtdriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtlayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanelayer.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_reader.cpp" />
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\test_geo_utils.cpp" />
-    <ClCompile Include="ogr\wcts\ogrwcts.cpp" />
-    <ClCompile Include="ogr\wcts\wctsclient.cpp" />
-    <ClCompile Include="port\cplgetsymbol.cpp" />
-    <ClCompile Include="port\cplkeywordparser.cpp" />
-    <ClCompile Include="port\cplstring.cpp" />
-    <ClCompile Include="port\cpl_atomic_ops.cpp" />
-    <ClCompile Include="port\cpl_conv.cpp" />
-    <ClCompile Include="port\cpl_csv.cpp" />
-    <ClCompile Include="port\cpl_error.cpp" />
-    <ClCompile Include="port\cpl_findfile.cpp" />
-    <ClCompile Include="port\cpl_getexecpath.cpp" />
-    <ClCompile Include="port\cpl_hash_set.cpp" />
-    <ClCompile Include="port\cpl_http.cpp" />
-    <ClCompile Include="port\cpl_list.cpp" />
-    <ClCompile Include="port\cpl_minixml.cpp" />
-    <ClCompile Include="port\cpl_minizip_ioapi.cpp" />
-    <ClCompile Include="port\cpl_minizip_unzip.cpp" />
-    <ClCompile Include="port\cpl_multiproc.cpp" />
-    <ClCompile Include="port\cpl_odbc.cpp" />
-    <ClCompile Include="port\cpl_path.cpp" />
-    <ClCompile Include="port\cpl_quad_tree.cpp" />
-    <ClCompile Include="port\cpl_recode_stub.cpp" />
-    <ClCompile Include="port\cpl_string.cpp" />
-    <ClCompile Include="port\cpl_strtod.cpp" />
-    <ClCompile Include="port\cpl_time.cpp" />
-    <ClCompile Include="port\cpl_vsil.cpp" />
-    <ClCompile Include="port\cpl_vsil_gzip.cpp" />
-    <ClCompile Include="port\cpl_vsil_simple.cpp" />
-    <ClCompile Include="port\cpl_vsil_subfile.cpp" />
-    <ClCompile Include="port\cpl_vsil_unix_stdio_64.cpp" />
-    <ClCompile Include="port\cpl_vsil_win32.cpp" />
-    <ClCompile Include="port\cpl_vsisimple.cpp" />
-    <ClCompile Include="port\cpl_vsi_mem.cpp" />
-    <ClCompile Include="port\cpl_win32ce_api.cpp" />
-    <ClCompile Include="port\xmlreformat.cpp" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/makegdal10.vcxproj.filters b/makegdal10.vcxproj.filters
deleted file mode 100644
index 3c35137..0000000
--- a/makegdal10.vcxproj.filters
+++ /dev/null
@@ -1,6189 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Include Files">
-      <UniqueIdentifier>{2f55a3da-3fbb-4feb-a97c-4b21b8d82cb0}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\alg">
-      <UniqueIdentifier>{3c8dd82a-4d13-4b46-ae61-7fb8c0937ca3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\bridge">
-      <UniqueIdentifier>{1141cd6a-d3f4-40d2-8835-73c9e1ab84d5}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts">
-      <UniqueIdentifier>{3b306177-22e5-4335-ad4b-9dc6974b190e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\aigrid">
-      <UniqueIdentifier>{a9d6e342-e6b4-41fb-bab7-d04e9f3b46cd}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\blx">
-      <UniqueIdentifier>{8f2f1cde-5371-4730-85bd-eb290e5e2231}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\bsb">
-      <UniqueIdentifier>{5200ecc8-0476-4bd5-94a7-34b2dd0e19c0}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ceos">
-      <UniqueIdentifier>{189cc4c4-ff9c-4435-893c-4ca3be8c0104}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ceos2">
-      <UniqueIdentifier>{d02b9674-173c-4f2a-b57c-cf8194411c09}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\dted">
-      <UniqueIdentifier>{fdb3c533-fce5-400e-bcd2-60ddb358ad4e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ecw">
-      <UniqueIdentifier>{068a88d1-0de9-4fb2-966a-8a1de1a9c23c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\envisat">
-      <UniqueIdentifier>{ad39a88e-93c1-4b28-8d7c-01ffeb365cb8}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ers">
-      <UniqueIdentifier>{7d3868ff-b774-449f-b42b-80e859a7d135}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\fit">
-      <UniqueIdentifier>{ab5124a1-3cc8-405d-bed0-993440b446e9}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\georaster">
-      <UniqueIdentifier>{f9ca78be-5556-4ebd-b9f0-9944ceb98ecb}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gif">
-      <UniqueIdentifier>{c8b9f41d-40e2-4db8-a174-8a7decc6d23c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gif\giflib">
-      <UniqueIdentifier>{7a2161ee-872f-4b57-b21e-b44041a9916f}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\grib">
-      <UniqueIdentifier>{7fc047ab-2073-411c-af58-398005df5095}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\grib\degrib18">
-      <UniqueIdentifier>{0bcc2343-2280-4289-87e2-0548f685f604}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\grib\degrib18\degrib">
-      <UniqueIdentifier>{b094e079-9f6a-40ee-9278-6eda00265ba4}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\grib\degrib18\g2clib-1.0.4">
-      <UniqueIdentifier>{7fffced3-4414-4e7d-a304-0e1f40f644a4}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gtiff">
-      <UniqueIdentifier>{83a76012-946d-4890-bbe3-57eaf09d1171}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gtiff\libgeotiff">
-      <UniqueIdentifier>{7e0695eb-f3df-4e92-a214-fbf12bdbdd68}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gtiff\libtiff">
-      <UniqueIdentifier>{9c44403b-c093-4a5b-9c24-5a83951439ed}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\gxf">
-      <UniqueIdentifier>{9546b9cf-7fe5-4306-bdaa-de40b91f5366}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\hdf4">
-      <UniqueIdentifier>{a49c61f6-06cf-47e6-bb21-0f4a98ed4464}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\hdf4\hdf-eos">
-      <UniqueIdentifier>{f136f844-6f5b-463a-bd2c-e13c89b7e1d4}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\hdf5">
-      <UniqueIdentifier>{d8b714fe-866a-4a94-ad5f-922cb00383e9}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\hfa">
-      <UniqueIdentifier>{04760ca6-9175-4daa-8d00-43dea11c2a2d}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ilwis">
-      <UniqueIdentifier>{a8eb8f61-6410-49f3-b566-85a37d85d778}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\ingr">
-      <UniqueIdentifier>{4eba1326-d7ec-4574-9440-01d6c1c55821}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\iso8211">
-      <UniqueIdentifier>{8fc006db-1e97-40fe-b457-34eea7543cb8}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\jp2kak">
-      <UniqueIdentifier>{4b60475c-6ca5-46ea-b469-7c21d9c879ad}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\jpeg">
-      <UniqueIdentifier>{b80aaa42-cb0e-4d0d-973b-f11a38be6a8e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\jpeg2000">
-      <UniqueIdentifier>{d06c876d-cc51-4dfe-8202-08245dd3a0b3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\jpeg\libjpeg">
-      <UniqueIdentifier>{fdab96b1-db99-4f3d-9295-dffaa0839e9c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\jpeg\libjpeg12">
-      <UniqueIdentifier>{49258e92-5b8f-4b94-b49b-47a3e65b4a6a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\mem">
-      <UniqueIdentifier>{5c3aea17-4c76-44e8-9f80-100a2e487347}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\mrsid">
-      <UniqueIdentifier>{bf2f4fef-45da-47e0-9182-037dadb909bb}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\msg">
-      <UniqueIdentifier>{d5f2db3b-12f5-427e-bbc8-64f59dac37d4}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\msgn">
-      <UniqueIdentifier>{d68de4f2-d518-40d5-8ae6-99748516ae1a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\netcdf">
-      <UniqueIdentifier>{668dc5b2-9487-4556-a878-eb241aa1ba93}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\nitf">
-      <UniqueIdentifier>{58bc633d-be8a-4b56-acb7-398df532152f}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\northwood">
-      <UniqueIdentifier>{ea792768-c8ad-4383-80aa-527273d61209}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcidsk">
-      <UniqueIdentifier>{3eefa40e-576b-4f39-98c9-3cf9fdaa72b4}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcidsk\sdk">
-      <UniqueIdentifier>{c2c26c6c-0de7-43b6-9b08-f789445322d0}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcidsk\sdk\channel">
-      <UniqueIdentifier>{0867d6c4-acf6-4cbf-b1ba-1359f490074e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcidsk\sdk\core">
-      <UniqueIdentifier>{1a466673-8690-483d-829c-03c5d35dfbc9}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcidsk\sdk\segment">
-      <UniqueIdentifier>{c96a2269-8520-4b79-91da-26a69f1ddff2}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcraster">
-      <UniqueIdentifier>{0658187a-93cc-4cd4-b878-49b6412a87ed}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pcraster\libcsf">
-      <UniqueIdentifier>{b21948ca-faa1-4b8e-8076-e011646fdffd}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pds">
-      <UniqueIdentifier>{780b4b7c-36b0-46ac-b597-595be3f5de25}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\pgchip">
-      <UniqueIdentifier>{40ad555e-7e5a-46c0-9fa4-53a55f36ed58}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\png">
-      <UniqueIdentifier>{a5f6ece0-aefb-4409-bd65-bc754acb4d6e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\png\libpng">
-      <UniqueIdentifier>{2e9c523e-a83c-4d6f-8d47-a4e5be16aae7}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\rasterlite">
-      <UniqueIdentifier>{af93aefe-41cd-4e53-85f0-aa88bca58c11}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\raw">
-      <UniqueIdentifier>{99f97897-780e-41be-9847-b48e34bd43bc}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\rmf">
-      <UniqueIdentifier>{3358daf0-f9b1-490b-aba0-7426411c7507}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\sde">
-      <UniqueIdentifier>{85035bd4-facd-46a1-9578-fbc87a33270a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\sdts">
-      <UniqueIdentifier>{94f5f379-9335-49d4-8906-807bef4ec41a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\terralib">
-      <UniqueIdentifier>{30b5a1bd-54fd-400f-8efa-aa2b9f13c68c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\vrt">
-      <UniqueIdentifier>{c2e41630-3cd3-4f25-b006-937c634bcde3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\wktraster">
-      <UniqueIdentifier>{b044f4a2-68b7-4062-bfc6-d49423f06027}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\wms">
-      <UniqueIdentifier>{68178620-c530-4688-88ef-dd098921e74a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\frmts\zlib">
-      <UniqueIdentifier>{2070067d-c02b-40a1-a79b-d615a0646f74}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\gcore">
-      <UniqueIdentifier>{5745d2bf-d658-40d7-b267-4ccd30cd9411}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr">
-      <UniqueIdentifier>{2847e7fc-14a9-43f1-aa6c-08f4bc673b3e}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts">
-      <UniqueIdentifier>{19fd9459-bd97-4b88-8469-1b53127372ca}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\avc">
-      <UniqueIdentifier>{9d52b360-8b65-46d5-93b9-f20aaed0fb1d}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\bna">
-      <UniqueIdentifier>{933074f0-e7c1-4be4-9eca-f52739c5b86a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\csv">
-      <UniqueIdentifier>{31c3ef4b-2668-4869-a741-e5b1a8fa4d45}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\dgn">
-      <UniqueIdentifier>{0bc460f6-dc12-4bb3-ba8b-708e434cf0e9}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\dgn\dist">
-      <UniqueIdentifier>{412e0bd2-e72f-40f0-8afd-18062fba4742}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\dods">
-      <UniqueIdentifier>{58d85331-bbdb-49de-866e-6b44f0c7b946}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\dxf">
-      <UniqueIdentifier>{590a9b54-025e-43b0-bf72-4d5d26df3ae3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\fme">
-      <UniqueIdentifier>{31e3ce42-110a-4011-8f58-859f9d15703f}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\generic">
-      <UniqueIdentifier>{525c4fca-d686-4229-aa7d-9f2c9f1e694a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\geoconcept">
-      <UniqueIdentifier>{d3245ad2-00d3-4c36-9f6f-1d66a0dc069a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\geojson">
-      <UniqueIdentifier>{074bf0fb-69aa-435e-8a48-db18d5008d5b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\geojson\jsonc">
-      <UniqueIdentifier>{1f2c10e3-ca1c-4a1d-b240-5227e82af0ae}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\georss">
-      <UniqueIdentifier>{f8900753-f23c-485f-9838-d124f60479b0}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\gml">
-      <UniqueIdentifier>{d443a5c8-4214-4c3e-85cc-ad489c74fc53}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\gmt">
-      <UniqueIdentifier>{dec8410d-d7fe-463c-b588-7ab3c987e67b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\gpx">
-      <UniqueIdentifier>{611248cf-6c5e-464b-84ee-619974b99e93}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\grass">
-      <UniqueIdentifier>{f66f5ad7-2fa2-4898-bf4f-be43e44c8f3b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\gtm">
-      <UniqueIdentifier>{40f59e07-013e-4790-96c5-dcf6e2a26a9f}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\idb">
-      <UniqueIdentifier>{bfb13fd8-4c09-408b-a9de-a90052009415}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\ili">
-      <UniqueIdentifier>{2f665bda-eaa3-4858-88e8-e2ae651344f1}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\ili\iom">
-      <UniqueIdentifier>{a263922b-03e7-415a-8375-2c71b5f7e39b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\ingres">
-      <UniqueIdentifier>{033a9c35-c99d-41c2-88ed-bf04f1450607}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\kml">
-      <UniqueIdentifier>{7dda55e5-aab1-4c3a-be13-8f0054b6198c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\mem">
-      <UniqueIdentifier>{669d0482-de71-4724-af30-0bda3d97e331}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\mitab">
-      <UniqueIdentifier>{025ea4f5-c6e6-45f4-8355-b12f19167bb3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\mysql">
-      <UniqueIdentifier>{b72fdc31-b01e-49b5-86c0-72c1e4f0804d}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\ntf">
-      <UniqueIdentifier>{d637acc7-e5cc-429a-9e06-75a5f1d0557c}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\oci">
-      <UniqueIdentifier>{4524a9af-8afb-429c-98f2-68cfea89a4fd}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\odbc">
-      <UniqueIdentifier>{e1b40b0f-50c9-4dd9-83cd-46baa77eec6a}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\ogdi">
-      <UniqueIdentifier>{d5803ee5-39fb-4acf-86ce-94aa883593b3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\pcidsk">
-      <UniqueIdentifier>{e0a10aeb-ddbe-4ae5-b116-2d178171e03b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\pg">
-      <UniqueIdentifier>{ca3dd2bd-1a17-4417-afc8-d2d86b7612ba}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\pgeo">
-      <UniqueIdentifier>{d1bb77f6-4c68-4ddd-8a89-ce573b823817}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\rec">
-      <UniqueIdentifier>{ac709f33-4a52-45e0-a10b-c9650ec34ac3}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\s57">
-      <UniqueIdentifier>{ec0f118f-a97b-42c8-b957-923e404f07eb}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\sde">
-      <UniqueIdentifier>{fe901426-e7fc-44ad-9efd-90630c3a0d3f}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\sdts">
-      <UniqueIdentifier>{f8fdef0b-ebf1-4aec-a262-6e370e1468c8}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\shape">
-      <UniqueIdentifier>{e7817e52-f3c8-46f3-82c9-fbfe22dab2a2}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\sqlite">
-      <UniqueIdentifier>{60333ed3-47d4-4b0f-9dab-57231270030b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\tiger">
-      <UniqueIdentifier>{dff3b123-5681-45e2-a056-91d8b6ef5b53}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\vrt">
-      <UniqueIdentifier>{51acbeac-d845-4dc9-820e-ed78fcb6ce7b}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\ogr\ogrsf_frmts\xplane">
-      <UniqueIdentifier>{5fa14b0e-b0da-4a70-8c23-536930ebd83d}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Include Files\port">
-      <UniqueIdentifier>{9b3244fd-36de-435c-b607-e1429aa5b3b7}</UniqueIdentifier>
-      <Extensions>*.h</Extensions>
-    </Filter>
-    <Filter Include="Make Files">
-      <UniqueIdentifier>{42b56f40-348e-4cfa-8158-d0354a076f10}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\alg">
-      <UniqueIdentifier>{b734fa2d-26f3-4ec1-94a9-0e5f3ab57666}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\apps">
-      <UniqueIdentifier>{cd42c377-c8ec-4c86-8775-e7b1152ba356}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts">
-      <UniqueIdentifier>{8722fc0c-8b1e-4c39-baad-21c16c68159b}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\aaigrid">
-      <UniqueIdentifier>{542576b9-574d-4284-8408-a0805bd245e7}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\adrg">
-      <UniqueIdentifier>{60d86538-ecef-4a78-a1cd-84b6eb21c2ce}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\aigrid">
-      <UniqueIdentifier>{71cf509a-816e-42b7-960c-3c851baf0183}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\airsar">
-      <UniqueIdentifier>{06c45a3d-c0eb-4cd4-8f14-dadae7fb4053}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\blx">
-      <UniqueIdentifier>{5942ad14-6516-4d8a-a225-29402777f02f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\bmp">
-      <UniqueIdentifier>{5310240d-4467-41ba-98e8-24b6c06ab367}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\bsb">
-      <UniqueIdentifier>{87de0449-be27-4d22-9807-e43d5204723f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ceos">
-      <UniqueIdentifier>{b4104479-4f97-4c96-b6dc-a60f31d23e53}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ceos2">
-      <UniqueIdentifier>{47c7b80e-3cc4-4d2c-9b9d-772740e79380}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\coasp">
-      <UniqueIdentifier>{ac4be524-2945-4b3d-810c-10088d531dba}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\cosar">
-      <UniqueIdentifier>{0dd3e2ff-0aee-4364-9a46-effa672243fc}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\dimap">
-      <UniqueIdentifier>{477c119a-e185-4397-a65c-2121cdd50e8d}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\dods">
-      <UniqueIdentifier>{00e50a8d-f77e-4e7e-9fec-1d81635d9cb4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\dted">
-      <UniqueIdentifier>{dc91b401-d6b4-4dcc-a419-9b233e959384}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ecw">
-      <UniqueIdentifier>{a43f6b51-5323-482d-96b1-d6df4a8b9027}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\elas">
-      <UniqueIdentifier>{d8969c54-4ca0-4e5d-9c9b-9b557bcb0539}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\envisat">
-      <UniqueIdentifier>{7a4f3278-fc1c-47e2-8848-0e02413f6d60}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\epsilon">
-      <UniqueIdentifier>{38a1598a-6bce-4a23-ad1d-ed58eaee9a6e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ers">
-      <UniqueIdentifier>{77af9b46-9d26-41f4-94f2-fbd0bbcf4706}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\fit">
-      <UniqueIdentifier>{56684134-120f-4f02-874e-5e85a5cb2595}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\fits">
-      <UniqueIdentifier>{2be76cd8-18d7-4b78-87e5-34fb24fc1bcf}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\georaster">
-      <UniqueIdentifier>{9b711462-887a-4ced-b5e0-a3db085c7f08}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gff">
-      <UniqueIdentifier>{6aa897e2-0cc0-460d-bbc9-b65e8b3b1c2a}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gif">
-      <UniqueIdentifier>{b21d9a8d-fbc1-4f63-b77b-9b748d68a4f3}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gif\giflib">
-      <UniqueIdentifier>{bc4cc257-2b9e-4ed0-b2f3-b27e5af71df4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\grib">
-      <UniqueIdentifier>{830b1b6a-7a5e-4a39-b44a-9c0051f52561}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\grib\degrib18">
-      <UniqueIdentifier>{d017451e-23e1-4e92-89e4-20390c6ef9cc}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\grib\degrib18\degrib">
-      <UniqueIdentifier>{c450bafb-17df-449f-b0e8-0921bcf7b591}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\grib\degrib18\g2clib-1.0.4">
-      <UniqueIdentifier>{0ad31015-518d-4f37-90b2-a241a3ef9abd}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gsg">
-      <UniqueIdentifier>{e96375c9-4921-47eb-8977-60c278e2b9af}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gtiff">
-      <UniqueIdentifier>{f22adb38-39e5-43ae-8b8b-ef39c5b70d06}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gtiff\libgeotiff">
-      <UniqueIdentifier>{199f18d8-5ccc-4492-890d-f44ae9dab2de}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gtiff\libtiff">
-      <UniqueIdentifier>{cc4fc296-cef4-4190-a7e4-f76a0d820479}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\gxf">
-      <UniqueIdentifier>{1dab7b71-ad97-4317-b5d7-613f74475757}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\hdf4">
-      <UniqueIdentifier>{14e7b046-573e-4cec-ab65-b7bae6f258f0}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\hdf4\hdf-eos">
-      <UniqueIdentifier>{31f50b4d-33d8-44be-bf49-57123f2b26a7}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\hdf5">
-      <UniqueIdentifier>{f6459896-835c-42c9-b008-b0443eecd921}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\hfa">
-      <UniqueIdentifier>{aa4c6ef8-6298-439d-adfe-bdf3a71182fc}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\idrisi">
-      <UniqueIdentifier>{44891628-8cc3-4a1e-96fd-54c172a7fba4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ilwis">
-      <UniqueIdentifier>{ac9b450e-741f-4701-8d1b-13a06c4335fe}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ingr">
-      <UniqueIdentifier>{8cb20333-f1ff-407c-8ca8-8d54b8d20e7f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\iso8211">
-      <UniqueIdentifier>{0293be19-2191-4d6a-be3e-d854541ad061}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jaxapalsar">
-      <UniqueIdentifier>{4e5b7033-f593-4c16-ac80-dd2831e6133b}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jdem">
-      <UniqueIdentifier>{9cb82099-f879-4bfc-8b53-2ed003b199fa}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jp2kak">
-      <UniqueIdentifier>{b1e74f20-8ccd-4770-82c8-6eedac20ab60}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jpeg">
-      <UniqueIdentifier>{71843f58-bcbb-4c63-8053-e1a1fd7c9909}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jpeg2000">
-      <UniqueIdentifier>{63b33bd9-2425-49fa-8f43-8e107934c21f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jpeg\libjpeg">
-      <UniqueIdentifier>{dd2ee477-f3c1-4411-b663-e37b40df46dd}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\jpeg\libjpeg12">
-      <UniqueIdentifier>{ef46adc5-905b-4f3a-bbb6-f42da0c8e1e1}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\l1b">
-      <UniqueIdentifier>{6cc7ab23-4684-4489-b06d-2292129848cb}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\leveller">
-      <UniqueIdentifier>{bcbe9172-2827-4929-b292-6a7a01ad17cd}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\mem">
-      <UniqueIdentifier>{73ea63da-eb29-4b61-8e79-6ffe0d45bf29}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\mrsid">
-      <UniqueIdentifier>{70d75129-1395-4a14-8e41-f59fd38fcc2b}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\msg">
-      <UniqueIdentifier>{de858920-083a-486d-a5bb-51972a8e8507}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\msgn">
-      <UniqueIdentifier>{298f35c4-4bf1-41cd-8e15-a31f681cf4eb}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\netcdf">
-      <UniqueIdentifier>{06c14359-ef3b-464e-b274-7ace4771f3d4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\nitf">
-      <UniqueIdentifier>{1d59e4e6-424c-410c-8771-22bc417e6f54}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\northwood">
-      <UniqueIdentifier>{f1644e14-6f93-440d-83a1-a4a73241be50}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\ogdi">
-      <UniqueIdentifier>{71829827-f223-4c42-80b2-461a7b5af526}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pcidsk">
-      <UniqueIdentifier>{ac3bba5d-ce9b-451a-96c1-8dd2cfba1d4a}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pcidsk\sdk">
-      <UniqueIdentifier>{504eb4ce-6329-46ac-8ca9-19ad8435a8dd}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pcraster">
-      <UniqueIdentifier>{73833e4d-65fb-49d9-8a97-08728bd0d738}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pcraster\libcsf">
-      <UniqueIdentifier>{e2a14749-e0e4-44a0-a602-4b594c36bba6}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pds">
-      <UniqueIdentifier>{c6bf39fc-6605-4941-8747-9d3229cf2cfd}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\pgchip">
-      <UniqueIdentifier>{53cdd94e-f2a7-4a4b-99c1-80120fe18dbe}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\png">
-      <UniqueIdentifier>{b9951f13-abbf-4b87-8b70-f3d0d333a6a8}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\png\libpng">
-      <UniqueIdentifier>{9e8c8f60-204b-4bb9-974d-b4b2be153f5e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\r">
-      <UniqueIdentifier>{4b9c7d67-0cb3-4b1d-bfaf-372a1d6215a3}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\rasterlite">
-      <UniqueIdentifier>{74870cdf-0ccd-44f6-a1a4-995acea13f55}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\raw">
-      <UniqueIdentifier>{c6bee287-968b-454a-a39d-229e451ccbb8}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\rik">
-      <UniqueIdentifier>{2861ce40-ea95-469f-87e1-6853b0f65cfb}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\rmf">
-      <UniqueIdentifier>{084c3aad-7f22-4200-b138-2600191180d3}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\rs2">
-      <UniqueIdentifier>{08736a67-5aec-4d4b-b30b-f88f794c14ee}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\saga">
-      <UniqueIdentifier>{89656196-16ae-4ec4-ad59-dcdee377e93e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\sde">
-      <UniqueIdentifier>{2eb14da4-e32a-40c8-8b92-62e315350edb}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\sdts">
-      <UniqueIdentifier>{f980a589-5cc5-41af-918a-09baf811c893}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\sgi">
-      <UniqueIdentifier>{aa25154a-c26e-4b5f-97f6-a4ea745da78c}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\srtmhgt">
-      <UniqueIdentifier>{f7585c1c-5ebc-4f01-87ae-23655c2f0a3d}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\terragen">
-      <UniqueIdentifier>{ce3ab765-f4ba-45bf-9cf7-9113638fc3c4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\terralib">
-      <UniqueIdentifier>{12fa7e3b-dc06-4f1f-8f7e-77896d2347a8}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\til">
-      <UniqueIdentifier>{3e7f5d6c-6eb8-4c8f-b7d6-9439efa7acac}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\tsx">
-      <UniqueIdentifier>{4f748adb-019c-4060-8fd3-559516138c63}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\usgsdem">
-      <UniqueIdentifier>{4ab16d32-5d6e-4c96-b168-a9387c5bca71}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\vrt">
-      <UniqueIdentifier>{eee6e27b-a972-43a8-b045-2fc576d46991}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\wcs">
-      <UniqueIdentifier>{f193bd7d-9341-48e2-a302-a99a804cd09e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\wktraster">
-      <UniqueIdentifier>{1fa50002-bf3c-4bae-8333-73fbe3a05f95}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\wms">
-      <UniqueIdentifier>{7f935bff-2ed4-4cb0-993c-f973ab7aa391}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\xpm">
-      <UniqueIdentifier>{bc0fa517-f05d-4743-9a53-b41e08b6d54f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\frmts\zlib">
-      <UniqueIdentifier>{60c52798-4a1e-4ac3-a469-c1c78e518f7a}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\gcore">
-      <UniqueIdentifier>{0bbdb3ab-3d03-4b68-ab32-c2bb9825f83e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr">
-      <UniqueIdentifier>{c72008d6-4385-488a-b822-2975cc6ba844}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts">
-      <UniqueIdentifier>{80d03b3c-fb8d-443f-bbda-3ac3ead5ebf5}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\avc">
-      <UniqueIdentifier>{5679e401-fa22-499e-b945-f89d34d9de1a}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\bna">
-      <UniqueIdentifier>{26075fe7-d8f4-4d9b-bed4-be5351f1015e}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\csv">
-      <UniqueIdentifier>{14993417-9359-45d0-a9c8-e6f4bee58856}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\dgn">
-      <UniqueIdentifier>{e9ea8222-7c5c-4f64-8b87-af2162bf1bdc}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\dgn\dist">
-      <UniqueIdentifier>{3585397d-77ba-4fd6-870c-1f15dd98ce26}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\dods">
-      <UniqueIdentifier>{2ad4036f-e259-4944-ad74-9fdead54fec0}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\dxf">
-      <UniqueIdentifier>{a3adc29b-b76f-4991-bbaf-7099c9eb1f4c}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\fme">
-      <UniqueIdentifier>{0bb7ab25-eec2-4b0e-ac3a-3f83cc0b0f92}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\generic">
-      <UniqueIdentifier>{b7ccd0d5-11b4-455d-af22-83cb01bcbb6f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\geoconcept">
-      <UniqueIdentifier>{d0b5907a-9144-4a2b-a76f-981cd90ed94f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\geojson">
-      <UniqueIdentifier>{bb37be53-c9e0-4345-8571-92d9291dd115}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\geojson\jsonc">
-      <UniqueIdentifier>{d07b3877-0263-44be-97cc-5163f316b626}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\georss">
-      <UniqueIdentifier>{257768d2-69cf-4e1e-89ff-cd68fa919d83}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\gml">
-      <UniqueIdentifier>{3c27d01d-934f-40cc-b2e2-c216fcad9751}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\gmt">
-      <UniqueIdentifier>{dfc538af-435c-4d80-8f26-d86fa77c2eb8}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\gpx">
-      <UniqueIdentifier>{1b554f07-35a6-4fbe-903c-d8a68a05d163}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\gtm">
-      <UniqueIdentifier>{e581c70c-b637-4dca-88c0-f8d6ef688464}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\idb">
-      <UniqueIdentifier>{f1139628-f050-4925-a605-29e9f25d8e3d}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\ili">
-      <UniqueIdentifier>{f46e984d-d9a9-4e05-831e-f83b1e411851}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\ili\iom">
-      <UniqueIdentifier>{8194ac09-865e-472c-be28-95138d397e41}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\kml">
-      <UniqueIdentifier>{b4ec30f6-c794-4063-874f-f400c7c5e183}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\mem">
-      <UniqueIdentifier>{da6692b7-9970-4f57-b459-0999b8b7c4e6}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\mitab">
-      <UniqueIdentifier>{769a16d2-d5c4-4797-882f-91f3f2e29ef7}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\mysql">
-      <UniqueIdentifier>{485f41f1-88b9-453f-9c2e-fdcf46582c90}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\ntf">
-      <UniqueIdentifier>{2ab5775f-cab3-4dfe-8b65-aeae53b2e0f4}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\oci">
-      <UniqueIdentifier>{65cb7d0d-2dfa-4955-84c9-34e8d8750130}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\odbc">
-      <UniqueIdentifier>{ed148028-e1b9-4e40-b897-caa6073448aa}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\ogdi">
-      <UniqueIdentifier>{faa218d4-50e1-4f6e-8210-5d38ff928ac9}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\pcidsk">
-      <UniqueIdentifier>{499448ca-4c3a-4b60-986c-24232bd6266d}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\pg">
-      <UniqueIdentifier>{f296b0ff-12dc-44e0-b506-c777539bfc22}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\pgeo">
-      <UniqueIdentifier>{2226ff9b-d167-4c00-9254-8f190b49855b}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\rec">
-      <UniqueIdentifier>{d1ccf4e8-18bc-4778-9a7f-e613b71ee74a}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\s57">
-      <UniqueIdentifier>{4a2453ef-38b8-4b1c-86d4-e0ce186aee07}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\sde">
-      <UniqueIdentifier>{ffc169ae-7a76-4576-9df3-64e79a66a18d}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\sdts">
-      <UniqueIdentifier>{2696a667-4bc6-4a5a-83aa-1c1fe89b371b}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\shape">
-      <UniqueIdentifier>{d7b5e869-59b3-4a80-b0be-261e44f66127}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\sqlite">
-      <UniqueIdentifier>{8e8306ae-ce17-4597-a835-281c5a667677}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\tiger">
-      <UniqueIdentifier>{2833ad7c-76c0-4998-924d-0ffe6fea02bf}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\vrt">
-      <UniqueIdentifier>{a4f4a834-0ef9-4f06-b262-27d943c1b184}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\ogrsf_frmts\xplane">
-      <UniqueIdentifier>{1df67e86-5f34-4cd1-9284-a70786b7868f}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\ogr\wcts">
-      <UniqueIdentifier>{18e924c8-4ed1-48d2-9489-ee75ac7f0242}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Make Files\port">
-      <UniqueIdentifier>{e581888f-ba3f-46c0-a586-4b23c9182823}</UniqueIdentifier>
-      <Extensions>*.vc;*.opt</Extensions>
-    </Filter>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{928ff5d3-ec5c-4b83-a886-88f7b11003fe}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\alg">
-      <UniqueIdentifier>{4dd123a8-c229-441c-9ed5-1b8b60f2af9e}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\apps">
-      <UniqueIdentifier>{42d527b2-1a70-4ad7-84e6-e9259eadcdc7}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\bridge">
-      <UniqueIdentifier>{4bfb8da9-bf92-401b-bbbe-e9dd626c525a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts">
-      <UniqueIdentifier>{518624cd-62ab-4869-91a5-f1058daf3aab}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\aaigrid">
-      <UniqueIdentifier>{baa2eb10-507b-415e-860d-1139146a4e72}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\adrg">
-      <UniqueIdentifier>{bb194839-0ba9-4d2b-ae58-304ecf18dad1}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\aigrid">
-      <UniqueIdentifier>{b9c7418e-3133-4707-bb46-66eb07adf9fd}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\airsar">
-      <UniqueIdentifier>{009dee38-f8cb-4464-bbc9-8c17af50bc8b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\blx">
-      <UniqueIdentifier>{ffec99a0-87eb-420d-a57a-1f933b749685}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\bmp">
-      <UniqueIdentifier>{ae135aa2-fb75-4b0d-8d3e-c4ee15c07053}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\bsb">
-      <UniqueIdentifier>{f25f6410-0d67-4ee6-b2c3-e89b906bea8f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ceos">
-      <UniqueIdentifier>{c38b0042-7ae7-45c3-9614-279122e49578}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ceos2">
-      <UniqueIdentifier>{45bb30fe-8394-4870-a970-427868cb09ce}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\coasp">
-      <UniqueIdentifier>{39e80543-e138-4d7f-89d4-285fdcc97df8}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\cosar">
-      <UniqueIdentifier>{1ae2b351-992c-47da-a85f-c972b39738e8}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\dimap">
-      <UniqueIdentifier>{bcb0f87a-a27b-4f23-90d1-7f1c87b77dc2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\dods">
-      <UniqueIdentifier>{260acefb-f3dc-4e25-b4b1-30c6df870c4b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\dted">
-      <UniqueIdentifier>{b62d8caf-336f-416a-bd3a-33262ccde8d9}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ecw">
-      <UniqueIdentifier>{c07c78f7-0925-42d3-aa28-b7493642f50d}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\elas">
-      <UniqueIdentifier>{f7c64f6c-7db3-4e27-8c3d-60cf2a935394}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\envisat">
-      <UniqueIdentifier>{a2bcb58e-b7eb-4e8c-92f5-6997141e6681}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\epsilon">
-      <UniqueIdentifier>{47d257e6-7eb2-4e2f-9ad1-531022f82829}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ers">
-      <UniqueIdentifier>{6cb43304-6666-40ea-882e-50b9690499eb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\fit">
-      <UniqueIdentifier>{72a2bea6-7044-4148-88a9-86b6ac933352}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\fits">
-      <UniqueIdentifier>{1f02864c-01b7-4e4a-8bd2-d3b9cca7a0ac}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\georaster">
-      <UniqueIdentifier>{691cd713-93c2-408b-afa2-dc0e7af30eb2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gff">
-      <UniqueIdentifier>{b43f0b1f-b87c-451a-9998-2f82520355b7}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gif">
-      <UniqueIdentifier>{7ce35c83-bf82-4912-afc4-0268b17c365a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gif\giflib">
-      <UniqueIdentifier>{143e2eae-4531-4a1f-9863-f0f3a3f95d5c}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\grass">
-      <UniqueIdentifier>{b7957e3d-7ac9-430a-a532-c97debe115db}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\grib">
-      <UniqueIdentifier>{f876a226-14ce-475a-afa5-b65b337d035b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\grib\degrib18">
-      <UniqueIdentifier>{e1695f5e-195e-4b10-9466-f3f420d3bb1f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\grib\degrib18\degrib">
-      <UniqueIdentifier>{c5b03968-ad62-4158-aa53-5ae2b4e78898}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\grib\degrib18\g2clib-1.0.4">
-      <UniqueIdentifier>{58a69973-0414-48d5-8a5a-8af860eb2821}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gsg">
-      <UniqueIdentifier>{8f7bff73-baa3-4352-9fc5-a1ca7519cfdf}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gtiff">
-      <UniqueIdentifier>{5c298d61-874d-4eee-92d9-eaddf4e24b41}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gtiff\libgeotiff">
-      <UniqueIdentifier>{4da6e344-6c25-4e03-b5c5-babf8d36e9b0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gtiff\libtiff">
-      <UniqueIdentifier>{f1a5e875-181b-489d-9645-3c2f7e593fe2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\gxf">
-      <UniqueIdentifier>{85210419-fdef-4eb8-86a2-e4d9f14e82e2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\hdf4">
-      <UniqueIdentifier>{c52edc0c-9fce-4140-9a2d-08467191a587}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\hdf4\hdf-eos">
-      <UniqueIdentifier>{22f669a4-ffa3-4544-93b2-c3fc5fa725c7}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\hdf5">
-      <UniqueIdentifier>{48970417-c1d1-4185-a512-7f2c6274849a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\hfa">
-      <UniqueIdentifier>{43697ef4-5167-4672-8f92-79757c64b191}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\idrisi">
-      <UniqueIdentifier>{00924f08-3ae5-466b-a40e-cc89bfd0c0fc}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ilwis">
-      <UniqueIdentifier>{c154702c-ecc7-48c5-b6c7-e20351f665af}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ingr">
-      <UniqueIdentifier>{c5d7150b-726c-49e4-aa28-6f6d3e239274}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\iso8211">
-      <UniqueIdentifier>{960fa934-c3a4-4655-8864-f7ce5562f8df}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jaxapalsar">
-      <UniqueIdentifier>{39a1c82b-0ef3-4c97-b781-6f5bf2ede265}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jdem">
-      <UniqueIdentifier>{dc58ab4e-9914-46bc-bc2f-f670acde1f03}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jp2kak">
-      <UniqueIdentifier>{f0d29641-a13f-4b73-92d1-3ebadf65d5b4}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jpeg">
-      <UniqueIdentifier>{c275e83d-26cc-482a-ae0b-7d1f3f844973}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jpeg2000">
-      <UniqueIdentifier>{5b649e18-4d6f-45c8-8cff-77544723d4ff}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jpeg\libjpeg">
-      <UniqueIdentifier>{5ac27fee-0f3f-42bf-a609-3d307140bd62}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\jpeg\libjpeg12">
-      <UniqueIdentifier>{317bee46-5af2-4e54-8701-18165d1bbe52}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\l1b">
-      <UniqueIdentifier>{8d9c84ca-1e5b-499d-ba91-ca13810c9d0a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\leveller">
-      <UniqueIdentifier>{6dd75b94-ce27-4eb5-924b-34c754d22806}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\mem">
-      <UniqueIdentifier>{29ea68d4-1515-4220-84a8-965fbfc9a223}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\mrsid">
-      <UniqueIdentifier>{525134bc-1915-41d9-ad97-f19b9b2c60b8}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\msg">
-      <UniqueIdentifier>{3d798d2d-259f-4dcb-9da5-d7a381458c4c}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\msgn">
-      <UniqueIdentifier>{76f5d67e-9db7-4ced-8a43-4e3c2d987e4b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\netcdf">
-      <UniqueIdentifier>{aae8336c-a4b0-43b3-b8d3-b121fb012e82}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\nitf">
-      <UniqueIdentifier>{be99b37f-5cac-474d-97bb-47b1b3b63b16}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\northwood">
-      <UniqueIdentifier>{c52d916b-799a-497d-bc76-ee0ff46ca32c}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\ogdi">
-      <UniqueIdentifier>{d60fbe29-e8bc-4d76-9f2e-44742f04c3fb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk">
-      <UniqueIdentifier>{5a144c06-df48-4c62-bb6d-c400eeb97a30}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk\sdk">
-      <UniqueIdentifier>{a62e8372-311b-4667-b1ef-054a4c59e9bc}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk\sdk\channel">
-      <UniqueIdentifier>{a72f4131-e27d-4ef2-ae4c-3729b0c64b67}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk\sdk\core">
-      <UniqueIdentifier>{42adb112-2ba4-4d8e-b296-6c481b7796f8}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk\sdk\port">
-      <UniqueIdentifier>{1fbc342e-a2ab-4394-b212-cf3c4bf4b7eb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcidsk\sdk\segment">
-      <UniqueIdentifier>{c4343979-5854-4d8f-9e10-7a2997dee515}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcraster">
-      <UniqueIdentifier>{46243e8c-bf24-4c24-8a0e-566c359fe14a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pcraster\libcsf">
-      <UniqueIdentifier>{2a443b3c-033e-4c6c-9fbf-015d64b47d9b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pds">
-      <UniqueIdentifier>{6511a0de-c451-49be-935f-fa208a7026ba}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\pgchip">
-      <UniqueIdentifier>{af1b7703-87d2-41d3-81f9-cd7ee63d64a7}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\png">
-      <UniqueIdentifier>{b919e4d4-99c9-4dea-b588-f5009b2e0751}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\png\libpng">
-      <UniqueIdentifier>{03efe141-6210-4b02-aba6-3e227dc7addf}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\r">
-      <UniqueIdentifier>{dbc9ed80-0b87-4f64-b77c-1f4e912bb9ca}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\rasterlite">
-      <UniqueIdentifier>{ba6592d4-8af0-4407-b079-9fc0530031ed}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\raw">
-      <UniqueIdentifier>{0d5b642f-5b2a-4ea3-8047-73a05b402a76}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\rik">
-      <UniqueIdentifier>{01d1ff02-ac15-474c-a4e3-076f7a4e0409}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\rmf">
-      <UniqueIdentifier>{32a00b73-ec95-4f72-b2a1-901599491d99}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\rs2">
-      <UniqueIdentifier>{341a53a4-3ba6-458e-b589-a76b256522bd}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\saga">
-      <UniqueIdentifier>{307285b9-79b7-42d2-9a71-e1dfa437c7fe}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\sde">
-      <UniqueIdentifier>{a5a18625-209d-4fd5-a1af-c6fd483ec8cc}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\sdts">
-      <UniqueIdentifier>{0c648c06-14e8-41cd-b220-26aa113108b0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\sgi">
-      <UniqueIdentifier>{b5caa7fe-d694-43cb-8840-c00e2232bdcf}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\srtmhgt">
-      <UniqueIdentifier>{1d0aabb1-ba83-454d-9014-044a9b0f54a2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\terragen">
-      <UniqueIdentifier>{9e4f9123-0c0e-430b-9dae-56096dc6ab2f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\terralib">
-      <UniqueIdentifier>{d15c77a0-1ea4-4344-8eae-25bcd1ba8245}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\til">
-      <UniqueIdentifier>{76b5736c-83df-4b37-8cd4-72a30db48b51}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\tsx">
-      <UniqueIdentifier>{33ae0250-9cc6-4079-b2a9-841ec4b2d0d2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\usgsdem">
-      <UniqueIdentifier>{d5466bed-99a4-471c-80c8-5c8aeee6a11a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\vrt">
-      <UniqueIdentifier>{533dd264-e9ef-4d09-a185-fb9c43e003bc}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\wcs">
-      <UniqueIdentifier>{fb4328c3-7e4d-41be-a2d9-0dde14b17fa5}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\wktraster">
-      <UniqueIdentifier>{12fcbc79-5bc5-4b3d-a6cb-c46e8059fc60}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\wms">
-      <UniqueIdentifier>{cb323329-4807-44fc-b5df-b303a81e1cfb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\xpm">
-      <UniqueIdentifier>{f706d687-b0ef-460e-a246-bd02dba3660f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\frmts\zlib">
-      <UniqueIdentifier>{907361dc-73c9-42c2-9268-f0fb0fd43cce}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\gcore">
-      <UniqueIdentifier>{9300a2d4-7d36-4aab-ab79-5cc7c5bb5efa}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr">
-      <UniqueIdentifier>{7eca3ad5-0cbb-4883-ae82-795162a2b34e}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts">
-      <UniqueIdentifier>{bba6c749-9c4f-4b4f-8679-3c9419e27452}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\avc">
-      <UniqueIdentifier>{60967d3d-4b1d-4a6e-968d-ecfc9dd3762f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\bna">
-      <UniqueIdentifier>{ebe4abf3-53b6-4ebe-91d8-39a746d3cd5a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\csv">
-      <UniqueIdentifier>{bcecf060-0de2-49c3-b2e1-1ecc585d76f0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\dgn">
-      <UniqueIdentifier>{72113818-56f5-423d-8bb2-fd642519e86b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\dods">
-      <UniqueIdentifier>{0db6569b-de3e-4a50-9e0e-2eeba3e48610}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\dxf">
-      <UniqueIdentifier>{18a2f869-f288-41a7-9849-9ae767208eaa}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\fme">
-      <UniqueIdentifier>{37c77c91-c646-419c-98e9-09d6db5abdd8}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\generic">
-      <UniqueIdentifier>{eb69582a-b36b-460e-be99-e6734f6ed0f0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\geoconcept">
-      <UniqueIdentifier>{bc2a685a-026c-4e07-90aa-5343d1d908df}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\geojson">
-      <UniqueIdentifier>{276d14a1-402c-4048-9dce-334913935193}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\geojson\jsonc">
-      <UniqueIdentifier>{ca2aeb79-28c1-4584-8822-841f17052f60}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\georss">
-      <UniqueIdentifier>{4cd19c31-5117-4a2c-bc6a-6af2012498ef}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\gml">
-      <UniqueIdentifier>{c59a1227-327e-41ca-837c-c0d39e516d7b}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\gmt">
-      <UniqueIdentifier>{90bdc50a-fcec-49f4-968a-edaac9c4edcd}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\gpx">
-      <UniqueIdentifier>{f2e43d7f-dd00-4235-89c8-32884b3c0ae0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\grass">
-      <UniqueIdentifier>{d2679b54-7dac-4c72-a109-562ef9e6a1fb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\gtm">
-      <UniqueIdentifier>{3bc9f5df-d2d2-435f-8fb5-d48d0c6d0b97}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\idb">
-      <UniqueIdentifier>{4ceefeef-3972-4bdc-996c-8aeee54fcbf6}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\ili">
-      <UniqueIdentifier>{2cd1cd82-e59a-48a9-b608-c686d0047f12}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\ili\iom">
-      <UniqueIdentifier>{feea39b9-2b50-4689-936f-bc6d9b6f65e1}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\ingres">
-      <UniqueIdentifier>{38704eee-109c-4dbd-b67e-31b3ab675d9f}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\kml">
-      <UniqueIdentifier>{e327db4e-01bb-4e6b-9853-83fcb865f06c}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\mem">
-      <UniqueIdentifier>{30801717-8c4a-4ac6-b647-9b12bc0b964e}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\mitab">
-      <UniqueIdentifier>{c18fc39c-d526-4238-bdde-9b249053b0a0}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\mysql">
-      <UniqueIdentifier>{2b4ecdf5-ccf4-4bdd-9e4c-0f9321b35f4d}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\ntf">
-      <UniqueIdentifier>{a697bea6-0a3d-48ec-812f-ab976ac06ce1}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\oci">
-      <UniqueIdentifier>{a5debf63-efc7-40e6-b0d2-cdb83ba29d8a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\odbc">
-      <UniqueIdentifier>{dfd896fa-e6a4-4059-b4de-b27cd37c9629}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\ogdi">
-      <UniqueIdentifier>{e778b26b-9ff7-40ce-8c2d-89639eb488b3}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\pcidsk">
-      <UniqueIdentifier>{94afdd11-3bb4-4960-a641-4aa860ffb3cb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\pg">
-      <UniqueIdentifier>{399bc467-50f7-4ec4-b6eb-236c998e23f5}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\pgeo">
-      <UniqueIdentifier>{79923a45-e8d7-445a-875a-48fadd89ad34}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\rec">
-      <UniqueIdentifier>{af9e70fa-dc06-429b-b80a-ed2843fb14e6}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\s57">
-      <UniqueIdentifier>{f8687351-e813-496e-b5f5-0095ea881547}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\sde">
-      <UniqueIdentifier>{d18152ca-a0c3-4482-a42b-f1b79f1bfeb7}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\sdts">
-      <UniqueIdentifier>{e5197010-ba99-4410-8838-bcb363a63cc2}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\shape">
-      <UniqueIdentifier>{f4ef6cdb-fdc1-47ac-822c-8110095d1547}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\sqlite">
-      <UniqueIdentifier>{64f23a02-0a7a-464d-8e1e-91b356ef737e}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\tiger">
-      <UniqueIdentifier>{9ad12224-548c-4252-9822-08d34051774a}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\vrt">
-      <UniqueIdentifier>{4f7efc9e-875c-4151-9ce4-10676317bcbb}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\ogrsf_frmts\xplane">
-      <UniqueIdentifier>{61a02ead-0532-431f-8ab0-5cf5450707de}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\ogr\wcts">
-      <UniqueIdentifier>{9bde6f67-208a-458f-b7d6-7c11843da325}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-    <Filter Include="Source Files\port">
-      <UniqueIdentifier>{dd1de2ac-f536-4de5-aa69-6695ce760f5e}</UniqueIdentifier>
-      <Extensions>*.c;*.cpp</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="alg\makefile.vc">
-      <Filter>Make Files\alg</Filter>
-    </None>
-    <None Include="apps\makefile.vc">
-      <Filter>Make Files\apps</Filter>
-    </None>
-    <None Include="frmts\aaigrid\makefile.vc">
-      <Filter>Make Files\frmts\aaigrid</Filter>
-    </None>
-    <None Include="frmts\adrg\makefile.vc">
-      <Filter>Make Files\frmts\adrg</Filter>
-    </None>
-    <None Include="frmts\aigrid\makefile.vc">
-      <Filter>Make Files\frmts\aigrid</Filter>
-    </None>
-    <None Include="frmts\airsar\makefile.vc">
-      <Filter>Make Files\frmts\airsar</Filter>
-    </None>
-    <None Include="frmts\blx\makefile.vc">
-      <Filter>Make Files\frmts\blx</Filter>
-    </None>
-    <None Include="frmts\bmp\makefile.vc">
-      <Filter>Make Files\frmts\bmp</Filter>
-    </None>
-    <None Include="frmts\bsb\makefile.vc">
-      <Filter>Make Files\frmts\bsb</Filter>
-    </None>
-    <None Include="frmts\ceos2\makefile.vc">
-      <Filter>Make Files\frmts\ceos2</Filter>
-    </None>
-    <None Include="frmts\ceos\makefile.vc">
-      <Filter>Make Files\frmts\ceos</Filter>
-    </None>
-    <None Include="frmts\coasp\makefile.vc">
-      <Filter>Make Files\frmts\coasp</Filter>
-    </None>
-    <None Include="frmts\cosar\makefile.vc">
-      <Filter>Make Files\frmts\cosar</Filter>
-    </None>
-    <None Include="frmts\dimap\makefile.vc">
-      <Filter>Make Files\frmts\dimap</Filter>
-    </None>
-    <None Include="frmts\dods\makefile.vc">
-      <Filter>Make Files\frmts\dods</Filter>
-    </None>
-    <None Include="frmts\dted\makefile.vc">
-      <Filter>Make Files\frmts\dted</Filter>
-    </None>
-    <None Include="frmts\ecw\makefile.vc">
-      <Filter>Make Files\frmts\ecw</Filter>
-    </None>
-    <None Include="frmts\elas\makefile.vc">
-      <Filter>Make Files\frmts\elas</Filter>
-    </None>
-    <None Include="frmts\envisat\makefile.vc">
-      <Filter>Make Files\frmts\envisat</Filter>
-    </None>
-    <None Include="frmts\epsilon\makefile.vc">
-      <Filter>Make Files\frmts\epsilon</Filter>
-    </None>
-    <None Include="frmts\ers\makefile.vc">
-      <Filter>Make Files\frmts\ers</Filter>
-    </None>
-    <None Include="frmts\fits\makefile.vc">
-      <Filter>Make Files\frmts\fits</Filter>
-    </None>
-    <None Include="frmts\fit\makefile.vc">
-      <Filter>Make Files\frmts\fit</Filter>
-    </None>
-    <None Include="frmts\georaster\makefile.vc">
-      <Filter>Make Files\frmts\georaster</Filter>
-    </None>
-    <None Include="frmts\gff\makefile.vc">
-      <Filter>Make Files\frmts\gff</Filter>
-    </None>
-    <None Include="frmts\gif\giflib\makefile.vc">
-      <Filter>Make Files\frmts\gif\giflib</Filter>
-    </None>
-    <None Include="frmts\gif\makefile.vc">
-      <Filter>Make Files\frmts\gif</Filter>
-    </None>
-    <None Include="frmts\grib\degrib18\degrib\makefile.vc">
-      <Filter>Make Files\frmts\grib\degrib18\degrib</Filter>
-    </None>
-    <None Include="frmts\grib\degrib18\g2clib-1.0.4\makefile.vc">
-      <Filter>Make Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </None>
-    <None Include="frmts\grib\degrib18\makefile.vc">
-      <Filter>Make Files\frmts\grib\degrib18</Filter>
-    </None>
-    <None Include="frmts\grib\makefile.vc">
-      <Filter>Make Files\frmts\grib</Filter>
-    </None>
-    <None Include="frmts\gsg\makefile.vc">
-      <Filter>Make Files\frmts\gsg</Filter>
-    </None>
-    <None Include="frmts\gtiff\libgeotiff\makefile.vc">
-      <Filter>Make Files\frmts\gtiff\libgeotiff</Filter>
-    </None>
-    <None Include="frmts\gtiff\libtiff\makefile.vc">
-      <Filter>Make Files\frmts\gtiff\libtiff</Filter>
-    </None>
-    <None Include="frmts\gtiff\makefile.vc">
-      <Filter>Make Files\frmts\gtiff</Filter>
-    </None>
-    <None Include="frmts\gxf\makefile.vc">
-      <Filter>Make Files\frmts\gxf</Filter>
-    </None>
-    <None Include="frmts\hdf4\hdf-eos\makefile.vc">
-      <Filter>Make Files\frmts\hdf4\hdf-eos</Filter>
-    </None>
-    <None Include="frmts\hdf4\makefile.vc">
-      <Filter>Make Files\frmts\hdf4</Filter>
-    </None>
-    <None Include="frmts\hdf5\makefile.vc">
-      <Filter>Make Files\frmts\hdf5</Filter>
-    </None>
-    <None Include="frmts\hfa\makefile.vc">
-      <Filter>Make Files\frmts\hfa</Filter>
-    </None>
-    <None Include="frmts\idrisi\makefile.vc">
-      <Filter>Make Files\frmts\idrisi</Filter>
-    </None>
-    <None Include="frmts\ilwis\makefile.vc">
-      <Filter>Make Files\frmts\ilwis</Filter>
-    </None>
-    <None Include="frmts\ingr\makefile.vc">
-      <Filter>Make Files\frmts\ingr</Filter>
-    </None>
-    <None Include="frmts\iso8211\makefile.vc">
-      <Filter>Make Files\frmts\iso8211</Filter>
-    </None>
-    <None Include="frmts\jaxapalsar\makefile.vc">
-      <Filter>Make Files\frmts\jaxapalsar</Filter>
-    </None>
-    <None Include="frmts\jdem\makefile.vc">
-      <Filter>Make Files\frmts\jdem</Filter>
-    </None>
-    <None Include="frmts\jp2kak\makefile.vc">
-      <Filter>Make Files\frmts\jp2kak</Filter>
-    </None>
-    <None Include="frmts\jpeg2000\makefile.vc">
-      <Filter>Make Files\frmts\jpeg2000</Filter>
-    </None>
-    <None Include="frmts\jpeg\libjpeg12\makefile.vc">
-      <Filter>Make Files\frmts\jpeg\libjpeg12</Filter>
-    </None>
-    <None Include="frmts\jpeg\libjpeg\makefile.vc">
-      <Filter>Make Files\frmts\jpeg\libjpeg</Filter>
-    </None>
-    <None Include="frmts\jpeg\makefile.vc">
-      <Filter>Make Files\frmts\jpeg</Filter>
-    </None>
-    <None Include="frmts\l1b\makefile.vc">
-      <Filter>Make Files\frmts\l1b</Filter>
-    </None>
-    <None Include="frmts\leveller\makefile.vc">
-      <Filter>Make Files\frmts\leveller</Filter>
-    </None>
-    <None Include="frmts\makefile.vc">
-      <Filter>Make Files\frmts</Filter>
-    </None>
-    <None Include="frmts\mem\makefile.vc">
-      <Filter>Make Files\frmts\mem</Filter>
-    </None>
-    <None Include="frmts\mrsid\makefile.vc">
-      <Filter>Make Files\frmts\mrsid</Filter>
-    </None>
-    <None Include="frmts\msgn\makefile.vc">
-      <Filter>Make Files\frmts\msgn</Filter>
-    </None>
-    <None Include="frmts\msg\makefile.vc">
-      <Filter>Make Files\frmts\msg</Filter>
-    </None>
-    <None Include="frmts\netcdf\makefile.vc">
-      <Filter>Make Files\frmts\netcdf</Filter>
-    </None>
-    <None Include="frmts\nitf\makefile.vc">
-      <Filter>Make Files\frmts\nitf</Filter>
-    </None>
-    <None Include="frmts\northwood\makefile.vc">
-      <Filter>Make Files\frmts\northwood</Filter>
-    </None>
-    <None Include="frmts\ogdi\makefile.vc">
-      <Filter>Make Files\frmts\ogdi</Filter>
-    </None>
-    <None Include="frmts\pcidsk\makefile.vc">
-      <Filter>Make Files\frmts\pcidsk</Filter>
-    </None>
-    <None Include="frmts\pcidsk\sdk\Makefile.vc">
-      <Filter>Make Files\frmts\pcidsk\sdk</Filter>
-    </None>
-    <None Include="frmts\pcraster\libcsf\makefile.vc">
-      <Filter>Make Files\frmts\pcraster\libcsf</Filter>
-    </None>
-    <None Include="frmts\pcraster\makefile.vc">
-      <Filter>Make Files\frmts\pcraster</Filter>
-    </None>
-    <None Include="frmts\pds\makefile.vc">
-      <Filter>Make Files\frmts\pds</Filter>
-    </None>
-    <None Include="frmts\pgchip\makefile.vc">
-      <Filter>Make Files\frmts\pgchip</Filter>
-    </None>
-    <None Include="frmts\png\libpng\makefile.vc">
-      <Filter>Make Files\frmts\png\libpng</Filter>
-    </None>
-    <None Include="frmts\png\makefile.vc">
-      <Filter>Make Files\frmts\png</Filter>
-    </None>
-    <None Include="frmts\rasterlite\makefile.vc">
-      <Filter>Make Files\frmts\rasterlite</Filter>
-    </None>
-    <None Include="frmts\raw\makefile.vc">
-      <Filter>Make Files\frmts\raw</Filter>
-    </None>
-    <None Include="frmts\rik\makefile.vc">
-      <Filter>Make Files\frmts\rik</Filter>
-    </None>
-    <None Include="frmts\rmf\makefile.vc">
-      <Filter>Make Files\frmts\rmf</Filter>
-    </None>
-    <None Include="frmts\rs2\makefile.vc">
-      <Filter>Make Files\frmts\rs2</Filter>
-    </None>
-    <None Include="frmts\r\makefile.vc">
-      <Filter>Make Files\frmts\r</Filter>
-    </None>
-    <None Include="frmts\saga\makefile.vc">
-      <Filter>Make Files\frmts\saga</Filter>
-    </None>
-    <None Include="frmts\sde\makefile.vc">
-      <Filter>Make Files\frmts\sde</Filter>
-    </None>
-    <None Include="frmts\sdts\makefile.vc">
-      <Filter>Make Files\frmts\sdts</Filter>
-    </None>
-    <None Include="frmts\sgi\makefile.vc">
-      <Filter>Make Files\frmts\sgi</Filter>
-    </None>
-    <None Include="frmts\srtmhgt\makefile.vc">
-      <Filter>Make Files\frmts\srtmhgt</Filter>
-    </None>
-    <None Include="frmts\terragen\makefile.vc">
-      <Filter>Make Files\frmts\terragen</Filter>
-    </None>
-    <None Include="frmts\terralib\makefile.vc">
-      <Filter>Make Files\frmts\terralib</Filter>
-    </None>
-    <None Include="frmts\til\makefile.vc">
-      <Filter>Make Files\frmts\til</Filter>
-    </None>
-    <None Include="frmts\tsx\makefile.vc">
-      <Filter>Make Files\frmts\tsx</Filter>
-    </None>
-    <None Include="frmts\usgsdem\makefile.vc">
-      <Filter>Make Files\frmts\usgsdem</Filter>
-    </None>
-    <None Include="frmts\vrt\makefile.vc">
-      <Filter>Make Files\frmts\vrt</Filter>
-    </None>
-    <None Include="frmts\wcs\makefile.vc">
-      <Filter>Make Files\frmts\wcs</Filter>
-    </None>
-    <None Include="frmts\wktraster\makefile.vc">
-      <Filter>Make Files\frmts\wktraster</Filter>
-    </None>
-    <None Include="frmts\wms\makefile.vc">
-      <Filter>Make Files\frmts\wms</Filter>
-    </None>
-    <None Include="frmts\xpm\makefile.vc">
-      <Filter>Make Files\frmts\xpm</Filter>
-    </None>
-    <None Include="frmts\zlib\makefile.vc">
-      <Filter>Make Files\frmts\zlib</Filter>
-    </None>
-    <None Include="gcore\makefile.vc">
-      <Filter>Make Files\gcore</Filter>
-    </None>
-    <None Include="makefile.vc">
-      <Filter>Make Files</Filter>
-    </None>
-    <None Include="nmake-wince.opt">
-      <Filter>Make Files</Filter>
-    </None>
-    <None Include="nmake.opt">
-      <Filter>Make Files</Filter>
-    </None>
-    <None Include="ogr\makefile.vc">
-      <Filter>Make Files\ogr</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\avc\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\avc</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\bna\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\bna</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\csv\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\csv</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\dgn\dist\Makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\dgn\dist</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\dgn\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\dgn</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\dods\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\dods</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\dxf\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\dxf</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\fme\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\fme</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\generic\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\generic</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\geoconcept\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\geojson\jsonc\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\geojson\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\geojson</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\georss\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\georss</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\gml\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\gml</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\gmt\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\gmt</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\gpx\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\gpx</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\gtm\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\gtm</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\idb\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\idb</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\ili\iom\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\ili\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\ili</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\kml\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\kml</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\mem\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\mem</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\mitab\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\mitab</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\mysql\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\mysql</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\ntf\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\ntf</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\oci\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\oci</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\odbc\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\odbc</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\ogdi\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\ogdi</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\pcidsk\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\pcidsk</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\pgeo\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\pg\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\pg</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\rec\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\rec</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\s57\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\s57</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\sde\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\sde</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\sdts\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\sdts</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\shape\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\shape</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\sqlite\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\tiger\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\tiger</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\vrt\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\vrt</Filter>
-    </None>
-    <None Include="ogr\ogrsf_frmts\xplane\makefile.vc">
-      <Filter>Make Files\ogr\ogrsf_frmts\xplane</Filter>
-    </None>
-    <None Include="ogr\wcts\makefile.vc">
-      <Filter>Make Files\ogr\wcts</Filter>
-    </None>
-    <None Include="port\cpl_config.h.vc">
-      <Filter>Make Files\port</Filter>
-    </None>
-    <None Include="port\makefile.vc">
-      <Filter>Make Files\port</Filter>
-    </None>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="alg\gdalgrid.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="alg\gdalwarper.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="alg\gdal_alg.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="alg\gdal_alg_priv.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="alg\gvgcpfit.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="alg\thinplatespline.h">
-      <Filter>Include Files\alg</Filter>
-    </ClInclude>
-    <ClInclude Include="bridge\gdalbridge.h">
-      <Filter>Include Files\bridge</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\aigrid\aigrid.h">
-      <Filter>Include Files\frmts\aigrid</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\blx\blx.h">
-      <Filter>Include Files\frmts\blx</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\bsb\bsb_read.h">
-      <Filter>Include Files\frmts\bsb</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ceos2\ceos.h">
-      <Filter>Include Files\frmts\ceos2</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ceos\ceosopen.h">
-      <Filter>Include Files\frmts\ceos</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\dted\dted_api.h">
-      <Filter>Include Files\frmts\dted</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ecw\jp2userbox.h">
-      <Filter>Include Files\frmts\ecw</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ecw\vsiiostream.h">
-      <Filter>Include Files\frmts\ecw</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\envisat\EnvisatFile.h">
-      <Filter>Include Files\frmts\envisat</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ers\ershdrnode.h">
-      <Filter>Include Files\frmts\ers</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\fit\fit.h">
-      <Filter>Include Files\frmts\fit</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\fit\gstEndian.h">
-      <Filter>Include Files\frmts\fit</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\fit\gstTypes.h">
-      <Filter>Include Files\frmts\fit</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\georaster\georaster_priv.h">
-      <Filter>Include Files\frmts\georaster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\georaster\oci_wrapper.h">
-      <Filter>Include Files\frmts\georaster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gif\giflib\gif_hash.h">
-      <Filter>Include Files\frmts\gif\giflib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gif\giflib\gif_lib.h">
-      <Filter>Include Files\frmts\gif\giflib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gif\giflib\gif_lib_private.h">
-      <Filter>Include Files\frmts\gif\giflib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\clock.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\datasource.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\degrib1.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\degrib2.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\engribapi.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\filedatasource.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\fileendian.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\grib2api.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\inventory.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\memendian.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\memorydatasource.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\meta.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\metaname.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\myassert.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\myerror.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\myutil.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\scan.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\tdlpack.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\type.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\degrib\weather.h">
-      <Filter>Include Files\frmts\grib\degrib18\degrib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\drstemplates.h">
-      <Filter>Include Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\grib2.h">
-      <Filter>Include Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.h">
-      <Filter>Include Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.h">
-      <Filter>Include Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\gt_overview.h">
-      <Filter>Include Files\frmts\gtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\cpl_serv.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geokeys.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geonames.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geotiff.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geotiffio.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geovalues.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_config.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_keyp.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_normalize.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_simpletags.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\geo_tiffp.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libgeotiff\xtiffio.h">
-      <Filter>Include Files\frmts\gtiff\libgeotiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\t4.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tiff.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tiffconf.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tiffio.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tiffiop.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tiffvers.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tif_config.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tif_dir.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tif_fax3.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\tif_predict.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gtiff\libtiff\uvcode.h">
-      <Filter>Include Files\frmts\gtiff\libtiff</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\gxf\gxfopen.h">
-      <Filter>Include Files\frmts\gxf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf4\hdf-eos\ease.h">
-      <Filter>Include Files\frmts\hdf4\hdf-eos</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf4\hdf-eos\HdfEosDef.h">
-      <Filter>Include Files\frmts\hdf4\hdf-eos</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf4\hdf-eos\HDFEOSVersion.h">
-      <Filter>Include Files\frmts\hdf4\hdf-eos</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf4\hdf4compat.h">
-      <Filter>Include Files\frmts\hdf4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf4\hdf4dataset.h">
-      <Filter>Include Files\frmts\hdf4</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf5\gh5_convenience.h">
-      <Filter>Include Files\frmts\hdf5</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hdf5\hdf5dataset.h">
-      <Filter>Include Files\frmts\hdf5</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hfa\hfa.h">
-      <Filter>Include Files\frmts\hfa</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\hfa\hfa_p.h">
-      <Filter>Include Files\frmts\hfa</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ilwis\ilwisdataset.h">
-      <Filter>Include Files\frmts\ilwis</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ingr\IngrTypes.h">
-      <Filter>Include Files\frmts\ingr</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ingr\IntergraphBand.h">
-      <Filter>Include Files\frmts\ingr</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ingr\IntergraphDataset.h">
-      <Filter>Include Files\frmts\ingr</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\ingr\JpegHelper.h">
-      <Filter>Include Files\frmts\ingr</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\iso8211\iso8211.h">
-      <Filter>Include Files\frmts\iso8211</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jp2kak\subfile_source.h">
-      <Filter>Include Files\frmts\jp2kak</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jp2kak\vsil_target.h">
-      <Filter>Include Files\frmts\jp2kak</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg2000\jpeg2000_vsil_io.h">
-      <Filter>Include Files\frmts\jpeg2000</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\gdalexif.h">
-      <Filter>Include Files\frmts\jpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jchuff.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jconfig.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jdct.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jdhuff.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jerror.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jinclude.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jmemsys.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jmorecfg.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jpegint.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jpeglib.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg12\jversion.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg12</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jchuff.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jconfig.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jdct.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jdhuff.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jerror.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jinclude.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jmemsys.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jmorecfg.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jpegint.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jpeglib.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\jpeg\libjpeg\jversion.h">
-      <Filter>Include Files\frmts\jpeg\libjpeg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\mem\memdataset.h">
-      <Filter>Include Files\frmts\mem</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\mrsid\mrsidstream.h">
-      <Filter>Include Files\frmts\mrsid</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msgn\msg_basic_types.h">
-      <Filter>Include Files\frmts\msgn</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msgn\msg_reader_core.h">
-      <Filter>Include Files\frmts\msgn</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msg\msgcommand.h">
-      <Filter>Include Files\frmts\msg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msg\msgdataset.h">
-      <Filter>Include Files\frmts\msg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msg\prologue.h">
-      <Filter>Include Files\frmts\msg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msg\reflectancecalculator.h">
-      <Filter>Include Files\frmts\msg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\msg\xritheaderparser.h">
-      <Filter>Include Files\frmts\msg</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\netcdf\netcdfdataset.h">
-      <Filter>Include Files\frmts\netcdf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\nitf\mgrs.h">
-      <Filter>Include Files\frmts\nitf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\nitf\nitflib.h">
-      <Filter>Include Files\frmts\nitf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\nitf\rpftoclib.h">
-      <Filter>Include Files\frmts\nitf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\northwood\northwood.h">
-      <Filter>Include Files\frmts\northwood</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\gdal_pcidsk.h">
-      <Filter>Include Files\frmts\pcidsk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cbandinterleavedchannel.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cpcidskchannel.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\channel\ctiledchannel.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\cpcidskfile.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\metadataset.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\mutexholder.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\pcidsk_utils.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\protectedfile.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\core\sysvirtualfile.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\core</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_buffer.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_channel.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_config.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_exception.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_file.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_georef.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_interfaces.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_io.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_mutex.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_pct.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_segment.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_shape.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_types.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\pcidsk_vectorsegment.h">
-      <Filter>Include Files\frmts\pcidsk\sdk</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskgeoref.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskpct.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidsksegment.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\metadatasegment.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\pcidskgeorefbuilder.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\segmentfactory.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\sysblockmap.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcidsk\sdk\segment\uuid.h">
-      <Filter>Include Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\libcsf\csf.h">
-      <Filter>Include Files\frmts\pcraster\libcsf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\libcsf\csfattr.h">
-      <Filter>Include Files\frmts\pcraster\libcsf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\libcsf\csfimpl.h">
-      <Filter>Include Files\frmts\pcraster\libcsf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\libcsf\csftypes.h">
-      <Filter>Include Files\frmts\pcraster\libcsf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\libcsf\pcrtypes.h">
-      <Filter>Include Files\frmts\pcraster\libcsf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\pcrasterdataset.h">
-      <Filter>Include Files\frmts\pcraster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\pcrasterrasterband.h">
-      <Filter>Include Files\frmts\pcraster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pcraster\pcrasterutil.h">
-      <Filter>Include Files\frmts\pcraster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pds\nasakeywordhandler.h">
-      <Filter>Include Files\frmts\pds</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\pgchip\pgchip.h">
-      <Filter>Include Files\frmts\pgchip</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\png\libpng\png.h">
-      <Filter>Include Files\frmts\png\libpng</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\png\libpng\pngconf.h">
-      <Filter>Include Files\frmts\png\libpng</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\rasterlite\rasterlitedataset.h">
-      <Filter>Include Files\frmts\rasterlite</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\raw\atlsci_spheroid.h">
-      <Filter>Include Files\frmts\raw</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\raw\rawdataset.h">
-      <Filter>Include Files\frmts\raw</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\rmf\rmfdataset.h">
-      <Filter>Include Files\frmts\rmf</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\sde\gdal_sde.h">
-      <Filter>Include Files\frmts\sde</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\sde\sdedataset.h">
-      <Filter>Include Files\frmts\sde</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\sde\sdeerror.h">
-      <Filter>Include Files\frmts\sde</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\sde\sderasterband.h">
-      <Filter>Include Files\frmts\sde</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\sdts\sdts_al.h">
-      <Filter>Include Files\frmts\sdts</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\terralib\TerraLibDataset.h">
-      <Filter>Include Files\frmts\terralib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\terralib\TerraLibRasterBand.h">
-      <Filter>Include Files\frmts\terralib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\vrt\gdal_vrt.h">
-      <Filter>Include Files\frmts\vrt</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\vrt\vrtdataset.h">
-      <Filter>Include Files\frmts\vrt</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wktraster\wktraster.h">
-      <Filter>Include Files\frmts\wktraster</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\gdalhttp.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\md5.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\minidriver_tileservice.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\minidriver_tms.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\minidriver_wms.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\minidriver_worldwind.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\stdinc.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\wms\wmsdriver.h">
-      <Filter>Include Files\frmts\wms</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\crc32.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\deflate.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\inffast.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\inffixed.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\inflate.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\inftrees.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\trees.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\zconf.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\zlib.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="frmts\zlib\zutil.h">
-      <Filter>Include Files\frmts\zlib</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdaljp2metadata.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_frmts.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_pam.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_priv.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_proxy.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_rat.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="gcore\gdal_version.h">
-      <Filter>Include Files\gcore</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\avc\avc.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\avc\avc_mbyte.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\avc\dbfopen.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\avc\ogr_avc.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\bna\ogrbnaparser.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\bna\ogr_bna.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\csv\ogr_csv.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\csv</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dgnlib.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dgnlibp.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\dist\cpl_config.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dgn\dist</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dgn\ogr_dgn.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dods\ogr_dods.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\dxf\ogr_dxf.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\fme\fme2ogr.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\generic\ogr_gensql.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\geoconcept.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\arraylist.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\bits.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\config.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\debug.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_object.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_object_private.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_tokener.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\json_util.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\linkhash.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\jsonc\printbuf.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonreader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonutils.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\geojson\ogr_geojson.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\georss\ogr_georss.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\georss</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gml\gmlreader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gml\gmlreaderp.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gml\ogr_gml.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gmt\ogr_gmt.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gmt</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gpx\ogr_gpx.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gpx</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\grass\ogrgrass.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\grass</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gtm\gtm.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\gtm\ogr_gtm.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\idb\ogr_idb.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili1reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili1readerp.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili2reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ili2readerp.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ilihelper.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iomhelper.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iom\iom.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\iom\iom_p.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ogr_ili1.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ili\ogr_ili2.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ingres\ogr_ingres.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kml.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlnode.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlutility.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\kml\kmlvector.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\kml\ogr_kml.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mem\ogr_mem.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mem</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_geometry.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_priv.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mitab\mitab_utils.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\mysql\ogr_mysql.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ntf\ntf.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\oci\ogr_oci.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\odbc\ogr_odbc.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ogdi\ogrogdi.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\ogdi</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ogrsf_frmts.h">
-      <Filter>Include Files\ogr\ogrsf_frmts</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\ogr_attrind.h">
-      <Filter>Include Files\ogr\ogrsf_frmts</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\pcidsk</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\pgeo\ogr_pgeo.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\pg\ogrpgutility.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\pg\ogr_pg.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\rec\ogr_rec.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\rec</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\s57\ogr_s57.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\s57\s57.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\s57\s57tables.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\sde\ogr_sde.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\sde</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\sdts\ogr_sdts.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\sdts</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\shape\ogrshape.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\shape\shapefil.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\sqlite\ogr_sqlite.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\tiger\ogr_tiger.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\vrt\ogr_vrt.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\vrt</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogrsf_frmts\xplane\ogr_xplane_reader.h">
-      <Filter>Include Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_api.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_core.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_expat.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_feature.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_featurestyle.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_geometry.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_geos.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_p.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_spatialref.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_srs_api.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\ogr_srs_esri_names.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="ogr\swq.h">
-      <Filter>Include Files\ogr</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cplkeywordparser.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_atomic_ops.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_config.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_config_extras.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_conv.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_csv.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_error.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_hash_set.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_http.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_list.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_minixml.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_minizip_ioapi.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_minizip_unzip.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_multiproc.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_odbc.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_port.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_quad_tree.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_string.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_time.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_vsi.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_vsi_virtual.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_win32ce_api.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-    <ClInclude Include="port\cpl_wince.h">
-      <Filter>Include Files\port</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="alg\contour.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalchecksum.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalcutline.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdaldither.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalgeoloc.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalgrid.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalmediancut.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalproximity.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalrasterize.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalrasterpolygonenumerator.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalsievefilter.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalsimplewarp.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdaltransformer.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalwarper.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalwarpkernel.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdalwarpoperation.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdal_crs.c">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdal_nrgcrs.c">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdal_rpc.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\gdal_tps.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\llrasterize.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\polygonize.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\rasterfill.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="alg\thinplatespline.cpp">
-      <Filter>Source Files\alg</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\dumpoverviews.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdal2ogr.c">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdaladdo.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalbuildvrt.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdaldem.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalenhance.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalflattenmask.c">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalinfo.c">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalmanage.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdaltindex.c">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdaltorture.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdaltransform.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalwarp.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdalwarpsimple.c">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdal_contour.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdal_grid.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdal_rasterize.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\gdal_translate.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\multireadtest.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\nearblack.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\ogr2ogr.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\ogrdissolve.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\ogrinfo.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\ogrtindex.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\testepsg.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="apps\test_ogrsf.cpp">
-      <Filter>Source Files\apps</Filter>
-    </ClCompile>
-    <ClCompile Include="bridge\bridge_test.cpp">
-      <Filter>Source Files\bridge</Filter>
-    </ClCompile>
-    <ClCompile Include="bridge\gbgetsymbol.cpp">
-      <Filter>Source Files\bridge</Filter>
-    </ClCompile>
-    <ClCompile Include="bridge\gdalbridge.cpp">
-      <Filter>Source Files\bridge</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aaigrid\aaigriddataset.cpp">
-      <Filter>Source Files\frmts\aaigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\adrg\adrgdataset.cpp">
-      <Filter>Source Files\frmts\adrg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\adrg\srpdataset.cpp">
-      <Filter>Source Files\frmts\adrg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aigrid\aigccitt.c">
-      <Filter>Source Files\frmts\aigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aigrid\aigdataset.cpp">
-      <Filter>Source Files\frmts\aigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aigrid\aigopen.c">
-      <Filter>Source Files\frmts\aigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aigrid\aitest.c">
-      <Filter>Source Files\frmts\aigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\aigrid\gridlib.c">
-      <Filter>Source Files\frmts\aigrid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\airsar\airsardataset.cpp">
-      <Filter>Source Files\frmts\airsar</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\blx\blx.c">
-      <Filter>Source Files\frmts\blx</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\blx\blxdataset.cpp">
-      <Filter>Source Files\frmts\blx</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\bmp\bmpdataset.cpp">
-      <Filter>Source Files\frmts\bmp</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\bsb\bsb2raw.c">
-      <Filter>Source Files\frmts\bsb</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\bsb\bsbdataset.cpp">
-      <Filter>Source Files\frmts\bsb</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\bsb\bsb_read.c">
-      <Filter>Source Files\frmts\bsb</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos2\ceos.c">
-      <Filter>Source Files\frmts\ceos2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos2\ceosrecipe.c">
-      <Filter>Source Files\frmts\ceos2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos2\ceossar.c">
-      <Filter>Source Files\frmts\ceos2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos2\link.c">
-      <Filter>Source Files\frmts\ceos2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos2\sar_ceosdataset.cpp">
-      <Filter>Source Files\frmts\ceos2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos\ceosdataset.cpp">
-      <Filter>Source Files\frmts\ceos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos\ceosopen.c">
-      <Filter>Source Files\frmts\ceos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ceos\ceostest.c">
-      <Filter>Source Files\frmts\ceos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\coasp\coasp_dataset.cpp">
-      <Filter>Source Files\frmts\coasp</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\cosar\cosar_dataset.cpp">
-      <Filter>Source Files\frmts\cosar</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dimap\dimapdataset.cpp">
-      <Filter>Source Files\frmts\dimap</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dods\dodsdataset2.cpp">
-      <Filter>Source Files\frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dted\dteddataset.cpp">
-      <Filter>Source Files\frmts\dted</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dted\dted_api.c">
-      <Filter>Source Files\frmts\dted</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dted\dted_create.c">
-      <Filter>Source Files\frmts\dted</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dted\dted_ptstream.c">
-      <Filter>Source Files\frmts\dted</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\dted\dted_test.c">
-      <Filter>Source Files\frmts\dted</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ecw\ecwcreatecopy.cpp">
-      <Filter>Source Files\frmts\ecw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ecw\ecwdataset.cpp">
-      <Filter>Source Files\frmts\ecw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ecw\jp2userbox.cpp">
-      <Filter>Source Files\frmts\ecw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\elas\elasdataset.cpp">
-      <Filter>Source Files\frmts\elas</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\envisat\dumpgeo.c">
-      <Filter>Source Files\frmts\envisat</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\envisat\envisatdataset.cpp">
-      <Filter>Source Files\frmts\envisat</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\envisat\EnvisatFile.c">
-      <Filter>Source Files\frmts\envisat</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\envisat\envisat_dump.c">
-      <Filter>Source Files\frmts\envisat</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\epsilon\epsilondataset.cpp">
-      <Filter>Source Files\frmts\epsilon</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ers\ersdataset.cpp">
-      <Filter>Source Files\frmts\ers</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ers\ershdrnode.cpp">
-      <Filter>Source Files\frmts\ers</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\fits\fitsdataset.cpp">
-      <Filter>Source Files\frmts\fits</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\fit\fit.cpp">
-      <Filter>Source Files\frmts\fit</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\fit\fitdataset.cpp">
-      <Filter>Source Files\frmts\fit</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gdalallregister.cpp">
-      <Filter>Source Files\frmts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\georaster\georaster_dataset.cpp">
-      <Filter>Source Files\frmts\georaster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\georaster\georaster_driver.cpp">
-      <Filter>Source Files\frmts\georaster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\georaster\georaster_rasterband.cpp">
-      <Filter>Source Files\frmts\georaster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\georaster\georaster_wrapper.cpp">
-      <Filter>Source Files\frmts\georaster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\georaster\oci_wrapper.cpp">
-      <Filter>Source Files\frmts\georaster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gff\gff_dataset.cpp">
-      <Filter>Source Files\frmts\gff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\biggifdataset.cpp">
-      <Filter>Source Files\frmts\gif</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\gifdataset.cpp">
-      <Filter>Source Files\frmts\gif</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\giflib\dgif_lib.c">
-      <Filter>Source Files\frmts\gif\giflib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\giflib\egif_lib.c">
-      <Filter>Source Files\frmts\gif\giflib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\giflib\gifalloc.c">
-      <Filter>Source Files\frmts\gif\giflib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\giflib\gif_err.c">
-      <Filter>Source Files\frmts\gif\giflib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gif\giflib\gif_hash.c">
-      <Filter>Source Files\frmts\gif\giflib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grass\grass57dataset.cpp">
-      <Filter>Source Files\frmts\grass</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grass\grassdataset.cpp">
-      <Filter>Source Files\frmts\grass</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\clock.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\degrib1.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\degrib2.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\engribapi.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\filedatasource.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\fileendian.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\grib1tab.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\grib2api.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\inventory.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\memendian.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\memorydatasource.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaname.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaparse.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\metaprint.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\myassert.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\myerror.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\myutil.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\scan.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\tdlpack.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\degrib\weather.c">
-      <Filter>Source Files\frmts\grib\degrib18\degrib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\cmplxpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\compack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\comunpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\dec_jpeg2000.cpp">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\dec_png.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\drstemplates.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\enc_jpeg2000.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\enc_png.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addfield.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addgrid.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_addlocal.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_create.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_free.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_getfld.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_gribend.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_info.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_miss.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack1.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack2.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack3.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack4.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack5.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack6.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\g2_unpack7.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\gbits.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\getdim.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\getpoly.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\int_power.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\jpcpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\jpcunpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\misspack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\mkieee.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pack_gp.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pngpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\pngunpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\rdieee.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\reduce.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\seekgb.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\simpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\simunpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\specpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\degrib18\g2clib-1.0.4\specunpack.c">
-      <Filter>Source Files\frmts\grib\degrib18\g2clib-1.0.4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\grib\gribdataset.cpp">
-      <Filter>Source Files\frmts\grib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gsg\gs7bgdataset.cpp">
-      <Filter>Source Files\frmts\gsg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gsg\gsagdataset.cpp">
-      <Filter>Source Files\frmts\gsg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gsg\gsbgdataset.cpp">
-      <Filter>Source Files\frmts\gsg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\geotiff.cpp">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\gt_citation.cpp">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\gt_overview.cpp">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\gt_wkt_srs.cpp">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geotiff_proj4.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_extra.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_free.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_get.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_names.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_new.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_normalize.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_print.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_set.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_simpletags.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_tiffp.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_trans.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\geo_write.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libgeotiff\xtiff.c">
-      <Filter>Source Files\frmts\gtiff\libgeotiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_aux.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_close.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_codec.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_color.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_compress.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dir.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirinfo.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirread.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dirwrite.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_dumpmode.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_error.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_extension.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_fax3.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_fax3sm.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_flush.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_getimage.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_jpeg.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_jpeg_12.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_luv.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_lzw.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_next.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_ojpeg.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_open.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_packbits.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_pixarlog.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_predict.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_print.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_read.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_strip.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_swab.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_thunder.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_tile.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_version.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_vsi.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_warning.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_write.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\libtiff\tif_zip.c">
-      <Filter>Source Files\frmts\gtiff\libtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\tifvsi.cpp">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gtiff\tif_float.c">
-      <Filter>Source Files\frmts\gtiff</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gxf\gxfdataset.cpp">
-      <Filter>Source Files\frmts\gxf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gxf\gxfopen.c">
-      <Filter>Source Files\frmts\gxf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gxf\gxf_ogcwkt.c">
-      <Filter>Source Files\frmts\gxf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\gxf\gxf_proj4.c">
-      <Filter>Source Files\frmts\gxf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf-eos\EHapi.c">
-      <Filter>Source Files\frmts\hdf4\hdf-eos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf-eos\gctp_wrap.c">
-      <Filter>Source Files\frmts\hdf4\hdf-eos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf-eos\GDapi.c">
-      <Filter>Source Files\frmts\hdf4\hdf-eos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf-eos\SWapi.c">
-      <Filter>Source Files\frmts\hdf4\hdf-eos</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf4dataset.cpp">
-      <Filter>Source Files\frmts\hdf4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf4\hdf4imagedataset.cpp">
-      <Filter>Source Files\frmts\hdf4</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf5\bagdataset.cpp">
-      <Filter>Source Files\frmts\hdf5</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf5\gh5_convenience.cpp">
-      <Filter>Source Files\frmts\hdf5</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf5\hdf5dataset.cpp">
-      <Filter>Source Files\frmts\hdf5</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf5\hdf5imagedataset.cpp">
-      <Filter>Source Files\frmts\hdf5</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hdf5\iso19115_srs.cpp">
-      <Filter>Source Files\frmts\hdf5</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfaband.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfacompress.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfadataset.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfadictionary.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfaentry.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfafield.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfaopen.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfatest.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfatype.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\hfa\hfa_overviews.cpp">
-      <Filter>Source Files\frmts\hfa</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\idrisi\IdrisiDataset.cpp">
-      <Filter>Source Files\frmts\idrisi</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ilwis\ilwiscoordinatesystem.cpp">
-      <Filter>Source Files\frmts\ilwis</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ilwis\ilwisdataset.cpp">
-      <Filter>Source Files\frmts\ilwis</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ingr\IngrTypes.cpp">
-      <Filter>Source Files\frmts\ingr</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ingr\IntergraphBand.cpp">
-      <Filter>Source Files\frmts\ingr</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ingr\IntergraphDataset.cpp">
-      <Filter>Source Files\frmts\ingr</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ingr\JpegHelper.cpp">
-      <Filter>Source Files\frmts\ingr</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\8211dump.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\8211view.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddffield.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddffielddefn.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddfmodule.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddfrecord.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddfsubfielddefn.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\ddfutils.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\mkcatalog.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\iso8211\timetest.cpp">
-      <Filter>Source Files\frmts\iso8211</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jaxapalsar\jaxapalsardataset.cpp">
-      <Filter>Source Files\frmts\jaxapalsar</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jdem\jdemdataset.cpp">
-      <Filter>Source Files\frmts\jdem</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jp2kak\jp2kakdataset.cpp">
-      <Filter>Source Files\frmts\jp2kak</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg2000\jpeg2000dataset.cpp">
-      <Filter>Source Files\frmts\jpeg2000</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg2000\jpeg2000_vsil_io.cpp">
-      <Filter>Source Files\frmts\jpeg2000</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\jpgdataset.cpp">
-      <Filter>Source Files\frmts\jpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\jpgdataset_12.cpp">
-      <Filter>Source Files\frmts\jpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcapimin12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcapistd12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jccoefct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jccolor12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcdctmgr12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jchuff12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcinit12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmainct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmarker12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcmaster12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcomapi12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcparam12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcphuff12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcprepct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jcsample12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jctrans12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdapimin12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdapistd12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdatadst12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdatasrc12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdcoefct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdcolor12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jddctmgr12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdhuff12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdinput12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmainct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmarker12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmaster12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdmerge12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdphuff12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdpostct12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdsample12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jdtrans12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jerror12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctflt12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctfst12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jfdctint12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctflt12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctfst12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctint12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jidctred12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jmemansi12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jmemmgr12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jquant112.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jquant212.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg12\jutils12.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg12</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcapimin.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcapistd.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jccoefct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jccolor.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcdctmgr.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jchuff.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcinit.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmainct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmarker.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcmaster.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcomapi.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcparam.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcphuff.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcprepct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jcsample.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jctrans.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdapimin.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdapistd.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdatadst.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdatasrc.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdcoefct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdcolor.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jddctmgr.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdhuff.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdinput.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmainct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmarker.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmaster.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdmerge.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdphuff.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdpostct.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdsample.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jdtrans.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jerror.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctflt.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctfst.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jfdctint.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctflt.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctfst.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctint.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jidctred.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jmemansi.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jmemmgr.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jquant1.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jquant2.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\libjpeg\jutils.c">
-      <Filter>Source Files\frmts\jpeg\libjpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\jpeg\vsidataio.cpp">
-      <Filter>Source Files\frmts\jpeg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\l1b\l1bdataset.cpp">
-      <Filter>Source Files\frmts\l1b</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\leveller\levellerdataset.cpp">
-      <Filter>Source Files\frmts\leveller</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\mem\memdataset.cpp">
-      <Filter>Source Files\frmts\mem</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\mrsid\mrsiddataset.cpp">
-      <Filter>Source Files\frmts\mrsid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\mrsid\mrsidstream.cpp">
-      <Filter>Source Files\frmts\mrsid</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msgn\msgndataset.cpp">
-      <Filter>Source Files\frmts\msgn</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msgn\msg_basic_types.cpp">
-      <Filter>Source Files\frmts\msgn</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msgn\msg_reader_core.cpp">
-      <Filter>Source Files\frmts\msgn</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msg\msgcommand.cpp">
-      <Filter>Source Files\frmts\msg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msg\msgdataset.cpp">
-      <Filter>Source Files\frmts\msg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msg\prologue.cpp">
-      <Filter>Source Files\frmts\msg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msg\reflectancecalculator.cpp">
-      <Filter>Source Files\frmts\msg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\msg\xritheaderparser.cpp">
-      <Filter>Source Files\frmts\msg</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\netcdf\gmtdataset.cpp">
-      <Filter>Source Files\frmts\netcdf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\netcdf\netcdfdataset.cpp">
-      <Filter>Source Files\frmts\netcdf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\mgrs.c">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfaridpcm.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfbilevel.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfdataset.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfdump.c">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitffile.c">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfimage.c">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfwritejpeg.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\nitfwritejpeg_12.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\rpftocdataset.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\nitf\rpftocfile.cpp">
-      <Filter>Source Files\frmts\nitf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\northwood\grcdataset.cpp">
-      <Filter>Source Files\frmts\northwood</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\northwood\grddataset.cpp">
-      <Filter>Source Files\frmts\northwood</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\northwood\northwood.cpp">
-      <Filter>Source Files\frmts\northwood</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\ogdi\ogdidataset.cpp">
-      <Filter>Source Files\frmts\ogdi</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\pcidskdataset.cpp">
-      <Filter>Source Files\frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\pcidskdataset2.cpp">
-      <Filter>Source Files\frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\pcidsktiledrasterband.cpp">
-      <Filter>Source Files\frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cbandinterleavedchannel.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cpcidskchannel.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\channel\ctiledchannel.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\channel</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\cpcidskfile.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\libjpeg_io.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\metadataset_p.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskbuffer.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskcreate.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskexception.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskinterfaces.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidskopen.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidsk_pubutils.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\pcidsk_utils.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\core\sysvirtualfile.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\core</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\port\io_stdio.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\port</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\port\io_win32.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\port</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\port\pthread_mutex.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\port</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\port\win32_mutex.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\port</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskpct.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidsksegment.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\metadatasegment_p.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\segmentfactory.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\segment_loader.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\sdk\segment\sysblockmap.cpp">
-      <Filter>Source Files\frmts\pcidsk\sdk\segment</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcidsk\vsi_pcidsk_io.cpp">
-      <Filter>Source Files\frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\angle.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\attravai.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\attrsize.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\cellsize.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\create2.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\csfglob.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\csfsup.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\delattr.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\dumconv.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\endian.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\filename.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gattrblk.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gattridx.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gcellrep.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gdattype.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\getattr.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\getx0.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gety0.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\ggisfid.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gmaxval.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gminval.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gnrcols.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gnrrows.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gproj.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gputproj.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gvalscal.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gvartype.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\gversion.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\ismv.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\kernlcsf.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\legend.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\mclose.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\mopen.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\moreattr.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\mperror.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\pgisfid.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\pmaxval.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\pminval.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\putallmv.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\putattr.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\putsomec.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\putx0.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\puty0.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\pvalscal.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rattrblk.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rcomp.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rcoords.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rdup2.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\reseterr.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rextend.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rmalloc.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\rrowcol.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\ruseas.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\setangle.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\setmv.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\setvtmv.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\strconst.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\strpad.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\swapio.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\trackmm.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\vs2.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\vsdef.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\vsis.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\vsvers.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\wattrblk.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\_getcell.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\_getrow.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\_gsomece.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\_putcell.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\libcsf\_rputrow.c">
-      <Filter>Source Files\frmts\pcraster\libcsf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\pcrasterdataset.cpp">
-      <Filter>Source Files\frmts\pcraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\pcrastermisc.cpp">
-      <Filter>Source Files\frmts\pcraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\pcrasterrasterband.cpp">
-      <Filter>Source Files\frmts\pcraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pcraster\pcrasterutil.cpp">
-      <Filter>Source Files\frmts\pcraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pds\isis2dataset.cpp">
-      <Filter>Source Files\frmts\pds</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pds\isis3dataset.cpp">
-      <Filter>Source Files\frmts\pds</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pds\nasakeywordhandler.cpp">
-      <Filter>Source Files\frmts\pds</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pds\pdsdataset.cpp">
-      <Filter>Source Files\frmts\pds</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pgchip\pgchipdataset.cpp">
-      <Filter>Source Files\frmts\pgchip</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pgchip\pgchiprasterband.cpp">
-      <Filter>Source Files\frmts\pgchip</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\pgchip\pgchiputilities.cpp">
-      <Filter>Source Files\frmts\pgchip</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\png.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngerror.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pnggccrd.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngget.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngmem.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngpread.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngread.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngrio.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngrtran.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngrutil.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngset.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngtrans.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngvcrd.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngwio.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngwrite.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngwtran.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\libpng\pngwutil.c">
-      <Filter>Source Files\frmts\png\libpng</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\png\pngdataset.cpp">
-      <Filter>Source Files\frmts\png</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rasterlite\rasterlitecreatecopy.cpp">
-      <Filter>Source Files\frmts\rasterlite</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rasterlite\rasterlitedataset.cpp">
-      <Filter>Source Files\frmts\rasterlite</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rasterlite\rasterliteoverviews.cpp">
-      <Filter>Source Files\frmts\rasterlite</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\atlsci_spheroid.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\btdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\cpgdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\dipxdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\doq1dataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\doq2dataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\ehdrdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\eirdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\envidataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\fastdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\fujibasdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\genbindataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\gscdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\hkvdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\idadataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\landataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\lcpdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\mffdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\ndfdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\pauxdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\pnmdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\raw\rawdataset.cpp">
-      <Filter>Source Files\frmts\raw</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rik\rikdataset.cpp">
-      <Filter>Source Files\frmts\rik</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rmf\rmfdataset.cpp">
-      <Filter>Source Files\frmts\rmf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rmf\rmflzw.cpp">
-      <Filter>Source Files\frmts\rmf</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\rs2\rs2dataset.cpp">
-      <Filter>Source Files\frmts\rs2</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\r\rcreatecopy.cpp">
-      <Filter>Source Files\frmts\r</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\r\rdataset.cpp">
-      <Filter>Source Files\frmts\r</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\saga\sagadataset.cpp">
-      <Filter>Source Files\frmts\saga</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sde\sdedataset.cpp">
-      <Filter>Source Files\frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sde\sdeerror.cpp">
-      <Filter>Source Files\frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sde\sderasterband.cpp">
-      <Filter>Source Files\frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdts2shp.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsattrreader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtscatd.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsdataset.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsindexedreader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsiref.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtslib.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtslinereader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtspointreader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtspolygonreader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsrasterreader.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtstransfer.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sdts\sdtsxref.cpp">
-      <Filter>Source Files\frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\sgi\sgidataset.cpp">
-      <Filter>Source Files\frmts\sgi</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\srtmhgt\srtmhgtdataset.cpp">
-      <Filter>Source Files\frmts\srtmhgt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\terragen\terragendataset.cpp">
-      <Filter>Source Files\frmts\terragen</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\terralib\TerraLibDataset.cpp">
-      <Filter>Source Files\frmts\terralib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\terralib\TerraLibRasterBand.cpp">
-      <Filter>Source Files\frmts\terralib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\til\tildataset.cpp">
-      <Filter>Source Files\frmts\til</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\tsx\tsxdataset.cpp">
-      <Filter>Source Files\frmts\tsx</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\usgsdem\usgsdemdataset.cpp">
-      <Filter>Source Files\frmts\usgsdem</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\usgsdem\usgsdem_create.cpp">
-      <Filter>Source Files\frmts\usgsdem</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtdataset.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtderivedrasterband.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtdriver.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtfilters.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtrasterband.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtrawrasterband.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtsourcedrasterband.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtsources.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\vrt\vrtwarped.cpp">
-      <Filter>Source Files\frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wcs\httpdriver.cpp">
-      <Filter>Source Files\frmts\wcs</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wcs\wcsdataset.cpp">
-      <Filter>Source Files\frmts\wcs</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wktraster\wktrasterdataset.cpp">
-      <Filter>Source Files\frmts\wktraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wktraster\wktrasterrasterband.cpp">
-      <Filter>Source Files\frmts\wktraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wktraster\wktrasterwrapper.cpp">
-      <Filter>Source Files\frmts\wktraster</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\cache.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\dataset.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\gdalhttp.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\md5.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\minidriver.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\minidriver_tileservice.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\minidriver_tms.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\minidriver_wms.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\minidriver_worldwind.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\rasterband.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\stuff.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\wms\wmsdriver.cpp">
-      <Filter>Source Files\frmts\wms</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\xpm\xpmdataset.cpp">
-      <Filter>Source Files\frmts\xpm</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\adler32.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\compress.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\crc32.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\deflate.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\gzio.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\infback.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\inffast.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\inflate.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\inftrees.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\trees.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\uncompr.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="frmts\zlib\zutil.c">
-      <Filter>Source Files\frmts\zlib</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalallvalidmaskband.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalcolortable.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaldataset.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaldefaultoverviews.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaldriver.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaldrivermanager.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalgmlcoverage.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaljp2box.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdaljp2metadata.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalmajorobject.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalmultidomainmetadata.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalnodatamaskband.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalnodatavaluesmaskband.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalopeninfo.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalpamdataset.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalpamproxydb.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalpamrasterband.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalproxydataset.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalproxypool.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalrasterband.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdalrasterblock.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdal_misc.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdal_rat.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\gdal_rpcimdio.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\overview.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="gcore\rasterio.cpp">
-      <Filter>Source Files\gcore</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\gml2ogrgeometry.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr2gmlgeometry.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ograssemblepolygon.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrct.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrcurve.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrfeature.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrfeaturedefn.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrfeaturequery.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrfeaturestyle.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrfielddefn.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrgeometry.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrgeometrycollection.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrgeometryfactory.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrlinearring.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrlinestring.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrmultilinestring.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrmultipoint.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrmultipolygon.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrpoint.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrpolygon.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_bin.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_binwr.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00gen.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00parse.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00read.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_e00write.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_mbyte.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_misc.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\avc_rawbin.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbindatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbindriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcbinlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravcdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00datasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00driver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravce00layer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\avc\ogravclayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\avc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnadatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnadriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnalayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\bna\ogrbnaparser.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\bna</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\csv</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\csv</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\csv</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgndump.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnfloat.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnhelp.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnopen.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnread.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnstroke.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnwrite.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\dgnwritetest.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgndatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgndriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dgn\ogrdgnlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dgn</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsfielddefn.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodsgrid.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dods</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxflayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfwriterds.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxfwriterlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_blockmap.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_dimension.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\dxf\ogrdxf_diskio.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\dxf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmecacheindex.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmedatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmedriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayercached.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\fme\ogrfmelayerdb.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\fme</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrregisterall.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrsfdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_attrind.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_gensql.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\generic\ogr_miattrind.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\generic</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\geoconcept.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geoconcept</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\arraylist.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\debug.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_object.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_tokener.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\json_util.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\linkhash.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\jsonc\printbuf.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson\jsonc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsondatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsondriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonreader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonutils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\geojson</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorssdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\georss</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorssdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\georss</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\georss\ogrgeorsslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\georss</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlfeature.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlfeatureclass.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlhandler.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlpropertydefn.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlreader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\gmlreadstate.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmldatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmldriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\ogrgmllayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\parsexsd.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\trstring.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gml\resolvexlinks.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gmt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gmt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gmt\ogrgmtlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gmt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gpx</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gpx</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gpx\ogrgpxlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gpx</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrassdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\grass</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrassdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\grass</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\grass\ogrgrasslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\grass</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtm.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtmtracklayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\gtmwaypointlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\gtm\ogrgtmlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\gtm</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridblayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\idb</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili1reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili2handler.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ili2reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ilihelper.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iomhelper.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_attr.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_basket.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_error.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_file.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_iterator.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_object.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_utilities.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\iom_value.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\tags.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\ustrings.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\iom\writer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili\iom</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1datasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1driver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili1layer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2datasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2driver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ili\ogrili2layer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ili</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringreslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresresultlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringresstatement.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ingres\ogringrestablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ingres</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kml.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kmlnode.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\kmlvector.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogr2kmlgeometry.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmldatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmldriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\kml\ogrkmllayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\kml</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mem</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mem</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mem\ogrmemlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mem</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_bounds.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_datfile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_feature.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_geometry.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_idfile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_indfile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_miffile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tabview.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mitab\mitab_utils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mitab</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqllayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\mysql</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfdump.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntffilereader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfrecord.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntfstroke.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_codelist.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_estlayers.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_generic.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ntf_raster.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntfdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntfdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntffeatureclasslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ntf\ogrntflayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ntf</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\fastload.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ocitest.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\oci_utils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocidatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocidriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocilayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociloaderlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociselectlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocisession.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistatement.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistringbuf.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocistroke.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrocitablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\oci\ogrociwritablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\oci</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbclayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbcselectlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\odbc\ogrodbctablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\odbc</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdidatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ogdi</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ogdi</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\ogdi</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidskdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidskdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pcidsk\ogrpcidsklayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pcidsk</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeodriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeolayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeoselectlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pgeo\ogrpgeotablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pgeo</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdebug.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpglayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgresultlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\pg\ogrpgtablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\pg</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ll_recio.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\rec</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrrecdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\rec</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrrecdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\rec</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\rec\ogrreclayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\rec</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ddfrecordindex.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57datasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57driver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\ogrs57layer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57classregistrar.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57dump.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57featuredefns.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57filecollector.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\s57\s57writer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\s57</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdedatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdedriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sde\ogrsdelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sde</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtsdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sdts</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\dbfopen.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapedriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\ogrshapelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shape2ogr.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shpopen.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shptree.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\shape\shp_vsi.c">
-      <Filter>Source Files\ogr\ogrsf_frmts\shape</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitedatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitedriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqliteselectlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\sqlite</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\ogrtigerlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeraltname.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerarealandmarks.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigercompletechain.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerentitynames.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerfeatureids.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerfilebase.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeridhistory.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerinfo.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerkeyfeatures.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerlandmarks.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigeroverunder.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpip.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpoint.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolychainlink.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygon.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygoncorrections.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerpolygoneconomic.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerspatialmetadata.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigertlidrange.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzerocellid.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\tiger</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtdatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtdriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\vrt\ogrvrtlayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\vrt</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogrxplanelayer.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\ogr_xplane_reader.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsf_frmts\xplane\test_geo_utils.cpp">
-      <Filter>Source Files\ogr\ogrsf_frmts\xplane</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrspatialreference.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrsurface.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogrutils.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_api.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_capi_test.c">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_expat.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_fromepsg.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_opt.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srsnode.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_dict.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_erm.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_esri.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_ozi.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_panorama.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_pci.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_proj4.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_usgs.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_validate.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\ogr_srs_xml.cpp">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\swq.c">
-      <Filter>Source Files\ogr</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\wcts\ogrwcts.cpp">
-      <Filter>Source Files\ogr\wcts</Filter>
-    </ClCompile>
-    <ClCompile Include="ogr\wcts\wctsclient.cpp">
-      <Filter>Source Files\ogr\wcts</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cplgetsymbol.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cplkeywordparser.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cplstring.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_atomic_ops.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_conv.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_csv.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_error.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_findfile.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_getexecpath.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_hash_set.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_http.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_list.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_minixml.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_minizip_ioapi.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_minizip_unzip.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_multiproc.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_odbc.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_path.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_quad_tree.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_recode_stub.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_string.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_strtod.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_time.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil_gzip.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil_simple.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil_subfile.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil_unix_stdio_64.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsil_win32.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsisimple.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_vsi_mem.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\cpl_win32ce_api.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-    <ClCompile Include="port\xmlreformat.cpp">
-      <Filter>Source Files\port</Filter>
-    </ClCompile>
-  </ItemGroup>
-</Project>
diff --git a/makegdal71.sln b/makegdal71.sln
deleted file mode 100644
index 116c879..0000000
--- a/makegdal71.sln
+++ /dev/null
@@ -1,21 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makegdal71", "makegdal71.vcproj", "{769DD10E-E284-46BE-9172-A35184250A3A}"
-	ProjectSection(ProjectDependencies) = postProject
-	EndProjectSection
-EndProject
-Global
-	GlobalSection(SolutionConfiguration) = preSolution
-		Debug = Debug
-		Release = Release
-	EndGlobalSection
-	GlobalSection(ProjectConfiguration) = postSolution
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug.ActiveCfg = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug.Build.0 = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release.ActiveCfg = Release|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-	EndGlobalSection
-	GlobalSection(ExtensibilityAddIns) = postSolution
-	EndGlobalSection
-EndGlobal
diff --git a/makegdal71.vcproj b/makegdal71.vcproj
deleted file mode 100644
index 8b3c89f..0000000
--- a/makegdal71.vcproj
+++ /dev/null
@@ -1,2365 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject            
-	ProjectType="Visual C++"
-	Version="7.10"
-	Name="makegdal"
-	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-	Keyword="MakeFileProj">
-	<Platforms>
-		<Platform Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0">
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 install"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 clean && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 install"
-				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 DEBUG=1 clean"
-				Output="gdal17.dll"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0">
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 && nmake -f makefile.vc MSVC_VER=1310 install"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 clean && nmake -f makefile.vc MSVC_VER=1310 && nmake -f makefile.vc MSVC_VER=1310 install"
-				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1310 clean"
-				Output="gdal17.dll"/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter Name="Make Files" Filter="*.vc;*.opt ">
-			<File RelativePath=".\makefile.vc" />
-			<File RelativePath=".\nmake-wince.opt" />
-			<File RelativePath=".\nmake.opt" />
-			<Filter Name="alg" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\alg\makefile.vc" />
-			</Filter>
-			<Filter Name="apps" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\apps\makefile.vc" />
-			</Filter>
-			<Filter Name="frmts" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\frmts\makefile.vc" />
-				<Filter Name="aaigrid" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\aaigrid\makefile.vc" />
-				</Filter>
-				<Filter Name="adrg" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\adrg\makefile.vc" />
-				</Filter>
-				<Filter Name="aigrid" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\aigrid\makefile.vc" />
-				</Filter>
-				<Filter Name="airsar" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\airsar\makefile.vc" />
-				</Filter>
-				<Filter Name="blx" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\blx\makefile.vc" />
-				</Filter>
-				<Filter Name="bmp" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\bmp\makefile.vc" />
-				</Filter>
-				<Filter Name="bsb" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\bsb\makefile.vc" />
-				</Filter>
-				<Filter Name="ceos" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ceos\makefile.vc" />
-				</Filter>
-				<Filter Name="ceos2" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ceos2\makefile.vc" />
-				</Filter>
-				<Filter Name="coasp" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\coasp\makefile.vc" />
-				</Filter>
-				<Filter Name="cosar" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\cosar\makefile.vc" />
-				</Filter>
-				<Filter Name="dimap" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\dimap\makefile.vc" />
-				</Filter>
-				<Filter Name="dods" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\dods\makefile.vc" />
-				</Filter>
-				<Filter Name="dted" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\dted\makefile.vc" />
-				</Filter>
-				<Filter Name="ecw" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ecw\makefile.vc" />
-				</Filter>
-				<Filter Name="elas" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\elas\makefile.vc" />
-				</Filter>
-				<Filter Name="envisat" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\envisat\makefile.vc" />
-				</Filter>
-				<Filter Name="epsilon" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\epsilon\makefile.vc" />
-				</Filter>
-				<Filter Name="ers" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ers\makefile.vc" />
-				</Filter>
-				<Filter Name="fit" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\fit\makefile.vc" />
-				</Filter>
-				<Filter Name="fits" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\fits\makefile.vc" />
-				</Filter>
-				<Filter Name="georaster" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\georaster\makefile.vc" />
-				</Filter>
-				<Filter Name="gff" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\gff\makefile.vc" />
-				</Filter>
-				<Filter Name="gif" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\gif\makefile.vc" />
-					<Filter Name="giflib" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\gif\giflib\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="grib" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\grib\makefile.vc" />
-					<Filter Name="degrib18" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\grib\degrib18\makefile.vc" />
-						<Filter Name="degrib" Filter="*.vc;*.opt     ">
-							<File RelativePath=".\frmts\grib\degrib18\degrib\makefile.vc" />
-						</Filter>
-						<Filter Name="g2clib-1.0.4" Filter="*.vc;*.opt     ">
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\makefile.vc" />
-						</Filter>
-						</Filter>
-						</Filter>
-				<Filter Name="gsg" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\gsg\makefile.vc" />
-				</Filter>
-				<Filter Name="gtiff" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\gtiff\makefile.vc" />
-					<Filter Name="libgeotiff" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\gtiff\libgeotiff\makefile.vc" />
-					</Filter>
-					<Filter Name="libtiff" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\gtiff\libtiff\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="gxf" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\gxf\makefile.vc" />
-				</Filter>
-				<Filter Name="hdf4" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\hdf4\makefile.vc" />
-					<Filter Name="hdf-eos" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\hdf4\hdf-eos\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="hdf5" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\hdf5\makefile.vc" />
-				</Filter>
-				<Filter Name="hfa" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\hfa\makefile.vc" />
-				</Filter>
-				<Filter Name="idrisi" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\idrisi\makefile.vc" />
-				</Filter>
-				<Filter Name="ilwis" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ilwis\makefile.vc" />
-				</Filter>
-				<Filter Name="ingr" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ingr\makefile.vc" />
-				</Filter>
-				<Filter Name="iso8211" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\iso8211\makefile.vc" />
-				</Filter>
-				<Filter Name="jaxapalsar" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\jaxapalsar\makefile.vc" />
-				</Filter>
-				<Filter Name="jdem" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\jdem\makefile.vc" />
-				</Filter>
-				<Filter Name="jp2kak" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\jp2kak\makefile.vc" />
-				</Filter>
-				<Filter Name="jpeg" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\jpeg\makefile.vc" />
-					<Filter Name="libjpeg" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg\makefile.vc" />
-					</Filter>
-					<Filter Name="libjpeg12" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg12\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="jpeg2000" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\jpeg2000\makefile.vc" />
-				</Filter>
-				<Filter Name="l1b" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\l1b\makefile.vc" />
-				</Filter>
-				<Filter Name="leveller" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\leveller\makefile.vc" />
-				</Filter>
-				<Filter Name="mem" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\mem\makefile.vc" />
-				</Filter>
-				<Filter Name="mrsid" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\mrsid\makefile.vc" />
-				</Filter>
-				<Filter Name="msg" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\msg\makefile.vc" />
-				</Filter>
-				<Filter Name="msgn" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\msgn\makefile.vc" />
-				</Filter>
-				<Filter Name="netcdf" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\netcdf\makefile.vc" />
-				</Filter>
-				<Filter Name="nitf" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\nitf\makefile.vc" />
-				</Filter>
-				<Filter Name="northwood" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\northwood\makefile.vc" />
-				</Filter>
-				<Filter Name="ogdi" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\ogdi\makefile.vc" />
-				</Filter>
-				<Filter Name="pcidsk" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\pcidsk\makefile.vc" />
-					<Filter Name="sdk" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\pcidsk\sdk\Makefile.vc" />
-						</Filter>
-						</Filter>
-				<Filter Name="pcraster" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\pcraster\makefile.vc" />
-					<Filter Name="libcsf" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\pcraster\libcsf\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="pds" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\pds\makefile.vc" />
-				</Filter>
-				<Filter Name="pgchip" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\pgchip\makefile.vc" />
-				</Filter>
-				<Filter Name="png" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\png\makefile.vc" />
-					<Filter Name="libpng" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\frmts\png\libpng\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="r" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\r\makefile.vc" />
-				</Filter>
-				<Filter Name="rasterlite" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\rasterlite\makefile.vc" />
-				</Filter>
-				<Filter Name="raw" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\raw\makefile.vc" />
-				</Filter>
-				<Filter Name="rik" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\rik\makefile.vc" />
-				</Filter>
-				<Filter Name="rmf" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\rmf\makefile.vc" />
-				</Filter>
-				<Filter Name="rs2" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\rs2\makefile.vc" />
-				</Filter>
-				<Filter Name="saga" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\saga\makefile.vc" />
-				</Filter>
-				<Filter Name="sde" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\sde\makefile.vc" />
-				</Filter>
-				<Filter Name="sdts" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\sdts\makefile.vc" />
-				</Filter>
-				<Filter Name="sgi" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\sgi\makefile.vc" />
-				</Filter>
-				<Filter Name="srtmhgt" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\srtmhgt\makefile.vc" />
-				</Filter>
-				<Filter Name="terragen" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\terragen\makefile.vc" />
-				</Filter>
-				<Filter Name="terralib" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\terralib\makefile.vc" />
-				</Filter>
-				<Filter Name="til" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\til\makefile.vc" />
-				</Filter>
-				<Filter Name="tsx" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\tsx\makefile.vc" />
-				</Filter>
-				<Filter Name="usgsdem" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\usgsdem\makefile.vc" />
-				</Filter>
-				<Filter Name="vrt" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\vrt\makefile.vc" />
-				</Filter>
-				<Filter Name="wcs" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\wcs\makefile.vc" />
-				</Filter>
-				<Filter Name="wktraster" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\wktraster\makefile.vc" />
-				</Filter>
-				<Filter Name="wms" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\wms\makefile.vc" />
-				</Filter>
-				<Filter Name="xpm" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\xpm\makefile.vc" />
-				</Filter>
-				<Filter Name="zlib" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\frmts\zlib\makefile.vc" />
-				</Filter>
-				</Filter>
-			<Filter Name="gcore" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\gcore\makefile.vc" />
-			</Filter>
-			<Filter Name="ogr" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\ogr\makefile.vc" />
-				<Filter Name="ogrsf_frmts" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\ogr\ogrsf_frmts\makefile.vc" />
-					<Filter Name="avc" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\makefile.vc" />
-					</Filter>
-					<Filter Name="bna" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\makefile.vc" />
-					</Filter>
-					<Filter Name="csv" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\csv\makefile.vc" />
-					</Filter>
-					<Filter Name="dgn" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\makefile.vc" />
-						<Filter Name="dist" Filter="*.vc;*.opt     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\dgn\dist\Makefile.vc" />
-						</Filter>
-						</Filter>
-					<Filter Name="dods" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\makefile.vc" />
-					</Filter>
-					<Filter Name="dxf" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\makefile.vc" />
-					</Filter>
-					<Filter Name="fme" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\makefile.vc" />
-					</Filter>
-					<Filter Name="generic" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\makefile.vc" />
-					</Filter>
-					<Filter Name="geoconcept" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\makefile.vc" />
-					</Filter>
-					<Filter Name="geojson" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\makefile.vc" />
-						<Filter Name="jsonc" Filter="*.vc;*.opt     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\makefile.vc" />
-						</Filter>
-						</Filter>
-					<Filter Name="georss" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\georss\makefile.vc" />
-					</Filter>
-					<Filter Name="gml" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\makefile.vc" />
-					</Filter>
-					<Filter Name="gmt" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gmt\makefile.vc" />
-					</Filter>
-					<Filter Name="gpx" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gpx\makefile.vc" />
-					</Filter>
-					<Filter Name="gtm" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\makefile.vc" />
-					</Filter>
-					<Filter Name="idb" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc" />
-					</Filter>
-					<Filter Name="ili" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\makefile.vc" />
-						<Filter Name="iom" Filter="*.vc;*.opt     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\makefile.vc" />
-						</Filter>
-						</Filter>
-					<Filter Name="kml" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\makefile.vc" />
-					</Filter>
-					<Filter Name="mem" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mem\makefile.vc" />
-					</Filter>
-					<Filter Name="mitab" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\makefile.vc" />
-					</Filter>
-					<Filter Name="mysql" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc" />
-					</Filter>
-					<Filter Name="ntf" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\makefile.vc" />
-					</Filter>
-					<Filter Name="oci" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\makefile.vc" />
-					</Filter>
-					<Filter Name="odbc" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\makefile.vc" />
-					</Filter>
-					<Filter Name="ogdi" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\makefile.vc" />
-					</Filter>
-					<Filter Name="pcidsk" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\makefile.vc" />
-					</Filter>
-					<Filter Name="pg" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc" />
-					</Filter>
-					<Filter Name="pgeo" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\makefile.vc" />
-					</Filter>
-					<Filter Name="rec" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\makefile.vc" />
-					</Filter>
-					<Filter Name="s57" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\makefile.vc" />
-					</Filter>
-					<Filter Name="sde" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sde\makefile.vc" />
-					</Filter>
-					<Filter Name="sdts" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sdts\makefile.vc" />
-					</Filter>
-					<Filter Name="shape" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc" />
-					</Filter>
-					<Filter Name="sqlite" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc" />
-					</Filter>
-					<Filter Name="tiger" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc" />
-					</Filter>
-					<Filter Name="vrt" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc" />
-					</Filter>
-					<Filter Name="xplane" Filter="*.vc;*.opt    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\makefile.vc" />
-					</Filter>
-					</Filter>
-				<Filter Name="wcts" Filter="*.vc;*.opt   ">
-					<File RelativePath=".\ogr\wcts\makefile.vc" />
-					</Filter>
-					</Filter>
-			<Filter Name="port" Filter="*.vc;*.opt  ">
-				<File RelativePath=".\port\cpl_config.h.vc" />
-				<File RelativePath=".\port\makefile.vc" />
-			</Filter>
-			</Filter>
-		<Filter Name="Include Files" Filter="*.h ">
-			<Filter Name="alg" Filter="*.h  ">
-				<File RelativePath=".\alg\gdalgrid.h" />
-				<File RelativePath=".\alg\gdalwarper.h" />
-				<File RelativePath=".\alg\gdal_alg.h" />
-				<File RelativePath=".\alg\gdal_alg_priv.h" />
-				<File RelativePath=".\alg\gvgcpfit.h" />
-				<File RelativePath=".\alg\thinplatespline.h" />
-			</Filter>
-			<Filter Name="bridge" Filter="*.h  ">
-				<File RelativePath=".\bridge\gdalbridge.h" />
-			</Filter>
-			<Filter Name="frmts" Filter="*.h  ">
-				<Filter Name="aigrid" Filter="*.h   ">
-					<File RelativePath=".\frmts\aigrid\aigrid.h" />
-				</Filter>
-				<Filter Name="blx" Filter="*.h   ">
-					<File RelativePath=".\frmts\blx\blx.h" />
-				</Filter>
-				<Filter Name="bsb" Filter="*.h   ">
-					<File RelativePath=".\frmts\bsb\bsb_read.h" />
-				</Filter>
-				<Filter Name="ceos" Filter="*.h   ">
-					<File RelativePath=".\frmts\ceos\ceosopen.h" />
-				</Filter>
-				<Filter Name="ceos2" Filter="*.h   ">
-					<File RelativePath=".\frmts\ceos2\ceos.h" />
-				</Filter>
-				<Filter Name="dted" Filter="*.h   ">
-					<File RelativePath=".\frmts\dted\dted_api.h" />
-				</Filter>
-				<Filter Name="ecw" Filter="*.h   ">
-					<File RelativePath=".\frmts\ecw\jp2userbox.h" />
-					<File RelativePath=".\frmts\ecw\vsiiostream.h" />
-				</Filter>
-				<Filter Name="envisat" Filter="*.h   ">
-					<File RelativePath=".\frmts\envisat\EnvisatFile.h" />
-				</Filter>
-				<Filter Name="ers" Filter="*.h   ">
-					<File RelativePath=".\frmts\ers\ershdrnode.h" />
-				</Filter>
-				<Filter Name="fit" Filter="*.h   ">
-					<File RelativePath=".\frmts\fit\fit.h" />
-					<File RelativePath=".\frmts\fit\gstEndian.h" />
-					<File RelativePath=".\frmts\fit\gstTypes.h" />
-				</Filter>
-				<Filter Name="georaster" Filter="*.h   ">
-					<File RelativePath=".\frmts\georaster\georaster_priv.h" />
-					<File RelativePath=".\frmts\georaster\oci_wrapper.h" />
-				</Filter>
-				<Filter Name="gif" Filter="*.h   ">
-					<Filter Name="giflib" Filter="*.h    ">
-						<File RelativePath=".\frmts\gif\giflib\gif_hash.h" />
-						<File RelativePath=".\frmts\gif\giflib\gif_lib.h" />
-						<File RelativePath=".\frmts\gif\giflib\gif_lib_private.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="grib" Filter="*.h   ">
-					<Filter Name="degrib18" Filter="*.h    ">
-						<Filter Name="degrib" Filter="*.h     ">
-							<File RelativePath=".\frmts\grib\degrib18\degrib\clock.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\datasource.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\degrib1.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\degrib2.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\engribapi.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\fileendian.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\grib2api.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\inventory.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\memendian.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\meta.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\metaname.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myassert.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myerror.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myutil.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\scan.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\type.h" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\weather.h" />
-						</Filter>
-						<Filter Name="g2clib-1.0.4" Filter="*.h     ">
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.h" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\grib2.h" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.h" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.h" />
-						</Filter>
-						</Filter>
-						</Filter>
-				<Filter Name="gtiff" Filter="*.h   ">
-					<File RelativePath=".\frmts\gtiff\gt_overview.h" />
-					<Filter Name="libgeotiff" Filter="*.h    ">
-						<File RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geokeys.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geonames.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geotiff.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geotiffio.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geovalues.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_config.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_keyp.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_simpletags.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.h" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\xtiffio.h" />
-					</Filter>
-					<Filter Name="libtiff" Filter="*.h    ">
-						<File RelativePath=".\frmts\gtiff\libtiff\t4.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tiff.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tiffconf.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tiffio.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tiffiop.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tiffvers.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_config.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dir.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_fax3.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_predict.h" />
-						<File RelativePath=".\frmts\gtiff\libtiff\uvcode.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="gxf" Filter="*.h   ">
-					<File RelativePath=".\frmts\gxf\gxfopen.h" />
-				</Filter>
-				<Filter Name="hdf4" Filter="*.h   ">
-					<File RelativePath=".\frmts\hdf4\hdf4compat.h" />
-					<File RelativePath=".\frmts\hdf4\hdf4dataset.h" />
-					<Filter Name="hdf-eos" Filter="*.h    ">
-						<File RelativePath=".\frmts\hdf4\hdf-eos\ease.h" />
-						<File RelativePath=".\frmts\hdf4\hdf-eos\HdfEosDef.h" />
-						<File RelativePath=".\frmts\hdf4\hdf-eos\HDFEOSVersion.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="hdf5" Filter="*.h   ">
-					<File RelativePath=".\frmts\hdf5\gh5_convenience.h" />
-					<File RelativePath=".\frmts\hdf5\hdf5dataset.h" />
-				</Filter>
-				<Filter Name="hfa" Filter="*.h   ">
-					<File RelativePath=".\frmts\hfa\hfa.h" />
-					<File RelativePath=".\frmts\hfa\hfa_p.h" />
-				</Filter>
-				<Filter Name="ilwis" Filter="*.h   ">
-					<File RelativePath=".\frmts\ilwis\ilwisdataset.h" />
-				</Filter>
-				<Filter Name="ingr" Filter="*.h   ">
-					<File RelativePath=".\frmts\ingr\IngrTypes.h" />
-					<File RelativePath=".\frmts\ingr\IntergraphBand.h" />
-					<File RelativePath=".\frmts\ingr\IntergraphDataset.h" />
-					<File RelativePath=".\frmts\ingr\JpegHelper.h" />
-				</Filter>
-				<Filter Name="iso8211" Filter="*.h   ">
-					<File RelativePath=".\frmts\iso8211\iso8211.h" />
-				</Filter>
-				<Filter Name="jp2kak" Filter="*.h   ">
-					<File RelativePath=".\frmts\jp2kak\subfile_source.h" />
-					<File RelativePath=".\frmts\jp2kak\vsil_target.h" />
-				</Filter>
-				<Filter Name="jpeg" Filter="*.h   ">
-					<File RelativePath=".\frmts\jpeg\gdalexif.h" />
-					<Filter Name="libjpeg" Filter="*.h    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg\jchuff.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jconfig.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdct.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdhuff.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jerror.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jinclude.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jmemsys.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jmorecfg.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jpegint.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jpeglib.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jversion.h" />
-					</Filter>
-					<Filter Name="libjpeg12" Filter="*.h    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jchuff.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jconfig.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdct.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdhuff.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jerror.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jinclude.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jmemsys.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jmorecfg.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jpegint.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jpeglib.h" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jversion.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="jpeg2000" Filter="*.h   ">
-					<File RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.h" />
-				</Filter>
-				<Filter Name="mem" Filter="*.h   ">
-					<File RelativePath=".\frmts\mem\memdataset.h" />
-				</Filter>
-				<Filter Name="mrsid" Filter="*.h   ">
-					<File RelativePath=".\frmts\mrsid\mrsidstream.h" />
-				</Filter>
-				<Filter Name="msg" Filter="*.h   ">
-					<File RelativePath=".\frmts\msg\msgcommand.h" />
-					<File RelativePath=".\frmts\msg\msgdataset.h" />
-					<File RelativePath=".\frmts\msg\prologue.h" />
-					<File RelativePath=".\frmts\msg\reflectancecalculator.h" />
-					<File RelativePath=".\frmts\msg\xritheaderparser.h" />
-				</Filter>
-				<Filter Name="msgn" Filter="*.h   ">
-					<File RelativePath=".\frmts\msgn\msg_basic_types.h" />
-					<File RelativePath=".\frmts\msgn\msg_reader_core.h" />
-				</Filter>
-				<Filter Name="netcdf" Filter="*.h   ">
-					<File RelativePath=".\frmts\netcdf\netcdfdataset.h" />
-				</Filter>
-				<Filter Name="nitf" Filter="*.h   ">
-					<File RelativePath=".\frmts\nitf\mgrs.h" />
-					<File RelativePath=".\frmts\nitf\nitflib.h" />
-					<File RelativePath=".\frmts\nitf\rpftoclib.h" />
-				</Filter>
-				<Filter Name="northwood" Filter="*.h   ">
-					<File RelativePath=".\frmts\northwood\northwood.h" />
-				</Filter>
-				<Filter Name="pcidsk" Filter="*.h   ">
-					<File RelativePath=".\frmts\pcidsk\gdal_pcidsk.h" />
-					<Filter Name="sdk" Filter="*.h    ">
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_buffer.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_channel.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_config.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_exception.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_file.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_georef.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_interfaces.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_io.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_mutex.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_pct.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_segment.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_shape.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_types.h" />
-						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_vectorsegment.h" />
-						<Filter Name="channel" Filter="*.h     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cbandinterleavedchannel.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cpcidskchannel.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\ctiledchannel.h" />
-						</Filter>
-						<Filter Name="core" Filter="*.h     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\metadataset.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\mutexholder.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_utils.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\protectedfile.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\sysvirtualfile.h" />
-						</Filter>
-						<Filter Name="segment" Filter="*.h     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\pcidskgeorefbuilder.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\segmentfactory.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\uuid.h" />
-						</Filter>
-						</Filter>
-						</Filter>
-				<Filter Name="pcraster" Filter="*.h   ">
-					<File RelativePath=".\frmts\pcraster\pcrasterdataset.h" />
-					<File RelativePath=".\frmts\pcraster\pcrasterrasterband.h" />
-					<File RelativePath=".\frmts\pcraster\pcrasterutil.h" />
-					<Filter Name="libcsf" Filter="*.h    ">
-						<File RelativePath=".\frmts\pcraster\libcsf\csf.h" />
-						<File RelativePath=".\frmts\pcraster\libcsf\csfattr.h" />
-						<File RelativePath=".\frmts\pcraster\libcsf\csfimpl.h" />
-						<File RelativePath=".\frmts\pcraster\libcsf\csftypes.h" />
-						<File RelativePath=".\frmts\pcraster\libcsf\pcrtypes.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="pds" Filter="*.h   ">
-					<File RelativePath=".\frmts\pds\nasakeywordhandler.h" />
-				</Filter>
-				<Filter Name="pgchip" Filter="*.h   ">
-					<File RelativePath=".\frmts\pgchip\pgchip.h" />
-				</Filter>
-				<Filter Name="png" Filter="*.h   ">
-					<Filter Name="libpng" Filter="*.h    ">
-						<File RelativePath=".\frmts\png\libpng\png.h" />
-						<File RelativePath=".\frmts\png\libpng\pngconf.h" />
-					</Filter>
-					</Filter>
-				<Filter Name="rasterlite" Filter="*.h   ">
-					<File RelativePath=".\frmts\rasterlite\rasterlitedataset.h" />
-				</Filter>
-				<Filter Name="raw" Filter="*.h   ">
-					<File RelativePath=".\frmts\raw\atlsci_spheroid.h" />
-					<File RelativePath=".\frmts\raw\rawdataset.h" />
-				</Filter>
-				<Filter Name="rmf" Filter="*.h   ">
-					<File RelativePath=".\frmts\rmf\rmfdataset.h" />
-				</Filter>
-				<Filter Name="sde" Filter="*.h   ">
-					<File RelativePath=".\frmts\sde\gdal_sde.h" />
-					<File RelativePath=".\frmts\sde\sdedataset.h" />
-					<File RelativePath=".\frmts\sde\sdeerror.h" />
-					<File RelativePath=".\frmts\sde\sderasterband.h" />
-				</Filter>
-				<Filter Name="sdts" Filter="*.h   ">
-					<File RelativePath=".\frmts\sdts\sdts_al.h" />
-				</Filter>
-				<Filter Name="terralib" Filter="*.h   ">
-					<File RelativePath=".\frmts\terralib\TerraLibDataset.h" />
-					<File RelativePath=".\frmts\terralib\TerraLibRasterBand.h" />
-				</Filter>
-				<Filter Name="vrt" Filter="*.h   ">
-					<File RelativePath=".\frmts\vrt\gdal_vrt.h" />
-					<File RelativePath=".\frmts\vrt\vrtdataset.h" />
-				</Filter>
-				<Filter Name="wktraster" Filter="*.h   ">
-					<File RelativePath=".\frmts\wktraster\wktraster.h" />
-				</Filter>
-				<Filter Name="wms" Filter="*.h   ">
-					<File RelativePath=".\frmts\wms\gdalhttp.h" />
-					<File RelativePath=".\frmts\wms\md5.h" />
-					<File RelativePath=".\frmts\wms\minidriver_tileservice.h" />
-					<File RelativePath=".\frmts\wms\minidriver_tms.h" />
-					<File RelativePath=".\frmts\wms\minidriver_wms.h" />
-					<File RelativePath=".\frmts\wms\minidriver_worldwind.h" />
-					<File RelativePath=".\frmts\wms\stdinc.h" />
-					<File RelativePath=".\frmts\wms\wmsdriver.h" />
-				</Filter>
-				<Filter Name="zlib" Filter="*.h   ">
-					<File RelativePath=".\frmts\zlib\crc32.h" />
-					<File RelativePath=".\frmts\zlib\deflate.h" />
-					<File RelativePath=".\frmts\zlib\inffast.h" />
-					<File RelativePath=".\frmts\zlib\inffixed.h" />
-					<File RelativePath=".\frmts\zlib\inflate.h" />
-					<File RelativePath=".\frmts\zlib\inftrees.h" />
-					<File RelativePath=".\frmts\zlib\trees.h" />
-					<File RelativePath=".\frmts\zlib\zconf.h" />
-					<File RelativePath=".\frmts\zlib\zlib.h" />
-					<File RelativePath=".\frmts\zlib\zutil.h" />
-				</Filter>
-				</Filter>
-			<Filter Name="gcore" Filter="*.h  ">
-				<File RelativePath=".\gcore\gdal.h" />
-				<File RelativePath=".\gcore\gdaljp2metadata.h" />
-				<File RelativePath=".\gcore\gdal_frmts.h" />
-				<File RelativePath=".\gcore\gdal_pam.h" />
-				<File RelativePath=".\gcore\gdal_priv.h" />
-				<File RelativePath=".\gcore\gdal_proxy.h" />
-				<File RelativePath=".\gcore\gdal_rat.h" />
-				<File RelativePath=".\gcore\gdal_version.h" />
-			</Filter>
-			<Filter Name="ogr" Filter="*.h  ">
-				<File RelativePath=".\ogr\ogr_api.h" />
-				<File RelativePath=".\ogr\ogr_core.h" />
-				<File RelativePath=".\ogr\ogr_expat.h" />
-				<File RelativePath=".\ogr\ogr_feature.h" />
-				<File RelativePath=".\ogr\ogr_featurestyle.h" />
-				<File RelativePath=".\ogr\ogr_geometry.h" />
-				<File RelativePath=".\ogr\ogr_geos.h" />
-				<File RelativePath=".\ogr\ogr_p.h" />
-				<File RelativePath=".\ogr\ogr_spatialref.h" />
-				<File RelativePath=".\ogr\ogr_srs_api.h" />
-				<File RelativePath=".\ogr\ogr_srs_esri_names.h" />
-				<File RelativePath=".\ogr\swq.h" />
-				<Filter Name="ogrsf_frmts" Filter="*.h   ">
-					<File RelativePath=".\ogr\ogrsf_frmts\ogrsf_frmts.h" />
-					<File RelativePath=".\ogr\ogrsf_frmts\ogr_attrind.h" />
-					<Filter Name="avc" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\dbfopen.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogr_avc.h" />
-					</Filter>
-					<Filter Name="bna" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogr_bna.h" />
-					</Filter>
-					<Filter Name="csv" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogr_csv.h" />
-					</Filter>
-					<Filter Name="dgn" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlib.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlibp.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\ogr_dgn.h" />
-						<Filter Name="dist" Filter="*.h     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\dgn\dist\cpl_config.h" />
-						</Filter>
-						</Filter>
-					<Filter Name="dods" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h" />
-					</Filter>
-					<Filter Name="dxf" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_dxf.h" />
-					</Filter>
-					<Filter Name="fme" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr.h" />
-					</Filter>
-					<Filter Name="generic" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.h" />
-					</Filter>
-					<Filter Name="geoconcept" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.h" />
-					</Filter>
-					<Filter Name="geojson" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogr_geojson.h" />
-						<Filter Name="jsonc" Filter="*.h     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\bits.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\config.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object_private.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.h" />
-						</Filter>
-						</Filter>
-					<Filter Name="georss" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogr_georss.h" />
-					</Filter>
-					<Filter Name="gml" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlreaderp.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h" />
-					</Filter>
-					<Filter Name="gmt" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h" />
-					</Filter>
-					<Filter Name="gpx" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogr_gpx.h" />
-					</Filter>
-					<Filter Name="grass" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrass.h" />
-					</Filter>
-					<Filter Name="gtm" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\gtm.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogr_gtm.h" />
-					</Filter>
-					<Filter Name="idb" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h" />
-					</Filter>
-					<Filter Name="ili" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1readerp.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili2readerp.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili1.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili2.h" />
-						<Filter Name="iom" Filter="*.h     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom.h" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_p.h" />
-						</Filter>
-						</Filter>
-					<Filter Name="ingres" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogr_ingres.h" />
-					</Filter>
-					<Filter Name="kml" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kml.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlutility.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogr_kml.h" />
-					</Filter>
-					<Filter Name="mem" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogr_mem.h" />
-					</Filter>
-					<Filter Name="mitab" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_priv.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.h" />
-					</Filter>
-					<Filter Name="mysql" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h" />
-					</Filter>
-					<Filter Name="ntf" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf.h" />
-					</Filter>
-					<Filter Name="oci" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogr_oci.h" />
-					</Filter>
-					<Filter Name="odbc" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogr_odbc.h" />
-					</Filter>
-					<Filter Name="ogdi" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdi.h" />
-					</Filter>
-					<Filter Name="pcidsk" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h" />
-					</Filter>
-					<Filter Name="pg" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogr_pg.h" />
-					</Filter>
-					<Filter Name="pgeo" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogr_pgeo.h" />
-					</Filter>
-					<Filter Name="rec" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\ogr_rec.h" />
-					</Filter>
-					<Filter Name="s57" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\ogr_s57.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57tables.h" />
-					</Filter>
-					<Filter Name="sde" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sde\ogr_sde.h" />
-					</Filter>
-					<Filter Name="sdts" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogr_sdts.h" />
-					</Filter>
-					<Filter Name="shape" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\ogrshape.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\shapefil.h" />
-					</Filter>
-					<Filter Name="sqlite" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h" />
-					</Filter>
-					<Filter Name="tiger" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h" />
-					</Filter>
-					<Filter Name="vrt" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h" />
-					</Filter>
-					<Filter Name="xplane" Filter="*.h    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.h" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.h" />
-					</Filter>
-					</Filter>
-				</Filter>
-			<Filter Name="port" Filter="*.h  ">
-				<File RelativePath=".\port\cplkeywordparser.h" />
-				<File RelativePath=".\port\cpl_atomic_ops.h" />
-				<File RelativePath=".\port\cpl_config.h" />
-				<File RelativePath=".\port\cpl_config_extras.h" />
-				<File RelativePath=".\port\cpl_conv.h" />
-				<File RelativePath=".\port\cpl_csv.h" />
-				<File RelativePath=".\port\cpl_error.h" />
-				<File RelativePath=".\port\cpl_hash_set.h" />
-				<File RelativePath=".\port\cpl_http.h" />
-				<File RelativePath=".\port\cpl_list.h" />
-				<File RelativePath=".\port\cpl_minixml.h" />
-				<File RelativePath=".\port\cpl_minizip_ioapi.h" />
-				<File RelativePath=".\port\cpl_minizip_unzip.h" />
-				<File RelativePath=".\port\cpl_multiproc.h" />
-				<File RelativePath=".\port\cpl_odbc.h" />
-				<File RelativePath=".\port\cpl_port.h" />
-				<File RelativePath=".\port\cpl_quad_tree.h" />
-				<File RelativePath=".\port\cpl_string.h" />
-				<File RelativePath=".\port\cpl_time.h" />
-				<File RelativePath=".\port\cpl_vsi.h" />
-				<File RelativePath=".\port\cpl_vsi_virtual.h" />
-				<File RelativePath=".\port\cpl_win32ce_api.h" />
-				<File RelativePath=".\port\cpl_wince.h" />
-			</Filter>
-			</Filter>
-		<Filter Name="Source Files" Filter="*.c;*.cpp ">
-			<Filter Name="alg" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\alg\gdal_crs.c" />
-				<File RelativePath=".\alg\gdal_nrgcrs.c" />
-				<File RelativePath=".\alg\contour.cpp" />
-				<File RelativePath=".\alg\gdalchecksum.cpp" />
-				<File RelativePath=".\alg\gdalcutline.cpp" />
-				<File RelativePath=".\alg\gdaldither.cpp" />
-				<File RelativePath=".\alg\gdalgeoloc.cpp" />
-				<File RelativePath=".\alg\gdalgrid.cpp" />
-				<File RelativePath=".\alg\gdalmediancut.cpp" />
-				<File RelativePath=".\alg\gdalproximity.cpp" />
-				<File RelativePath=".\alg\gdalrasterize.cpp" />
-				<File RelativePath=".\alg\gdalrasterpolygonenumerator.cpp" />
-				<File RelativePath=".\alg\gdalsievefilter.cpp" />
-				<File RelativePath=".\alg\gdalsimplewarp.cpp" />
-				<File RelativePath=".\alg\gdaltransformer.cpp" />
-				<File RelativePath=".\alg\gdalwarper.cpp" />
-				<File RelativePath=".\alg\gdalwarpkernel.cpp" />
-				<File RelativePath=".\alg\gdalwarpoperation.cpp" />
-				<File RelativePath=".\alg\gdal_rpc.cpp" />
-				<File RelativePath=".\alg\gdal_tps.cpp" />
-				<File RelativePath=".\alg\llrasterize.cpp" />
-				<File RelativePath=".\alg\polygonize.cpp" />
-				<File RelativePath=".\alg\rasterfill.cpp" />
-				<File RelativePath=".\alg\thinplatespline.cpp" />
-			</Filter>
-			<Filter Name="apps" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\apps\gdal2ogr.c" />
-				<File RelativePath=".\apps\gdalflattenmask.c" />
-				<File RelativePath=".\apps\gdalinfo.c" />
-				<File RelativePath=".\apps\gdaltindex.c" />
-				<File RelativePath=".\apps\gdalwarpsimple.c" />
-				<File RelativePath=".\apps\dumpoverviews.cpp" />
-				<File RelativePath=".\apps\gdaladdo.cpp" />
-				<File RelativePath=".\apps\gdalbuildvrt.cpp" />
-				<File RelativePath=".\apps\gdaldem.cpp" />
-				<File RelativePath=".\apps\gdalenhance.cpp" />
-				<File RelativePath=".\apps\gdalmanage.cpp" />
-				<File RelativePath=".\apps\gdaltorture.cpp" />
-				<File RelativePath=".\apps\gdaltransform.cpp" />
-				<File RelativePath=".\apps\gdalwarp.cpp" />
-				<File RelativePath=".\apps\gdal_contour.cpp" />
-				<File RelativePath=".\apps\gdal_grid.cpp" />
-				<File RelativePath=".\apps\gdal_rasterize.cpp" />
-				<File RelativePath=".\apps\gdal_translate.cpp" />
-				<File RelativePath=".\apps\multireadtest.cpp" />
-				<File RelativePath=".\apps\nearblack.cpp" />
-				<File RelativePath=".\apps\ogr2ogr.cpp" />
-				<File RelativePath=".\apps\ogrdissolve.cpp" />
-				<File RelativePath=".\apps\ogrinfo.cpp" />
-				<File RelativePath=".\apps\ogrtindex.cpp" />
-				<File RelativePath=".\apps\testepsg.cpp" />
-				<File RelativePath=".\apps\test_ogrsf.cpp" />
-			</Filter>
-			<Filter Name="bridge" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\bridge\bridge_test.cpp" />
-				<File RelativePath=".\bridge\gbgetsymbol.cpp" />
-				<File RelativePath=".\bridge\gdalbridge.cpp" />
-			</Filter>
-			<Filter Name="frmts" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\frmts\gdalallregister.cpp" />
-				<Filter Name="aaigrid" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\aaigrid\aaigriddataset.cpp" />
-				</Filter>
-				<Filter Name="adrg" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\adrg\adrgdataset.cpp" />
-					<File RelativePath=".\frmts\adrg\srpdataset.cpp" />
-				</Filter>
-				<Filter Name="aigrid" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\aigrid\aigccitt.c" />
-					<File RelativePath=".\frmts\aigrid\aigopen.c" />
-					<File RelativePath=".\frmts\aigrid\aitest.c" />
-					<File RelativePath=".\frmts\aigrid\gridlib.c" />
-					<File RelativePath=".\frmts\aigrid\aigdataset.cpp" />
-				</Filter>
-				<Filter Name="airsar" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\airsar\airsardataset.cpp" />
-				</Filter>
-				<Filter Name="blx" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\blx\blx.c" />
-					<File RelativePath=".\frmts\blx\blxdataset.cpp" />
-				</Filter>
-				<Filter Name="bmp" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\bmp\bmpdataset.cpp" />
-				</Filter>
-				<Filter Name="bsb" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\bsb\bsb2raw.c" />
-					<File RelativePath=".\frmts\bsb\bsb_read.c" />
-					<File RelativePath=".\frmts\bsb\bsbdataset.cpp" />
-				</Filter>
-				<Filter Name="ceos" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ceos\ceosopen.c" />
-					<File RelativePath=".\frmts\ceos\ceostest.c" />
-					<File RelativePath=".\frmts\ceos\ceosdataset.cpp" />
-				</Filter>
-				<Filter Name="ceos2" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ceos2\ceos.c" />
-					<File RelativePath=".\frmts\ceos2\ceosrecipe.c" />
-					<File RelativePath=".\frmts\ceos2\ceossar.c" />
-					<File RelativePath=".\frmts\ceos2\link.c" />
-					<File RelativePath=".\frmts\ceos2\sar_ceosdataset.cpp" />
-				</Filter>
-				<Filter Name="coasp" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\coasp\coasp_dataset.cpp" />
-				</Filter>
-				<Filter Name="cosar" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\cosar\cosar_dataset.cpp" />
-				</Filter>
-				<Filter Name="dimap" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\dimap\dimapdataset.cpp" />
-				</Filter>
-				<Filter Name="dods" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\dods\dodsdataset2.cpp" />
-				</Filter>
-				<Filter Name="dted" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\dted\dted_api.c" />
-					<File RelativePath=".\frmts\dted\dted_create.c" />
-					<File RelativePath=".\frmts\dted\dted_ptstream.c" />
-					<File RelativePath=".\frmts\dted\dted_test.c" />
-					<File RelativePath=".\frmts\dted\dteddataset.cpp" />
-				</Filter>
-				<Filter Name="ecw" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ecw\ecwcreatecopy.cpp" />
-					<File RelativePath=".\frmts\ecw\ecwdataset.cpp" />
-					<File RelativePath=".\frmts\ecw\jp2userbox.cpp" />
-				</Filter>
-				<Filter Name="elas" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\elas\elasdataset.cpp" />
-				</Filter>
-				<Filter Name="envisat" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\envisat\dumpgeo.c" />
-					<File RelativePath=".\frmts\envisat\EnvisatFile.c" />
-					<File RelativePath=".\frmts\envisat\envisat_dump.c" />
-					<File RelativePath=".\frmts\envisat\envisatdataset.cpp" />
-				</Filter>
-				<Filter Name="epsilon" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\epsilon\epsilondataset.cpp" />
-				</Filter>
-				<Filter Name="ers" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ers\ersdataset.cpp" />
-					<File RelativePath=".\frmts\ers\ershdrnode.cpp" />
-				</Filter>
-				<Filter Name="fit" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\fit\fit.cpp" />
-					<File RelativePath=".\frmts\fit\fitdataset.cpp" />
-				</Filter>
-				<Filter Name="fits" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\fits\fitsdataset.cpp" />
-				</Filter>
-				<Filter Name="georaster" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\georaster\georaster_dataset.cpp" />
-					<File RelativePath=".\frmts\georaster\georaster_driver.cpp" />
-					<File RelativePath=".\frmts\georaster\georaster_rasterband.cpp" />
-					<File RelativePath=".\frmts\georaster\georaster_wrapper.cpp" />
-					<File RelativePath=".\frmts\georaster\oci_wrapper.cpp" />
-				</Filter>
-				<Filter Name="gff" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\gff\gff_dataset.cpp" />
-				</Filter>
-				<Filter Name="gif" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\gif\biggifdataset.cpp" />
-					<File RelativePath=".\frmts\gif\gifdataset.cpp" />
-					<Filter Name="giflib" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\gif\giflib\dgif_lib.c" />
-						<File RelativePath=".\frmts\gif\giflib\egif_lib.c" />
-						<File RelativePath=".\frmts\gif\giflib\gifalloc.c" />
-						<File RelativePath=".\frmts\gif\giflib\gif_err.c" />
-						<File RelativePath=".\frmts\gif\giflib\gif_hash.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="grass" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\grass\grass57dataset.cpp" />
-					<File RelativePath=".\frmts\grass\grassdataset.cpp" />
-					</Filter>
-				<Filter Name="grib" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\grib\gribdataset.cpp" />
-					<Filter Name="degrib18" Filter="*.c;*.cpp    ">
-						<Filter Name="degrib" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\grib\degrib18\degrib\clock.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\engribapi.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\grib2api.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\memendian.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myassert.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myerror.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\myutil.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\scan.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\weather.c" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\degrib1.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\degrib2.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\fileendian.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\grib1tab.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\inventory.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\metaname.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\metaparse.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\metaprint.cpp" />
-							<File RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.cpp" />
-						</Filter>
-						<Filter Name="g2clib-1.0.4" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\cmplxpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\compack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\comunpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_png.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_jpeg2000.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_png.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addfield.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addgrid.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addlocal.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_create.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_free.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_getfld.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_gribend.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_info.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_miss.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack1.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack2.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack3.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack4.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack5.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack6.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack7.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gbits.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getdim.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getpoly.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\int_power.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcunpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\misspack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\mkieee.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pack_gp.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngunpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\rdieee.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\reduce.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\seekgb.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simunpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specunpack.c" />
-							<File RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_jpeg2000.cpp" />
-						</Filter>
-						</Filter>
-						</Filter>
-				<Filter Name="gsg" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\gsg\gs7bgdataset.cpp" />
-					<File RelativePath=".\frmts\gsg\gsagdataset.cpp" />
-					<File RelativePath=".\frmts\gsg\gsbgdataset.cpp" />
-				</Filter>
-				<Filter Name="gtiff" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\gtiff\tif_float.c" />
-					<File RelativePath=".\frmts\gtiff\geotiff.cpp" />
-					<File RelativePath=".\frmts\gtiff\gt_citation.cpp" />
-					<File RelativePath=".\frmts\gtiff\gt_overview.cpp" />
-					<File RelativePath=".\frmts\gtiff\gt_wkt_srs.cpp" />
-					<File RelativePath=".\frmts\gtiff\tifvsi.cpp" />
-					<Filter Name="libgeotiff" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geotiff_proj4.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_extra.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_free.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_get.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_names.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_new.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_print.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_set.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_simpletags.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_trans.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\geo_write.c" />
-						<File RelativePath=".\frmts\gtiff\libgeotiff\xtiff.c" />
-					</Filter>
-					<Filter Name="libtiff" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_aux.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_close.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_codec.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_color.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_compress.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dir.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dirinfo.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dirread.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dirwrite.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_dumpmode.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_error.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_extension.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_fax3.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_fax3sm.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_flush.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_getimage.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_jpeg.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_jpeg_12.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_luv.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_lzw.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_next.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_ojpeg.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_open.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_packbits.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_pixarlog.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_predict.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_print.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_read.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_strip.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_swab.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_thunder.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_tile.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_version.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_vsi.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_warning.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_write.c" />
-						<File RelativePath=".\frmts\gtiff\libtiff\tif_zip.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="gxf" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\gxf\gxfopen.c" />
-					<File RelativePath=".\frmts\gxf\gxf_ogcwkt.c" />
-					<File RelativePath=".\frmts\gxf\gxf_proj4.c" />
-					<File RelativePath=".\frmts\gxf\gxfdataset.cpp" />
-				</Filter>
-				<Filter Name="hdf4" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\hdf4\hdf4dataset.cpp" />
-					<File RelativePath=".\frmts\hdf4\hdf4imagedataset.cpp" />
-					<Filter Name="hdf-eos" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\hdf4\hdf-eos\EHapi.c" />
-						<File RelativePath=".\frmts\hdf4\hdf-eos\gctp_wrap.c" />
-						<File RelativePath=".\frmts\hdf4\hdf-eos\GDapi.c" />
-						<File RelativePath=".\frmts\hdf4\hdf-eos\SWapi.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="hdf5" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\hdf5\bagdataset.cpp" />
-					<File RelativePath=".\frmts\hdf5\gh5_convenience.cpp" />
-					<File RelativePath=".\frmts\hdf5\hdf5dataset.cpp" />
-					<File RelativePath=".\frmts\hdf5\hdf5imagedataset.cpp" />
-					<File RelativePath=".\frmts\hdf5\iso19115_srs.cpp" />
-				</Filter>
-				<Filter Name="hfa" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\hfa\hfaband.cpp" />
-					<File RelativePath=".\frmts\hfa\hfacompress.cpp" />
-					<File RelativePath=".\frmts\hfa\hfadataset.cpp" />
-					<File RelativePath=".\frmts\hfa\hfadictionary.cpp" />
-					<File RelativePath=".\frmts\hfa\hfaentry.cpp" />
-					<File RelativePath=".\frmts\hfa\hfafield.cpp" />
-					<File RelativePath=".\frmts\hfa\hfaopen.cpp" />
-					<File RelativePath=".\frmts\hfa\hfatest.cpp" />
-					<File RelativePath=".\frmts\hfa\hfatype.cpp" />
-					<File RelativePath=".\frmts\hfa\hfa_overviews.cpp" />
-				</Filter>
-				<Filter Name="idrisi" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\idrisi\IdrisiDataset.cpp" />
-				</Filter>
-				<Filter Name="ilwis" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ilwis\ilwiscoordinatesystem.cpp" />
-					<File RelativePath=".\frmts\ilwis\ilwisdataset.cpp" />
-				</Filter>
-				<Filter Name="ingr" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ingr\IngrTypes.cpp" />
-					<File RelativePath=".\frmts\ingr\IntergraphBand.cpp" />
-					<File RelativePath=".\frmts\ingr\IntergraphDataset.cpp" />
-					<File RelativePath=".\frmts\ingr\JpegHelper.cpp" />
-				</Filter>
-				<Filter Name="iso8211" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\iso8211\8211dump.cpp" />
-					<File RelativePath=".\frmts\iso8211\8211view.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddffield.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddffielddefn.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddfmodule.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddfrecord.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddfsubfielddefn.cpp" />
-					<File RelativePath=".\frmts\iso8211\ddfutils.cpp" />
-					<File RelativePath=".\frmts\iso8211\mkcatalog.cpp" />
-					<File RelativePath=".\frmts\iso8211\timetest.cpp" />
-				</Filter>
-				<Filter Name="jaxapalsar" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\jaxapalsar\jaxapalsardataset.cpp" />
-				</Filter>
-				<Filter Name="jdem" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\jdem\jdemdataset.cpp" />
-				</Filter>
-				<Filter Name="jp2kak" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\jp2kak\jp2kakdataset.cpp" />
-				</Filter>
-				<Filter Name="jpeg" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\jpeg\jpgdataset.cpp" />
-					<File RelativePath=".\frmts\jpeg\jpgdataset_12.cpp" />
-					<File RelativePath=".\frmts\jpeg\vsidataio.cpp" />
-					<Filter Name="libjpeg" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcapimin.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcapistd.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jccoefct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jccolor.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcdctmgr.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jchuff.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcinit.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcmainct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcmarker.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcmaster.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcomapi.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcparam.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcphuff.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcprepct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jcsample.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jctrans.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdapimin.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdapistd.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdatadst.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdatasrc.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdcoefct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdcolor.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jddctmgr.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdhuff.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdinput.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdmainct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdmarker.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdmaster.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdmerge.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdphuff.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdpostct.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdsample.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jdtrans.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jerror.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jfdctflt.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jfdctfst.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jfdctint.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jidctflt.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jidctfst.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jidctint.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jidctred.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jmemansi.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jmemmgr.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jquant1.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jquant2.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg\jutils.c" />
-					</Filter>
-					<Filter Name="libjpeg12" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcapimin12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcapistd12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jccoefct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jccolor12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcdctmgr12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jchuff12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcinit12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcmainct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcmarker12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcmaster12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcomapi12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcparam12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcphuff12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcprepct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jcsample12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jctrans12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdapimin12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdapistd12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdatadst12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdatasrc12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdcoefct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdcolor12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jddctmgr12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdhuff12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdinput12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdmainct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdmarker12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdmaster12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdmerge12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdphuff12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdpostct12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdsample12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jdtrans12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jerror12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jfdctflt12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jfdctfst12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jfdctint12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jidctflt12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jidctfst12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jidctint12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jidctred12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jmemansi12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jmemmgr12.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jquant112.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jquant212.c" />
-						<File RelativePath=".\frmts\jpeg\libjpeg12\jutils12.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="jpeg2000" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\jpeg2000\jpeg2000dataset.cpp" />
-					<File RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.cpp" />
-				</Filter>
-				<Filter Name="l1b" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\l1b\l1bdataset.cpp" />
-				</Filter>
-				<Filter Name="leveller" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\leveller\levellerdataset.cpp" />
-				</Filter>
-				<Filter Name="mem" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\mem\memdataset.cpp" />
-				</Filter>
-				<Filter Name="mrsid" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\mrsid\mrsiddataset.cpp" />
-					<File RelativePath=".\frmts\mrsid\mrsidstream.cpp" />
-				</Filter>
-				<Filter Name="msg" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\msg\msgcommand.cpp" />
-					<File RelativePath=".\frmts\msg\msgdataset.cpp" />
-					<File RelativePath=".\frmts\msg\prologue.cpp" />
-					<File RelativePath=".\frmts\msg\reflectancecalculator.cpp" />
-					<File RelativePath=".\frmts\msg\xritheaderparser.cpp" />
-				</Filter>
-				<Filter Name="msgn" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\msgn\msgndataset.cpp" />
-					<File RelativePath=".\frmts\msgn\msg_basic_types.cpp" />
-					<File RelativePath=".\frmts\msgn\msg_reader_core.cpp" />
-				</Filter>
-				<Filter Name="netcdf" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\netcdf\gmtdataset.cpp" />
-					<File RelativePath=".\frmts\netcdf\netcdfdataset.cpp" />
-				</Filter>
-				<Filter Name="nitf" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\nitf\mgrs.c" />
-					<File RelativePath=".\frmts\nitf\nitfdump.c" />
-					<File RelativePath=".\frmts\nitf\nitffile.c" />
-					<File RelativePath=".\frmts\nitf\nitfimage.c" />
-					<File RelativePath=".\frmts\nitf\nitfaridpcm.cpp" />
-					<File RelativePath=".\frmts\nitf\nitfbilevel.cpp" />
-					<File RelativePath=".\frmts\nitf\nitfdataset.cpp" />
-					<File RelativePath=".\frmts\nitf\nitfwritejpeg.cpp" />
-					<File RelativePath=".\frmts\nitf\nitfwritejpeg_12.cpp" />
-					<File RelativePath=".\frmts\nitf\rpftocdataset.cpp" />
-					<File RelativePath=".\frmts\nitf\rpftocfile.cpp" />
-				</Filter>
-				<Filter Name="northwood" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\northwood\grcdataset.cpp" />
-					<File RelativePath=".\frmts\northwood\grddataset.cpp" />
-					<File RelativePath=".\frmts\northwood\northwood.cpp" />
-				</Filter>
-				<Filter Name="ogdi" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\ogdi\ogdidataset.cpp" />
-				</Filter>
-				<Filter Name="pcidsk" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\pcidsk\pcidskdataset.cpp" />
-					<File RelativePath=".\frmts\pcidsk\pcidskdataset2.cpp" />
-					<File RelativePath=".\frmts\pcidsk\pcidsktiledrasterband.cpp" />
-					<File RelativePath=".\frmts\pcidsk\vsi_pcidsk_io.cpp" />
-					<Filter Name="sdk" Filter="*.c;*.cpp    ">
-						<Filter Name="channel" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cbandinterleavedchannel.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cpcidskchannel.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\channel\ctiledchannel.cpp" />
-						</Filter>
-						<Filter Name="core" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\libjpeg_io.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\metadataset_p.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidskbuffer.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidskcreate.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidskexception.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidskinterfaces.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidskopen.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_pubutils.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_utils.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\core\sysvirtualfile.cpp" />
-						</Filter>
-						<Filter Name="port" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\port\io_stdio.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\port\io_win32.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\port\pthread_mutex.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\port\win32_mutex.cpp" />
-						</Filter>
-						<Filter Name="segment" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment_p.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\segmentfactory.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\segment_loader.cpp" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.cpp" />
-						</Filter>
-						</Filter>
-						</Filter>
-				<Filter Name="pcraster" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\pcraster\pcrasterdataset.cpp" />
-					<File RelativePath=".\frmts\pcraster\pcrastermisc.cpp" />
-					<File RelativePath=".\frmts\pcraster\pcrasterrasterband.cpp" />
-					<File RelativePath=".\frmts\pcraster\pcrasterutil.cpp" />
-					<Filter Name="libcsf" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\pcraster\libcsf\angle.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\attravai.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\attrsize.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\cellsize.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\create2.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\csfglob.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\csfsup.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\delattr.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\dumconv.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\endian.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\filename.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gattrblk.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gattridx.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gcellrep.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gdattype.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\getattr.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\getx0.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gety0.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\ggisfid.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gmaxval.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gminval.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gnrcols.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gnrrows.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gproj.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gputproj.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gvalscal.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gvartype.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\gversion.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\ismv.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\kernlcsf.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\legend.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\mclose.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\mopen.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\moreattr.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\mperror.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\pgisfid.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\pmaxval.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\pminval.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\putallmv.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\putattr.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\putsomec.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\putx0.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\puty0.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\pvalscal.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rattrblk.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rcomp.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rcoords.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rdup2.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\reseterr.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rextend.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rmalloc.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\rrowcol.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\ruseas.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\setangle.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\setmv.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\setvtmv.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\strconst.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\strpad.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\swapio.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\trackmm.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\vs2.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\vsdef.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\vsis.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\vsvers.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\wattrblk.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\_getcell.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\_getrow.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\_gsomece.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\_putcell.c" />
-						<File RelativePath=".\frmts\pcraster\libcsf\_rputrow.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="pds" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\pds\isis2dataset.cpp" />
-					<File RelativePath=".\frmts\pds\isis3dataset.cpp" />
-					<File RelativePath=".\frmts\pds\nasakeywordhandler.cpp" />
-					<File RelativePath=".\frmts\pds\pdsdataset.cpp" />
-				</Filter>
-				<Filter Name="pgchip" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\pgchip\pgchipdataset.cpp" />
-					<File RelativePath=".\frmts\pgchip\pgchiprasterband.cpp" />
-					<File RelativePath=".\frmts\pgchip\pgchiputilities.cpp" />
-				</Filter>
-				<Filter Name="png" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\png\pngdataset.cpp" />
-					<Filter Name="libpng" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\frmts\png\libpng\png.c" />
-						<File RelativePath=".\frmts\png\libpng\pngerror.c" />
-						<File RelativePath=".\frmts\png\libpng\pnggccrd.c" />
-						<File RelativePath=".\frmts\png\libpng\pngget.c" />
-						<File RelativePath=".\frmts\png\libpng\pngmem.c" />
-						<File RelativePath=".\frmts\png\libpng\pngpread.c" />
-						<File RelativePath=".\frmts\png\libpng\pngread.c" />
-						<File RelativePath=".\frmts\png\libpng\pngrio.c" />
-						<File RelativePath=".\frmts\png\libpng\pngrtran.c" />
-						<File RelativePath=".\frmts\png\libpng\pngrutil.c" />
-						<File RelativePath=".\frmts\png\libpng\pngset.c" />
-						<File RelativePath=".\frmts\png\libpng\pngtrans.c" />
-						<File RelativePath=".\frmts\png\libpng\pngvcrd.c" />
-						<File RelativePath=".\frmts\png\libpng\pngwio.c" />
-						<File RelativePath=".\frmts\png\libpng\pngwrite.c" />
-						<File RelativePath=".\frmts\png\libpng\pngwtran.c" />
-						<File RelativePath=".\frmts\png\libpng\pngwutil.c" />
-					</Filter>
-					</Filter>
-				<Filter Name="r" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\r\rcreatecopy.cpp" />
-					<File RelativePath=".\frmts\r\rdataset.cpp" />
-				</Filter>
-				<Filter Name="rasterlite" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\rasterlite\rasterlitecreatecopy.cpp" />
-					<File RelativePath=".\frmts\rasterlite\rasterlitedataset.cpp" />
-					<File RelativePath=".\frmts\rasterlite\rasterliteoverviews.cpp" />
-				</Filter>
-				<Filter Name="raw" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\raw\atlsci_spheroid.cpp" />
-					<File RelativePath=".\frmts\raw\btdataset.cpp" />
-					<File RelativePath=".\frmts\raw\cpgdataset.cpp" />
-					<File RelativePath=".\frmts\raw\dipxdataset.cpp" />
-					<File RelativePath=".\frmts\raw\doq1dataset.cpp" />
-					<File RelativePath=".\frmts\raw\doq2dataset.cpp" />
-					<File RelativePath=".\frmts\raw\ehdrdataset.cpp" />
-					<File RelativePath=".\frmts\raw\eirdataset.cpp" />
-					<File RelativePath=".\frmts\raw\envidataset.cpp" />
-					<File RelativePath=".\frmts\raw\fastdataset.cpp" />
-					<File RelativePath=".\frmts\raw\fujibasdataset.cpp" />
-					<File RelativePath=".\frmts\raw\genbindataset.cpp" />
-					<File RelativePath=".\frmts\raw\gscdataset.cpp" />
-					<File RelativePath=".\frmts\raw\hkvdataset.cpp" />
-					<File RelativePath=".\frmts\raw\idadataset.cpp" />
-					<File RelativePath=".\frmts\raw\landataset.cpp" />
-					<File RelativePath=".\frmts\raw\lcpdataset.cpp" />
-					<File RelativePath=".\frmts\raw\mffdataset.cpp" />
-					<File RelativePath=".\frmts\raw\ndfdataset.cpp" />
-					<File RelativePath=".\frmts\raw\pauxdataset.cpp" />
-					<File RelativePath=".\frmts\raw\pnmdataset.cpp" />
-					<File RelativePath=".\frmts\raw\rawdataset.cpp" />
-				</Filter>
-				<Filter Name="rik" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\rik\rikdataset.cpp" />
-				</Filter>
-				<Filter Name="rmf" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\rmf\rmfdataset.cpp" />
-					<File RelativePath=".\frmts\rmf\rmflzw.cpp" />
-				</Filter>
-				<Filter Name="rs2" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\rs2\rs2dataset.cpp" />
-				</Filter>
-				<Filter Name="saga" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\saga\sagadataset.cpp" />
-				</Filter>
-				<Filter Name="sde" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\sde\sdedataset.cpp" />
-					<File RelativePath=".\frmts\sde\sdeerror.cpp" />
-					<File RelativePath=".\frmts\sde\sderasterband.cpp" />
-				</Filter>
-				<Filter Name="sdts" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\sdts\sdts2shp.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsattrreader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtscatd.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsdataset.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsindexedreader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsiref.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtslib.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtslinereader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtspointreader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtspolygonreader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsrasterreader.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtstransfer.cpp" />
-					<File RelativePath=".\frmts\sdts\sdtsxref.cpp" />
-				</Filter>
-				<Filter Name="sgi" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\sgi\sgidataset.cpp" />
-				</Filter>
-				<Filter Name="srtmhgt" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\srtmhgt\srtmhgtdataset.cpp" />
-				</Filter>
-				<Filter Name="terragen" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\terragen\terragendataset.cpp" />
-				</Filter>
-				<Filter Name="terralib" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\terralib\TerraLibDataset.cpp" />
-					<File RelativePath=".\frmts\terralib\TerraLibRasterBand.cpp" />
-				</Filter>
-				<Filter Name="til" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\til\tildataset.cpp" />
-				</Filter>
-				<Filter Name="tsx" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\tsx\tsxdataset.cpp" />
-				</Filter>
-				<Filter Name="usgsdem" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\usgsdem\usgsdemdataset.cpp" />
-					<File RelativePath=".\frmts\usgsdem\usgsdem_create.cpp" />
-				</Filter>
-				<Filter Name="vrt" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\vrt\vrtdataset.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtderivedrasterband.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtdriver.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtfilters.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtrasterband.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtrawrasterband.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtsourcedrasterband.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtsources.cpp" />
-					<File RelativePath=".\frmts\vrt\vrtwarped.cpp" />
-				</Filter>
-				<Filter Name="wcs" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\wcs\httpdriver.cpp" />
-					<File RelativePath=".\frmts\wcs\wcsdataset.cpp" />
-				</Filter>
-				<Filter Name="wktraster" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\wktraster\wktrasterdataset.cpp" />
-					<File RelativePath=".\frmts\wktraster\wktrasterrasterband.cpp" />
-					<File RelativePath=".\frmts\wktraster\wktrasterwrapper.cpp" />
-				</Filter>
-				<Filter Name="wms" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\wms\cache.cpp" />
-					<File RelativePath=".\frmts\wms\dataset.cpp" />
-					<File RelativePath=".\frmts\wms\gdalhttp.cpp" />
-					<File RelativePath=".\frmts\wms\md5.cpp" />
-					<File RelativePath=".\frmts\wms\minidriver.cpp" />
-					<File RelativePath=".\frmts\wms\minidriver_tileservice.cpp" />
-					<File RelativePath=".\frmts\wms\minidriver_tms.cpp" />
-					<File RelativePath=".\frmts\wms\minidriver_wms.cpp" />
-					<File RelativePath=".\frmts\wms\minidriver_worldwind.cpp" />
-					<File RelativePath=".\frmts\wms\rasterband.cpp" />
-					<File RelativePath=".\frmts\wms\stuff.cpp" />
-					<File RelativePath=".\frmts\wms\wmsdriver.cpp" />
-				</Filter>
-				<Filter Name="xpm" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\xpm\xpmdataset.cpp" />
-				</Filter>
-				<Filter Name="zlib" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\frmts\zlib\adler32.c" />
-					<File RelativePath=".\frmts\zlib\compress.c" />
-					<File RelativePath=".\frmts\zlib\crc32.c" />
-					<File RelativePath=".\frmts\zlib\deflate.c" />
-					<File RelativePath=".\frmts\zlib\gzio.c" />
-					<File RelativePath=".\frmts\zlib\infback.c" />
-					<File RelativePath=".\frmts\zlib\inffast.c" />
-					<File RelativePath=".\frmts\zlib\inflate.c" />
-					<File RelativePath=".\frmts\zlib\inftrees.c" />
-					<File RelativePath=".\frmts\zlib\trees.c" />
-					<File RelativePath=".\frmts\zlib\uncompr.c" />
-					<File RelativePath=".\frmts\zlib\zutil.c" />
-				</Filter>
-				</Filter>
-			<Filter Name="gcore" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\gcore\gdalallvalidmaskband.cpp" />
-				<File RelativePath=".\gcore\gdalcolortable.cpp" />
-				<File RelativePath=".\gcore\gdaldataset.cpp" />
-				<File RelativePath=".\gcore\gdaldefaultoverviews.cpp" />
-				<File RelativePath=".\gcore\gdaldriver.cpp" />
-				<File RelativePath=".\gcore\gdaldrivermanager.cpp" />
-				<File RelativePath=".\gcore\gdalgmlcoverage.cpp" />
-				<File RelativePath=".\gcore\gdaljp2box.cpp" />
-				<File RelativePath=".\gcore\gdaljp2metadata.cpp" />
-				<File RelativePath=".\gcore\gdalmajorobject.cpp" />
-				<File RelativePath=".\gcore\gdalmultidomainmetadata.cpp" />
-				<File RelativePath=".\gcore\gdalnodatamaskband.cpp" />
-				<File RelativePath=".\gcore\gdalnodatavaluesmaskband.cpp" />
-				<File RelativePath=".\gcore\gdalopeninfo.cpp" />
-				<File RelativePath=".\gcore\gdalpamdataset.cpp" />
-				<File RelativePath=".\gcore\gdalpamproxydb.cpp" />
-				<File RelativePath=".\gcore\gdalpamrasterband.cpp" />
-				<File RelativePath=".\gcore\gdalproxydataset.cpp" />
-				<File RelativePath=".\gcore\gdalproxypool.cpp" />
-				<File RelativePath=".\gcore\gdalrasterband.cpp" />
-				<File RelativePath=".\gcore\gdalrasterblock.cpp" />
-				<File RelativePath=".\gcore\gdal_misc.cpp" />
-				<File RelativePath=".\gcore\gdal_rat.cpp" />
-				<File RelativePath=".\gcore\gdal_rpcimdio.cpp" />
-				<File RelativePath=".\gcore\overview.cpp" />
-				<File RelativePath=".\gcore\rasterio.cpp" />
-			</Filter>
-			<Filter Name="ogr" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\ogr\ogr_capi_test.c" />
-				<File RelativePath=".\ogr\swq.c" />
-				<File RelativePath=".\ogr\gml2ogrgeometry.cpp" />
-				<File RelativePath=".\ogr\ogr2gmlgeometry.cpp" />
-				<File RelativePath=".\ogr\ograssemblepolygon.cpp" />
-				<File RelativePath=".\ogr\ogrct.cpp" />
-				<File RelativePath=".\ogr\ogrcurve.cpp" />
-				<File RelativePath=".\ogr\ogrfeature.cpp" />
-				<File RelativePath=".\ogr\ogrfeaturedefn.cpp" />
-				<File RelativePath=".\ogr\ogrfeaturequery.cpp" />
-				<File RelativePath=".\ogr\ogrfeaturestyle.cpp" />
-				<File RelativePath=".\ogr\ogrfielddefn.cpp" />
-				<File RelativePath=".\ogr\ogrgeometry.cpp" />
-				<File RelativePath=".\ogr\ogrgeometrycollection.cpp" />
-				<File RelativePath=".\ogr\ogrgeometryfactory.cpp" />
-				<File RelativePath=".\ogr\ogrlinearring.cpp" />
-				<File RelativePath=".\ogr\ogrlinestring.cpp" />
-				<File RelativePath=".\ogr\ogrmultilinestring.cpp" />
-				<File RelativePath=".\ogr\ogrmultipoint.cpp" />
-				<File RelativePath=".\ogr\ogrmultipolygon.cpp" />
-				<File RelativePath=".\ogr\ogrpoint.cpp" />
-				<File RelativePath=".\ogr\ogrpolygon.cpp" />
-				<File RelativePath=".\ogr\ogrspatialreference.cpp" />
-				<File RelativePath=".\ogr\ogrsurface.cpp" />
-				<File RelativePath=".\ogr\ogrutils.cpp" />
-				<File RelativePath=".\ogr\ogr_api.cpp" />
-				<File RelativePath=".\ogr\ogr_expat.cpp" />
-				<File RelativePath=".\ogr\ogr_fromepsg.cpp" />
-				<File RelativePath=".\ogr\ogr_opt.cpp" />
-				<File RelativePath=".\ogr\ogr_srsnode.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_dict.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_erm.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_esri.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_ozi.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_panorama.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_pci.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_proj4.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_usgs.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_validate.cpp" />
-				<File RelativePath=".\ogr\ogr_srs_xml.cpp" />
-				<Filter Name="ogrsf_frmts" Filter="*.c;*.cpp   ">
-					<Filter Name="avc" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_bin.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_binwr.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00gen.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00parse.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00read.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00write.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_misc.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_rawbin.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbinlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravcdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00datasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00driver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00layer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\avc\ogravclayer.cpp" />
-					</Filter>
-					<Filter Name="bna" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnalayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.cpp" />
-					</Filter>
-					<Filter Name="csv" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp" />
-					</Filter>
-					<Filter Name="dgn" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgndump.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwritetest.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnfloat.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnhelp.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnopen.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnread.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnstroke.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwrite.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgnlayer.cpp" />
-						</Filter>
-					<Filter Name="dods" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsfielddefn.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsgrid.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodslayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp" />
-					</Filter>
-					<Filter Name="dxf" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxflayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfwriterds.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfwriterlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_blockmap.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_dimension.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_diskio.cpp" />
-					</Filter>
-					<Filter Name="fme" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmecacheindex.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayercached.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayerdb.cpp" />
-					</Filter>
-					<Filter Name="generic" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogrdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogrlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogrregisterall.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogr_attrind.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\generic\ogr_miattrind.cpp" />
-					</Filter>
-					<Filter Name="geoconcept" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp" />
-					</Filter>
-					<Filter Name="geojson" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.cpp" />
-						<Filter Name="jsonc" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.c" />
-							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.c" />
-						</Filter>
-						</Filter>
-					<Filter Name="georss" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorssdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorssdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorsslayer.cpp" />
-					</Filter>
-					<Filter Name="gml" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeature.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeatureclass.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlhandler.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlpropertydefn.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\gmlreadstate.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmllayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\trstring.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gml\resolvexlinks.cpp" />
-					</Filter>
-					<Filter Name="gmt" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtlayer.cpp" />
-					</Filter>
-					<Filter Name="gpx" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxlayer.cpp" />
-					</Filter>
-					<Filter Name="grass" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrasslayer.cpp" />
-					</Filter>
-					<Filter Name="gtm" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\gtm.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\gtmtracklayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\gtmwaypointlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmlayer.cpp" />
-					</Filter>
-					<Filter Name="idb" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridblayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp" />
-					</Filter>
-					<Filter Name="ili" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili2handler.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1datasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1driver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1layer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2datasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2driver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2layer.cpp" />
-						<Filter Name="iom" Filter="*.c;*.cpp     ">
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_attr.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_basket.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_error.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_file.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_iterator.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_object.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_utilities.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_value.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\reader.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\tags.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\ustrings.cpp" />
-							<File RelativePath=".\ogr\ogrsf_frmts\ili\iom\writer.cpp" />
-						</Filter>
-						</Filter>
-					<Filter Name="ingres" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringreslayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresresultlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresstatement.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ingres\ogringrestablelayer.cpp" />
-					</Filter>
-					<Filter Name="kml" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kml.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogr2kmlgeometry.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmllayer.cpp" />
-					</Filter>
-					<Filter Name="mem" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemlayer.cpp" />
-					</Filter>
-					<Filter Name="mitab" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_bounds.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_datfile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_idfile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_indfile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_miffile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabview.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.cpp" />
-					</Filter>
-					<Filter Name="mysql" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqllayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp" />
-					</Filter>
-					<Filter Name="ntf" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntfdump.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntffilereader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntfrecord.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntfstroke.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_codelist.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_estlayers.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_generic.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_raster.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntffeatureclasslayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntflayer.cpp" />
-					</Filter>
-					<Filter Name="oci" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\fastload.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ocitest.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\oci_utils.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocilayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrociloaderlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrociselectlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocisession.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistatement.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistringbuf.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistroke.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrocitablelayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\oci\ogrociwritablelayer.cpp" />
-					</Filter>
-					<Filter Name="odbc" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbclayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcselectlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbctablelayer.cpp" />
-					</Filter>
-					<Filter Name="ogdi" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp" />
-					</Filter>
-					<Filter Name="pcidsk" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidskdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidskdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidsklayer.cpp" />
-					</Filter>
-					<Filter Name="pg" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdebug.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpglayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgresultlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgtablelayer.cpp" />
-					</Filter>
-					<Filter Name="pgeo" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeolayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeoselectlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeotablelayer.cpp" />
-					</Filter>
-					<Filter Name="rec" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\ll_recio.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\rec\ogrreclayer.cpp" />
-					</Filter>
-					<Filter Name="s57" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\ddfrecordindex.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57datasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57driver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57layer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57classregistrar.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57dump.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57featuredefns.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57filecollector.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\s57\s57writer.cpp" />
-					</Filter>
-					<Filter Name="sde" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdelayer.cpp" />
-					</Filter>
-					<Filter Name="sdts" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp" />
-					</Filter>
-					<Filter Name="shape" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\dbfopen.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\shpopen.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\shptree.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\shp_vsi.c" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapelayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\shape\shape2ogr.cpp" />
-					</Filter>
-					<Filter Name="sqlite" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitelayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteselectlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp" />
-					</Filter>
-					<Filter Name="tiger" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerlayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigeraltname.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerarealandmarks.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigercompletechain.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerentitynames.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfeatureids.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfilebase.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigeridhistory.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerinfo.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerkeyfeatures.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerlandmarks.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigeroverunder.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpip.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpoint.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolychainlink.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygon.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoncorrections.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoneconomic.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerspatialmetadata.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigertlidrange.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzerocellid.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp" />
-					</Filter>
-					<Filter Name="vrt" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtlayer.cpp" />
-					</Filter>
-					<Filter Name="xplane" Filter="*.c;*.cpp    ">
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanelayer.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.cpp" />
-						<File RelativePath=".\ogr\ogrsf_frmts\xplane\test_geo_utils.cpp" />
-					</Filter>
-					</Filter>
-				<Filter Name="wcts" Filter="*.c;*.cpp   ">
-					<File RelativePath=".\ogr\wcts\ogrwcts.cpp" />
-					<File RelativePath=".\ogr\wcts\wctsclient.cpp" />
-					</Filter>
-					</Filter>
-			<Filter Name="port" Filter="*.c;*.cpp  ">
-				<File RelativePath=".\port\cplgetsymbol.cpp" />
-				<File RelativePath=".\port\cplkeywordparser.cpp" />
-				<File RelativePath=".\port\cplstring.cpp" />
-				<File RelativePath=".\port\cpl_atomic_ops.cpp" />
-				<File RelativePath=".\port\cpl_conv.cpp" />
-				<File RelativePath=".\port\cpl_csv.cpp" />
-				<File RelativePath=".\port\cpl_error.cpp" />
-				<File RelativePath=".\port\cpl_findfile.cpp" />
-				<File RelativePath=".\port\cpl_getexecpath.cpp" />
-				<File RelativePath=".\port\cpl_hash_set.cpp" />
-				<File RelativePath=".\port\cpl_http.cpp" />
-				<File RelativePath=".\port\cpl_list.cpp" />
-				<File RelativePath=".\port\cpl_minixml.cpp" />
-				<File RelativePath=".\port\cpl_minizip_ioapi.cpp" />
-				<File RelativePath=".\port\cpl_minizip_unzip.cpp" />
-				<File RelativePath=".\port\cpl_multiproc.cpp" />
-				<File RelativePath=".\port\cpl_odbc.cpp" />
-				<File RelativePath=".\port\cpl_path.cpp" />
-				<File RelativePath=".\port\cpl_quad_tree.cpp" />
-				<File RelativePath=".\port\cpl_recode_stub.cpp" />
-				<File RelativePath=".\port\cpl_string.cpp" />
-				<File RelativePath=".\port\cpl_strtod.cpp" />
-				<File RelativePath=".\port\cpl_time.cpp" />
-				<File RelativePath=".\port\cpl_vsil.cpp" />
-				<File RelativePath=".\port\cpl_vsil_gzip.cpp" />
-				<File RelativePath=".\port\cpl_vsil_simple.cpp" />
-				<File RelativePath=".\port\cpl_vsil_subfile.cpp" />
-				<File RelativePath=".\port\cpl_vsil_unix_stdio_64.cpp" />
-				<File RelativePath=".\port\cpl_vsil_win32.cpp" />
-				<File RelativePath=".\port\cpl_vsisimple.cpp" />
-				<File RelativePath=".\port\cpl_vsi_mem.cpp" />
-				<File RelativePath=".\port\cpl_win32ce_api.cpp" />
-				<File RelativePath=".\port\xmlreformat.cpp" />
-			</Filter>
-			</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/makegdal80.sln b/makegdal80.sln
deleted file mode 100644
index 4f4006e..0000000
--- a/makegdal80.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makegdal80", "makegdal80.vcproj", "{769DD10E-E284-46BE-9172-A35184250A3A}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Release|Win32 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Debug|Win32.Build.0 = Debug|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release|Win32.ActiveCfg = Release|Win32
-		{769DD10E-E284-46BE-9172-A35184250A3A}.Release|Win32.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/makegdal80.vcproj b/makegdal80.vcproj
deleted file mode 100644
index 96f3373..0000000
--- a/makegdal80.vcproj
+++ /dev/null
@@ -1,8258 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="makegdal"
-	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-	Keyword="MakeFileProj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 DEBUG=1"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 DEBUG=1 clean && nmake -f makefile.vc MSVC_VER=1400 DEBUG=1"
-				CleanCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 DEBUG=1 clean"
-				Output="gdal17.dll"
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 && nmake -f makefile.vc MSVC_VER=1400 install"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 clean && nmake -f makefile.vc MSVC_VER=1400 && nmake -f makefile.vc MSVC_VER=1400 install"
-				CleanCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 clean"
-				Output="gdal17.dll"
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Make Files"
-			Filter="*.vc;*.opt "
-			>
-			<File
-				RelativePath=".\makefile.vc"
-				>
-			</File>
-			<File
-				RelativePath=".\nmake-wince.opt"
-				>
-			</File>
-			<File
-				RelativePath=".\nmake.opt"
-				>
-			</File>
-			<Filter
-				Name="alg"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\alg\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="apps"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\apps\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\frmts\makefile.vc"
-					>
-				</File>
-				<Filter
-					Name="aaigrid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\aaigrid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="adrg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\adrg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="aigrid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="airsar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\airsar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\blx\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bmp"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\bmp\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="coasp"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\coasp\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="cosar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\cosar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dimap"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dimap\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dods"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dods\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dted\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="elas"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\elas\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="epsilon"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\epsilon\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ers\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\fit\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fits"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\fits\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gff"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gff\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gif\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="giflib"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gif\giflib\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\grib\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="degrib18"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\grib\degrib18\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="degrib"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\makefile.vc"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gsg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gsg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="idrisi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\idrisi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jaxapalsar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jaxapalsar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jdem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jdem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libjpeg12"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="jpeg2000"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg2000\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="l1b"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\l1b\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="leveller"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\leveller\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\mem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\msg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="northwood"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\northwood\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ogdi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ogdi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="sdk"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\Makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pds\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\png\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libpng"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="r"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\r\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rasterlite"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rasterlite\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\raw\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rik"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rik\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rs2"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rs2\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="saga"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\saga\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sde\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sgi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sgi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="srtmhgt"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\srtmhgt\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terragen"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\terragen\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="til"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\til\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="tsx"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\tsx\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="usgsdem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\usgsdem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wcs"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\wcs\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wktraster"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\wktraster\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\wms\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="xpm"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\xpm\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="kmlsuperoverlay"
-					>
-					<File
-						RelativePath=".\frmts\kmlsuperoverlay\makefile.vc"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\gcore\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\ogr\makefile.vc"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="avc"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="dist"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\dgn\dist\Makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dxf"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="georss"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\georss\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gtm"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pcidsk"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pcidsk\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="wcts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\ogr\wcts\makefile.vc"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\port\cpl_config.h.vc"
-					>
-				</File>
-				<File
-					RelativePath=".\port\makefile.vc"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Include Files"
-			Filter="*.h "
-			>
-			<Filter
-				Name="alg"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\alg\gdal_alg.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_alg_priv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgrid.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarper.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gvgcpfit.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\thinplatespline.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="bridge"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\bridge\gdalbridge.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.h  "
-				>
-				<Filter
-					Name="aigrid"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\aigrid.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\blx\blx.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\bsb_read.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\ceosopen.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\ceos.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\dted\dted_api.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\jp2userbox.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\vsiiostream.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\EnvisatFile.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ers\ershdrnode.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\fit\fit.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\gstEndian.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\gstTypes.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\georaster_priv.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\oci_wrapper.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="giflib"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gif\giflib\gif_hash.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\gif_lib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\gif_lib_private.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="degrib18"
-						Filter="*.h    "
-						>
-						<Filter
-							Name="degrib"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\clock.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\datasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib1.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib2.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\engribapi.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\fileendian.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib2api.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\inventory.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memendian.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\meta.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaname.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myassert.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myerror.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myutil.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\scan.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\type.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\weather.h"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\grib2.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\gt_overview.h"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_config.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_keyp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_simpletags.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geokeys.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geonames.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiffio.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geovalues.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\xtiffio.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\t4.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_config.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dir.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_predict.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffconf.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffio.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffiop.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffvers.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\uvcode.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\gxfopen.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4compat.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4dataset.h"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\ease.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\HdfEosDef.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\HDFEOSVersion.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\gh5_convenience.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5dataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\hfa.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfa_p.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\ilwisdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\IngrTypes.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphBand.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphDataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\JpegHelper.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\iso8211.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\subfile_source.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jp2kak\vsil_target.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\gdalexif.h"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jchuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jconfig.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdct.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdhuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jerror.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jinclude.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemsys.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmorecfg.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jpegint.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jpeglib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jversion.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libjpeg12"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jchuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jconfig.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdct.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdhuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jerror.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jinclude.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jmemsys.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jmorecfg.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jpegint.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jpeglib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jversion.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="jpeg2000"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\mem\memdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\mrsidstream.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\msg\msgcommand.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\msgdataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\prologue.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\reflectancecalculator.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\xritheaderparser.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\msg_basic_types.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msg_reader_core.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\netcdfdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\mgrs.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitflib.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftoclib.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="northwood"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\northwood\northwood.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\gdal_pcidsk.h"
-						>
-					</File>
-					<Filter
-						Name="sdk"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_buffer.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_channel.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_config.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_exception.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_file.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_georef.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_interfaces.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_io.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_mutex.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_pct.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_segment.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_shape.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_types.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcidsk\sdk\pcidsk_vectorsegment.h"
-							>
-						</File>
-						<Filter
-							Name="channel"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cbandinterleavedchannel.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cpcidskchannel.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\ctiledchannel.h"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="core"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\metadataset.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\mutexholder.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_utils.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\protectedfile.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\sysvirtualfile.h"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="segment"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\pcidskgeorefbuilder.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\segmentfactory.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\uuid.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterdataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterrasterband.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterutil.h"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csf.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfattr.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfimpl.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csftypes.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pcrtypes.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pds\nasakeywordhandler.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\pgchip.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="libpng"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\png.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngconf.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="rasterlite"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\rasterlite\rasterlitedataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\raw\atlsci_spheroid.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\rawdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\rmfdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\sde\gdal_sde.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdedataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdeerror.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sderasterband.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\sdts_al.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibDataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibRasterBand.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\gdal_vrt.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wktraster"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\wktraster\wktraster.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\wms\gdalhttp.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\md5.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tileservice.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tms.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_wms.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_worldwind.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\stdinc.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\wmsdriver.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\crc32.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\deflate.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffast.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffixed.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inflate.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inftrees.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\trees.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zconf.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zlib.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zutil.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="kmlsuperoverlay"
-					>
-					<File
-						RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\gcore\gdal.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_frmts.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_pam.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_priv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_proxy.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rat.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_version.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2metadata.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\ogr\ogr_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_core.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_expat.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_feature.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_featurestyle.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_geometry.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_geos.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_p.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_spatialref.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_esri_names.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\swq.h"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\ogr_attrind.h"
-						>
-					</File>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\ogrsf_frmts.h"
-						>
-					</File>
-					<Filter
-						Name="avc"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\dbfopen.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogr_avc.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogr_bna.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogr_csv.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlibp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogr_dgn.h"
-							>
-						</File>
-						<Filter
-							Name="dist"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\dgn\dist\cpl_config.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dxf"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_dxf.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogr_geojson.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.h"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\bits.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\config.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object_private.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="georss"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\georss\ogr_georss.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreaderp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogr_gpx.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="grass"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrass.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gtm"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\gtm.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\ogr_gtm.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1readerp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2readerp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili1.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili2.h"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_p.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="ingres"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogr_ingres.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kml.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlutility.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogr_kml.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogr_mem.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_priv.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogr_oci.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogr_odbc.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdi.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pcidsk"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogr_pg.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogr_pgeo.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogr_rec.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogr_s57.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57tables.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogr_sde.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogr_sdts.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshape.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shapefil.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vfk"
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\ogr_vfk.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreaderp.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\port\cpl_atomic_ops.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_config.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_config_extras.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_conv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_csv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_error.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_hash_set.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_http.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_list.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minixml.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_ioapi.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_unzip.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_multiproc.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_odbc.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_port.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_quad_tree.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_string.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_time.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi_virtual.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_win32ce_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_wince.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplkeywordparser.h"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Source Files"
-			Filter="*.c;*.cpp "
-			>
-			<Filter
-				Name="alg"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\alg\contour.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_crs.c"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_nrgcrs.c"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_rpc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_tps.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalchecksum.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalcutline.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdaldither.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgeoloc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgrid.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalmediancut.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalproximity.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalrasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalrasterpolygonenumerator.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalsievefilter.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalsimplewarp.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdaltransformer.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarper.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarpkernel.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarpoperation.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\llrasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\polygonize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\rasterfill.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\thinplatespline.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="apps"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\apps\dumpoverviews.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal2ogr.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_contour.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_grid.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_rasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_translate.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaladdo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalbuildvrt.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaldem.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalenhance.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalflattenmask.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalinfo.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalmanage.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltindex.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltorture.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltransform.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalwarp.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalwarpsimple.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\multireadtest.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\nearblack.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogr2ogr.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrdissolve.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrinfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrtindex.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\test_ogrsf.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\testepsg.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="bridge"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\bridge\bridge_test.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\bridge\gbgetsymbol.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\bridge\gdalbridge.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\frmts\gdalallregister.cpp"
-					>
-				</File>
-				<Filter
-					Name="aaigrid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\aaigrid\aaigriddataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="adrg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\adrg\adrgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\adrg\srpdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="aigrid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\aigccitt.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aigdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aigopen.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aitest.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\gridlib.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="airsar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\airsar\airsardataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\blx\blx.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\blx\blxdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bmp"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\bmp\bmpdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\bsb2raw.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\bsb\bsb_read.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\bsb\bsbdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\ceosdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos\ceosopen.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos\ceostest.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\ceos.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\ceosrecipe.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\ceossar.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\link.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\sar_ceosdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="coasp"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\coasp\coasp_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="cosar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\cosar\cosar_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dimap"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dimap\dimapdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dods"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dods\dodsdataset2.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dted\dted_api.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_create.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_ptstream.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_test.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dteddataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\ecwcreatecopy.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\ecwdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\jp2userbox.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="elas"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\elas\elasdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\dumpgeo.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\envisat_dump.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\envisatdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\EnvisatFile.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="epsilon"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\epsilon\epsilondataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ers\ersdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ers\ershdrnode.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\fit\fit.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\fitdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fits"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\fits\fitsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\georaster_dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_driver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_rasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_wrapper.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\oci_wrapper.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gff"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gff\gff_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gif\biggifdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gif\gifdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="giflib"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gif\giflib\dgif_lib.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\egif_lib.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\gif_err.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\gif_hash.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\giflib\gifalloc.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grass"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\grass\grass57dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\grass\grassdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\grib\gribdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="degrib18"
-						Filter="*.c;*.cpp    "
-						>
-						<Filter
-							Name="degrib"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\clock.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib1.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib2.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\engribapi.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\fileendian.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib1tab.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib2api.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\inventory.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memendian.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaname.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaparse.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaprint.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myassert.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myerror.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myutil.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\scan.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\weather.c"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\cmplxpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\compack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\comunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_jpeg2000.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_png.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_jpeg2000.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_png.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addfield.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addgrid.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addlocal.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_create.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_free.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_getfld.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_gribend.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_info.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_miss.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack1.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack2.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack3.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack4.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack5.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack6.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack7.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gbits.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getdim.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getpoly.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\int_power.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\misspack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\mkieee.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pack_gp.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\rdieee.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\reduce.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\seekgb.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specunpack.c"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gsg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gsg\gs7bgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gsg\gsagdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gsg\gsbgdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\geotiff.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\gt_citation.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\gt_overview.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\gt_wkt_srs.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\tif_float.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\tifvsi.cpp"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_extra.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_free.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_get.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_names.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_new.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_print.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_set.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_simpletags.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_trans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiff_proj4.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\xtiff.c"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_aux.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_close.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_codec.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_color.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_compress.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dir.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirinfo.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirwrite.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dumpmode.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_error.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_extension.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3sm.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_flush.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_getimage.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_jpeg.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_jpeg_12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_luv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_lzw.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_next.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_ojpeg.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_open.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_packbits.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_pixarlog.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_predict.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_print.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_read.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_strip.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_swab.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_thunder.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_tile.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_version.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_vsi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_warning.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_zip.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\gxf_ogcwkt.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxf_proj4.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxfopen.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4imagedataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\EHapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\gctp_wrap.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\GDapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\SWapi.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\bagdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\gh5_convenience.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5imagedataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\iso19115_srs.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\hfa_overviews.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfacompress.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfadataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfadictionary.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaentry.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfafield.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaopen.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfatest.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfatype.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="idrisi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\idrisi\IdrisiDataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\ilwiscoordinatesystem.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ilwis\ilwisdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\IngrTypes.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphBand.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphDataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\JpegHelper.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\8211dump.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\8211view.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddffield.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddffielddefn.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfmodule.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfrecord.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfsubfielddefn.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfutils.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\mkcatalog.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\timetest.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jaxapalsar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jaxapalsar\jaxapalsardataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jdem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jdem\jdemdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\jp2kakdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\jpgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jpeg\jpgdataset_12.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jpeg\vsidataio.cpp"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcapimin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcapistd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jccoefct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jccolor.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcdctmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jchuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcinit.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmainct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmarker.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmaster.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcomapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcparam.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcphuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcprepct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcsample.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jctrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdapimin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdapistd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdatadst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdatasrc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdcoefct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdcolor.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jddctmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdhuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdinput.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmainct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmarker.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmaster.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmerge.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdphuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdpostct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdsample.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdtrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jerror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctflt.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctfst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctint.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctflt.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctfst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctint.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctred.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemansi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jquant1.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jquant2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jutils.c"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libjpeg12"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcapimin12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcapistd12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jccoefct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jccolor12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcdctmgr12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jchuff12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcinit12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcmainct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcmarker12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcmaster12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcomapi12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcparam12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcphuff12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcprepct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jcsample12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jctrans12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdapimin12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdapistd12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdatadst12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdatasrc12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdcoefct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdcolor12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jddctmgr12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdhuff12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdinput12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdmainct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdmarker12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdmaster12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdmerge12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdphuff12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdpostct12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdsample12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jdtrans12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jerror12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jfdctflt12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jfdctfst12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jfdctint12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jidctflt12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jidctfst12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jidctint12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jidctred12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jmemansi12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jmemmgr12.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jquant112.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jquant212.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg12\jutils12.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="jpeg2000"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jpeg2000\jpeg2000dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="l1b"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\l1b\l1bdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="leveller"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\leveller\levellerdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\mem\memdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\mrsiddataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\mrsid\mrsidstream.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\msg\msgcommand.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\msgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\prologue.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\reflectancecalculator.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\xritheaderparser.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\msg_basic_types.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msg_reader_core.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msgndataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\gmtdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\netcdf\netcdfdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\mgrs.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfaridpcm.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfbilevel.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfdump.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitffile.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfimage.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfwritejpeg.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfwritejpeg_12.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftocdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftocfile.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="northwood"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\northwood\grcdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\northwood\grddataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\northwood\northwood.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ogdi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ogdi\ogdidataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\pcidskdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcidsk\pcidskdataset2.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcidsk\pcidsktiledrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcidsk\vsi_pcidsk_io.cpp"
-						>
-					</File>
-					<Filter
-						Name="sdk"
-						Filter="*.c;*.cpp    "
-						>
-						<Filter
-							Name="channel"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cbandinterleavedchannel.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cpcidskchannel.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\cpixelinterleavedchannel.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\channel\ctiledchannel.cpp"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="core"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\libjpeg_io.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\metadataset_p.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_pubutils.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidsk_utils.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidskbuffer.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidskcreate.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidskexception.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidskinterfaces.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\pcidskopen.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\core\sysvirtualfile.cpp"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="port"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\port\io_stdio.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\port\io_win32.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\port\pthread_mutex.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\port\win32_mutex.cpp"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="segment"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment_p.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\segment_loader.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\segmentfactory.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.cpp"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrastermisc.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterutil.cpp"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_getcell.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_getrow.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_gsomece.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_putcell.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_rputrow.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\angle.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\attravai.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\attrsize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\cellsize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\create2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfglob.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfsup.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\delattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\dumconv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\endian.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\filename.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gattrblk.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gattridx.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gcellrep.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gdattype.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\getattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\getx0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gety0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ggisfid.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gmaxval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gminval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gnrcols.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gnrrows.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gproj.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gputproj.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gvalscal.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gvartype.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gversion.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ismv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\kernlcsf.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\legend.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mclose.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\moreattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mperror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pgisfid.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pmaxval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pminval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putallmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putsomec.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putx0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\puty0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pvalscal.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rattrblk.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rcomp.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rcoords.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rdup2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\reseterr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rextend.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rmalloc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rrowcol.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ruseas.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setangle.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setvtmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\strconst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\strpad.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\swapio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\trackmm.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vs2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsdef.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsis.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsvers.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\wattrblk.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pds\isis2dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\isis3dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\nasakeywordhandler.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\pdsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\pgchipdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pgchip\pgchiprasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pgchip\pgchiputilities.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\png\pngdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="libpng"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\png.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngerror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pnggccrd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngget.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngmem.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngpread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrtran.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrutil.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngset.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngtrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngvcrd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwrite.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwtran.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwutil.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="r"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\r\rcreatecopy.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\r\rdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rasterlite"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rasterlite\rasterlitecreatecopy.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\rasterlite\rasterlitedataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\rasterlite\rasterliteoverviews.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\raw\atlsci_spheroid.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\btdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\cpgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\dipxdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\doq1dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\doq2dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\ehdrdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\eirdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\envidataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\fastdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\fujibasdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\genbindataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\gscdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\hkvdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\idadataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\landataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\lcpdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\mffdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\ndfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\pauxdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\pnmdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\rawdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rik"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rik\rikdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\rmfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\rmf\rmflzw.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rs2"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rs2\rs2dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="saga"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\saga\sagadataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sde\sdedataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdeerror.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sderasterband.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\sdts2shp.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsattrreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtscatd.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsindexedreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsiref.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtslib.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtslinereader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtspointreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtspolygonreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsrasterreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtstransfer.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsxref.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sgi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sgi\sgidataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="srtmhgt"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\srtmhgt\srtmhgtdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terragen"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\terragen\terragendataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibDataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibRasterBand.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="til"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\til\tildataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="tsx"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\tsx\tsxdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="usgsdem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\usgsdem\usgsdem_create.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\usgsdem\usgsdemdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\vrtdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtderivedrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtfilters.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtrawrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtsourcedrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtsources.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtwarped.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wcs"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\wcs\httpdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wcs\wcsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wktraster"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\wktraster\wktrasterdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wktraster\wktrasterrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wktraster\wktrasterwrapper.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\wms\cache.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\gdalhttp.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\md5.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tileservice.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tms.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_wms.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_worldwind.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\rasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\stuff.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\wmsdriver.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="xpm"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\xpm\xpmdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\adler32.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\compress.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\crc32.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\deflate.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\gzio.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\infback.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffast.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inflate.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inftrees.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\trees.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\uncompr.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zutil.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="kmlsuperoverlay"
-					>
-					<File
-						RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.cpp"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\gcore\gdal_misc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rat.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rpcimdio.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalallvalidmaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalcolortable.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldefaultoverviews.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldriver.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldrivermanager.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalgmlcoverage.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2box.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2metadata.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalmajorobject.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalmultidomainmetadata.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalnodatamaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalnodatavaluesmaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalopeninfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamdataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamproxydb.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamrasterband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalproxydataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalproxypool.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalrasterband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalrasterblock.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\overview.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\rasterio.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\ogr\gml2ogrgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr2gmlgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_api.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_capi_test.c"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_expat.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_fromepsg.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_opt.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_dict.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_erm.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_esri.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_ozi.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_panorama.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_pci.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_proj4.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_usgs.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_validate.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_xml.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srsnode.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ograssemblepolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrct.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrcurve.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeature.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturedefn.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturequery.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturestyle.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfielddefn.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometrycollection.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometryfactory.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrlinearring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrlinestring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultilinestring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultipoint.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultipolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrpoint.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrpolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrspatialreference.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrsurface.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrutils.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\swq.c"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.c;*.cpp   "
-					>
-					<Filter
-						Name="avc"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_bin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_binwr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00gen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00parse.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00read.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_misc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_rawbin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbinlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravclayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnalayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgndump.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnfloat.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnhelp.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnopen.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnread.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnstroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwrite.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwritetest.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgnlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsfielddefn.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsgrid.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dxf"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_blockmap.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_dimension.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_diskio.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxflayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfwriterds.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfwriterlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmecacheindex.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayercached.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayerdb.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_attrind.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_miattrind.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrregisterall.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.cpp"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.c"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="georss"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorssdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorssdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\georss\ogrgeorsslayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeature.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeatureclass.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlhandler.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlpropertydefn.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreadstate.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmllayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\trstring.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\resolvexlinks.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="grass"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrasslayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gtm"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\gtm.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\gtmtracklayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\gtmwaypointlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridblayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2handler.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2layer.cpp"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_attr.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_basket.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_error.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_file.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_iterator.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_object.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_utilities.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_value.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\reader.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\tags.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\ustrings.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\writer.cpp"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="ingres"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringreslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresstatement.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringrestablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kml.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogr2kmlgeometry.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmllayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_bounds.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_datfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_idfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_indfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_miffile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabview.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqllayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_codelist.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_estlayers.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_generic.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_raster.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfdump.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntffilereader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfrecord.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfstroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntffeatureclasslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntflayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\fastload.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\oci_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ocitest.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocilayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociloaderlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocisession.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistatement.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistringbuf.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocitablelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociwritablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbclayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbctablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pcidsk"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidskdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidskdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogrpcidsklayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdebug.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpglayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgtablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeolayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeoselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeotablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ll_recio.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrreclayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ddfrecordindex.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57classregistrar.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57dump.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57featuredefns.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57filecollector.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57writer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\dbfopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shape2ogr.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shp_vsi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shpopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shptree.c"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeraltname.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerarealandmarks.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigercompletechain.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerentitynames.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfeatureids.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfilebase.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeridhistory.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerinfo.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerkeyfeatures.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerlandmarks.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeroverunder.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpip.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpoint.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolychainlink.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygon.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoncorrections.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoneconomic.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerspatialmetadata.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigertlidrange.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzerocellid.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\test_geo_utils.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vfk"
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\drv_vfk.html"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\GNUmakefile"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\makefile.vc"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfklayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkdatablock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkfeature.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkproperty.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkpropertydefn.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.cpp"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="wcts"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\ogr\wcts\ogrwcts.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\ogr\wcts\wctsclient.cpp"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\port\cpl_atomic_ops.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_conv.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_csv.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_error.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_findfile.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_getexecpath.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_hash_set.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_http.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_list.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minixml.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_ioapi.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_unzip.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_multiproc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_odbc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_path.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_quad_tree.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_recode_stub.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_string.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_strtod.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_time.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi_mem.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_gzip.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_simple.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_subfile.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_unix_stdio_64.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_win32.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsisimple.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_win32ce_api.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplgetsymbol.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplkeywordparser.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplstring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\xmlreformat.cpp"
-					>
-				</File>
-			</Filter>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/makegdal90.vcproj b/makegdal90.vcproj
deleted file mode 100644
index 1094853..0000000
--- a/makegdal90.vcproj
+++ /dev/null
@@ -1,7158 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="makegdal90"
-	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-	Keyword="MakeFileProj"
-	TargetFrameworkVersion="131072"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 clean && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1"
-				CleanCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 DEBUG=1 clean"
-				Output="gdal17.dll"
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
-			<Tool
-				Name="VCNMakeTool"
-				BuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 clean && nmake -f makefile.vc MSVC_VER=1500"
-				CleanCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1500 clean"
-				Output="gdal17.dll"
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Make Files"
-			Filter="*.vc;*.opt "
-			>
-			<File
-				RelativePath=".\makefile.vc"
-				>
-			</File>
-			<File
-				RelativePath=".\nmake-wince.opt"
-				>
-			</File>
-			<File
-				RelativePath=".\nmake.opt"
-				>
-			</File>
-			<Filter
-				Name="alg"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\alg\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="apps"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\apps\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\frmts\makefile.vc"
-					>
-				</File>
-				<Filter
-					Name="aaigrid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\aaigrid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="adrg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\adrg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="aigrid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="airsar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\airsar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\blx\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bmp"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\bmp\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="coasp"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\coasp\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="cosar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\cosar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dimap"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dimap\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dods"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dods\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\dted\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="elas"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\elas\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ers\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\fit\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fits"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\fits\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gff"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gff\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gif\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libungif"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gif\libungif\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\grib\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="degrib18"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\grib\degrib18\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="degrib"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\makefile.vc"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gsg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gsg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="idrisi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\idrisi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jaxapalsar"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jaxapalsar\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jdem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jdem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="jpeg2000"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg2000\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="l1b"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\l1b\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="leveller"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\leveller\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\mem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\msg\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ogdi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\ogdi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pds\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\png\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="libpng"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\raw\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rik"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rik\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rs2"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\rs2\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sde\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sgi"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\sgi\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="srtmhgt"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\srtmhgt\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terragen"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\terragen\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="tsx"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\tsx\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="usgsdem"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\usgsdem\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wcs"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\wcs\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\wms\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="xpm"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\xpm\makefile.vc"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\makefile.vc"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\gcore\makefile.vc"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\ogr\makefile.vc"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\makefile.vc"
-						>
-					</File>
-					<Filter
-						Name="avc"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="dist"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\dgn\dist\Makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\makefile.vc"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.vc;*.opt     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\makefile.vc"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.vc;*.opt    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\makefile.vc"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="wcts"
-					Filter="*.vc;*.opt   "
-					>
-					<File
-						RelativePath=".\ogr\wcts\makefile.vc"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.vc;*.opt  "
-				>
-				<File
-					RelativePath=".\port\cpl_config.h.vc"
-					>
-				</File>
-				<File
-					RelativePath=".\port\makefile.vc"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Include Files"
-			Filter="*.h "
-			>
-			<Filter
-				Name="alg"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\alg\gdal_alg.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_alg_priv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgrid.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarper.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gvgcpfit.h"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\thinplatespline.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="bridge"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\bridge\gdalbridge.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.h  "
-				>
-				<Filter
-					Name="aigrid"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\aigrid.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\blx\blx.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\bsb_read.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\ceosopen.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\ceos.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\dted\dted_api.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\jp2userbox.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\vsiiostream.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\EnvisatFile.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ers\ershdrnode.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\fit\fit.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\gstEndian.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\gstTypes.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\georaster_priv.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\oci_wrapper.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="libungif"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gif\libungif\gif_lib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\libungif\gif_lib_private.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="degrib18"
-						Filter="*.h    "
-						>
-						<Filter
-							Name="degrib"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\clock.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\datasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib1.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib2.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\engribapi.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\fileendian.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib2api.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\inventory.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memendian.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\meta.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaname.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myassert.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myerror.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myutil.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\scan.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\type.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\weather.h"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\grib2.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.h"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\gt_overview.h"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_config.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_keyp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geokeys.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geonames.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiffio.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geovalues.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\xtiffio.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\t4.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_config.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dir.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_predict.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffconf.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffio.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffiop.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tiffvers.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\uvcode.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\gxfopen.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4compat.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4dataset.h"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\ease.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\HdfEosDef.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\HDFEOSVersion.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5dataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\hfa.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfa_p.h"
-						>
-					</File>
-					<Filter
-						Name="addtiffo_src"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\hfa\addtiffo_src\rawblockedimage.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\ilwisdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\IngrTypes.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphBand.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphDataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\JpegHelper.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\iso8211.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\subfile_source.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jp2kak\vsil_target.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\gdalexif.h"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jchuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jconfig.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdct.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdhuff.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jerror.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jinclude.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemsys.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmorecfg.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jpegint.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jpeglib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jversion.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\mem\memdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\mrsidstream.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\msg\msgcommand.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\msgdataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\prologue.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\reflectancecalculator.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\xritheaderparser.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\msg_basic_types.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msg_reader_core.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\netcdfdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\mgrs.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitflib.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftoclib.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\gdal_pcidsk.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterdataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterrasterband.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterutil.h"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csf.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfattr.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfimpl.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csftypes.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pcrtypes.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pds\nasakeywordhandler.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\pgchip.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.h   "
-					>
-					<Filter
-						Name="libpng"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\png.h"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngconf.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\raw\atlsci_spheroid.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\rawdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\rmfdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\sde\gdal_sde.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdedataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdeerror.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sderasterband.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\sdts_al.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibDataset.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibRasterBand.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\gdal_vrt.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtdataset.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\wms\gdalhttp.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\md5.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tileservice.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_wms.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_worldwind.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\stdinc.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\wmsdriver.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\crc32.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\deflate.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffast.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffixed.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inflate.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inftrees.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\trees.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zconf.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zlib.h"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zutil.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\gcore\gdal.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_frmts.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_pam.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_priv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_proxy.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rat.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_version.h"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2metadata.h"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\ogr\ogr_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_core.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_feature.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_featurestyle.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_geometry.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_geos.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_p.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_spatialref.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\swq.h"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.h   "
-					>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\ogr_attrind.h"
-						>
-					</File>
-					<File
-						RelativePath=".\ogr\ogrsf_frmts\ogrsf_frmts.h"
-						>
-					</File>
-					<Filter
-						Name="avc"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\dbfopen.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogr_avc.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogr_bna.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogr_csv.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlib.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnlibp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogr_dgn.h"
-							>
-						</File>
-						<Filter
-							Name="dist"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\dgn\dist\cpl_config.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogr_geojson.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.h"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\bits.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\config.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object_private.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreaderp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogr_gpx.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="grass"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrass.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1readerp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2readerp.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili1.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogr_ili2.h"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.h     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom.h"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_p.h"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="ingres"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogr_ingres.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kml.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlutility.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogr_kml.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogr_mem.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_priv.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogr_oci.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogr_odbc.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdi.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogr_pg.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogr_pgeo.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogr_rec.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogr_s57.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57tables.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogr_sde.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogr_sdts.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshape.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shapefil.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.h    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.h"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.h"
-							>
-						</File>
-					</Filter>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.h  "
-				>
-				<File
-					RelativePath=".\port\cpl_conv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_csv.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_error.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_hash_set.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_http.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_list.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minixml.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_ioapi.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_unzip.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_multiproc.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_odbc.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_port.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_quad_tree.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_string.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi_virtual.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_win32ce_api.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_wince.h"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplkeywordparser.h"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="Source Files"
-			Filter="*.c;*.cpp "
-			>
-			<Filter
-				Name="alg"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\alg\contour.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_crs.c"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_nrgcrs.c"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_rpc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdal_tps.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalchecksum.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalcutline.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdaldither.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgeoloc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalgrid.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalmediancut.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalproximity.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalrasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalrasterpolygonenumerator.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalsievefilter.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalsimplewarp.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdaltransformer.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarper.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarpkernel.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\gdalwarpoperation.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\llrasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\polygonize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\rasterfill.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\alg\thinplatespline.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="apps"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\apps\dumpoverviews.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal2ogr.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_contour.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_grid.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_rasterize.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdal_translate.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaladdo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalbuildvrt.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalenhance.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalflattenmask.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalinfo.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalmanage.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltindex.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltorture.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdaltransform.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalwarp.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\gdalwarpsimple.c"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\multireadtest.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\nearblack.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogr2ogr.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrdissolve.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrinfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\ogrtindex.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\test_ogrsf.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\apps\testepsg.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="bridge"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\bridge\bridge_test.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\bridge\gbgetsymbol.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\bridge\gdalbridge.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="frmts"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\frmts\gdalallregister.cpp"
-					>
-				</File>
-				<Filter
-					Name="aaigrid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\aaigrid\aaigriddataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="adrg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\adrg\adrgdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="aigrid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\aigrid\aigccitt.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aigdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aigopen.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\aitest.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\aigrid\gridlib.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="airsar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\airsar\airsardataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="blx"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\blx\blx.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\blx\blxdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bmp"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\bmp\bmpdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="bsb"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\bsb\bsb2raw.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\bsb\bsb_read.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\bsb\bsbdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ceos\ceosdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos\ceosopen.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos\ceostest.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ceos2"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ceos2\ceos.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\ceosrecipe.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\ceossar.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\link.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ceos2\sar_ceosdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="coasp"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\coasp\coasp_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="cosar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\cosar\cosar_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dimap"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dimap\dimapdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dods"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dods\dodsdataset2.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="dted"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\dted\dted_api.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_create.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_ptstream.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dted_test.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\dted\dteddataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ecw"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ecw\ecwcreatecopy.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\ecwdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ecw\jp2userbox.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="elas"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\elas\elasdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="envisat"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\envisat\dumpgeo.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\envisat_dump.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\envisatdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\envisat\EnvisatFile.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ers"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ers\ersdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ers\ershdrnode.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fit"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\fit\fit.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\fit\fitdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="fits"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\fits\fitsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="georaster"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\georaster\georaster_dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_driver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_rasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\georaster_wrapper.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\georaster\oci_wrapper.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gff"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gff\gff_dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gif"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gif\gifdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="libungif"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gif\libungif\dgif_lib.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\libungif\egif_lib.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\libungif\gif_err.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gif\libungif\gifalloc.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="grass"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\grass\grass57dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\grass\grassdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="grib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\grib\gribdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="degrib18"
-						Filter="*.c;*.cpp    "
-						>
-						<Filter
-							Name="degrib"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\clock.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib1.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\degrib2.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\engribapi.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\filedatasource.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\fileendian.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib1tab.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\grib2api.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\inventory.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memendian.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\memorydatasource.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaname.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaparse.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\metaprint.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myassert.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myerror.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\myutil.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\scan.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\tdlpack.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\degrib\weather.c"
-								>
-							</File>
-						</Filter>
-						<Filter
-							Name="g2clib-1.0.4"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\cmplxpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\compack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\comunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_jpeg2000.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\dec_png.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\drstemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_jpeg2000.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\enc_png.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addfield.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addgrid.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_addlocal.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_create.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_free.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_getfld.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_gribend.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_info.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_miss.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack1.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack2.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack3.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack4.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack5.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack6.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\g2_unpack7.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gbits.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getdim.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\getpoly.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\gridtemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\int_power.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\jpcunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\misspack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\mkieee.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pack_gp.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pdstemplates.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\pngunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\rdieee.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\reduce.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\seekgb.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\simunpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specpack.c"
-								>
-							</File>
-							<File
-								RelativePath=".\frmts\grib\degrib18\g2clib-1.0.4\specunpack.c"
-								>
-							</File>
-						</Filter>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gsg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gsg\gs7bgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gsg\gsagdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gsg\gsbgdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="gtiff"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gtiff\geotiff.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\gt_overview.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\gt_wkt_srs.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\tif_float.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gtiff\tifvsi.cpp"
-						>
-					</File>
-					<Filter
-						Name="libgeotiff"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_extra.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_free.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_get.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_names.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_new.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_normalize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_print.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_set.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_tiffp.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_trans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geo_write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\geotiff_proj4.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libgeotiff\xtiff.c"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="libtiff"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_aux.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_close.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_codec.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_color.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_compress.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dir.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirinfo.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dirwrite.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_dumpmode.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_error.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_extension.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_fax3sm.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_flush.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_getimage.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_jpeg.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_luv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_lzw.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_next.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_ojpeg.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_open.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_packbits.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_pixarlog.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_predict.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_print.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_read.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_strip.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_swab.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_thunder.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_tile.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_version.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_vsi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_warning.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\gtiff\libtiff\tif_zip.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="gxf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\gxf\gxf_ogcwkt.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxf_proj4.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\gxf\gxfopen.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hdf4"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf4\hdf4imagedataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="hdf-eos"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\EHapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\gctp_wrap.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\GDapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hdf4\hdf-eos\SWapi.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="hdf5"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hdf5\hdf5imagedataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="hfa"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\hfa\geoextra.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfa_overviews.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfacompress.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfadataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfadictionary.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaentry.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfafield.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfaopen.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfatest.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\hfatype.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\img2tif.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\hfa\imggeotiff.cpp"
-						>
-					</File>
-					<Filter
-						Name="addtiffo_src"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\hfa\addtiffo_src\rawblockedimage.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\hfa\addtiffo_src\tif_overview.cpp"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="idrisi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\idrisi\IdrisiDataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ilwis"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ilwis\ilwiscoordinatesystem.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ilwis\ilwisdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ingr"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ingr\IngrTypes.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphBand.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\IntergraphDataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\ingr\JpegHelper.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="iso8211"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\iso8211\8211dump.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\8211view.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddffield.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddffielddefn.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfmodule.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfrecord.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfsubfielddefn.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\ddfutils.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\mkcatalog.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\iso8211\timetest.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jaxapalsar"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jaxapalsar\jaxapalsardataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jdem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jdem\jdemdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jp2kak"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jp2kak\jp2kakdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="jpeg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg\jpgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\jpeg\vsidataio.cpp"
-						>
-					</File>
-					<Filter
-						Name="libjpeg"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcapimin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcapistd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jccoefct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jccolor.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcdctmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jchuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcinit.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmainct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmarker.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcmaster.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcomapi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcparam.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcphuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcprepct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jcsample.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jctrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdapimin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdapistd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdatadst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdatasrc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdcoefct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdcolor.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jddctmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdhuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdinput.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmainct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmarker.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmaster.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdmerge.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdphuff.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdpostct.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdsample.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jdtrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jerror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctflt.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctfst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jfdctint.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctflt.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctfst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctint.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jidctred.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemansi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jmemmgr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jquant1.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jquant2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\jpeg\libjpeg\jutils.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="jpeg2000"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\jpeg2000\jpeg2000dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="l1b"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\l1b\l1bdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="leveller"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\leveller\levellerdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\mem\memdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mrsid"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\mrsid\mrsiddataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\mrsid\mrsidstream.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msg"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\msg\msgcommand.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\msgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\prologue.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\reflectancecalculator.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msg\xritheaderparser.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="msgn"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\msgn\msg_basic_types.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msg_reader_core.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\msgn\msgndataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="netcdf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\netcdf\gmtdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\netcdf\netcdfdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="nitf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\nitf\mgrs.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfaridpcm.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfbilevel.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfdump.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitffile.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\nitfimage.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftocdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\nitf\rpftocfile.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="ogdi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\ogdi\ogdidataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcidsk"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pcidsk\pcidskdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcidsk\pcidsktiledrasterband.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pcraster"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrastermisc.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pcraster\pcrasterutil.cpp"
-						>
-					</File>
-					<Filter
-						Name="libcsf"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_getcell.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_getrow.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_gsomece.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_putcell.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\_rputrow.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\angle.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\attravai.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\attrsize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\cellsize.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\create2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfglob.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\csfsup.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\delattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\dumconv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\endian.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\filename.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gattrblk.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gattridx.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gcellrep.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gdattype.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\getattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\getx0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gety0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ggisfid.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gmaxval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gminval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gnrcols.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gnrrows.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gproj.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gputproj.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gvalscal.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gvartype.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\gversion.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ismv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\kernlcsf.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\legend.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mclose.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\moreattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\mperror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pgisfid.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pmaxval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pminval.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putallmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putattr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putsomec.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\putx0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\puty0.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\pvalscal.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rattrblk.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rcomp.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rcoords.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rdup2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\reseterr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rextend.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rmalloc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\rrowcol.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\ruseas.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setangle.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\setvtmv.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\strconst.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\strpad.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\swapio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\trackmm.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vs2.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsdef.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsis.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\vsvers.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\pcraster\libcsf\wattrblk.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="pds"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pds\isis2dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\isis3dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\nasakeywordhandler.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pds\pdsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="pgchip"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\pgchip\pgchipdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pgchip\pgchiprasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\pgchip\pgchiputilities.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="png"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\png\pngdataset.cpp"
-						>
-					</File>
-					<Filter
-						Name="libpng"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\frmts\png\libpng\png.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngerror.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pnggccrd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngget.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngmem.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngpread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngread.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrtran.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngrutil.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngset.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngtrans.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngvcrd.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwio.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwrite.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwtran.c"
-							>
-						</File>
-						<File
-							RelativePath=".\frmts\png\libpng\pngwutil.c"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="raw"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\raw\atlsci_spheroid.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\btdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\cpgdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\dipxdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\doq1dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\doq2dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\ehdrdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\eirdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\envidataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\fastdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\fujibasdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\genbindataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\gscdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\hkvdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\idadataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\landataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\lcpdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\mffdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\ndfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\pauxdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\pnmdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\raw\rawdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rik"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rik\rikdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rmf"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rmf\rmfdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\rmf\rmflzw.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="rs2"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\rs2\rs2dataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sde"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sde\sdedataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sdeerror.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sde\sderasterband.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sdts"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sdts\sdts2shp.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsattrreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtscatd.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsindexedreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsiref.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtslib.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtslinereader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtspointreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtspolygonreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsrasterreader.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtstransfer.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\sdts\sdtsxref.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="sgi"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\sgi\sgidataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="srtmhgt"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\srtmhgt\srtmhgtdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terragen"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\terragen\terragendataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="terralib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibDataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\terralib\TerraLibRasterBand.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="tsx"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\tsx\tsxdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="usgsdem"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\usgsdem\usgsdem_create.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\usgsdem\usgsdemdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="vrt"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\vrt\vrtdataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtderivedrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtfilters.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtrawrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtsourcedrasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtsources.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\vrt\vrtwarped.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wcs"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\wcs\httpdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wcs\wcsdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="wms"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\wms\cache.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\dataset.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\gdalhttp.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\md5.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_tileservice.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_wms.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\minidriver_worldwind.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\rasterband.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\stuff.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\wms\wmsdriver.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="xpm"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\xpm\xpmdataset.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="zlib"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\frmts\zlib\adler32.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\compress.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\crc32.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\deflate.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\gzio.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\infback.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inffast.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inflate.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\inftrees.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\trees.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\uncompr.c"
-						>
-					</File>
-					<File
-						RelativePath=".\frmts\zlib\zutil.c"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="gcore"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\gcore\gdal_misc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rat.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdal_rpcimdio.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalallvalidmaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalcolortable.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldefaultoverviews.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldriver.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaldrivermanager.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalgmlcoverage.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2box.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdaljp2metadata.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalmajorobject.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalmultidomainmetadata.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalnodatamaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalnodatavaluesmaskband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalopeninfo.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamdataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamproxydb.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalpamrasterband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalproxydataset.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalproxypool.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalrasterband.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\gdalrasterblock.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\overview.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\gcore\rasterio.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="ogr"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\ogr\gml2ogrgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr2gmlgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_api.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_capi_test.c"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_fromepsg.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_opt.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_dict.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_erm.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_esri.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_panorama.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_pci.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_proj4.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_usgs.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_validate.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srs_xml.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogr_srsnode.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ograssemblepolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrct.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrcurve.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeature.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturedefn.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturequery.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfeaturestyle.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrfielddefn.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometry.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometrycollection.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrgeometryfactory.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrlinearring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrlinestring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultilinestring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultipoint.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrmultipolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrpoint.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrpolygon.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrspatialreference.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrsurface.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\ogrutils.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\ogr\swq.c"
-					>
-				</File>
-				<Filter
-					Name="ogrsf_frmts"
-					Filter="*.c;*.cpp   "
-					>
-					<Filter
-						Name="avc"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_bin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_binwr.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00gen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00parse.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00read.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_e00write.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_misc.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\avc_rawbin.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbindriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcbinlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravcdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravce00layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\avc\ogravclayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="bna"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnadriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnalayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="csv"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dgn"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgndump.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnfloat.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnhelp.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnopen.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnread.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnstroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwrite.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\dgnwritetest.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgndriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dgn\ogrdgnlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="dods"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsfielddefn.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodsgrid.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="fme"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmecacheindex.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayercached.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\fme\ogrfmelayerdb.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="generic"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_attrind.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_gensql.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogr_miattrind.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrregisterall.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geoconcept"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\geoconcept_syscoord.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="geojson"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsondriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonreader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonutils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\geojson\ogrgeojsonwriter.cpp"
-							>
-						</File>
-						<Filter
-							Name="jsonc"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\arraylist.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\debug.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_object.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_tokener.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\json_util.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\linkhash.c"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.c"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="gml"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeature.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlfeatureclass.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlhandler.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlpropertydefn.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\gmlreadstate.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\ogrgmllayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\trstring.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gml\resolvexlinks.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gmt"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gmt\ogrgmtlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="gpx"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="grass"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrassdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\grass\ogrgrasslayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="idb"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridblayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ili"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2handler.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ili2reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ilihelper.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\iomhelper.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili1layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ili\ogrili2layer.cpp"
-							>
-						</File>
-						<Filter
-							Name="iom"
-							Filter="*.c;*.cpp     "
-							>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_attr.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_basket.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_error.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_file.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_iterator.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_object.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_utilities.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\iom_value.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\reader.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\tags.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\ustrings.cpp"
-								>
-							</File>
-							<File
-								RelativePath=".\ogr\ogrsf_frmts\ili\iom\writer.cpp"
-								>
-							</File>
-						</Filter>
-					</Filter>
-					<Filter
-						Name="ingres"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringreslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringresstatement.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ingres\ogringrestablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="kml"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kml.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlnode.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogr2kmlgeometry.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmllayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mem"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mitab"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_bounds.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_datfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_geometry.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_idfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_indfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_miffile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tabview.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="mysql"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqllayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ntf"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_codelist.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_estlayers.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_generic.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntf_raster.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfdump.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntffilereader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfrecord.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ntfstroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntfdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntffeatureclasslayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ntf\ogrntflayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="oci"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\fastload.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\oci_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ocitest.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocidriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocilayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociloaderlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocisession.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistatement.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistringbuf.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocistroke.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrocitablelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\oci\ogrociwritablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="odbc"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbclayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbcselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\odbc\ogrodbctablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="ogdi"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pg"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpglayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgresultlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgtablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="pgeo"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeolayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeoselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeotablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="rec"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ll_recio.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrrecdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\rec\ogrreclayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="s57"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ddfrecordindex.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57datasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57driver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\ogrs57layer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57classregistrar.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57dump.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57featuredefns.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57filecollector.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\s57\s57writer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sde"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sde\ogrsdelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sdts"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="shape"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\dbfopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shape2ogr.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shp_vsi.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shpopen.c"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\shape\shptree.c"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="sqlite"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteselectlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="tiger"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerlayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeraltname.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerarealandmarks.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigercompletechain.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerentitynames.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfeatureids.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerfilebase.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeridhistory.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerinfo.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerkeyfeatures.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerlandmarks.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigeroverunder.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpip.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpoint.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolychainlink.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygon.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoncorrections.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerpolygoneconomic.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerspatialmetadata.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigertlidrange.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzerocellid.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="vrt"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtdriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\vrt\ogrvrtlayer.cpp"
-							>
-						</File>
-					</Filter>
-					<Filter
-						Name="xplane"
-						Filter="*.c;*.cpp    "
-						>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_apt_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_awy_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_fix_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_geo_utils.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_nav_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogr_xplane_reader.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanelayer.cpp"
-							>
-						</File>
-						<File
-							RelativePath=".\ogr\ogrsf_frmts\xplane\test_geo_utils.cpp"
-							>
-						</File>
-					</Filter>
-				</Filter>
-				<Filter
-					Name="wcts"
-					Filter="*.c;*.cpp   "
-					>
-					<File
-						RelativePath=".\ogr\wcts\ogrwcts.cpp"
-						>
-					</File>
-					<File
-						RelativePath=".\ogr\wcts\wctsclient.cpp"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="port"
-				Filter="*.c;*.cpp  "
-				>
-				<File
-					RelativePath=".\port\cpl_conv.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_csv.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_error.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_findfile.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_getexecpath.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_hash_set.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_http.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_list.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minixml.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_ioapi.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_minizip_unzip.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_multiproc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_odbc.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_path.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_quad_tree.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_recode_stub.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_string.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_strtod.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsi_mem.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_gzip.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_simple.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_unix_stdio_64.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsil_win32.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_vsisimple.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cpl_win32ce_api.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplgetsymbol.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplkeywordparser.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\cplstring.cpp"
-					>
-				</File>
-				<File
-					RelativePath=".\port\xmlreformat.cpp"
-					>
-				</File>
-			</Filter>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/makegdal_gen.bat b/makegdal_gen.bat
index e6e8e7f..2667358 100644
--- a/makegdal_gen.bat
+++ b/makegdal_gen.bat
@@ -6,7 +6,7 @@
 ::  Name:     makegdal_gen.bat
 ::  Project:  GDAL 
 ::  Purpose:  Generate MS Visual Studio 2003...N project files    
-::  Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+::  Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
 :: 
 :: ****************************************************************************
 ::  Copyright (c) 2007, Ivan Lucena    
@@ -35,14 +35,32 @@
 ::  *********************
 
 if "%1"=="" (
-    echo Usage: makegdal_gen "MS Visual C++ version" ^> makegdalNN.vcproj
+    echo Usage: makegdal_gen "MS Visual C++ version" "platform{32,64}" ^> makegdalNN.vcproj
     echo Examples:
-    echo    makegdal_gen 7.10 ^> makegdal71.vcproj
-    echo    makegdal_gen 8.00 ^> makegdal80.vcproj
+    echo    makegdal_gen  7.10 32 ^> makegdal71.vcproj
+    echo    makegdal_gen  8.00 64 ^> makegdal80.vcproj
+    echo    makegdal_gen  9.00 64 ^> makegdal90.vcproj
+    echo    makegdal_gen 10.00 64 ^> makegdal10.vcproj
     goto :end
 )
 
 ::  *********************
+::  Get plataform 32 or 64
+::  *********************
+
+set _plat_=%2
+
+if "%_plat_%"=="" (
+    set _plat_=32
+)
+
+if "%_plat_%"=="32" (
+    set _plat_=Win32
+) else (
+    set _plat_=x64
+)
+
+::  *********************
 ::  Get Visual C++ version
 ::  *********************
 
@@ -64,6 +82,10 @@ if "%_vcver_%"=="8.00" (
 if "%_vcver_%"=="9.00" (
 	set _clver_=1500
 )
+if "%_vcver_%"=="10.00" (
+	set _vcver_=9.00
+	set _clver_=1600
+)
 
 ::  *********************
 ::  Get GDAL Version
@@ -85,11 +107,11 @@ echo 	Name="makegdal%_vcnum_%"
 echo 	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
 echo 	Keyword="MakeFileProj"^>
 echo 	^<Platforms^>
-echo 		^<Platform Name="Win32"/^>
+echo 		^<Platform Name="%_plat_%"/^>
 echo 	^</Platforms^>
 echo 	^<Configurations^>
 echo 		^<Configuration
-echo 			Name="Debug|Win32"
+echo 			Name="Debug|%_plat_%"
 echo 			OutputDirectory="$(ConfigurationName)"
 echo 			IntermediateDirectory="$(ConfigurationName)"
 echo 			ConfigurationType="0"^>
@@ -101,7 +123,7 @@ echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc
 echo 				Output="gdal%_gdalnum_%.dll"/^>
 echo 		^</Configuration^>
 echo 		^<Configuration
-echo 			Name="Release|Win32"
+echo 			Name="Release|%_plat_%"
 echo 			OutputDirectory="$(ConfigurationName)"
 echo 			IntermediateDirectory="$(ConfigurationName)"
 echo 			ConfigurationType="0"^>
@@ -116,9 +138,9 @@ echo 	^</Configurations^>
 echo 	^<References^>
 echo 	^</References^>
 echo 	^<Files^>
-call :create_filter . "*.vc;*.opt" "Make Files"    "	"
-call :create_filter . "*.h"        "Include Files" "	"
-call :create_filter . "*.c;*.cpp"  "Source Files"  "	"
+call :create_filter . "*.vc;*.opt;*.local" "Make Files"    "	"
+call :create_filter . "*.h"                "Include Files" "	"
+call :create_filter . "*.c;*.cpp"          "Source Files"  "	"
 echo 	^</Files^>
 echo 	^<Globals^>
 echo 	^</Globals^>
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index 74cc19b..96d3f1d 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,8 +1,8 @@
-.TH "gdal-config" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal-config \- .TH "gdal-config" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal-config \- .TH "gdal-config" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index c16201d..f6b804e 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,8 +1,8 @@
-.TH "gdal2tiles" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal2tiles \- .TH "gdal2tiles" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal2tiles \- .TH "gdal2tiles" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
new file mode 100644
index 0000000..c11e578
--- /dev/null
+++ b/man/man1/gdal_calc.1
@@ -0,0 +1,74 @@
+.TH "gdal_calc" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gdal_calc \- .TH "gdal_calc" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gdal_calc \- Command line raster calculator with numpy syntax
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+
+gdal_calc.py [-A <filename>] [--A_band] [-B...-Z filename] [other_options]
+
+Options:
+  -h, --help            show this help message and exit
+  --calc=CALC           calculation in gdalnumeric syntax using +-/* or any
+                        numpy array functions (i.e. logical_and())
+  -A A                  input gdal raster file, note you can use any letter
+                        A-Z
+  --A_band=A_BAND       number of raster band for file A (default 0)
+  --outfile=OUTF        output file to generate or fill
+  --NoDataValue=NODATAVALUE
+                        set output nodata value (Defaults to datatype specific
+                        value)
+  --type=TYPE           output datatype, must be one of ['Int32', 'Int16',
+                        'Float64', 'UInt16', 'Byte', 'UInt32', 'Float32']
+  --format=FORMAT       GDAL format for output file (default 'GTiff')
+  --creation-option=CREATION_OPTIONS, --co=CREATION_OPTIONS
+                        Passes a creation option to the output format driver.
+                        Multiple options may be listed. See format specific
+                        documentation for legal creation options for each
+                        format.
+  --allBands=ALLBANDS   process all bands of given raster (A-Z)
+  --overwrite           overwrite output file if it already exists
+  --debug               print debugging information
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+Command line raster calculator with numpy syntax. Use any basic arithmetic supported by numpy arrays such as +-*\\ along with logical operators such as >. Note that all files must have the same dimensions, but no projection checking is performed.
+.SH "EXAMPLE"
+.PP
+add two files together 
+.PP
+.nf
+
+gdal_calc.py -A input1.tif -B input2.tif --outfile=result.tif --calc="A+B"
+
+.fi
+.PP
+.PP
+average of two layers 
+.PP
+.nf
+
+gdal_calc.py -A input.tif -B input2.tif --outfile=result.tif --calc="(A+B)/2"
+
+.fi
+.PP
+.PP
+set values of zero and below to null 
+.PP
+.nf
+
+gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
+
+.fi
+.PP
+.SH "AUTHORS"
+.PP
+Chris Yesson <chris dot='' yesson='' at='' ioz='' dot='' ac='' dot='' uk>=''> Etienne Tourigny <etourigny dot='' dev='' at='' gmail='' dot='' com>=''> 
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index a0be14f..9d792ab 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,8 +1,8 @@
-.TH "gdal_contour" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_contour \- .TH "gdal_contour" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_contour \- .TH "gdal_contour" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index 291a446..c8e4ae9 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,8 +1,8 @@
-.TH "gdal_edit" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_edit \- .TH "gdal_edit" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_edit \- .TH "gdal_edit" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -12,7 +12,7 @@ gdal_edit \- Edit in place various information of an existing GDAL dataset
 .PP
 .nf
 
-gdal_edit [--help-general] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
+gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
           [-tr xres yres] [-unsetgt] [-a_nodata value]
           [-gcp pixel line easting northing [elevation]]*
           [-mo "META-TAG=VALUE"]*  datasetname
@@ -26,6 +26,9 @@ It works only with raster formats that support update access to existing dataset
 .IP "\fB\fB--help-general\fP:\fP" 1c
 Gives a brief usage message for the generic GDAL commandline options and exit. 
 .PP
+.IP "\fB\fB-ro\fP:\fP" 1c
+(GDAL >= 1.11) Open the dataset in read-only. Might be usefull for drivers refusing to use the dataset in update-mode. In which case, updated information will go into PAM .aux.xml files.
+.PP
 .IP "\fB\fB-a_srs\fP \fIsrs_def\fP:\fP" 1c
 .PP
 Defines the target coordinate system. This coordinate system will be written to the dataset.
@@ -40,7 +43,7 @@ Set target resolution. The values must be expressed in georeferenced units. Both
 Remove the georeference information.
 .PP
 .IP "\fB\fB-a_nodata\fP \fIvalue\fP:\fP" 1c
-Assign a specified nodata value to output bands. Can be set to \fInone\fP to remove a nodata value if one exists for the dataset.
+Assign a specified nodata value to output bands.
 .PP
 .IP "\fB\fB-gcp\fP \fIpixel line easting northing [elevation]\fP:\fP" 1c
 Add the indicated ground control point to the dataset. This option may be provided multiple times to provide a set of GCPs. 
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index 74852b1..64832ba 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,8 +1,8 @@
-.TH "gdal_fillnodata" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_fillnodata \- .TH "gdal_fillnodata" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_fillnodata \- .TH "gdal_fillnodata" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index c67949b..6e98eb7 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,8 +1,8 @@
-.TH "gdal_grid" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_grid \- .TH "gdal_grid" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_grid \- .TH "gdal_grid" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -15,7 +15,7 @@ gdal_grid \- creates regular grid from the scattered data
 gdal_grid [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
           CInt16/CInt32/CFloat32/CFloat64}]
 	  [-of format] [-co "NAME=VALUE"]
-	  [-zfield field_name]
+	  [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]
 	  [-a_srs srs_def] [-spat xmin ymin xmax ymax]
           [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]
           [-clipsrcsql sql_statement] [-clipsrclayer layer]
@@ -53,6 +53,12 @@ Override the projection for the output file. The \fIsrs_def\fP may be any of the
 .IP "\fB\fB-zfield\fP \fIfield_name\fP:\fP" 1c
 Identifies an attribute field on the features to be used to get a Z value from. This value overrides Z value read from feature geometry record (naturally, if you have a Z value in geometry, otherwise you have no choice and should specify a field name containing Z value).
 .PP
+.IP "\fB\fB-z_increase\fP \fIincrease_value\fP:\fP" 1c
+Addition to the attribute field on the features to be used to get a Z value from. The addition should be the same unit as Z value. The result value will be Z value + Z increase value. The default value is 0.
+.PP
+.IP "\fB\fB-z_multiply\fP \fImultiply_value\fP:\fP" 1c
+This is multiplication ratio for Z field. This can be used for shift from e.g. foot to meters or from elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value. The default value is 1.
+.PP
 .IP "\fB\fB-a\fP \fI[algorithm[:parameter1=value1][:parameter2=value2]...]\fP: \fP" 1c
 Set the interpolation algorithm or data metric name and (optionally) its parameters. See \fBINTERPOLATION ALGORITHMS\fP and \fBDATA METRICS\fP sections for further discussion of available options.
 .PP
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index 77bf5da..7e9f288 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,8 +1,8 @@
-.TH "gdal_merge" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_merge \- .TH "gdal_merge" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_merge \- .TH "gdal_merge" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index ec38ddf..0d494b0 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,8 +1,8 @@
-.TH "gdal_polygonize" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_polygonize \- .TH "gdal_polygonize" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_polygonize \- .TH "gdal_polygonize" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index ea7f41b..87f0c68 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,8 +1,8 @@
-.TH "gdal_proximity" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_proximity \- .TH "gdal_proximity" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_proximity \- .TH "gdal_proximity" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 08fb520..b0f3b7a 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,8 +1,8 @@
-.TH "gdal_rasterize" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_rasterize \- .TH "gdal_rasterize" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_rasterize \- .TH "gdal_rasterize" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 3e0c73c..9bdebf1 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,8 +1,8 @@
-.TH "gdal_retile" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_retile \- .TH "gdal_retile" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_retile \- .TH "gdal_retile" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index cfaa052..508d010 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,8 +1,8 @@
-.TH "gdal_sieve" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_sieve \- .TH "gdal_sieve" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_sieve \- .TH "gdal_sieve" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index de00559..dfc039f 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,8 +1,8 @@
-.TH "gdal_translate" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_translate \- .TH "gdal_translate" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_translate \- .TH "gdal_translate" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -17,12 +17,12 @@ gdal_translate [--help-general]
              CInt16/CInt32/CFloat32/CFloat64}] [-strict]
        [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]
        [-outsize xsize[%] ysize[%]]
-       [-unscale] [-scale [src_min src_max [dst_min dst_max]]]
+       [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*
        [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry] [-epo] [-eco]
        [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]
        [-gcp pixel line easting northing [elevation]]*
        [-mo "META-TAG=VALUE"]* [-q] [-sds]
-       [-co "NAME=VALUE"]* [-stats]
+       [-co "NAME=VALUE"]* [-stats] [-norat]
        src_dataset dst_dataset
 .fi
 .PP
@@ -45,7 +45,9 @@ Select an input band \fIband\fP for output. Bands are numbered from 1. Multiple
 .IP "\fB\fB-outsize\fP \fIxsize[%] ysize[%]\fP:\fP" 1c
 Set the size of the output file. Outsize is in pixels and lines unless '%' is attached in which case it is as a fraction of the input image size. 
 .IP "\fB\fB-scale\fP \fI[src_min src_max [dst_min dst_max]]\fP:\fP" 1c
-Rescale the input pixels values from the range \fIsrc_min\fP to \fIsrc_max\fP to the range \fIdst_min\fP to \fIdst_max\fP. If omitted the output range is 0 to 255. If omitted the input range is automatically computed from the source data. 
+Rescale the input pixels values from the range \fIsrc_min\fP to \fIsrc_max\fP to the range \fIdst_min\fP to \fIdst_max\fP. If omitted the output range is 0 to 255. If omitted the input range is automatically computed from the source data. Before GDAL 1.11, it can be specified only once, and in that case, it applies to all bands of the output dataset. Starting with GDAL 1.11, -scale can be repeated several times (if specified only once, it also applies to all bands of the output dataset), [...]
+.IP "\fB\fB-exponent\fP \fI exp_val\fP:\fP" 1c
+(From GDAL 1.11) To apply non-linear scaling with a power function. exp_val is the exponent of the power function (must be postive). This option must be used with the -scale option. If specified only once, -exponent applies to all bands of the output image. It can be repeated several times so as to specify per band parameters. It is also possible to use the '-exponent_bn' syntax where bn is a band number (e.g. '-exponent_2' for the 2nd band of the output dataset) to specify the parameter [...]
 .IP "\fB\fB-unscale\fP:\fP" 1c
 Apply the scale/offset metadata for the bands to convert scaled values to unscaled values. It is also often necessary to reset the output datatype with the \fB-ot\fP switch. 
 .IP "\fB\fB-srcwin\fP \fIxoff yoff xsize ysize\fP:\fP" 1c
@@ -71,9 +73,11 @@ Add the indicated ground control point to the output dataset. This option may be
 .IP "\fB\fB-q\fP:\fP" 1c
 Suppress progress monitor and other non-error output. 
 .IP "\fB\fB-sds\fP:\fP" 1c
-Copy all subdatasets of this file to individual output files. Use with formats like HDF or OGDI that have subdatasets. 
+Copy all subdatasets of this file to individual output files. Use with formats like HDF or OGDI that have subdatasets. The output file naming scheme has changed in GDAL 1.11 (e.g. ofile_1.tif, ofile_2.tif). 
 .IP "\fB\fB-stats\fP:\fP" 1c
 (GDAL >= 1.8.0) Force (re)computation of statistics. 
+.IP "\fB\fB-norat\fP\fP" 1c
+(GDAL >= 1.11) Do not copy source RAT into destination dataset. 
 .IP "\fB\fIsrc_dataset\fP:\fP" 1c
 The source dataset name. It can be either file name, URL of data source or subdataset name for multi-dataset files. 
 .IP "\fB\fIdst_dataset\fP:\fP" 1c
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index 3f52008..b2101a3 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,8 +1,8 @@
-.TH "gdal_utilities" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_utilities \- .TH "gdal_utilities" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdal_utilities \- .TH "gdal_utilities" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -60,9 +60,13 @@ gdal_utilities \- The following utility programs are distributed with GDAL.
 .IP "\(bu" 2
 \fBgdal_edit.py\fP - Edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata) 
 .IP "\(bu" 2
+\fBgdal_calc.py\fP - Command line raster calculator with numpy syntax 
+.IP "\(bu" 2
 \fBgdal-config\fP - Get options required to build software using GDAL. 
 .IP "\(bu" 2
 \fBgdalmanage\fP - Identify, copy, rename and delete raster. 
+.IP "\(bu" 2
+\fBgdalcompare.py\fP - Compare two images and report on differences. 
 .PP
 .SH "Creating New Files"
 .PP
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 20c20f1..022ecf5 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,8 +1,8 @@
-.TH "gdaladdo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaladdo \- .TH "gdaladdo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdaladdo \- .TH "gdaladdo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index a6c664b..20af7cc 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,8 +1,8 @@
-.TH "gdalbuildvrt" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalbuildvrt \- .TH "gdalbuildvrt" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalbuildvrt \- .TH "gdalbuildvrt" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
new file mode 100644
index 0000000..1375a0f
--- /dev/null
+++ b/man/man1/gdalcompare.1
@@ -0,0 +1,38 @@
+.TH "gdalcompare" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gdalcompare \- .TH "gdalcompare" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gdalcompare \- compare two images
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+
+gdalcompare.py [-sds] golden_file new_file
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The gdalcompare.py script compares two GDAL supported datasets and reports the differences. In addition to reporting differences to the standard out the script will also return the difference count in it's exit value.
+.PP
+Image pixels, and various metadata are checked. There is also a byte by byte comparison done which will count as one difference. So if it is only important that the GDAL visible data is identical a difference count of 1 (the binary difference) should be considered acceptable.
+.PP
+.IP "\fB\fB-sds\fP:\fP" 1c
+If this flag is passed the script will compare all subdatasets that are part of the dataset, otherwise subdatasets are ignored.
+.PP
+.IP "\fB\fIgolden_file\fP:\fP" 1c
+The file that is considered correct, referred to as the golden file.
+.PP
+.IP "\fB\fInew_file\fP:\fP" 1c
+The file being compared to the golden file, referred to as the new file.
+.PP
+.PP
+.PP
+Note that the gdalcompare.py script can also be called as a library from python code though it is not typically in the python path for including. The primary entry point is gdalcompare.compare() which takes a golden gdal.Dataset and a new gdal.Dataset as arguments and returns a difference count (excluding the binary comparison). The gdalcompare.compare_sds() entry point can be used to compare subdatasets.
+.SH "AUTHORS"
+.PP
+Frank Warmerdam <warmerdam at pobox.com> 
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index 94d0804..45f664c 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,8 +1,8 @@
-.TH "gdaldem" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaldem \- .TH "gdaldem" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdaldem \- .TH "gdaldem" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -53,8 +53,14 @@ gdaldem \- Tools to analyze and visualize DEMs. (since GDAL 1.7.0)
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
 
 Notes :
-  Scale is the ratio of vertical units to horizontal
-   for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120)
+  gdaldem generally assumes that x, y and z units are identical.  If x (east-west)
+  and y (north-south) units are identical, but z (elevation) units are different, the
+  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For 
+  LatLong projections near the equator, where units of latitude and units of 
+  longitude are similar, elevation (z) units can be converted to be compatible
+  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in 
+  meters).  For locations not near the equator, it would be best to reproject your
+  grid using gdalwarp before using gdaldem.
 
 .fi
 .PP
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 31fcaab..cd82d04 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,8 +1,8 @@
-.TH "gdalinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalinfo \- .TH "gdalinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalinfo \- .TH "gdalinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -13,8 +13,9 @@ gdalinfo \- lists information about a raster dataset
 .nf
 
 gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
-         [-norat] [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*
-	 [-sd subdataset] datasetname
+         [-norat] [-noct] [-nofl] [-checksum] [-proj4]
+         [-listmdd] [-mdd domain|`all`]*
+         [-sd subdataset] datasetname
 .fi
 .PP
 .SH "DESCRIPTION"
@@ -38,8 +39,10 @@ Suppress printing of raster attribute table.
 Suppress printing of color table. 
 .IP "\fB\fB-checksum\fP\fP" 1c
 Force computation of the checksum for each band in the dataset. 
+.IP "\fB\fB-listmdd\fP\fP" 1c
+(GDAL >= 1.11) List all metadata domains available for the dataset. 
 .IP "\fB\fB-mdd domain\fP\fP" 1c
-Report metadata for the specified domain 
+Report metadata for the specified domain. Starting with GDAL 1.11, 'all' can be used to report metadata in all domains 
 .IP "\fB\fB-nofl\fP\fP" 1c
 (GDAL >= 1.9.0) Only display the first file of the file list. 
 .IP "\fB\fB-sd\fP \fIsubdataset\fP\fP" 1c
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index 1de0c66..a2a238c 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,8 +1,8 @@
-.TH "gdallocationinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdallocationinfo \- .TH "gdallocationinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdallocationinfo \- .TH "gdallocationinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index ffae1f3..8e5ed0c 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,8 +1,8 @@
-.TH "gdalmanage" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmanage \- .TH "gdalmanage" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalmanage \- .TH "gdalmanage" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index ebe3a46..a52472e 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,8 +1,8 @@
-.TH "gdalmove" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmove \- .TH "gdalmove" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalmove \- .TH "gdalmove" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index 99a0ae6..41c6092 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,8 +1,8 @@
-.TH "gdalsrsinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalsrsinfo \- .TH "gdalsrsinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalsrsinfo \- .TH "gdalsrsinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index eaf4b0f..8301cd8 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,40 +1,65 @@
-.TH "gdaltindex" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltindex \- .TH "gdaltindex" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdaltindex \- .TH "gdaltindex" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltindex \- builds a shapefile as a raster tileindex
+gdaltindex \- Builds a shapefile as a raster tileindex
 .SH "SYNOPSIS"
 .PP
 .PP
 .nf
 
-gdaltindex [-tileindex field_name] [-write_absolute_path] [-skip_different_projection] [-t_srs target_srs] index_file [gdal_file]*
+gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path]
+           [-skip_different_projection] [-t_srs target_srs]
+           [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]
+           [-lyr_name name] index_file [gdal_file]*
 .fi
 .PP
 .SH "DESCRIPTION"
 .PP
 This program builds a shapefile with a record for each input raster file, an attribute containing the filename, and a polygon geometry outlining the raster. This output is suitable for use with \fCMapServer\fP as a raster tileindex.
 .PP
-.PD 0
-.IP "\(bu" 2
-The shapefile (index_file) will be created if it doesn't already exist, otherwise it will append to the existing file. 
-.IP "\(bu" 2
-The default tile index field is 'location'. 
-.IP "\(bu" 2
-Raster filenames will be put in the file exactly as they are specified on the commandline unless the option -write_absolute_path is used. 
-.IP "\(bu" 2
-If -skip_different_projection is specified, only files with same projection ref as files already inserted in the tileindex will be inserted (unless t_srs is specified). 
-.IP "\(bu" 2
-If -t_srs is specified, geometries of input files will be transformed to the desired target coordinate reference system. Note that using this option generates files that are NOT compatible with MapServer. 
-.IP "\(bu" 2
-Simple rectangular polygons are generated in the same coordinate reference system as the rasters, or in target reference system if the -t_srs option is used. 
+.IP "\fB\fB-f\fP format:\fP" 1c
+(GDAL >= 1.11) 
 .PP
-.SH "EXAMPLE"
+The OGR format of the output tile index file. Default is Esri Shapefile.  
+.IP "\fB\fB-tileindex\fP field_name: \fP" 1c
 .PP
+The output field name to hold the file path/location to the indexed rasters. The default tile index field name is \fClocation\fP.  
+.IP "\fB\fB-write_absolute_path\fP: \fP" 1c
+.PP
+The absolute path to the raster files is stored in the tile index file. By default the raster filenames will be put in the file exactly as they are specified on the command line.  
+.IP "\fB\fB-skip_different_projection\fP: \fP" 1c
+.PP
+Only files with same projection as files already inserted in the tileindex will be inserted (unless \fC-t_srs\fP is specified). Default does not check projection and accepts all inputs.  
+.IP "\fB\fB-t_srs\fP target_srs: \fP" 1c
+.PP
+Geometries of input files will be transformed to the desired target coordinate reference system. Using this option generates files that are not compatible with MapServer < 6.4. Default creates simple rectangular polygons in the same coordinate reference system as the input rasters.  
+.IP "\fB\fB-src_srs_name\fP field_name:\fP" 1c
+(GDAL >= 1.11) 
+.PP
+The name of the field to store the SRS of each tile. This field name can be used as the value of the TILESRS keyword in MapServer >= 6.4.  
+.IP "\fB\fB-src_srs_format\fP type:\fP" 1c
+(GDAL >= 1.11) 
+.PP
+The format in which the SRS of each tile must be written. Types can be AUTO, WKT, EPSG, PROJ.  
+.IP "\fB\fB-lyr_name\fP name: \fP" 1c
+.PP
+Layer name to create/append to in the output tile index file.  
+.IP "\fB\fBindex_file\fP: \fP" 1c
+.PP
+The name of the output file to create/append to. The default shapefile will be created if it doesn't already exist, otherwise it will append to the existing file.  
+.IP "\fB\fBgdal_file\fP: \fP" 1c
+.PP
+The input GDAL raster files, can be multiple files separated by spaces. Wildcards my also be used. Stores the file locations in the same style as specified here, unless \fC-write_absolute_path\fP option is also used.  
+.PP
+.SH "EXAMPLES"
+.PP
+.PP
+Produce a shapefile (\fCdoq_index.shp\fP) with a record for every image that the utility found in the \fCdoq\fP folder. Each record holds information that points to the location of the image and also a bounding rectangle shape showing the bounds of the image:
 .PP
 .PP
 .nf
@@ -42,6 +67,15 @@ Simple rectangular polygons are generated in the same coordinate reference syste
 gdaltindex doq_index.shp doq/*.tif
 .fi
 .PP
+.PP
+The \fC-t_srs\fP option can also be used to transform all input rasters into the same output projection:
+.PP
+.PP
+.nf
+
+gdaltindex -t_srs EPSG:4326 -src_srs_name src_srs tile_index_mixed_srs.shp *.tif
+.fi
+.PP
 .SH "AUTHOR"
 .PP
 Frank Warmerdam <warmerdam at pobox.com> 
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index 4752ae7..9fecbb5 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,8 +1,8 @@
-.TH "gdaltransform" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltransform \- .TH "gdaltransform" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdaltransform \- .TH "gdaltransform" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index c761da6..4ff7d8e 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,8 +1,8 @@
-.TH "gdalwarp" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalwarp \- .TH "gdalwarp" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+gdalwarp \- .TH "gdalwarp" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -84,7 +84,7 @@ mode resampling, selects the value which appears most often of all the sampled p
 .IP "\fB\fB-srcnodata\fP \fIvalue [value...]\fP:\fP" 1c
 Set nodata masking values for input bands (different values can be supplied for each band). If more than one value is supplied all values should be quoted to keep them together as a single operating system argument. Masked values will not be used in interpolation. Use a value of \fCNone\fP to ignore intrinsic nodata settings on the source dataset. 
 .IP "\fB\fB-dstnodata\fP \fIvalue [value...]\fP:\fP" 1c
-Set nodata values for output bands (different values can be supplied for each band). If more than one value is supplied all values should be quoted to keep them together as a single operating system argument. New files will be initialized to this value and if possible the nodata value will be recorded in the output file. 
+Set nodata values for output bands (different values can be supplied for each band). If more than one value is supplied all values should be quoted to keep them together as a single operating system argument. New files will be initialized to this value and if possible the nodata value will be recorded in the output file. Use a value of \fCNone\fP to ensure that nodata is not defined (GDAL>=2.0). If this argument is not used then nodata values will be copied from the source dataset (GDAL>=2.0). 
 .IP "\fB\fB-dstalpha\fP:\fP" 1c
 Create an output alpha band to identify nodata (unset/transparent) pixels.  
 .IP "\fB\fB-wm\fP \fImemory_in_mb\fP:\fP" 1c
@@ -127,7 +127,7 @@ The destination file name.
 .PP
 Mosaicing into an existing output file is supported if the output file already exists. The spatial extent of the existing file will not be modified to accomodate new data, so you may have to remove it in that case, or use the -overwrite option.
 .PP
-Polygon cutlines may be used as a mask to restrict the area of the destination file that may be updated, including blending. If the OGR layer containing the cutline features has no explicit SRS, the cutline features must be in the georeferenced units of the destination file. When outputing to a not yet existing target dataset, its extent will be the one of the original raster unless -te or -crop_to_cutline are specified.
+Polygon cutlines may be used as a mask to restrict the area of the destination file that may be updated, including blending. If the OGR layer containing the cutline features has no explicit SRS, the cutline features must be in the SRS of the destination file. When outputing to a not yet existing target dataset, its extent will be the one of the original raster unless -te or -crop_to_cutline are specified.
 .SH "EXAMPLE"
 .PP
 For instance, an eight bit spot scene stored in GeoTIFF with control points mapping the corners to lat/long could be warped to a UTM projection with a command like this:
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index db691fd..4f3e154 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,8 +1,8 @@
-.TH "nearblack" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-nearblack \- .TH "nearblack" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+nearblack \- .TH "nearblack" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index b92dc47..72fe1c2 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,8 +1,8 @@
-.TH "ogr2ogr" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogr2ogr \- .TH "ogr2ogr" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+ogr2ogr \- .TH "ogr2ogr" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -17,11 +17,11 @@ Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
                [-select field_list] [-where restricted_where] 
                [-progress] [-sql <sql statement>] [-dialect dialect]
                [-preserve_fid] [-fid FID]
-               [-spat xmin ymin xmax ymax]
+               [-spat xmin ymin xmax ymax] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
                [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
                dst_datasource_name src_datasource_name
-               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3] [layer [layer ...]]
+               [-lco NAME=VALUE] [-nln name] [-nlt type] [-dim 2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
                [-gt n]
@@ -33,7 +33,8 @@ Advanced options :
                [-clipdstwhere expression]
                [-wrapdateline] [-datelineoffset val]
                [[-simplify tolerance] | [-segmentize max_dist]]
-               [-fieldTypeToString All|(type1[,type2]*)]
+               [-addfields]
+               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]
                [-fieldmap identity | index1[,index2]*]
                [-splitlistfields] [-maxsubfields val]
                [-explodecollections] [-zfield field_name]
@@ -66,7 +67,7 @@ Delete the output layer and recreate it empty
 .IP "\fB\fB-update\fP:\fP" 1c
 Open existing output datasource in update mode rather than trying to create a new one 
 .IP "\fB\fB-select\fP\fI field_list\fP:\fP" 1c
-Comma-delimited list of fields from input layer to copy to the new layer. A field is skipped if mentioned previously in the list even if the input layer has duplicate field names. (Defaults to all; any field is skipped if a subsequent field with same name is found.) 
+Comma-delimited list of fields from input layer to copy to the new layer. A field is skipped if mentioned previously in the list even if the input layer has duplicate field names. (Defaults to all; any field is skipped if a subsequent field with same name is found.) Starting with OGR 1.11, geometry fields can also be specified in the list. 
 .IP "\fB\fB-progress\fP:\fP" 1c
 (starting with GDAL 1.7.0) Display progress on terminal. Only works if input layers have the 'fast feature count' capability. 
 .IP "\fB\fB-sql\fP \fIsql_statement\fP:\fP" 1c
@@ -79,6 +80,8 @@ Attribute query (like SQL WHERE)
 Continue after a failure, skipping the failed feature. 
 .IP "\fB\fB-spat\fP\fI xmin ymin xmax ymax\fP:\fP" 1c
 spatial query extents. Only features whose geometry intersects the extents will be selected. The geometries will not be clipped unless -clipsrc is specified 
+.IP "\fB\fB-geomfield\fP \fIfield\fP:\fP" 1c
+(OGR >= 1.11) Name of the geometry field on which the spatial filter operates on. 
 .IP "\fB\fB-dsco\fP \fINAME=VALUE\fP:\fP" 1c
 Dataset creation option (format specific) 
 .IP "\fB\fB-lco\fP\fI NAME=VALUE\fP:\fP" 1c
@@ -88,7 +91,7 @@ Assign an alternate name to the new layer
 .IP "\fB\fB-nlt\fP\fI type\fP:\fP" 1c
 Define the geometry type for the created layer. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING. Add '25D' to the name to get 2.5D versions. Starting with GDAL 1.10, PROMOTE_TO_MULTI can be used to automatically promote layers that mix polygon or multipolygons to multipolygons, and layers that mix linestrings or multilinestrings to multilinestrings. Can be usefull when converting shapefiles to PostGIS (and other target dr [...]
 .IP "\fB\fB-dim\fP\fI val\fP:\fP" 1c
-(starting with GDAL 1.10) Force the coordinate dimension to val (valid values are 2 or 3). This affects both the layer geometry type, and feature geometries. 
+(starting with GDAL 1.10) Force the coordinate dimension to val (valid values are 2 or 3). This affects both the layer geometry type, and feature geometries. Starting with GDAL 1.11, the value can be set to 'layer_dim' to instruct feature geometries to be promoted to the coordinate dimension declared by the layer.  
 .IP "\fB\fB-a_srs\fP\fI srs_def\fP:\fP" 1c
 Assign an output SRS 
 .IP "\fB\fB-t_srs\fP\fI srs_def\fP:\fP" 1c
@@ -106,7 +109,7 @@ Srs_def can be a full WKT definition (hard to escape properly), or a well known
 Advanced options :
 .PP
 .IP "\fB\fB-gt\fP \fIn\fP:\fP" 1c
-group \fIn\fP features per transaction (default 200). Increase the value for better performance when writing into DBMS drivers that have transaction support. 
+group \fIn\fP features per transaction (default 20000 in OGR 1.11, 200 in previous releases). Increase the value for better performance when writing into DBMS drivers that have transaction support. 
 .IP "\fB\fB-clipsrc\fP\fI [xmin ymin xmax ymax]|WKT|datasource|spat_extent\fP: \fP" 1c
 (starting with GDAL 1.7.0) clip geometries to the specified bounding box (expressed in source SRS), WKT geometry (POLYGON or MULTIPOLYGON), from a datasource or to the spatial extent of the \fB-spat\fP option if you use the \fIspat_extent\fP keyword. When specifying a datasource, you will generally want to use it in combination of the \fB-clipsrclayer\fP, \fB-clipsrcwhere\fP or \fB-clipsrcsql\fP options 
 .IP "\fB\fB-clipsrcsql\fP \fIsql_statement\fP:\fP" 1c
@@ -133,6 +136,8 @@ Restrict desired geometries based on attribute query.
 (starting with GDAL 1.6.0) maximum distance between 2 nodes. Used to create intermediate points 
 .IP "\fB\fB-fieldTypeToString\fP\fI type1, ...\fP:\fP" 1c
 (starting with GDAL 1.7.0) converts any field of the specified type to a field of type string in the destination layer. Valid types are : Integer, Real, String, Date, Time, DateTime, Binary, IntegerList, RealList, StringList. Special value \fBAll\fP can be used to convert all fields to strings. This is an alternate way to using the CAST operator of OGR SQL, that may avoid typing a long SQL query. 
+.IP "\fB\fB-unsetFieldWidth\fP:\fP" 1c
+(starting with GDAL 1.11) set field width and precision to 0. 
 .IP "\fB\fB-splitlistfields\fP:\fP" 1c
 (starting with GDAL 1.8.0) split fields of type StringList, RealList or IntegerList into as many fields of type String, Real or Integer as necessary. 
 .IP "\fB\fB-maxsubfields\fP \fIval\fP:\fP" 1c
@@ -149,10 +154,12 @@ To be combined with -splitlistfields to limit the number of subfields created fo
 (starting with GDAL 1.10.0) Force use of thin plate spline transformer based on available GCPs. 
 .IP "\fB\fB-fieldmap\fP:\fP" 1c
 (starting with GDAL 1.10.0) Specifies the list of field indexes to be copied from the source to the destination. The (n)th value specified in the list is the index of the field in the target layer definition in which the n(th) field of the source layer must be copied. Index count starts at zero. There must be exactly as many values in the list as the count of the fields in the source layer. We can use the 'identity' setting to specify that the fields should be transferred by using the sa [...]
+.IP "\fB\fB-addfields\fP:\fP" 1c
+(starting with GDAL 1.11) This is a specialized version of -append. Contrary to -append, -addfields has the effect of adding, to existing target layers, the new fields found in source layers. This option is usefull when merging files that have non-strictly identical structures. This might not work for output formats that don't support adding fields to existing non-empty layers. 
 .PP
 .SH "PERFORMANCE HINTS"
 .PP
-When writing into transactional DBMS (SQLite/PostgreSQL,MySQL, etc...), it might be beneficial to increase the number of INSERT statements executed between BEGIN TRANSACTION and COMMIT TRANSACTION statements. This number is specified with the -gt option. For example, for SQLite, explicitly defining \fB-gt 1024\fP usually ensures a noticeable performance boost; defining an even bigger \fB-gt 65536\fP ensures optimal performance while populating some table containing many hundredth thousan [...]
+When writing into transactional DBMS (SQLite/PostgreSQL,MySQL, etc...), it might be beneficial to increase the number of INSERT statements executed between BEGIN TRANSACTION and COMMIT TRANSACTION statements. This number is specified with the -gt option. For example, for SQLite, explicitly defining \fB-gt 65536\fP ensures optimal performance while populating some table containing many hundredth thousand or million rows. However, note that if there are failed insertions, the scope of -ski [...]
 .PP
 For PostgreSQL, the PG_USE_COPY config option can be set to YES for significantly insertion performance boot. See the PG driver documentation page.
 .PP
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index f3e869a..0a962f6 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,8 +1,8 @@
-.TH "ogr_utilities" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogr_utilities \- .TH "ogr_utilities" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+ogr_utilities \- .TH "ogr_utilities" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -15,5 +15,7 @@ ogr_utilities \- The following utilities are distributed as part of the OGR Simp
 \fBogr2ogr\fP - Converts simple features data between file formats 
 .IP "\(bu" 2
 \fBogrtindex\fP - Creates a tileindex 
+.IP "\(bu" 2
+\fBogrlineref\fP - Create linear reference and provide some calculations using it 
 .PP
 
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 043d3c6..0717bb1 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,8 +1,8 @@
-.TH "ogrinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrinfo \- .TH "ogrinfo" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+ogrinfo \- .TH "ogrinfo" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -14,7 +14,7 @@ ogrinfo \- lists information about an OGR supported data source
 .nf
 
 ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]
-        [-spat xmin ymin xmax ymax] [-fid fid]
+        [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
         [-sql statement] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
         [-geom={YES/NO/SUMMARY}][--formats]
         datasource_name [layer [layer ...]]
@@ -41,6 +41,8 @@ Execute the indicated SQL statement and return the result.
 SQL dialect. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL. Starting with GDAL 1.10, the 'SQLITE' dialect can also be used with any datasource. 
 .IP "\fB\fB-spat\fP \fIxmin ymin xmax ymax\fP:\fP" 1c
 The area of interest. Only features within the rectangle will be reported. 
+.IP "\fB\fB-geomfield\fP \fIfield\fP:\fP" 1c
+(OGR >= 1.11) Name of the geometry field on which the spatial filter operates on. 
 .IP "\fB\fB-fid\fP \fIfid\fP:\fP" 1c
 If provided, only the feature with this feature id will be reported. Operates exclusive of the spatial or attribute queries. Note: if you want to select several features based on their feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL. So, '-where 'fid in (1,3,5)'' would select features 1, 3 and 5. 
 .IP "\fB\fB-fields\fP={YES/NO}:\fP" 1c
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
new file mode 100644
index 0000000..a623e4b
--- /dev/null
+++ b/man/man1/ogrlineref.1
@@ -0,0 +1,110 @@
+.TH "ogrlineref" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+ogrlineref \- .TH "ogrlineref" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+ogrlineref \- The utility can be used for:
+.IP "\(bu" 2
+create linear reference file from input data
+.IP "\(bu" 2
+return the 'linear referenced' distance for the projection of the input coordinates (point) on the path
+.IP "\(bu" 2
+return the coordinates (point) on the path according to the 'linear referenced' distance
+.IP "\(bu" 2
+return the portion of the path according to the 'linear referenced' begin and end distances
+.PP
+.SH "SYNOPSIS"
+.PP
+.PP
+.PP
+.nf
+
+ogrlineref [--help-general] [-progress] [-quiet]
+           [-f format_name] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE]...]
+           [-create]
+           [-l src_line_datasource_name] [-ln layer_name] [-lf field_name]
+           [-p src_repers_datasource_name] [-pn layer_name] [-pm pos_field_name] [-pf field_name]
+           [-r src_parts_datasource_name] [-rn layer_name]
+           [-o dst_datasource_name] [-on layer_name]  [-of field_name] [-s step]
+           [-get_pos] [-x long] [-y lat]
+           [-get_coord] [-m position]
+           [-get_subline] [-mb position] [-me position]
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The ogrlineref program can be used to create a linear reference - a file containing a segments of special length (e.g. 1 km in reference units) and get coordinates, linear referenced distances or sublines (subpaths) from this file. The utility not required the M or Z values in geometry. The results can be stored in any OGR supported format. Also some information writed to the stdout.
+.PP
+.IP "\fB\fB--help-general\fP:\fP" 1c
+Show the usage. 
+.IP "\fB\fB-progress\fP:\fP" 1c
+Show progress. 
+.IP "\fB\fB-quiet\fP:\fP" 1c
+Supress all messages except errors and results. 
+.IP "\fB\fB-f\fP \fIformat_name\fP:\fP" 1c
+Select an output format name. The default is to create a shapefile. 
+.IP "\fB\fB-dsco\fP \fINAME=VALUE\fP:\fP" 1c
+Dataset creation option (format specific) 
+.IP "\fB\fB-lco\fP\fI NAME=VALUE\fP:\fP" 1c
+Layer creation option (format specific) 
+.IP "\fB\fB-create\fP:\fP" 1c
+Create the linear reference file (linestring of parts). 
+.IP "\fB\fB-l\fP\fIsrc_line_datasource_name\fP:\fP" 1c
+The path to input linestring datasource (e.g. the road) 
+.IP "\fB\fB-ln\fP\fIlayer_name\fP:\fP" 1c
+The layer name in datasource 
+.IP "\fB\fB-lf\fP\fIfield_name\fP:\fP" 1c
+The field name of uniq values to separate the input lines (e.g. the set of roads) 
+.IP "\fB\fB-p\fP\fIsrc_repers_datasource_name\fP:\fP" 1c
+The path to linear references points (e.g. the road mile-stones) 
+.IP "\fB\fB-pn\fP\fIlayer_name\fP:\fP" 1c
+The layer name in datasource 
+.IP "\fB\fB-pm\fP\fIpos_field_name\fP:\fP" 1c
+The field name of distances along path (e.g. mile-stones values) 
+.IP "\fB\fB-pf\fP\fIfield_name\fP:\fP" 1c
+The field name of uniq values to map input reference points to lines 
+.IP "\fB\fB-r\fP\fIsrc_parts_datasource_name\fP:\fP" 1c
+The path to linear reference file 
+.IP "\fB\fB-rn\fP\fIlayer_name\fP:\fP" 1c
+The layer name in datasource 
+.IP "\fB\fB-o\fP\fIdst_datasource_name\fP:\fP" 1c
+The path to output linear reference file (linestring datasource) 
+.IP "\fB\fB-on\fP\fIlayer_name\fP:\fP" 1c
+The layer name in datasource 
+.IP "\fB\fB-of\fP\fIfield_name\fP:\fP" 1c
+The field name for storing the uniq values of input lines 
+.IP "\fB\fB-s\fP\fIstep\fP:\fP" 1c
+The part size in linear units 
+.IP "\fB\fB-get_pos\fP:\fP" 1c
+Return linear referenced postion for input X, Y 
+.IP "\fB\fB-x\fP\fIlong\fP:\fP" 1c
+Input X coordinate 
+.IP "\fB\fB-y\fP\fIlat\fP:\fP" 1c
+Input Y coordinate 
+.IP "\fB\fB-get_coord\fP:\fP" 1c
+Return point on path for input linear distance 
+.IP "\fB\fB-m\fP\fIposition\fP:\fP" 1c
+The input linear distance 
+.IP "\fB\fB-get_subline\fP:\fP" 1c
+Return the portion of the input path from and to input linear positions 
+.IP "\fB\fB-mb\fP\fIposition\fP:\fP" 1c
+The input begin linear distance 
+.IP "\fB\fB-me\fP\fIposition\fP:\fP" 1c
+The input end linear distance 
+.PP
+.SH "EXAMPLE"
+.PP
+This example would create a shapefile (parts.shp) containing a data needed for linear referencing (1 km parts): 
+.PP
+.nf
+
+% ogrlineref -create -l roads.shp -p references.shp -pm dist -o parts.shp -s 1000 -progress
+
+.fi
+.PP
+.SH "AUTHORS"
+.PP
+Dmitry Baryshnikov <polimax at mail.ru> 
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index e474036..e5e3196 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,8 +1,8 @@
-.TH "ogrtindex" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrtindex \- .TH "ogrtindex" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+ogrtindex \- .TH "ogrtindex" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index 78b002d..ce45733 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,8 +1,8 @@
-.TH "pct2rgb" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-pct2rgb \- .TH "pct2rgb" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+pct2rgb \- .TH "pct2rgb" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 6b0c75b..a1cfd4d 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,8 +1,8 @@
-.TH "rgb2pct" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-rgb2pct \- .TH "rgb2pct" 1 "Mon Aug 26 2013" "GDAL" \" -*- nroff -*-
+rgb2pct \- .TH "rgb2pct" 1 "Wed Apr 16 2014" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/mkgdaldist.sh b/mkgdaldist.sh
index 4a49278..0b89004 100755
--- a/mkgdaldist.sh
+++ b/mkgdaldist.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $Id: mkgdaldist.sh 24265 2012-04-20 03:55:40Z warmerdam $
+# $Id: mkgdaldist.sh 25966 2013-04-29 20:33:17Z nowakpl $
 #
 # mkgdaldist.sh - prepares GDAL source distribution package
 #
@@ -138,6 +138,7 @@ mv gdal gdal-${GDAL_VERSION}
 rm -f ../gdal-${GDAL_VERSION}${RC}.tar.gz ../gdal${COMPRESSED_VERSION}${RC}.zip
 
 tar cf ../gdal-${GDAL_VERSION}${RC}.tar gdal-${GDAL_VERSION}
+xz -k9e ../gdal-${GDAL_VERSION}${RC}.tar
 gzip -9 ../gdal-${GDAL_VERSION}${RC}.tar
 zip -qr ../gdal${COMPRESSED_VERSION}${RC}.zip gdal-${GDAL_VERSION}
 
@@ -150,11 +151,12 @@ else
 MD5=md5sum
 fi
 
-$MD5 ../gdal-${GDAL_VERSION}${RC}.tar.gz > ../gdal-${GDAL_VERSION}${RC}.tar.gz.md5
-$MD5 ../gdal${COMPRESSED_VERSION}${RC}.zip > ../gdal${COMPRESSED_VERSION}${RC}.zip.md5
+cd ..
+$MD5 gdal-${GDAL_VERSION}${RC}.tar.xz > gdal-${GDAL_VERSION}${RC}.tar.xz.md5
+$MD5 gdal-${GDAL_VERSION}${RC}.tar.gz > gdal-${GDAL_VERSION}${RC}.tar.gz.md5
+$MD5 gdal${COMPRESSED_VERSION}${RC}.zip > gdal${COMPRESSED_VERSION}${RC}.zip.md5
 
 echo "* Cleaning..."
-cd ..
 rm -rf dist_wrk
 
 echo "*** The End ***"
diff --git a/nmake.opt b/nmake.opt
index 9317853..936cfcc 100644
--- a/nmake.opt
+++ b/nmake.opt
@@ -1,4 +1,4 @@
-# $Id: nmake.opt 25907 2013-04-13 21:19:24Z rouault $
+# $Id: nmake.opt 27143 2014-04-09 12:35:26Z rouault $
 #
 # nmake.opt - main configuration file for NMAKE makefiles.
 #
@@ -7,6 +7,12 @@
 # nmake -f makefile.vc MSVC_VER=1400
 # nmake -f makefile.vc MSVC_VER=1500 DEBUG=1
 # nmake -f makefile.vc MSVC_VER=1600 DEBUG=1 ANALYZE=1
+# nmake -f makefile.vc MSVC_VER=1600 DEBUG=1 ANALYZE=1 WITH_PDB=1
+#
+# Options:
+#    DEBUG - set to disable optimizations and link with debug runtimes; also implies WITH_PDB.
+#  ANALYZE - set to enable code analysis output.
+# WITH_PDB - set to enable output of PDB files, supported for both debug and release modes.
 #
 ###############################################################################
 # For convenience, user may put custom settings in a local settings file
@@ -25,6 +31,7 @@
 # Check version of Visual C++ compiler:
 # nmake -f makefile.vc MSVC_VER=xxxx
 # where xxxx is one of following:
+# 1800 = 12.0(2013)
 # 1700 = 11.0(2012)
 # 1600 = 10.0(2010)
 # 1500 = 9.0 (2008)
@@ -106,18 +113,29 @@ CXX_ANALYZE_FLAGS=/analyze
 CXX_ANALYZE_FLAGS=
 !ENDIF
 
+# Force PDB output for DEBUG mode
+!IFDEF DEBUG
+WITH_PDB=1
+!ENDIF
+
+!IFDEF WITH_PDB
+CXX_PDB_FLAGS=/Zi /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb
+!ELSE
+CXX_PDB_FLAGS=
+!ENDIF
+
 !IFNDEF OPTFLAGS
 !IF $(MSVC_VER) >= 1400
 !IFNDEF DEBUG
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) /nologo /MD /EHsc /Ox /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /Ox /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
 !ELSE
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) /nologo /MD /EHsc /Zi /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb /DDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DDEBUG
 !ENDIF
 !ELSE
 !IFNDEF DEBUG
-OPTFLAGS=	/nologo /MD /EHsc /GR /Ox /DNDEBUG
+OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /Ox /DNDEBUG
 !ELSE
-OPTFLAGS=	/nologo /MD /EHsc /GR /Zi /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb  /DDEBUG
+OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /DDEBUG
 !ENDIF
 !ENDIF  #MSVC_VER
 !ENDIF  # OPTFLAGS
@@ -159,7 +177,7 @@ STDCALL=YES
 
 # Version number embedded in DLL name. 
 !IFNDEF VERSION
-VERSION =	110
+VERSION =	111
 !ENDIF
 
 # Comment the following out if you want PAM supported disabled
@@ -393,6 +411,8 @@ INGRES_LIB = "$(INGRES_HOME)\lib\iilibapi.lib" \
 #SQLITE_LIB=C:\osgeo4w\lib\spatialite_i.lib
 # Uncomment following line if libsqlite3 has been compiled with SQLITE_HAS_COLUMN_METADATA=yes
 #SQLITE_HAS_COLUMN_METADATA=yes
+# Uncomment following line if spatialite is 4.1.2 or later
+#SPATIALITE_412_OR_LATER=yes
 
 # PCRE Library (REGEXP support for SQLite) for example from http://sourceforge.net/projects/gnuwin32/files/pcre/7.0/pcre-7.0.exe/download
 #PCRE_INC=-I"C:\Program Files\GNUWin32\include" -DHAVE_PCRE
@@ -488,12 +508,13 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 # Uncomment for libdap >= 3.9
 #DODS_FLAGS = -DLIBDAP_39
 
-# Uncomment for GEOS support
+# Uncomment for GEOS support (GEOS >= 3.1.0 required)
 #GEOS_DIR=C:/warmerda/geos
 #GEOS_CFLAGS = -I$(GEOS_DIR)/capi -I$(GEOS_DIR)/source/headers -DHAVE_GEOS
 #GEOS_LIB     = $(GEOS_DIR)/source/geos_c_i.lib
 
 # Uncomment for SOSI support
+#SOSI_PLUGIN = YES
 #SOSI_ENABLED = YES
 #SOSI_INC_DIR = e:/sosi
 #SOSI_LIBS = e:/sosi/FYBA.lib e:/sosi/GM.lib e:/sosi/UT.lib
diff --git a/ogr/GNUmakefile b/ogr/GNUmakefile
index fa7639a..4c904e0 100644
--- a/ogr/GNUmakefile
+++ b/ogr/GNUmakefile
@@ -96,3 +96,5 @@ parser:
 	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < swq_parser.cpp > swq_parser.cpp.tmp
 	mv swq_parser.cpp.tmp swq_parser.cpp
 
+osr_cs_wkt_parser:
+	bison --no-lines -p osr_cs_wkt_ -d -oosr_cs_wkt_parser.c osr_cs_wkt_grammar.y
diff --git a/ogr/file.lst b/ogr/file.lst
index 5f72311..52b5cd4 100644
--- a/ogr/file.lst
+++ b/ogr/file.lst
@@ -44,5 +44,7 @@ OBJ =	ogrgeometryfactory.o \
 	ogr_expat.o \
 	ogrpgeogeometry.o \
 	ogrgeomediageometry.o \
-	ogr_geocoding.o
-	
+	ogr_geocoding.o \
+    osr_cs_wkt.o \
+	osr_cs_wkt_parser.o \
+    ogrgeomfielddefn.o
diff --git a/ogr/generate_encoding_table.c b/ogr/generate_encoding_table.c
index 2a51d62..8c8b092 100644
--- a/ogr/generate_encoding_table.c
+++ b/ogr/generate_encoding_table.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: generate_encoding_table.c 24982 2012-09-26 19:41:33Z rouault $
+ * $Id: generate_encoding_table.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR
  * Purpose:  Generate a mapping table from a 1-byte encoding to unicode,
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp
index 2d92605..9edabcb 100644
--- a/ogr/gml2ogrgeometry.cpp
+++ b/ogr/gml2ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gml2ogrgeometry.cpp 25552 2013-01-26 11:45:41Z rouault $
+ * $Id: gml2ogrgeometry.cpp 27135 2014-04-06 09:58:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Code to translate between GML and OGR geometry forms.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -261,11 +262,47 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
 
 /* -------------------------------------------------------------------- */
 /*      Handle <coordinates> case.                                      */
+/*      Note that we don't do a strict validation, so we accept and     */
+/*      sometimes generate output whereas we should just reject it.     */
 /* -------------------------------------------------------------------- */
     if( psCoordinates != NULL )
     {
         const char *pszCoordString = GetElementText( psCoordinates );
+
+        const char *pszDecimal = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "decimal", NULL);
+        char chDecimal = '.';
+        if( pszDecimal != NULL )
+        {
+            if( strlen(pszDecimal) != 1 || (pszDecimal[0] >= '0' && pszDecimal[0] <= '9') )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for decimal attribute");
+                return FALSE;
+            }
+            chDecimal = pszDecimal[0];
+        }
+
+        const char *pszCS = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "cs", NULL);
         char chCS = ',';
+        if( pszCS != NULL )
+        {
+            if( strlen(pszCS) != 1 || (pszCS[0] >= '0' && pszCS[0] <= '9') )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for cs attribute");
+                return FALSE;
+            }
+            chCS = pszCS[0];
+        }
+        const char *pszTS = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "ts", NULL);
+        char chTS = ' ';
+        if( pszTS != NULL )
+        {
+            if( strlen(pszTS) != 1 || (pszTS[0] >= '0' && pszTS[0] <= '9') )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for tes attribute");
+                return FALSE;
+            }
+            chTS = pszTS[0];
+        }
 
         if( pszCoordString == NULL )
         {
@@ -279,9 +316,12 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             int nDimension = 2;
 
             // parse out 2 or 3 tuple. 
-            dfX = OGRFastAtof( pszCoordString );
+            if( chDecimal == '.' )
+                dfX = OGRFastAtof( pszCoordString );
+            else
+                dfX = CPLAtofDelim( pszCoordString, chDecimal) ;
             while( *pszCoordString != '\0'
-                   && *pszCoordString != ','
+                   && *pszCoordString != chCS
                    && !isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
 
@@ -291,7 +331,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                         "Corrupt <coordinates> value." );
                 return FALSE;
             }
-            else if( chCS == ',' && isspace((unsigned char)*pszCoordString) )
+            else if( chCS == ',' && pszCS == NULL && isspace((unsigned char)*pszCoordString) )
             {
                 /* In theory, the coordinates inside a coordinate tuple should be */
                 /* separated by a comma. However it has been found in the wild */
@@ -299,27 +339,36 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 /* See https://52north.org/twiki/bin/view/Processing/WPS-IDWExtension-ObservationCollectionExample */
                 /* or http://agisdemo.faa.gov/aixmServices/getAllFeaturesByLocatorId?locatorId=DFW */
                 chCS = ' ';
+                chTS = ',';
             }
 
             pszCoordString++;
-            dfY = OGRFastAtof( pszCoordString );
+            if( chDecimal == '.' )
+                dfY = OGRFastAtof( pszCoordString );
+            else
+                dfY = CPLAtofDelim( pszCoordString, chDecimal) ;
             while( *pszCoordString != '\0' 
-                   && *pszCoordString != ','
+                   && *pszCoordString != chCS
+                   && *pszCoordString != chTS
                    && !isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
 
             if( *pszCoordString == chCS )
             {
                 pszCoordString++;
-                dfZ = OGRFastAtof( pszCoordString );
+                if( chDecimal == '.' )
+                    dfZ = OGRFastAtof( pszCoordString );
+                else
+                    dfZ = CPLAtofDelim( pszCoordString, chDecimal) ;
                 nDimension = 3;
                 while( *pszCoordString != '\0' 
-                       && *pszCoordString != ','
+                       && *pszCoordString != chCS
+                       && *pszCoordString != chTS
                        && !isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
             }
 
-            if ( chCS == ' ' && *pszCoordString == ',' )
+            if( *pszCoordString == chTS )
             {
                 pszCoordString++;
             }
@@ -625,6 +674,13 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                                       int bFaceHoleNegative ) 
 
 {
+    if( psNode != NULL && strcmp(psNode->pszValue, "?xml") == 0 )
+        psNode = psNode->psNext;
+    while( psNode != NULL && psNode->eType == CXT_Comment )
+        psNode = psNode->psNext;
+    if( psNode == NULL )
+        return NULL;
+
     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
     if (bGetSecondaryGeometryOption < 0)
         bGetSecondaryGeometryOption = CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
@@ -761,22 +817,29 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
             {
                 const CPLXMLNode* psCurveChild = GetChildElement(psChild);
-                OGRLineString *poLS;
+                OGRGeometry* poGeom;
                 if (psCurveChild != NULL)
-                    poLS = (OGRLineString *) 
+                    poGeom =
                         GML2OGRGeometry_XMLNode( psCurveChild, bGetSecondaryGeometryOption,
                                                  nRecLevel + 1);
                 else
-                    poLS = NULL;
+                    poGeom = NULL;
 
-                if( poLS == NULL 
-                    || wkbFlatten(poLS->getGeometryType()) != wkbLineString )
+                // try to join multiline string to one linestring
+                if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
                 {
-                    delete poLS;
+                    poGeom = OGRGeometryFactory::forceToLineString( poGeom, false );
+                }
+
+                if( poGeom == NULL 
+                    || wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
+                {
+                    delete poGeom;
                     delete poLinearRing;
                     return NULL;
                 }
 
+                OGRLineString *poLS = (OGRLineString *) poGeom;
                 if( poLS->getNumPoints() < 2 )
                 {
                     // skip it
@@ -1057,6 +1120,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
     {
         const CPLXMLNode *psChild;
         OGRMultiPolygon *poMPoly = new OGRMultiPolygon();
+        int bReconstructTopology = FALSE;
 
         // Iterate over children
         for( psChild = psNode->psChild; 
@@ -1071,31 +1135,81 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 OGRPolygon *poPolygon;
 
                 if (psSurfaceChild != NULL)
-                    poPolygon = (OGRPolygon *) 
-                        GML2OGRGeometry_XMLNode( psSurfaceChild, bGetSecondaryGeometryOption,
-                                                 nRecLevel + 1);
-                else
-                    poPolygon = NULL;
-
-                if( poPolygon == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
-                              BareGMLElement(psChild->pszValue));
-                    delete poMPoly;
-                    return NULL;
-                }
+                    /* Cf #5421 where there are PolygonPatch with only inner rings */
+                    const CPLXMLNode* psPolygonPatch = GetChildElement(GetChildElement(psSurfaceChild));
+                    if( psPolygonPatch != NULL &&
+                        psPolygonPatch->eType == CXT_Element &&
+                        EQUAL(BareGMLElement(psPolygonPatch->pszValue),"PolygonPatch") &&
+                        GetChildElement(psPolygonPatch) != NULL &&
+                        EQUAL(BareGMLElement(GetChildElement(psPolygonPatch)->pszValue),"interior") )
+                    {
+                        // Find all inner rings 
+                        for( const CPLXMLNode* psChild2 = psPolygonPatch->psChild; 
+                            psChild2 != NULL;
+                            psChild2 = psChild2->psNext ) 
+                        {
+                            if( psChild2->eType == CXT_Element
+                                && (EQUAL(BareGMLElement(psChild2->pszValue),"interior")))
+                            {
+                                const CPLXMLNode* psInteriorChild = GetChildElement(psChild2);
+                                OGRLinearRing* poRing;
+                                if (psInteriorChild != NULL)
+                                    poRing = (OGRLinearRing *) 
+                                        GML2OGRGeometry_XMLNode( psInteriorChild, bGetSecondaryGeometryOption,
+                                                                nRecLevel + 1);
+                                else
+                                    poRing = NULL;
+                                if (poRing == NULL)
+                                {
+                                    CPLError( CE_Failure, CPLE_AppDefined, "Invalid interior ring");
+                                    delete poMPoly;
+                                    return NULL;
+                                }
+                                if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
+                                {
+                                    CPLError( CE_Failure, CPLE_AppDefined, 
+                                            "%s: Got %.500s geometry as innerBoundaryIs instead of LINEARRING.",
+                                            pszBaseGeometry, poRing->getGeometryName() );
+                                    delete poRing;
+                                    delete poMPoly;
+                                    return NULL;
+                                }
+
+                                bReconstructTopology = TRUE;
+                                poPolygon = new OGRPolygon();
+                                poPolygon->addRingDirectly( poRing );
+                                poMPoly->addGeometryDirectly( poPolygon );
+                            }
+                        }
+                    }
+                    else
+                    {
+                        poPolygon = (OGRPolygon *) 
+                            GML2OGRGeometry_XMLNode( psSurfaceChild, bGetSecondaryGeometryOption,
+                                                     nRecLevel + 1);
 
-                if( !EQUAL(poPolygon->getGeometryName(),"POLYGON") )
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Got %.500s geometry as polygonMember instead of MULTIPOLYGON.",
-                              poPolygon->getGeometryName() );
-                    delete poPolygon;
-                    delete poMPoly;
-                    return NULL;
-                }
+                        if( poPolygon == NULL )
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
+                                    BareGMLElement(psChild->pszValue));
+                            delete poMPoly;
+                            return NULL;
+                        }
 
-                poMPoly->addGeometryDirectly( poPolygon );
+                        if( !EQUAL(poPolygon->getGeometryName(),"POLYGON") )
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined, 
+                                    "Got %.500s geometry as polygonMember instead of MULTIPOLYGON.",
+                                    poPolygon->getGeometryName() );
+                            delete poPolygon;
+                            delete poMPoly;
+                            return NULL;
+                        }
+
+                        poMPoly->addGeometryDirectly( poPolygon );
+                    }
+                }
             }
             else if (psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"surfaceMembers") )
@@ -1108,7 +1222,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     if( psChild2->eType == CXT_Element
                         && (EQUAL(BareGMLElement(psChild2->pszValue),"Surface") ||
                             EQUAL(BareGMLElement(psChild2->pszValue),"Polygon") ||
-                            EQUAL(BareGMLElement(psChild2->pszValue),"PolygonPatch")) )
+                            EQUAL(BareGMLElement(psChild2->pszValue),"PolygonPatch") ||
+                            EQUAL(BareGMLElement(psChild2->pszValue),"CompositeSurface")) )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2, bGetSecondaryGeometryOption,
                                                                        nRecLevel + 1);
@@ -1148,7 +1263,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             }
         }
 
-        return poMPoly;
+        if( bReconstructTopology )
+        {
+            int nPolygonCount = poMPoly->getNumGeometries();
+            OGRGeometry** papoPolygons = new OGRGeometry*[ nPolygonCount ];
+            for(int i=0;i<nPolygonCount;i++)
+            {
+                papoPolygons[i] = poMPoly->getGeometryRef(0);
+                poMPoly->removeGeometry(0, FALSE);
+            }
+            delete poMPoly;
+            int bResultValidGeometry = FALSE;
+            OGRGeometry* poRet = OGRGeometryFactory::organizePolygons(
+                papoPolygons, nPolygonCount, &bResultValidGeometry );
+            delete[] papoPolygons;
+            return poRet;
+        }
+        else
+            return poMPoly;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1171,23 +1303,23 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 OGRPoint *poPoint;
 
                 if (psPointChild != NULL)
+                {
                     poPoint = (OGRPoint *) 
                         GML2OGRGeometry_XMLNode( psPointChild, bGetSecondaryGeometryOption,
                                                  nRecLevel + 1);
-                else
-                    poPoint = NULL;
-                if( poPoint == NULL 
-                    || wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "MultiPoint: Got %.500s geometry as pointMember instead of POINT",
-                              poPoint ? poPoint->getGeometryName() : "NULL" );
-                    delete poPoint;
-                    delete poMP;
-                    return NULL;
-                }
+                    if( poPoint == NULL 
+                        || wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                "MultiPoint: Got %.500s geometry as pointMember instead of POINT",
+                                poPoint ? poPoint->getGeometryName() : "NULL" );
+                        delete poPoint;
+                        delete poMP;
+                        return NULL;
+                    }
 
-                poMP->addGeometryDirectly( poPoint );
+                    poMP->addGeometryDirectly( poPoint );
+                }
             }
             else if (psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"pointMembers") )
@@ -1300,25 +1432,31 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     psCurve = FindBareXMLChild( psChild, "LineString" );
                 if( psCurve == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Failed to get curve element in curveMember" );
-                    delete poMLS;
-                    return NULL;
+                    if( GetChildElement(psChild) != NULL )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                "Failed to get curve element in curveMember" );
+                        delete poMLS;
+                        return NULL;
+                    }
                 }
-                poGeom = GML2OGRGeometry_XMLNode( psCurve, bGetSecondaryGeometryOption,
-                                                  nRecLevel + 1);
-                if( poGeom == NULL ||
-                    ( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) )
+                else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "MultiCurve: Got %.500s geometry as Member instead of LINESTRING.",
-                              poGeom ? poGeom->getGeometryName() : "NULL" );
-                    if( poGeom != NULL ) delete poGeom;
-                    delete poMLS;
-                    return NULL;
-                }
+                    poGeom = GML2OGRGeometry_XMLNode( psCurve, bGetSecondaryGeometryOption,
+                                                    nRecLevel + 1);
+                    if( poGeom == NULL ||
+                        ( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                "MultiCurve: Got %.500s geometry as Member instead of LINESTRING.",
+                                poGeom ? poGeom->getGeometryName() : "NULL" );
+                        if( poGeom != NULL ) delete poGeom;
+                        delete poMLS;
+                        return NULL;
+                    }
 
-                poMLS->addGeometryDirectly( (OGRLineString *)poGeom );
+                    poMLS->addGeometryDirectly( (OGRLineString *)poGeom );
+                }
             }
             else if (psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMembers") )
@@ -1426,10 +1564,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     delete poLS;
                     return NULL;
                 }
-                if( poGeom != NULL )
+                OGRLineString *poAddLS = (OGRLineString *)poGeom;
+                if( poAddLS != NULL && poAddLS->getNumPoints() >= 2 )
                 {
-                    OGRLineString *poAddLS = (OGRLineString *)poGeom;
-                    if( poLS->getNumPoints() > 0 && poAddLS->getNumPoints() > 0
+                    if( poLS->getNumPoints() > 0
                         && fabs(poLS->getX(poLS->getNumPoints()-1)
                                 - poAddLS->getX(0)) < 1e-14
                         && fabs(poLS->getY(poLS->getNumPoints()-1)
@@ -1446,8 +1584,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                         // Add the whole new line string
                         poLS->addSubLineString( poAddLS );
                     }
-                    delete poGeom;
                 }
+                delete poGeom;
             }
         }
 
@@ -1478,20 +1616,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 OGRGeometry *poGeom;
 
                 if (psGeometryChild != NULL)
+                {
                     poGeom = GML2OGRGeometry_XMLNode( psGeometryChild, bGetSecondaryGeometryOption,
                                                       nRecLevel + 1 );
-                else
-                    poGeom = NULL;
-                if( poGeom == NULL )
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "GeometryCollection: Failed to get geometry in geometryMember" );
-                    delete poGeom;
-                    delete poGC;
-                    return NULL;
-                }
+                    if( poGeom == NULL )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                "GeometryCollection: Failed to get geometry in geometryMember" );
+                        delete poGeom;
+                        delete poGC;
+                        return NULL;
+                    }
 
-                poGC->addGeometryDirectly( poGeom );
+                    poGC->addGeometryDirectly( poGeom );
+                }
             }
         }
 
@@ -2000,13 +2138,58 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                   return NULL;
                 }
 
+                OGRLineString *poLS;
+                OGRLineString *poAddLS;
                 if( !bFaceOrientation )
                 {
-                  if( poFaceGeom->getNumPoints() > 0 )
-                    ((OGRLinearRing *)poEdgeGeom)->addSubLineString( (OGRLineString *)poFaceGeom );
+                  poLS = (OGRLineString *)poEdgeGeom;
+                  poAddLS = (OGRLineString *)poFaceGeom;
+                  if( poAddLS->getNumPoints() < 2 )
+                  {
+                      /* skip it */
+                  }
+                  else if( poLS->getNumPoints() > 0
+                      && fabs(poLS->getX(poLS->getNumPoints()-1)
+                              - poAddLS->getX(0)) < 1e-14
+                      && fabs(poLS->getY(poLS->getNumPoints()-1)
+                              - poAddLS->getY(0)) < 1e-14
+                      && fabs(poLS->getZ(poLS->getNumPoints()-1)
+                              - poAddLS->getZ(0)) < 1e-14) 
+                  {
+                      // Skip the first point of the new linestring to avoid
+                      // invalidate duplicate points
+                      poLS->addSubLineString( poAddLS, 1 );
+                  }
+                  else
+                  {
+                      // Add the whole new line string
+                      poLS->addSubLineString( poAddLS );
+                  }
                   poFaceGeom->empty();
                 }
-                poFaceGeom->addSubLineString( (OGRLinearRing *)poEdgeGeom );
+                poLS = (OGRLineString *)poFaceGeom;
+                poAddLS = (OGRLineString *)poEdgeGeom;
+                if( poAddLS->getNumPoints() < 2 )
+                {
+                    /* skip it */
+                }
+                else if( poLS->getNumPoints() > 0
+                    && fabs(poLS->getX(poLS->getNumPoints()-1)
+                            - poAddLS->getX(0)) < 1e-14
+                    && fabs(poLS->getY(poLS->getNumPoints()-1)
+                            - poAddLS->getY(0)) < 1e-14
+                    && fabs(poLS->getZ(poLS->getNumPoints()-1)
+                            - poAddLS->getZ(0)) < 1e-14) 
+                {
+                    // Skip the first point of the new linestring to avoid
+                    // invalidate duplicate points
+                    poLS->addSubLineString( poAddLS, 1 );
+                }
+                else
+                {
+                    // Add the whole new line string
+                    poLS->addSubLineString( poAddLS );
+                }
                 delete poEdgeGeom;
               }
             }
diff --git a/ogr/makefile.vc b/ogr/makefile.vc
index 1e5eb46..451fbc4 100644
--- a/ogr/makefile.vc
+++ b/ogr/makefile.vc
@@ -31,7 +31,8 @@ OBJ_OGR	=	ogrgeometryfactory.obj ogrpoint.obj ogrcurve.obj ogr_api.obj \
 		ogr_srs_ozi.obj ogr_srs_erm.obj ogr_expat.obj \
 		swq.obj swq_parser.obj swq_select.obj swq_op_registrar.obj \
 		swq_op_general.obj swq_expr_node.obj ogrpgeogeometry.obj \
-		ogrgeomediageometry.obj ogr_geocoding.obj
+		ogrgeomediageometry.obj ogr_geocoding.obj osr_cs_wkt.obj \
+		osr_cs_wkt_parser.obj ogrgeomfielddefn.obj
 
 default:        ogr.lib 
 
diff --git a/ogr/ogr2gmlgeometry.cpp b/ogr/ogr2gmlgeometry.cpp
index c9e1151..cff0cdf 100644
--- a/ogr/ogr2gmlgeometry.cpp
+++ b/ogr/ogr2gmlgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2gmlgeometry.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: ogr2gmlgeometry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Translator
  * Purpose:  Code to translate OGRGeometry to GML string representation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogr_api.cpp b/ogr/ogr_api.cpp
index 1e0fd8e..261ef32 100644
--- a/ogr/ogr_api.cpp
+++ b/ogr/ogr_api.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.cpp 22416 2011-05-22 20:19:45Z rouault $
+ * $Id: ogr_api.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API Functions that don't correspond one-to-one with C++ 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -69,6 +70,38 @@ int OGR_G_GetPointCount( OGRGeometryH hGeom )
 }
 
 /************************************************************************/
+/*                        OGR_G_SetPointCount()                         */
+/************************************************************************/
+/**
+ * \brief Set number of points in a geometry.
+ *
+ * This method primary exists to preset the number of points in a linestring
+ * geometry before setPoint() is used to assign them to avoid reallocating
+ * the array larger with each call to addPoint(). 
+ *
+ * @param nNewPointCount the new number of points for geometry.
+ */
+
+void OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetPointCount" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbLineString:
+      {
+        OGRLineString *poLine = (OGRLineString *) hGeom;
+        poLine->setNumPoints( nNewPointCount );
+        break;
+      }
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
 /*                             OGR_G_GetX()                             */
 /************************************************************************/
 /**
@@ -333,6 +366,73 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
 /*                           OGR_G_SetPoint()                           */
 /************************************************************************/
 /**
+ * \brief Assign all points in a point or a line string geometry.
+ *
+ * This method clear any existing points assigned to this geometry,
+ * and assigns a whole new set.
+ *
+ * @param hGeom handle to the geometry to set the coordinates.
+ * @param nPointsIn number of points being passed in padfX and padfY.
+ * @param padfX list of X coordinates of points being assigned.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param padfY list of Y coordinates of points being assigned.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param padfZ list of Z coordinates of points being assigned (defaults to NULL for 2D objects).
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ */
+
+void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
+                              void* pabyX, int nXStride,
+                              void* pabyY, int nYStride,
+                              void* pabyZ, int nZStride )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetPoints" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+        ((OGRPoint *) hGeom)->setX( pabyX ? *( (double *)pabyX ) : 0.0 );
+        ((OGRPoint *) hGeom)->setY( pabyY ? *( (double *)pabyY ) : 0.0 );
+        ((OGRPoint *) hGeom)->setZ( pabyZ ? *( (double *)pabyZ ) : 0.0 );
+        break;
+      }
+      case wkbLineString:
+      {
+        OGRLineString* poLine = (OGRLineString *) hGeom;
+
+        if( nXStride == 0 && nYStride == 0 && nZStride == 0 )
+        {
+          poLine->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ ); 
+        }
+        else
+        {
+          double x, y, z;		  
+          x = y = z = 0;
+          poLine->setNumPoints( nPointsIn );
+
+          for (int i = 0; i < nPointsIn; ++i)
+          {
+            if( pabyX ) x = *(double*)((char*)pabyX + i * nXStride);
+            if( pabyY ) y = *(double*)((char*)pabyY + i * nYStride);
+            if( pabyZ ) z = *(double*)((char*)pabyZ + i * nZStride);
+
+            poLine->setPoint( i, x, y, z );
+          }
+        }
+        break;
+      }
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_SetPoint()                           */
+/************************************************************************/
+/**
  * \brief Set the location of a vertex in a point or linestring geometry.
  *
  * If iPoint is larger than the number of existing
diff --git a/ogr/ogr_api.h b/ogr/ogr_api.h
index e5bc762..7067acc 100644
--- a/ogr/ogr_api.h
+++ b/ogr/ogr_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.h 25545 2013-01-25 17:55:47Z warmerdam $
+ * $Id: ogr_api.h 27071 2014-03-21 21:52:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API for OGR Geometry, Feature, Layers, DataSource and drivers.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -189,12 +190,17 @@ double CPL_DLL OGR_G_GetY( OGRGeometryH, int );
 double CPL_DLL OGR_G_GetZ( OGRGeometryH, int );
 void   CPL_DLL OGR_G_GetPoint( OGRGeometryH, int iPoint, 
                                double *, double *, double * );
+void   CPL_DLL OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount );
 void   CPL_DLL OGR_G_SetPoint( OGRGeometryH, int iPoint, 
                                double, double, double );
 void   CPL_DLL OGR_G_SetPoint_2D( OGRGeometryH, int iPoint, 
                                   double, double );
 void   CPL_DLL OGR_G_AddPoint( OGRGeometryH, double, double, double );
 void   CPL_DLL OGR_G_AddPoint_2D( OGRGeometryH, double, double );
+void   CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
+                                void* pabyX, int nXStride,
+                                void* pabyY, int nYStride,
+                                void* pabyZ, int nZStride );
 
 /* Methods for getting/setting rings and members collections */
 
@@ -230,6 +236,7 @@ typedef void *OGRFeatureDefnH;
 typedef void *OGRFeatureH;
 typedef void *OGRStyleTableH;
 #endif
+typedef struct OGRGeomFieldDefnHS *OGRGeomFieldDefnH;
 
 /* OGRFieldDefn */
 
@@ -253,6 +260,24 @@ void   CPL_DLL OGR_Fld_SetIgnored( OGRFieldDefnH hDefn, int );
 
 const char CPL_DLL *OGR_GetFieldTypeName( OGRFieldType );
 
+/* OGRGeomFieldDefnH */
+
+OGRGeomFieldDefnH    CPL_DLL OGR_GFld_Create( const char *, OGRwkbGeometryType ) CPL_WARN_UNUSED_RESULT;
+void                 CPL_DLL OGR_GFld_Destroy( OGRGeomFieldDefnH );
+
+void                 CPL_DLL OGR_GFld_SetName( OGRGeomFieldDefnH, const char * );
+const char           CPL_DLL *OGR_GFld_GetNameRef( OGRGeomFieldDefnH );
+
+OGRwkbGeometryType   CPL_DLL OGR_GFld_GetType( OGRGeomFieldDefnH );
+void                 CPL_DLL OGR_GFld_SetType( OGRGeomFieldDefnH, OGRwkbGeometryType );
+
+OGRSpatialReferenceH CPL_DLL OGR_GFld_GetSpatialRef( OGRGeomFieldDefnH );
+void                 CPL_DLL OGR_GFld_SetSpatialRef( OGRGeomFieldDefnH,
+                                                     OGRSpatialReferenceH hSRS );
+
+int                  CPL_DLL OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn );
+void                 CPL_DLL OGR_GFld_SetIgnored( OGRGeomFieldDefnH hDefn, int );
+
 /* OGRFeatureDefn */
 
 OGRFeatureDefnH CPL_DLL OGR_FD_Create( const char * ) CPL_WARN_UNUSED_RESULT;
@@ -275,6 +300,18 @@ int    CPL_DLL OGR_FD_Reference( OGRFeatureDefnH );
 int    CPL_DLL OGR_FD_Dereference( OGRFeatureDefnH );
 int    CPL_DLL OGR_FD_GetReferenceCount( OGRFeatureDefnH );
 
+int               CPL_DLL OGR_FD_GetGeomFieldCount( OGRFeatureDefnH hFDefn );
+OGRGeomFieldDefnH CPL_DLL OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hFDefn,
+                                                   int i );
+int               CPL_DLL OGR_FD_GetGeomFieldIndex( OGRFeatureDefnH hFDefn,
+                                                    const char *pszName);
+
+void              CPL_DLL OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hFDefn,
+                                                   OGRGeomFieldDefnH hGFldDefn);
+OGRErr            CPL_DLL OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hFDefn,
+                                                      int iGeomField );
+int               CPL_DLL OGR_FD_IsSame( OGRFeatureDefnH hFDefn,
+                                         OGRFeatureDefnH hOtherFDefn );
 /* OGRFeature */
 
 OGRFeatureH CPL_DLL OGR_F_Create( OGRFeatureDefnH ) CPL_WARN_UNUSED_RESULT;
@@ -317,6 +354,20 @@ void   CPL_DLL OGR_F_SetFieldBinary( OGRFeatureH, int, int, GByte * );
 void   CPL_DLL OGR_F_SetFieldDateTime( OGRFeatureH, int, 
                                        int, int, int, int, int, int, int );
 
+int               CPL_DLL OGR_F_GetGeomFieldCount( OGRFeatureH hFeat );
+OGRGeomFieldDefnH CPL_DLL OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat,
+                                                     int iField );
+int               CPL_DLL OGR_F_GetGeomFieldIndex( OGRFeatureH hFeat,
+                                                   const char *pszName);
+
+OGRGeometryH      CPL_DLL OGR_F_GetGeomFieldRef( OGRFeatureH hFeat,
+                                                 int iField );
+OGRErr            CPL_DLL OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat,
+                                                      int iField,
+                                                      OGRGeometryH hGeom );
+OGRErr            CPL_DLL OGR_F_SetGeomField( OGRFeatureH hFeat,
+                                              int iField, OGRGeometryH hGeom );
+
 long   CPL_DLL OGR_F_GetFID( OGRFeatureH );
 OGRErr CPL_DLL OGR_F_SetFID( OGRFeatureH, long );
 void   CPL_DLL OGR_F_DumpReadable( OGRFeatureH, FILE * );
@@ -352,6 +403,11 @@ OGRGeometryH CPL_DLL OGR_L_GetSpatialFilter( OGRLayerH );
 void   CPL_DLL OGR_L_SetSpatialFilter( OGRLayerH, OGRGeometryH );
 void   CPL_DLL OGR_L_SetSpatialFilterRect( OGRLayerH, 
                                            double, double, double, double );
+void     CPL_DLL OGR_L_SetSpatialFilterEx( OGRLayerH, int iGeomField,
+                                           OGRGeometryH hGeom );
+void     CPL_DLL OGR_L_SetSpatialFilterRectEx( OGRLayerH, int iGeomField,
+                                               double dfMinX, double dfMinY,
+                                               double dfMaxX, double dfMaxY );
 OGRErr CPL_DLL OGR_L_SetAttributeFilter( OGRLayerH, const char * );
 void   CPL_DLL OGR_L_ResetReading( OGRLayerH );
 OGRFeatureH CPL_DLL OGR_L_GetNextFeature( OGRLayerH );
@@ -362,10 +418,15 @@ OGRErr CPL_DLL OGR_L_CreateFeature( OGRLayerH, OGRFeatureH );
 OGRErr CPL_DLL OGR_L_DeleteFeature( OGRLayerH, long );
 OGRFeatureDefnH CPL_DLL OGR_L_GetLayerDefn( OGRLayerH );
 OGRSpatialReferenceH CPL_DLL OGR_L_GetSpatialRef( OGRLayerH );
+int    CPL_DLL OGR_L_FindFieldIndex( OGRLayerH, const char *, int bExactMatch );
 int    CPL_DLL OGR_L_GetFeatureCount( OGRLayerH, int );
 OGRErr CPL_DLL OGR_L_GetExtent( OGRLayerH, OGREnvelope *, int );
+OGRErr  CPL_DLL OGR_L_GetExtentEx( OGRLayerH, int iGeomField,
+                                   OGREnvelope *psExtent, int bForce );
 int    CPL_DLL OGR_L_TestCapability( OGRLayerH, const char * );
 OGRErr CPL_DLL OGR_L_CreateField( OGRLayerH, OGRFieldDefnH, int );
+OGRErr CPL_DLL OGR_L_CreateGeomField( OGRLayerH hLayer,
+                                      OGRGeomFieldDefnH hFieldDefn, int bForce );
 OGRErr CPL_DLL OGR_L_DeleteField( OGRLayerH, int iField );
 OGRErr CPL_DLL OGR_L_ReorderFields( OGRLayerH, int* panMap );
 OGRErr CPL_DLL OGR_L_ReorderField( OGRLayerH, int iOldFieldPos, int iNewFieldPos );
@@ -504,6 +565,9 @@ int CPL_DLL OGR_ST_GetRGBFromString(OGRStyleToolH hST, const char *pszColor,
 
 OGRStyleTableH  CPL_DLL OGR_STBL_Create( void ) CPL_WARN_UNUSED_RESULT;
 void    CPL_DLL OGR_STBL_Destroy( OGRStyleTableH hSTBL ); 
+int     CPL_DLL OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
+                                   const char *pszName,
+                                   const char *pszStyleString);
 int     CPL_DLL OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
                                          const char *pszFilename );
 int     CPL_DLL OGR_STBL_LoadStyleTable( OGRStyleTableH hStyleTable,
diff --git a/ogr/ogr_apitut.dox b/ogr/ogr_apitut.dox
index 0ba038a..9e42246 100644
--- a/ogr/ogr_apitut.dox
+++ b/ogr/ogr_apitut.dox
@@ -212,7 +212,70 @@ For each 2D geometry type there is a corresponding 2.5D type code.  The 2D
 and 2.5D geometry cases are handled by the same C++ class, so our code will
 handle 2D or 3D cases properly.  
 
-Note that OGRFeature::GetGeometryRef() returns a pointer to
+Starting with OGR 1.11,
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">
+several geometry fields</a> can be associated to a feature.
+
+In C++ :
+\code
+    OGRGeometry *poGeometry;
+    int iGeomField;
+    int nGeomFieldCount;
+
+    nGeomFieldCount = poFeature->GetGeomFieldCount();
+    for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ )
+    {
+        poGeometry = poFeature->GetGeomFieldRef(iGeomField);
+        if( poGeometry != NULL 
+                && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
+        {
+            OGRPoint *poPoint = (OGRPoint *) poGeometry;
+
+            printf( "%.3f,%3.f\n", poPoint->getX(), poPoint->getY() );
+        }
+        else
+        {
+            printf( "no point geometry\n" );
+        }
+    }
+\endcode
+
+In C :
+\code
+    OGRGeometryH hGeometry;
+    int iGeomField;
+    int nGeomFieldCount;
+
+    nGeomFieldCount = OGR_F_GetGeomFieldCount(hFeature);
+    for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ )
+    {
+        hGeometry = OGR_F_GetGeomFieldRef(hFeature, iGeomField);
+        if( hGeometry != NULL 
+                && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint )
+        {
+            printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0),
+                    OGR_G_GetY(hGeometry, 0) );
+        }
+        else
+        {
+            printf( "no point geometry\n" );
+        }
+    }
+\endcode
+
+In Python:
+\code
+    nGeomFieldCount = feat.GetGeomFieldCount()
+    for iGeomField in range(nGeomFieldCount):
+        geom = feat.GetGeomFieldRef(iGeomField)
+        if geom is not None and geom.GetGeometryType() == ogr.wkbPoint:
+            print "%.3f, %.3f" % ( geom.GetX(), geom.GetY() )
+        else:
+            print "no point geometry\n"
+\endcode
+
+Note that OGRFeature::GetGeometryRef() and OGRFeature::GetGeomFieldRef()
+return a pointer to
 the internal geometry owned by the OGRFeature.  There we don't actually 
 deleted the return geometry.  However, the OGRLayer::GetNextFeature() method
 returns a copy of the feature that is now owned by us.  So at the end of
@@ -886,4 +949,145 @@ while len(linelist) == 3:
 ds = None
 \endcode
 
+Starting with OGR 1.11,
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">
+several geometry fields</a> can be associated to a feature. This capability
+is just available for a few file formats, such as PostGIS.
+
+To create such datasources, geometry fields must be first created.
+Spatial reference system objects can be associated to each geometry field.
+
+In C++ :
+\code
+    OGRGeomFieldDefn oPointField( "PointField", wkbPoint );
+    OGRSpatialReference* poSRS = new OGRSpatialReference();
+    poSRS->importFromEPSG(4326);
+    oPointField.SetSpatialRef(poSRS);
+    poSRS->Release();
+    
+    if( poLayer->CreateGeomField( &oPointField ) != OGRERR_NONE )
+    {
+        printf( "Creating field PointField failed.\n" );
+        exit( 1 );
+    }
+    
+    OGRGeomFieldDefn oFieldPoint2( "PointField2", wkbPoint );
+    poSRS = new OGRSpatialReference();
+    poSRS->importFromEPSG(32631);
+    oPointField2.SetSpatialRef(poSRS);
+    poSRS->Release();
+    
+    if( poLayer->CreateGeomField( &oPointField2 ) != OGRERR_NONE )
+    {
+        printf( "Creating field PointField2 failed.\n" );
+        exit( 1 );
+    }
+\endcode
+
+In C :
+\code
+    OGRGeomFieldDefnH hPointField;
+    OGRGeomFieldDefnH hPointField2;
+    OGRSpatialReferenceH hSRS;
+
+    hPointField = OGR_GFld_Create( "PointField", wkbPoint );
+    hSRS = OSRNewSpatialReference( NULL );
+    OSRImportFromEPSG(hSRS, 4326);
+    OGR_GFld_SetSpatialRef(hPointField, hSRS);
+    OSRRelease(hSRS);
+    
+    if( OGR_L_CreateGeomField( hLayer, hPointField ) != OGRERR_NONE )
+    {
+        printf( "Creating field PointField failed.\n" );
+        exit( 1 );
+    }
+    
+    OGR_GFld_Destroy( hPointField );
+
+    hPointField2 = OGR_GFld_Create( "PointField2", wkbPoint );
+    OSRImportFromEPSG(hSRS, 32631);
+    OGR_GFld_SetSpatialRef(hPointField2, hSRS);
+    OSRRelease(hSRS);
+    
+    if( OGR_L_CreateGeomField( hLayer, hPointField2 ) != OGRERR_NONE )
+    {
+        printf( "Creating field PointField2 failed.\n" );
+        exit( 1 );
+    }
+    
+    OGR_GFld_Destroy( hPointField2 );
+\endcode
+
+To write a feature to disk, we must create a local OGRFeature, set attributes
+and attach geometries before trying to write it to the layer.  It is 
+imperative that this feature be instantiated from the OGRFeatureDefn 
+associated with the layer it will be written to.
+
+In C++ :
+\code
+        OGRFeature *poFeature;
+        OGRGeometry *poGeometry;
+        char* pszWKT;
+
+        poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
+        
+        pszWKT = (char*) "POINT (2 49)";
+        OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry );
+        poFeature->SetGeomFieldDirectly( "PointField", poGeometry );
+        
+        pszWKT = (char*) "POINT (500000 4500000)";
+        OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry );
+        poFeature->SetGeomFieldDirectly( "PointField2", poGeometry );
+        
+        if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+        {
+            printf( "Failed to create feature.\n" );
+            exit( 1 );
+        }
+
+        OGRFeature::DestroyFeature( poFeature );
+\endcode
+
+In C :
+\code
+        OGRFeatureH hFeature;
+        OGRGeometryH hGeometry;
+        char* pszWKT;
+
+        poFeature = OGR_F_Create( OGR_L_GetLayerDefn(hLayer) );
+        
+        pszWKT = (char*) "POINT (2 49)";
+        OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry );
+        OGR_F_SetGeomFieldDirectly( hFeature,
+            OGR_F_GetGeomFieldIndex(hFeature, "PointField"), hGeometry );
+        
+        pszWKT = (char*) "POINT (500000 4500000)";
+        OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry );
+        OGR_F_SetGeomFieldDirectly( hFeature,
+            OGR_F_GetGeomFieldIndex(hFeature, "PointField2"), hGeometry );
+        
+        if( OGR_L_CreateFeature( hFeature ) != OGRERR_NONE )
+        {
+            printf( "Failed to create feature.\n" );
+            exit( 1 );
+        }
+
+        OGR_F_Destroy( hFeature );
+\endcode
+
+In Python :
+\code
+        feat = ogr.Feature( lyr.GetLayerDefn() )
+        
+        feat.SetGeomFieldDirectly( "PointField",
+            ogr.CreateGeometryFromWkt( "POINT (2 49)" ) )
+        feat.SetGeomFieldDirectly( "PointField2",
+            ogr.CreateGeometryFromWkt( "POINT (500000 4500000)" ) )
+
+        if lyr.CreateFeature( feat ) != 0 )
+        {
+            print( "Failed to create feature.\n" );
+            sys.exit( 1 );
+        }
+\endcode
 */
diff --git a/ogr/ogr_arch.dox b/ogr/ogr_arch.dox
index 5ac9b0f..195d414 100644
--- a/ogr/ogr_arch.dox
+++ b/ogr/ogr_arch.dox
@@ -98,7 +98,7 @@ The OGRSpatialReference class is intended to store an OpenGIS Spatial
 Reference System definition.  Currently local, geographic and projected
 coordinate systems are supported.  Vertical coordinate systems, geocentric 
 coordinate systems, and compound (horizontal + vertical) coordinate systems
-are not supported.<p>
+are as well supported in recent GDAL versions.<p>
 
 The spatial coordinate system data model is inherited from the OpenGIS
 <b>Well Known Text</b> format.  A simple form of this is defined in the
@@ -117,7 +117,9 @@ describing how to use the OGRSpatialReference class.<p>
 The OGRGeometry captures the geometry of a vector feature ... the 
 spatial position/region of a feature.  The OGRFeature contains this 
 geometry, and adds feature attributes, feature id, 
-and a feature class identify.<p>
+and a feature class identifier. Starting with OGR 1.11,
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">
+several geometries</a> can be associated to a OGRFeature.<p>
 
 The set of attributes, their types, names and so forth is represented
 via the OGRFeatureDefn class.  One OGRFeatureDefn normally exists for a
@@ -139,8 +141,12 @@ If this is wkbUnknown then any type of geometry is allowed.  This implies that
 features in a given layer can potentially be of different geometry types
 though they will always share a common attribute schema. <p>
 
-The OGRFeatureDefn also contains a concept of default spatial reference
-system for all features of that type and a feature class name (normally 
+Starting with OGR 1.11, several geometry fields can be associated to a feature
+class. Each geometry field has its own indicator of geometry type allowed,
+returned by OGRGeomFieldDefn::GetType(), and its spatial reference system,
+returned by OGRGeomFieldDefn::GetSpatialRef().
+
+The OGRFeatureDefn also contains a feature class name (normally 
 used as a layer name).<p>
 
 
diff --git a/ogr/ogr_core.h b/ogr/ogr_core.h
index e2851b6..a0c98fe 100644
--- a/ogr/ogr_core.h
+++ b/ogr/ogr_core.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_core.h 23947 2012-02-11 17:37:02Z rouault $
+ * $Id: ogr_core.h 27058 2014-03-19 22:19:21Z kyle $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define some core portability services for cross-platform OGR code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -61,7 +62,17 @@ class CPL_DLL OGREnvelope
     double      MinY;
     double      MaxY;
 
+/* See http://trac.osgeo.org/gdal/ticket/5299 for details on this pragma */
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && !defined(_MSC_VER)) 
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#pragma GCC diagnostic push
+#endif
     int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0; }
+
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && !defined(_MSC_VER))
+#pragma GCC diagnostic pop
+#endif
+
     void Merge( OGREnvelope const& sOther ) {
         if( IsInit() )
         {
@@ -247,7 +258,7 @@ class CPL_DLL OGREnvelope3D : public OGREnvelope
     {
         return MinX <= other.MinX && MinY <= other.MinY &&
                MaxX >= other.MaxX && MaxY >= other.MaxY &&
-               MaxZ >= other.MaxZ && MaxZ >= other.MaxZ;
+               MinZ <= other.MinZ && MaxZ >= other.MaxZ;
     }
 };
 #else
@@ -288,12 +299,12 @@ typedef int     OGRBoolean;
 /* -------------------------------------------------------------------- */
 /*      ogr_geometry.h related definitions.                             */
 /* -------------------------------------------------------------------- */
+
 /**
  * List of well known binary geometry types.  These are used within the BLOBs
  * but are also returned from OGRGeometry::getGeometryType() to identify the
  * type of a geometry object.
  */
-
 typedef enum 
 {
     wkbUnknown = 0,         /**< unknown type, non-standard */
@@ -319,6 +330,19 @@ typedef enum
     wkbGeometryCollection25D = 0x80000007 /**< 2.5D extension as per 99-402 */
 } OGRwkbGeometryType;
 
+/**
+ * Output variants of WKB we support. 
+ * 99-402 was a short-lived extension to SFSQL 1.1 that used a high-bit flag
+ * to indicate the presence of Z coordiantes in a WKB geometry.
+ * SQL/MM Part 3 and SFSQL 1.2 use offsets of 1000 (Z), 2000 (M) and 3000 (ZM)
+ * to indicate the present of higher dimensional coordinates in a WKB geometry.
+ */
+typedef enum 
+{
+    wkbVariantOgc, /**< Old-style 99-402 extended dimension (Z) WKB types */
+    wkbVariantIso  /**< SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types */
+} OGRwkbVariant;
+
 #define wkb25DBit 0x80000000
 #define wkbFlatten(x)  ((OGRwkbGeometryType) ((x) & (~wkb25DBit)))
 
@@ -463,9 +487,11 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 #define OLCFastSetNextByIndex  "FastSetNextByIndex"
 #define OLCStringsAsUTF8       "StringsAsUTF8"
 #define OLCIgnoreFields        "IgnoreFields"
+#define OLCCreateGeomField     "CreateGeomField"
 
 #define ODsCCreateLayer        "CreateLayer"
 #define ODsCDeleteLayer        "DeleteLayer"
+#define ODsCCreateGeomFieldAfterCreateLayer   "CreateGeomFieldAfterCreateLayer"
 
 #define ODrCCreateDataSource   "CreateDataSource"
 #define ODrCDeleteDataSource   "DeleteDataSource"
diff --git a/ogr/ogr_expat.cpp b/ogr/ogr_expat.cpp
index 2142de4..f9faeed 100644
--- a/ogr/ogr_expat.cpp
+++ b/ogr/ogr_expat.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_expat.cpp 24982 2012-09-26 19:41:33Z rouault $
+ * $Id: ogr_expat.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR
  * Purpose:  Convenience function for parsing with Expat library
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2009, Even Rouault
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "ogr_expat.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogr_expat.cpp 24982 2012-09-26 19:41:33Z rouault $");
+CPL_CVSID("$Id: ogr_expat.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define OGR_EXPAT_MAX_ALLOWED_ALLOC 10000000
 
diff --git a/ogr/ogr_expat.h b/ogr/ogr_expat.h
index 4510528..c08ced0 100644
--- a/ogr/ogr_expat.h
+++ b/ogr/ogr_expat.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_expat.h 18063 2009-11-21 21:11:49Z warmerdam $
+ * $Id: ogr_expat.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR
  * Purpose:  Convenience function for parsing with Expat library
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2009, Even Rouault
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogr_feature.h b/ogr/ogr_feature.h
index 8a9ca30..8c43ed6 100644
--- a/ogr/ogr_feature.h
+++ b/ogr/ogr_feature.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_feature.h 24849 2012-08-25 12:22:05Z rouault $
+ * $Id: ogr_feature.h 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Class for representing a whole feature, and layer schemas.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -98,6 +99,49 @@ class CPL_DLL OGRFieldDefn
 };
 
 /************************************************************************/
+/*                          OGRGeomFieldDefn                            */
+/************************************************************************/
+
+/**
+ * Definition of a geometry field of an OGRFeatureDefn. A geometry field
+ * is described by a name, a geometry type and a spatial reference system.
+ *
+ * @since OGR 2.0
+ */
+
+class CPL_DLL OGRGeomFieldDefn
+{
+protected:
+        char                *pszName;
+        OGRwkbGeometryType   eGeomType; /* all values possible except wkbNone */
+        OGRSpatialReference* poSRS;
+
+        int                 bIgnore;
+
+        void                Initialize( const char *, OGRwkbGeometryType );
+
+public:
+                            OGRGeomFieldDefn(const char *pszNameIn,
+                                             OGRwkbGeometryType eGeomTypeIn);
+                            OGRGeomFieldDefn( OGRGeomFieldDefn * );
+        virtual            ~OGRGeomFieldDefn();
+
+        void                SetName( const char * );
+        const char         *GetNameRef() { return pszName; }
+
+        OGRwkbGeometryType  GetType() { return eGeomType; }
+        void                SetType( OGRwkbGeometryType eTypeIn );
+
+        virtual OGRSpatialReference* GetSpatialRef();
+        void                 SetSpatialRef(OGRSpatialReference* poSRS);
+
+        int                 IsIgnored() { return bIgnore; }
+        void                SetIgnored( int bIgnore ) { this->bIgnore = bIgnore; }
+
+        int                 IsSame( OGRGeomFieldDefn * );
+};
+
+/************************************************************************/
 /*                            OGRFeatureDefn                            */
 /************************************************************************/
 
@@ -113,55 +157,65 @@ class CPL_DLL OGRFieldDefn
  * This object also can contain some other information such as a name, the
  * base geometry type and potentially other metadata.
  *
+ * Starting with GDAL 1.11, in addition to attribute fields, it can also
+ * contain multiple geometry fields.
+ *
  * It is reasonable for different translators to derive classes from
  * OGRFeatureDefn with additional translator specific information. 
  */
 
 class CPL_DLL OGRFeatureDefn
 {
-  private:
+  protected:
     volatile int nRefCount;
     
     int         nFieldCount;
     OGRFieldDefn **papoFieldDefn;
 
-    OGRwkbGeometryType eGeomType;
+    int                nGeomFieldCount;
+    OGRGeomFieldDefn **papoGeomFieldDefn;
 
     char        *pszFeatureClassName;
-    
-    int         bIgnoreGeometry;
+
     int         bIgnoreStyle;
     
   public:
                 OGRFeatureDefn( const char * pszName = NULL );
     virtual    ~OGRFeatureDefn();
 
-    const char  *GetName() { return pszFeatureClassName; }
+    virtual const char  *GetName();
+
+    virtual int         GetFieldCount();
+    virtual OGRFieldDefn *GetFieldDefn( int i );
+    virtual int         GetFieldIndex( const char * );
+
+    virtual void        AddFieldDefn( OGRFieldDefn * );
+    virtual OGRErr      DeleteFieldDefn( int iField );
+    virtual OGRErr      ReorderFieldDefns( int* panMap );
 
-    int         GetFieldCount() { return nFieldCount; }
-    OGRFieldDefn *GetFieldDefn( int i );
-    int         GetFieldIndex( const char * );
+    virtual int         GetGeomFieldCount();
+    virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i );
+    virtual int         GetGeomFieldIndex( const char * );
 
-    void        AddFieldDefn( OGRFieldDefn * );
-    OGRErr      DeleteFieldDefn( int iField );
-    OGRErr      ReorderFieldDefns( int* panMap );
+    virtual void        AddGeomFieldDefn( OGRGeomFieldDefn *, int bCopy = TRUE );
+    virtual OGRErr      DeleteGeomFieldDefn( int iGeomField );
 
-    OGRwkbGeometryType GetGeomType() { return eGeomType; }
-    void        SetGeomType( OGRwkbGeometryType );
+    virtual OGRwkbGeometryType GetGeomType();
+    virtual void        SetGeomType( OGRwkbGeometryType );
 
-    OGRFeatureDefn *Clone();
+    virtual OGRFeatureDefn *Clone();
 
     int         Reference() { return CPLAtomicInc(&nRefCount); }
     int         Dereference() { return CPLAtomicDec(&nRefCount); }
     int         GetReferenceCount() { return nRefCount; }
     void        Release();
 
-    int         IsGeometryIgnored() { return bIgnoreGeometry; }
-    void        SetGeometryIgnored( int bIgnore ) { bIgnoreGeometry = bIgnore; }
-    int        IsStyleIgnored() { return bIgnoreStyle; }
-    void        SetStyleIgnored( int bIgnore ) { bIgnoreStyle = bIgnore; }
+    virtual int         IsGeometryIgnored();
+    virtual void        SetGeometryIgnored( int bIgnore );
+    virtual int        IsStyleIgnored() { return bIgnoreStyle; }
+    virtual void        SetStyleIgnored( int bIgnore ) { bIgnoreStyle = bIgnore; }
 
-    int         IsSame( const OGRFeatureDefn * poOtherFeatureDefn ) const;
+    virtual int         IsSame( OGRFeatureDefn * poOtherFeatureDefn );
 
     static OGRFeatureDefn  *CreateFeatureDefn( const char *pszName = NULL );
     static void         DestroyFeatureDefn( OGRFeatureDefn * );
@@ -181,7 +235,7 @@ class CPL_DLL OGRFeature
 
     long                nFID;
     OGRFeatureDefn      *poDefn;
-    OGRGeometry         *poGeometry;
+    OGRGeometry        **papoGeometries;
     OGRField            *pauFields;
 
   protected: 
@@ -197,9 +251,22 @@ class CPL_DLL OGRFeature
     
     OGRErr              SetGeometryDirectly( OGRGeometry * );
     OGRErr              SetGeometry( OGRGeometry * );
-    OGRGeometry        *GetGeometryRef() { return poGeometry; }
+    OGRGeometry        *GetGeometryRef();
     OGRGeometry        *StealGeometry();
 
+    int                 GetGeomFieldCount()
+                                { return poDefn->GetGeomFieldCount(); }
+    OGRGeomFieldDefn   *GetGeomFieldDefnRef( int iField )
+                                { return poDefn->GetGeomFieldDefn(iField); }
+    int                 GetGeomFieldIndex( const char * pszName)
+                                { return poDefn->GetGeomFieldIndex(pszName); }
+
+    OGRGeometry*        GetGeomFieldRef(int iField);
+    OGRGeometry*        StealGeometry(int iField);
+    OGRGeometry*        GetGeomFieldRef(const char* pszFName);
+    OGRErr              SetGeomFieldDirectly( int iField, OGRGeometry * );
+    OGRErr              SetGeomField( int iField, OGRGeometry * );
+
     OGRFeature         *Clone();
     virtual OGRBoolean  Equal( OGRFeature * poFeature );
 
@@ -209,7 +276,7 @@ class CPL_DLL OGRFeature
     int                 GetFieldIndex( const char * pszName)
                                       { return poDefn->GetFieldIndex(pszName);}
 
-    int                 IsFieldSet( int iField ) const;
+    int                 IsFieldSet( int iField );
     
     void                UnsetField( int iField );
     
@@ -220,7 +287,7 @@ class CPL_DLL OGRFeature
     const char         *GetFieldAsString( int i );
     const int          *GetFieldAsIntegerList( int i, int *pnCount );
     const double       *GetFieldAsDoubleList( int i, int *pnCount );
-    char              **GetFieldAsStringList( int i ) const;
+    char              **GetFieldAsStringList( int i );
     GByte              *GetFieldAsBinary( int i, int *pnCount );
     int                 GetFieldAsDateTime( int i, 
                                      int *pnYear, int *pnMonth, int *pnDay,
@@ -291,6 +358,8 @@ class CPL_DLL OGRFeature
 
     OGRErr              RemapFields( OGRFeatureDefn *poNewDefn, 
                                      int *panRemapSource );
+    OGRErr              RemapGeomFields( OGRFeatureDefn *poNewDefn, 
+                                     int *panRemapSource );
 
     virtual const char *GetStyleString();
     virtual void        SetStyleString( const char * );
diff --git a/ogr/ogr_fromepsg.cpp b/ogr/ogr_fromepsg.cpp
index 2d0105f..0ce5a6b 100644
--- a/ogr/ogr_fromepsg.cpp
+++ b/ogr/ogr_fromepsg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_fromepsg.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: ogr_fromepsg.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Generate an OGRSpatialReference object based on an EPSG
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_p.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_fromepsg.cpp 25727 2013-03-10 14:56:33Z rouault $");
+CPL_CVSID("$Id: ogr_fromepsg.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #  define PI 3.14159265358979323846
diff --git a/ogr/ogr_geocoding.cpp b/ogr/ogr_geocoding.cpp
index e6e0fdf..bc78731 100644
--- a/ogr/ogr_geocoding.cpp
+++ b/ogr/ogr_geocoding.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_geocoding.cpp 25930 2013-04-18 19:16:13Z rouault $
+ * $Id: ogr_geocoding.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -77,7 +77,7 @@ int OGR_gettimeofday(struct timeval *tv, struct timezone *tzIgnored)
 #include "ogr_mem.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogr_geocoding.cpp 25930 2013-04-18 19:16:13Z rouault $");
+CPL_CVSID("$Id: ogr_geocoding.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 struct _OGRGeocodingSessionHS
 {
@@ -119,6 +119,8 @@ static double dfLastQueryTimeStampMapQuestNominatim = 0.0;
 #define FIELD_URL                "url"
 #define FIELD_BLOB               "blob"
 
+#ifdef OGR_ENABLED
+
 /************************************************************************/
 /*                       OGRGeocodeGetParameter()                       */
 /************************************************************************/
@@ -176,6 +178,8 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
     return bValidFormat;
 }
 
+#endif /* #ifdef OGR_ENABLED */
+
 /************************************************************************/
 /*                       OGRGeocodeCreateSession()                      */
 /************************************************************************/
@@ -231,6 +235,7 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
 
 OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
 {
+#ifdef OGR_ENABLED
     OGRGeocodingSessionH hSession =
         (OGRGeocodingSessionH)CPLCalloc(1, sizeof(_OGRGeocodingSessionHS));
 
@@ -352,6 +357,10 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
         (pszReverseQueryTemplate) ? CPLStrdup(pszReverseQueryTemplate) : NULL;
 
     return hSession;
+#else
+    CPLError(CE_Failure, CPLE_NotSupported, "Requires OGR support");
+    return NULL;
+#endif
 }
 
 /************************************************************************/
@@ -367,6 +376,7 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
  */
 void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
 {
+#ifdef OGR_ENABLED
     if( hSession == NULL )
         return;
     CPLFree(hSession->pszCacheFilename);
@@ -381,8 +391,11 @@ void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
     if( hSession->poDS )
         OGRReleaseDataSource((OGRDataSourceH) hSession->poDS);
     CPLFree(hSession);
+#endif
 }
 
+#ifdef OGR_ENABLED
+
 /************************************************************************/
 /*                        OGRGeocodeGetCacheLayer()                     */
 /************************************************************************/
@@ -1317,6 +1330,8 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
     return hLayer;
 }
 
+#endif /* #ifdef OGR_ENABLED */
+
 /************************************************************************/
 /*                              OGRGeocode()                            */
 /************************************************************************/
@@ -1371,6 +1386,7 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
                      char** papszStructuredQuery,
                      char** papszOptions)
 {
+#ifdef OGR_ENABLED
     VALIDATE_POINTER1( hSession, "OGRGeocode", NULL );
     if( (pszQuery == NULL && papszStructuredQuery == NULL) ||
         (pszQuery != NULL && papszStructuredQuery != NULL) )
@@ -1421,8 +1437,13 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
     }
 
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
+#else
+    return NULL;
+#endif
 }
 
+#ifdef OGR_ENABLED
+
 /************************************************************************/
 /*                      OGRGeocodeReverseSubstitute()                   */
 /************************************************************************/
@@ -1451,6 +1472,8 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
     return osURL;
 }
 
+#endif /* #ifdef OGR_ENABLED */
+
 /************************************************************************/
 /*                         OGRGeocodeReverse()                          */
 /************************************************************************/
@@ -1498,6 +1521,7 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
                             double dfLon, double dfLat,
                             char** papszOptions)
 {
+#ifdef OGR_ENABLED
     VALIDATE_POINTER1( hSession, "OGRGeocodeReverse", NULL );
 
     if( hSession->pszReverseQueryTemplate == NULL )
@@ -1520,6 +1544,9 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
     }
 
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
+#else
+    return NULL;
+#endif
 }
 
 /************************************************************************/
@@ -1536,5 +1563,7 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
  */
 void OGRGeocodeFreeResult(OGRLayerH hLayer)
 {
+#ifdef OGR_ENABLED
     delete (OGRLayer*) hLayer;
+#endif
 }
diff --git a/ogr/ogr_geocoding.h b/ogr/ogr_geocoding.h
index d89fcf4..2e5125a 100644
--- a/ogr/ogr_geocoding.h
+++ b/ogr/ogr_geocoding.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_geocoding.h 25378 2012-12-29 00:28:36Z rouault $
+ * $Id: ogr_geocoding.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogr_geometry.h b/ogr/ogr_geometry.h
index 1e82509..9890575 100644
--- a/ogr/ogr_geometry.h
+++ b/ogr/ogr_geometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geometry.h 25450 2013-01-04 23:15:38Z rouault $
+ * $Id: ogr_geometry.h 27088 2014-03-24 23:18:08Z bishop $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating simple features that is not specific
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -55,6 +56,7 @@ class OGRRawPoint
 };
 
 typedef struct GEOSGeom_t *GEOSGeom;
+typedef struct GEOSContextHandle_HS *GEOSContextHandle_t;
 
 /************************************************************************/
 /*                             OGRGeometry                              */
@@ -81,6 +83,7 @@ class CPL_DLL OGRGeometry
 
   protected:
     int                   nCoordDimension;
+    int getIsoGeometryType() const;
     
   public:
                 OGRGeometry();
@@ -101,7 +104,7 @@ class CPL_DLL OGRGeometry
     // IWks Interface
     virtual int WkbSize() const = 0;
     virtual OGRErr importFromWkb( unsigned char *, int=-1 )=0;
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const = 0;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const = 0;
     virtual OGRErr importFromWkt( char ** ppszInput ) = 0;
     virtual OGRErr exportToWkt( char ** ppszDstText ) const = 0;
     
@@ -113,7 +116,11 @@ class CPL_DLL OGRGeometry
     virtual char * exportToGML( const char* const * papszOptions = NULL ) const;
 	virtual char * exportToKML() const;
     virtual char * exportToJson() const;
-    virtual GEOSGeom exportToGEOS() const;
+
+    static GEOSContextHandle_t createGEOSContext();
+    static void freeGEOSContext(GEOSContextHandle_t hGEOSCtxt);
+    virtual GEOSGeom exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const;
+
     virtual void closeRings();
 
     virtual void setCoordinateDimension( int nDimension ); 
@@ -189,7 +196,7 @@ class CPL_DLL OGRPoint : public OGRGeometry
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int=-1 );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText ) const;
     
@@ -271,7 +278,7 @@ class CPL_DLL OGRLineString : public OGRCurve
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1 );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText ) const;
 
@@ -288,6 +295,8 @@ class CPL_DLL OGRLineString : public OGRCurve
     virtual void StartPoint(OGRPoint *) const;
     virtual void EndPoint(OGRPoint *) const;
     virtual void Value( double, OGRPoint * ) const;
+    virtual double Project(const OGRPoint *) const;
+    virtual OGRLineString* getSubLine(double, double, int) const;
     
     // ILineString methods
     int         getNumPoints() const { return nPointCount; }
@@ -301,9 +310,10 @@ class CPL_DLL OGRLineString : public OGRCurve
     
     // non standard.
     virtual void setCoordinateDimension( int nDimension ); 
-    void        setNumPoints( int );
+    void        setNumPoints( int nNewPointCount, int bZeroizeNewContent = TRUE );
     void        setPoint( int, OGRPoint * );
     void        setPoint( int, double, double );
+    void        setZ( int, double );
     void        setPoint( int, double, double, double );
     void        setPoints( int, OGRRawPoint *, double * = NULL );
     void        setPoints( int, double * padfX, double * padfY,
@@ -385,7 +395,7 @@ class CPL_DLL OGRLinearRing : public OGRLineString
     // object cant be serialized on its own. 
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int=-1 );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const;
 };
 
 /************************************************************************/
@@ -442,7 +452,7 @@ class CPL_DLL OGRPolygon : public OGRSurface
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1 );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText ) const;
 
@@ -466,6 +476,9 @@ class CPL_DLL OGRPolygon : public OGRSurface
     OGRLinearRing *getInteriorRing( int );
     const OGRLinearRing *getInteriorRing( int ) const;
 
+    OGRLinearRing *stealExteriorRing();
+    OGRLinearRing *stealInteriorRing(int);
+
     OGRBoolean IsPointOnSurface( const OGRPoint * ) const;
 
     virtual void closeRings();
@@ -509,7 +522,7 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1 );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char * ) const;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText ) const;
 
@@ -652,7 +665,7 @@ class CPL_DLL OGRGeometryFactory
     static OGRErr createFromFgf( unsigned char *, OGRSpatialReference *,
                                  OGRGeometry **, int = -1, int * = NULL );
     static OGRGeometry *createFromGML( const char * );
-    static OGRGeometry *createFromGEOS( GEOSGeom );
+    static OGRGeometry *createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom );
 
     static void   destroyGeometry( OGRGeometry * );
     static OGRGeometry *createGeometry( OGRwkbGeometryType );
@@ -667,9 +680,6 @@ class CPL_DLL OGRGeometryFactory
                                            int nPolygonCount,
                                            int *pbResultValidGeometry,
                                            const char **papszOptions = NULL);
-
-    static void *getGEOSGeometryFactory();
-
     static int haveGEOS();
 
     static OGRGeometry* transformWithOptions( const OGRGeometry* poSrcGeom,
diff --git a/ogr/ogr_opt.cpp b/ogr/ogr_opt.cpp
index 526d1df..383b203 100644
--- a/ogr/ogr_opt.cpp
+++ b/ogr/ogr_opt.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_opt.cpp 22332 2011-05-08 15:32:37Z rouault $
+ * $Id: ogr_opt.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features
  * Purpose:  Functions for getting list of projection types, and their parms.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogr_opt.cpp 22332 2011-05-08 15:32:37Z rouault $");
+CPL_CVSID("$Id: ogr_opt.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const char *papszParameterDefinitions[] = {
     SRS_PP_CENTRAL_MERIDIAN,    "Central Meridian",     "Long",  "0.0",
diff --git a/ogr/ogr_p.h b/ogr/ogr_p.h
index 4734327..d97af45 100644
--- a/ogr/ogr_p.h
+++ b/ogr/ogr_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_p.h 23638 2011-12-22 21:02:56Z rouault $
+ * $Id: ogr_p.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Some private helper functions and stuff for OGR implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,6 +43,9 @@
 #include "ogr_core.h"
 #include "ogr_geometry.h"
 
+/* A default name for the default geometry column, instead of '' */
+#define OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME     "_ogr_geometry_"
+
 #ifdef CPL_MSB 
 #  define OGR_SWAP(x)   (x == wkbNDR)
 #else
@@ -130,4 +134,18 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                                       int bOrientation = TRUE,
                                       int bFaceHoleNegative = FALSE );
 
+/************************************************************************/
+/*                        PostGIS EWKB encoding                         */
+/************************************************************************/
+
+OGRGeometry CPL_DLL *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID );
+OGRGeometry CPL_DLL *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID );
+char CPL_DLL * OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId );
+
+/************************************************************************/
+/*                        WKB Type Handling encoding                    */
+/************************************************************************/
+
+OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbGeometryType *eGeometryType, OGRBoolean *b3D );
+
 #endif /* ndef OGR_P_H_INCLUDED */
diff --git a/ogr/ogr_spatialref.h b/ogr/ogr_spatialref.h
index a0669f7..b0f2f8a 100644
--- a/ogr/ogr_spatialref.h
+++ b/ogr/ogr_spatialref.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_spatialref.h 26289 2013-08-10 18:05:31Z rouault $
+ * $Id: ogr_spatialref.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating spatial reference systems in a
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogr_sql.dox b/ogr/ogr_sql.dox
index c11223f..93962dc 100644
--- a/ogr/ogr_sql.dox
+++ b/ogr/ogr_sql.dox
@@ -190,6 +190,7 @@ Currently casting to the following target types are supported:
 <li> date(field_length)
 <li> time(field_length)
 <li> timestamp(field_length)
+<li> geometry, geometry(geometry_type), geometry(geometry_type,epsg_code)
 </ol>
 
 Specifying the field_length and/or the field_precision is optional.  An
@@ -204,6 +205,10 @@ supported if the CAST operator is the "outer most" operators on a field
 in the field definition list.  In other contexts it is still useful to
 convert between numeric, string and date data types.
 
+Starting with OGR 1.11, casting a WKT string to a geometry is allowed.
+geometry_type can be POINT[Z], LINESTRING[Z], POLYGON[Z], MULTIPOINT[Z],
+MULTILINESTRING[Z], MULTIPOLYGON[Z], GEOMETRYCOLLECTION[Z] or GEOMETRY[Z].
+
 \subsection ogr_sql_where WHERE
 
 The argument to the WHERE clause is a logical expression used select records 
diff --git a/ogr/ogr_srs_api.h b/ogr/ogr_srs_api.h
index cd1f76c..8fe73fd 100644
--- a/ogr/ogr_srs_api.h
+++ b/ogr/ogr_srs_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_api.h 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: ogr_srs_api.h 27109 2014-03-28 20:26:34Z kyle $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API and constant declarations for OGR Spatial References.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -229,6 +230,45 @@ typedef enum {
 #define SRS_UL_LINK_Clarke      "Link_Clarke"          
 #define SRS_UL_LINK_Clarke_CONV              "0.2011661949"
 
+#define SRS_UL_KILOMETER        "Kilometer"
+#define SRS_UL_KILOMETER_CONV                "1000."
+#define SRS_UL_DECIMETER        "Decimeter"
+#define SRS_UL_DECIMETER_CONV                "0.1"
+#define SRS_UL_CENTIMETER       "Centimeter"
+#define SRS_UL_CENTIMETER_CONV               "0.01"
+#define SRS_UL_MILLIMETER       "Millimeter"
+#define SRS_UL_MILLIMETER_CONV               "0.001"
+#define SRS_UL_INTL_NAUT_MILE   "Nautical_Mile_International"
+#define SRS_UL_INTL_NAUT_MILE_CONV           "1852.0"
+#define SRS_UL_INTL_INCH        "Inch_International"
+#define SRS_UL_INTL_INCH_CONV                "0.0254"
+#define SRS_UL_INTL_FOOT        "Foot_International"
+#define SRS_UL_INTL_FOOT_CONV                    "0.3048"
+#define SRS_UL_INTL_YARD        "Yard_International"
+#define SRS_UL_INTL_YARD_CONV                "0.9144"
+#define SRS_UL_INTL_STAT_MILE   "Statute_Mile_International"
+#define SRS_UL_INTL_STAT_MILE_CONV           "1609.344"
+#define SRS_UL_INTL_FATHOM      "Fathom_International"
+#define SRS_UL_INTL_FATHOM_CONV              "1.8288"
+#define SRS_UL_INTL_CHAIN       "Chain_International"
+#define SRS_UL_INTL_CHAIN_CONV               "20.1168"
+#define SRS_UL_INTL_LINK        "Link_International"
+#define SRS_UL_INTL_LINK_CONV                "0.201168"
+#define SRS_UL_US_INCH          "Inch_US_Surveyor"
+#define SRS_UL_US_INCH_CONV                  "0.025400050800101603"
+#define SRS_UL_US_YARD          "Yard_US_Surveyor"
+#define SRS_UL_US_YARD_CONV                  "0.914401828803658"
+#define SRS_UL_US_CHAIN         "Chain_US_Surveyor"
+#define SRS_UL_US_CHAIN_CONV                 "20.11684023368047"
+#define SRS_UL_US_STAT_MILE     "Statute_Mile_US_Surveyor"
+#define SRS_UL_US_STAT_MILE_CONV             "1609.347218694437"
+#define SRS_UL_INDIAN_YARD      "Yard_Indian"
+#define SRS_UL_INDIAN_YARD_CONV              "0.91439523"
+#define SRS_UL_INDIAN_FOOT      "Foot_Indian"
+#define SRS_UL_INDIAN_FOOT_CONV              "0.30479841"
+#define SRS_UL_INDIAN_CHAIN     "Chain_Indian"
+#define SRS_UL_INDIAN_CHAIN_CONV             "20.11669506"
+
 #define SRS_UA_DEGREE           "degree"
 #define SRS_UA_DEGREE_CONV                  "0.0174532925199433"
 #define SRS_UA_RADIAN           "radian"
@@ -685,13 +725,13 @@ OCTTransformEx( OGRCoordinateTransformationH hCT,
 /* this is really private to OGR. */
 char *OCTProj4Normalize( const char *pszProj4Src );
 
-void OCTCleanupProjMutex();
+void OCTCleanupProjMutex( void );
 
 /* -------------------------------------------------------------------- */
 /*      Projection transform dictionary query.                          */
 /* -------------------------------------------------------------------- */
 
-char CPL_DLL ** OPTGetProjectionMethods();
+char CPL_DLL ** OPTGetProjectionMethods( void );
 char CPL_DLL ** OPTGetParameterList( const char * pszProjectionMethod,
                              char ** ppszUserName );
 int CPL_DLL OPTGetParameterInfo( const char * pszProjectionMethod,
diff --git a/ogr/ogr_srs_erm.cpp b/ogr/ogr_srs_erm.cpp
index 14028b9..e5e7aaa 100644
--- a/ogr/ogr_srs_erm.cpp
+++ b/ogr/ogr_srs_erm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_erm.cpp 22996 2011-08-28 09:27:35Z rouault $
+ * $Id: ogr_srs_erm.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement ERMapper projection conversions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_srs_erm.cpp 22996 2011-08-28 09:27:35Z rouault $");
+CPL_CVSID("$Id: ogr_srs_erm.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OSRImportFromERM()                           */
diff --git a/ogr/ogr_srs_esri.cpp b/ogr/ogr_srs_esri.cpp
index c4d8692..b8e4f51 100644
--- a/ogr/ogr_srs_esri.cpp
+++ b/ogr/ogr_srs_esri.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_esri.cpp 26258 2013-07-31 22:41:28Z kyle $
+ * $Id: ogr_srs_esri.cpp 27050 2014-03-18 00:09:03Z kyle $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from ESRI .prj definitions.
@@ -7,6 +7,8 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2013, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +36,7 @@
 
 #include "ogr_srs_esri_names.h"
 
-CPL_CVSID("$Id: ogr_srs_esri.cpp 26258 2013-07-31 22:41:28Z kyle $");
+CPL_CVSID("$Id: ogr_srs_esri.cpp 27050 2014-03-18 00:09:03Z kyle $");
 
 void  SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName );
 int   RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName, 
diff --git a/ogr/ogr_srs_ozi.cpp b/ogr/ogr_srs_ozi.cpp
index d0a8096..f020147 100644
--- a/ogr/ogr_srs_ozi.cpp
+++ b/ogr/ogr_srs_ozi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_ozi.cpp 25256 2012-11-26 20:19:03Z rouault $
+ * $Id: ogr_srs_ozi.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation from OziExplorer
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_ozi.cpp 25256 2012-11-26 20:19:03Z rouault $");
+CPL_CVSID("$Id: ogr_srs_ozi.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OSRImportFromOzi()                          */
diff --git a/ogr/ogr_srs_panorama.cpp b/ogr/ogr_srs_panorama.cpp
index 85b1f2d..5acef79 100644
--- a/ogr/ogr_srs_panorama.cpp
+++ b/ogr/ogr_srs_panorama.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_panorama.cpp 25019 2012-09-30 13:25:39Z rouault $
+ * $Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from "Panorama" GIS
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_panorama.cpp 25019 2012-09-30 13:25:39Z rouault $");
+CPL_CVSID("$Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define TO_DEGREES 57.2957795130823208766
 #define TO_RADIANS 0.017453292519943295769
@@ -67,7 +68,7 @@ CPL_CVSID("$Id: ogr_srs_panorama.cpp 25019 2012-09-30 13:25:39Z rouault $");
 #define PAN_PROJ_EQC    27L     // Equirectangular
 #define PAN_PROJ_CEA    28L     // Cylindrical Equal Area (Lambert)
 #define PAN_PROJ_IMWP   29L     // International Map of the World Polyconic
-
+#define PAN_PROJ_MILLER 34L     // Miller
 /************************************************************************/
 /*  "Panorama" datum codes.                                             */
 /************************************************************************/
@@ -126,7 +127,18 @@ static const long aoEllips[] =
     7015,   // Everest, 1830
     7004,   // Bessel, 1841
     7001,   // Airy, 1830
-    7030    // WGS, 1984 (GPS)
+    7030,   // WGS, 1984 (GPS)
+    0,      // FIXME: PZ90.02
+    7019,   // GRS, 1980 (NAD1983)
+    7022,   // International, 1924 (Hayford, 1909) XXX?
+    7036,   // South American, 1969
+    7021,   // Indonesian, 1974
+    7020,   // Helmert 1906
+    0,      // FIXME: Fisher 1960
+    0,      // FIXME: Fisher 1968
+    0,      // FIXME: Haff 1960
+    7042,   // Everest, 1830
+    7003   // Australian National, 1965
 };
 
 #define NUMBER_OF_ELLIPSOIDS    (sizeof(aoEllips)/sizeof(aoEllips[0]))
@@ -392,6 +404,12 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
                              padfPrjParams[5], padfPrjParams[6] );
             break;
 
+        case PAN_PROJ_MILLER:
+            SetMC(TO_DEGREES * padfPrjParams[5],
+                TO_DEGREES * padfPrjParams[4],
+                padfPrjParams[6], padfPrjParams[7]);
+            break;
+
         default:
             CPLDebug( "OSR_Panorama", "Unsupported projection: %ld", iProjSys );
             SetLocalCS( CPLString().Printf("\"Panorama\" projection number %ld",
diff --git a/ogr/ogr_srs_pci.cpp b/ogr/ogr_srs_pci.cpp
index b5c811d..d7ba2ad 100644
--- a/ogr/ogr_srs_pci.cpp
+++ b/ogr/ogr_srs_pci.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_pci.cpp 22898 2011-08-07 20:31:33Z rouault $
+ * $Id: ogr_srs_pci.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from PCI georeferencing
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_pci.cpp 22898 2011-08-07 20:31:33Z rouault $");
+CPL_CVSID("$Id: ogr_srs_pci.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef struct 
 {
diff --git a/ogr/ogr_srs_proj4.cpp b/ogr/ogr_srs_proj4.cpp
index a471fe4..8be829f 100644
--- a/ogr/ogr_srs_proj4.cpp
+++ b/ogr/ogr_srs_proj4.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_proj4.cpp 26137 2013-07-05 19:30:23Z rouault $
+ * $Id: ogr_srs_proj4.cpp 27108 2014-03-28 20:25:46Z kyle $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to PROJ.4.
@@ -7,6 +7,8 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc. 
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2014, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +35,7 @@
 
 extern int EPSGGetWGS84Transform( int nGeogCS, double *padfTransform );
 
-CPL_CVSID("$Id: ogr_srs_proj4.cpp 26137 2013-07-05 19:30:23Z rouault $");
+CPL_CVSID("$Id: ogr_srs_proj4.cpp 27108 2014-03-28 20:25:46Z kyle $");
 
 /* -------------------------------------------------------------------- */
 /*      The following list comes from osrs/proj/src/pj_ellps.c          */
@@ -782,7 +784,8 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     else if( EQUAL(pszProj,"lcc") ) 
     {
         if( OSR_GDV(papszNV, "lat_0", 0.0 ) 
-            == OSR_GDV(papszNV, "lat_1", 0.0 ) )
+            == OSR_GDV(papszNV, "lat_1", 0.0 ) &&
+            CSLFetchNameValue( papszNV, "lat_2" ) == NULL )
         {
             /* 1SP form */
             SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ), 
@@ -1123,20 +1126,81 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             else
                 SetLinearUnits( "unknown", CPLAtofM(pszValue) );
         }
+        /*
+        ** All units reported by cs2cs -lu are supported, fall back to meter.
+        */
         else if( (pszValue = CSLFetchNameValue(papszNV, "units")) != NULL )
         {
             if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") || EQUAL(pszValue,"metre") )
                 SetLinearUnits( SRS_UL_METER, 1.0 );
-            else if( EQUAL(pszValue,"km") )
-                SetLinearUnits( "kilometre", 1000.0 );
-            else if( EQUAL(pszValue,"us-ft" ) )
-                SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
-            else if( EQUAL(pszValue,"ft" ) )
-                SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
-            else if( EQUAL(pszValue,"yd" ) )
-                SetLinearUnits( pszValue, 0.9144 );
-            else if( EQUAL(pszValue,"us-yd" ) )
-                SetLinearUnits( pszValue, 0.914401828803658 );
+            /*
+            ** Leave as 'kilometre' instead of SRS_UL_KILOMETER due to
+            ** historical usage
+            */
+            else if( EQUAL( pszValue,"km") )
+                SetLinearUnits( "kilometre",
+                                CPLAtof( SRS_UL_KILOMETER_CONV ) );
+            else if( EQUAL( pszValue,"us-ft" ) )
+                SetLinearUnits( SRS_UL_US_FOOT,
+                                CPLAtof( SRS_UL_US_FOOT_CONV ) );
+            /*
+            ** Leave as 'Foot (International)' or SRS_UL_FOOT instead of
+            ** SRS_UL_INTL_FOOT due to historical usage
+            */
+            else if( EQUAL( pszValue,"ft" ) )
+                SetLinearUnits( SRS_UL_FOOT,
+                                CPLAtof( SRS_UL_FOOT_CONV) );
+            else if( EQUAL( pszValue,"yd" ) )
+                SetLinearUnits( SRS_UL_INTL_YARD,
+                                CPLAtof( SRS_UL_INTL_YARD_CONV ) );
+            else if( EQUAL( pszValue,"us-yd" ) )
+                SetLinearUnits( SRS_UL_US_YARD,
+                                CPLAtof( SRS_UL_US_YARD_CONV ) );
+            else if( EQUAL( pszValue,"dm" ) )
+                SetLinearUnits( SRS_UL_DECIMETER, 
+                                CPLAtof( SRS_UL_DECIMETER_CONV ) );
+            else if( EQUAL( pszValue,"cm" ) )
+                SetLinearUnits( SRS_UL_CENTIMETER,
+                                CPLAtof( SRS_UL_CENTIMETER_CONV ) );
+            else if( EQUAL( pszValue,"mm" ) )
+                SetLinearUnits( SRS_UL_MILLIMETER,
+                                CPLAtof( SRS_UL_MILLIMETER_CONV ) );
+            else if( EQUAL( pszValue,"kmi" ) )
+                SetLinearUnits( SRS_UL_INTL_NAUT_MILE,
+                                CPLAtof( SRS_UL_INTL_NAUT_MILE_CONV ) );
+            else if( EQUAL( pszValue,"in" ) )
+                SetLinearUnits( SRS_UL_INTL_INCH,
+                                CPLAtof( SRS_UL_INTL_INCH_CONV ) );
+            else if( EQUAL( pszValue,"mi" ) )
+                SetLinearUnits( SRS_UL_INTL_STAT_MILE,
+                                CPLAtof( SRS_UL_INTL_STAT_MILE_CONV ) );
+            else if( EQUAL( pszValue,"fath" ) )
+                SetLinearUnits( SRS_UL_INTL_FATHOM,
+                                CPLAtof( SRS_UL_INTL_FATHOM_CONV ) );
+            else if( EQUAL( pszValue,"ch" ) )
+                SetLinearUnits( SRS_UL_INTL_CHAIN,
+                                CPLAtof( SRS_UL_INTL_CHAIN_CONV ) );
+            else if( EQUAL( pszValue,"link" ) )
+                SetLinearUnits( SRS_UL_INTL_LINK,
+                                CPLAtof( SRS_UL_INTL_LINK_CONV ) );
+            else if( EQUAL( pszValue,"us-in" ) )
+                SetLinearUnits( SRS_UL_US_INCH,
+                                CPLAtof( SRS_UL_US_INCH_CONV ) );
+            else if( EQUAL( pszValue, "us-ch" ) )
+                SetLinearUnits( SRS_UL_US_CHAIN,
+                                CPLAtof( SRS_UL_US_CHAIN_CONV ) );
+            else if( EQUAL( pszValue, "us-mi" ) )
+                SetLinearUnits( SRS_UL_US_STAT_MILE,
+                                CPLAtof( SRS_UL_US_STAT_MILE_CONV ) );
+            else if( EQUAL( pszValue, "ind-yd" ) )
+                SetLinearUnits( SRS_UL_INDIAN_YARD,
+                                CPLAtof( SRS_UL_INDIAN_YARD_CONV ) );
+            else if( EQUAL( pszValue, "ind-ft" ) )
+                SetLinearUnits( SRS_UL_INDIAN_FOOT,
+                                CPLAtof( SRS_UL_INDIAN_FOOT_CONV ) );
+            else if( EQUAL( pszValue, "ind-ch" ) )
+                SetLinearUnits( SRS_UL_INDIAN_CHAIN,
+                                CPLAtof( SRS_UL_INDIAN_CHAIN_CONV ) );
             else // This case is untranslatable.  Should add all proj.4 unts
                 SetLinearUnits( pszValue, 1.0 );
         }
@@ -1169,6 +1233,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Handle geoidgrids via an extension node and COMPD_CS.           */
 /* -------------------------------------------------------------------- */
     pszValue = CSLFetchNameValue(papszNV, "geoidgrids");
+    OGR_SRSNode *poVERT_CS = NULL;
     if( pszValue != NULL )
     {
         OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
@@ -1182,32 +1247,23 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         SetNode( "COMPD_CS", osName );
         GetRoot()->AddChild( poHorizSRS );
 
-        OGR_SRSNode *poVertSRS;
-        
-        poVertSRS = new OGR_SRSNode( "VERT_CS" );
-        GetRoot()->AddChild( poVertSRS );
-        poVertSRS->AddChild( new OGR_SRSNode( "Unnamed" ) );
+        poVERT_CS = new OGR_SRSNode( "VERT_CS" );
+        GetRoot()->AddChild( poVERT_CS );
+        poVERT_CS->AddChild( new OGR_SRSNode( "Unnamed" ) );
 
         CPLString osTarget = GetRoot()->GetValue();
         osTarget += "|VERT_CS|VERT_DATUM";
 
         SetNode( osTarget, "Unnamed" );
         
-        poVertSRS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
+        poVERT_CS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
         SetExtension( osTarget, "PROJ4_GRIDS", pszValue );
-
-        OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
-
-        poAxis->AddChild( new OGR_SRSNode( "Up" ) );
-        poAxis->AddChild( new OGR_SRSNode( "UP" ) );
-        
-        poVertSRS->AddChild( poAxis );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Handle vertical units.                                          */
 /* -------------------------------------------------------------------- */
-    if( GetRoot()->GetNode( "VERT_CS" ) != NULL )
+    if( poVERT_CS != NULL )
     {
         const char *pszUnitName = NULL;
         const char *pszUnitConv = NULL;
@@ -1270,25 +1326,52 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
         if( pszUnitName != NULL )
         {
-            OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
             OGR_SRSNode *poUnits; 
 
             poUnits = new OGR_SRSNode( "UNIT" );
             poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
             poUnits->AddChild( new OGR_SRSNode( pszUnitConv ) );
-            
+
             poVERT_CS->AddChild( poUnits );
         }
     }
 
+    /* Add AXIS to VERT_CS node */
+    if( poVERT_CS != NULL )
+    {
+        OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
+
+        poAxis->AddChild( new OGR_SRSNode( "Up" ) );
+        poAxis->AddChild( new OGR_SRSNode( "UP" ) );
+
+        poVERT_CS->AddChild( poAxis );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      do we want to insert a PROJ.4 EXTENSION item?                   */
 /* -------------------------------------------------------------------- */
     if( strstr(pszProj4,"wktext") != NULL || bAddProj4Extension )
         SetExtension( GetRoot()->GetValue(), "PROJ4", pszProj4 );
-        
+
+/* -------------------------------------------------------------------- */
+/*      Preserve authority (for example IGNF)                           */
+/* -------------------------------------------------------------------- */
+    const char *pszINIT = CSLFetchNameValue(papszNV,"init");
+    const char *pszColumn;
+    if( pszINIT != NULL && (pszColumn = strchr(pszINIT, ':')) != NULL &&
+        GetRoot()->FindChild( "AUTHORITY" ) < 0 )
+    {
+        CPLString osAuthority;
+        osAuthority.assign(pszINIT, pszColumn - pszINIT);
+        OGR_SRSNode* poAuthNode = new OGR_SRSNode( "AUTHORITY" );
+        poAuthNode->AddChild( new OGR_SRSNode( osAuthority ) );
+        poAuthNode->AddChild( new OGR_SRSNode( pszColumn + 1 ) );
+
+        GetRoot()->AddChild( poAuthNode );
+    }
+
     CSLDestroy( papszNV );
-    
+
     return OGRERR_NONE;
 }
 
diff --git a/ogr/ogr_srs_usgs.cpp b/ogr/ogr_srs_usgs.cpp
index 4c30093..de0d50a 100644
--- a/ogr/ogr_srs_usgs.cpp
+++ b/ogr/ogr_srs_usgs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_usgs.cpp 24243 2012-04-15 04:36:02Z warmerdam $
+ * $Id: ogr_srs_usgs.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from USGS georeferencing
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_usgs.cpp 24243 2012-04-15 04:36:02Z warmerdam $");
+CPL_CVSID("$Id: ogr_srs_usgs.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*  GCTP projection codes.                                              */
diff --git a/ogr/ogr_srs_validate.cpp b/ogr/ogr_srs_validate.cpp
index b73eedc..351fc77 100644
--- a/ogr/ogr_srs_validate.cpp
+++ b/ogr/ogr_srs_validate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_validate.cpp 24323 2012-04-27 05:45:18Z warmerdam $
+ * $Id: ogr_srs_validate.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of the OGRSpatialReference::Validate() method and
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +31,9 @@
 
 #include "ogr_spatialref.h"
 #include "ogr_p.h"
+#include "osr_cs_wkt.h"
 
-CPL_CVSID("$Id: ogr_srs_validate.cpp 24323 2012-04-27 05:45:18Z warmerdam $");
+CPL_CVSID("$Id: ogr_srs_validate.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* why would fipszone and zone be paramers when they relate to a composite
    projection which renders done into a non-zoned projection? */
@@ -567,7 +569,36 @@ OGRErr OGRSpatialReference::Validate()
         return OGRERR_CORRUPT_DATA;
     }
 
-    return Validate(poRoot);
+    OGRErr eErr = Validate(poRoot);
+
+    /* Even if hand-validation has succeeded, try a more formal validation */
+    /* using the CT spec grammar */
+    static int bUseCTGrammar = -1;
+    if( bUseCTGrammar < 0 )
+        bUseCTGrammar = CSLTestBoolean(CPLGetConfigOption("OSR_USE_CT_GRAMMAR", "TRUE"));
+
+    if( eErr == OGRERR_NONE && bUseCTGrammar )
+    {
+        osr_cs_wkt_parse_context sContext;
+        char* pszWKT = NULL;
+
+        exportToWkt(&pszWKT);
+
+        sContext.pszInput = pszWKT;
+        sContext.pszLastSuccess = pszWKT;
+        sContext.pszNext = pszWKT;
+        sContext.szErrorMsg[0] = '\0';
+
+        if( osr_cs_wkt_parse(&sContext) != 0 )
+        {
+            CPLDebug( "OGRSpatialReference::Validate", "%s",
+                      sContext.szErrorMsg );
+            eErr = OGRERR_CORRUPT_DATA;
+        }
+
+        CPLFree(pszWKT);
+    }
+    return eErr;
 }
 
 
@@ -615,6 +646,11 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 if (eErr != OGRERR_NONE)
                     return eErr;
             }
+            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            {
+                // We do not try to control the sub-organization of 
+                // EXTENSION nodes.
+            }
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
@@ -1058,6 +1094,11 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                     return OGRERR_CORRUPT_DATA;
                 }
             }
+            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            {
+                // We do not try to control the sub-organization of 
+                // EXTENSION nodes.
+            }
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
diff --git a/ogr/ogr_srs_xml.cpp b/ogr/ogr_srs_xml.cpp
index c4a1f69..bca763f 100644
--- a/ogr/ogr_srs_xml.cpp
+++ b/ogr/ogr_srs_xml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_xml.cpp 25019 2012-09-30 13:25:39Z rouault $
+ * $Id: ogr_srs_xml.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to OGC XML (014r4).
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam (warmerdam at pobox.com)
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogr_srsnode.cpp b/ogr/ogr_srsnode.cpp
index 4bba46a..5b6858b 100644
--- a/ogr/ogr_srsnode.cpp
+++ b/ogr/ogr_srsnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srsnode.cpp 26289 2013-08-10 18:05:31Z rouault $
+ * $Id: ogr_srsnode.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGR_SRSNode class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogr_srsnode.cpp 26289 2013-08-10 18:05:31Z rouault $");
+CPL_CVSID("$Id: ogr_srsnode.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGR_SRSNode()                             */
diff --git a/ogr/ograssemblepolygon.cpp b/ogr/ograssemblepolygon.cpp
index dace951..f748249 100644
--- a/ogr/ograssemblepolygon.cpp
+++ b/ogr/ograssemblepolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograssemblepolygon.cpp 23327 2011-11-05 20:03:42Z rouault $
+ * $Id: ograssemblepolygon.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Reader
  * Purpose:  Implements polygon assembly from a bunch of arcs.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_api.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograssemblepolygon.cpp 23327 2011-11-05 20:03:42Z rouault $");
+CPL_CVSID("$Id: ograssemblepolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            CheckPoints()                             */
diff --git a/ogr/ogrct.cpp b/ogr/ogrct.cpp
index 93ae0e3..3b4c0e7 100644
--- a/ogr/ogrct.cpp
+++ b/ogr/ogrct.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrct.cpp 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: ogrct.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSCoordinateTransformation class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -38,7 +39,7 @@
 #include "proj_api.h"
 #endif
 
-CPL_CVSID("$Id: ogrct.cpp 25627 2013-02-10 10:17:19Z rouault $");
+CPL_CVSID("$Id: ogrct.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* ==================================================================== */
 /*      PROJ.4 interface stuff.                                         */
@@ -117,7 +118,6 @@ class OGRProj4CT : public OGRCoordinateTransformation
     void        *psPJSource;
     int         bSourceLatLong;
     double      dfSourceToRadians;
-    double      dfSourceFromRadians;
     int         bSourceWrap;
     double      dfSourceWrapLong;
     
@@ -125,11 +125,12 @@ class OGRProj4CT : public OGRCoordinateTransformation
     OGRSpatialReference *poSRSTarget;
     void        *psPJTarget;
     int         bTargetLatLong;
-    double      dfTargetToRadians;
     double      dfTargetFromRadians;
     int         bTargetWrap;
     double      dfTargetWrapLong;
 
+    int         bIdentityTransform;
+
     int         nErrorCount;
     
     int         bCheckWithInvertProj;
@@ -463,6 +464,7 @@ OGRProj4CT::OGRProj4CT()
     psPJSource = NULL;
     psPJTarget = NULL;
     
+    bIdentityTransform = FALSE;
     nErrorCount = 0;
     
     bCheckWithInvertProj = FALSE;
@@ -569,7 +571,6 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
 /*      systems.                                                        */
 /* -------------------------------------------------------------------- */
     dfSourceToRadians = DEG_TO_RAD;
-    dfSourceFromRadians = RAD_TO_DEG;
     bSourceWrap = FALSE;
     dfSourceWrapLong = 0.0;
 
@@ -581,12 +582,9 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
             dfSourceToRadians = atof(poUNITS->GetChild(1)->GetValue());
             if( dfSourceToRadians == 0.0 )
                 dfSourceToRadians = DEG_TO_RAD;
-            else
-                dfSourceFromRadians = 1 / dfSourceToRadians;
         }
     }
 
-    dfTargetToRadians = DEG_TO_RAD;
     dfTargetFromRadians = RAD_TO_DEG;
     bTargetWrap = FALSE;
     dfTargetWrapLong = 0.0;
@@ -596,10 +594,8 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
         if( poUNITS && poUNITS->GetChildCount() >= 2 )
         {
-            dfTargetToRadians = atof(poUNITS->GetChild(1)->GetValue());
-            if( dfTargetToRadians == 0.0 )
-                dfTargetToRadians = DEG_TO_RAD;
-            else
+            double dfTargetToRadians = atof(poUNITS->GetChild(1)->GetValue());
+            if( dfTargetToRadians != 0.0 )
                 dfTargetFromRadians = 1 / dfTargetToRadians;
         }
     }
@@ -651,17 +647,17 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     // means debug output could be one "increment" late. 
     static int   nDebugReportCount = 0;
 
-    char        *pszProj4Defn = NULL;
+    char        *pszSrcProj4Defn = NULL;
 
-    if( poSRSSource->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
+    if( poSRSSource->exportToProj4( &pszSrcProj4Defn ) != OGRERR_NONE )
     {
-        CPLFree( pszProj4Defn );
+        CPLFree( pszSrcProj4Defn );
         return FALSE;
     }
 
-    if( strlen(pszProj4Defn) == 0 )
+    if( strlen(pszSrcProj4Defn) == 0 )
     {
-        CPLFree( pszProj4Defn );
+        CPLFree( pszSrcProj4Defn );
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "No PROJ.4 translation for source SRS, coordinate\n"
                   "transformation initialization has failed." );
@@ -669,9 +665,9 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     }
 
     if (pjctx)
-        psPJSource = pfn_pj_init_plus_ctx( pjctx, pszProj4Defn );
+        psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
     else
-        psPJSource = pfn_pj_init_plus( pszProj4Defn );
+        psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );
     
     if( psPJSource == NULL )
     {
@@ -683,7 +679,7 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
             CPLMutexHolderD(&hPROJMutex);
             CPLError( CE_Failure, CPLE_NotSupported, 
                       "Failed to initialize PROJ.4 with `%s'.\n%s", 
-                      pszProj4Defn, pfn_pj_strerrno(pj_errno) );
+                      pszSrcProj4Defn, pfn_pj_strerrno(pj_errno) );
         }
         else if( pfn_pj_get_errno_ref != NULL
             && pfn_pj_strerrno != NULL )
@@ -692,38 +688,42 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
 
             CPLError( CE_Failure, CPLE_NotSupported, 
                       "Failed to initialize PROJ.4 with `%s'.\n%s", 
-                      pszProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
+                      pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
         }
         else
         {
             CPLError( CE_Failure, CPLE_NotSupported, 
                       "Failed to initialize PROJ.4 with `%s'.\n", 
-                      pszProj4Defn );
+                      pszSrcProj4Defn );
         }
     }
     
     if( nDebugReportCount < 10 )
-        CPLDebug( "OGRCT", "Source: %s", pszProj4Defn );
-    
-    CPLFree( pszProj4Defn );
+        CPLDebug( "OGRCT", "Source: %s", pszSrcProj4Defn );
 
     if( psPJSource == NULL )
+    {
+        CPLFree( pszSrcProj4Defn );
         return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Establish PROJ.4 handle for target if projection.               */
 /* -------------------------------------------------------------------- */
-    pszProj4Defn = NULL;
 
-    if( poSRSTarget->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
+    char        *pszDstProj4Defn = NULL;
+
+    if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
     {
-        CPLFree( pszProj4Defn );
+        CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
         return FALSE;
     }
 
-    if( strlen(pszProj4Defn) == 0 )
+    if( strlen(pszDstProj4Defn) == 0 )
     {
-        CPLFree( pszProj4Defn );
+        CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "No PROJ.4 translation for destination SRS, coordinate\n"
                   "transformation initialization has failed." );
@@ -731,25 +731,43 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     }
 
     if (pjctx)
-        psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszProj4Defn );
+        psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
     else
-        psPJTarget = pfn_pj_init_plus( pszProj4Defn );
+        psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );
     
     if( psPJTarget == NULL )
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "Failed to initialize PROJ.4 with `%s'.", 
-                  pszProj4Defn );
+                  pszDstProj4Defn );
     
     if( nDebugReportCount < 10 )
     {
-        CPLDebug( "OGRCT", "Target: %s", pszProj4Defn );
+        CPLDebug( "OGRCT", "Target: %s", pszDstProj4Defn );
         nDebugReportCount++;
     }
 
-    CPLFree( pszProj4Defn );
-    
     if( psPJTarget == NULL )
+    {
+        CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
         return FALSE;
+    }
+
+    /* Determine if we really have a transformation to do */
+    bIdentityTransform = (strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0);
+
+    /* In case of identity transform, under the following conditions, */
+    /* we can also avoid transforming from deegrees <--> radians. */
+    if( bIdentityTransform && bSourceLatLong && !bSourceWrap &&
+        bTargetLatLong && !bTargetWrap &&
+        abs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
+    {
+        /*bSourceLatLong = FALSE;
+        bTargetLatLong = FALSE;*/
+    }
+
+    CPLFree( pszSrcProj4Defn );
+    CPLFree( pszDstProj4Defn );
 
     return TRUE;
 }
@@ -858,14 +876,16 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 /* -------------------------------------------------------------------- */
 /*      Do the transformation using PROJ.4.                             */
 /* -------------------------------------------------------------------- */
-    if (pjctx == NULL)
+    if( !bIdentityTransform && pjctx == NULL )
     {
         /* The mutex has already been created */
         CPLAssert(hPROJMutex != NULL);
         CPLAcquireMutex(hPROJMutex, 1000.0);
     }
-        
-    if (bCheckWithInvertProj)
+
+    if( bIdentityTransform )
+        err = 0;
+    else if (bCheckWithInvertProj)
     {
         /* For some projections, we cannot detect if we are trying to reproject */
         /* coordinates outside the validity area of the projection. So let's do */
@@ -962,7 +982,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
         return FALSE;
     }
 
-    if (pjctx == NULL)
+    if( !bIdentityTransform && pjctx == NULL )
         CPLReleaseMutex(hPROJMutex);
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrfeature.cpp b/ogr/ogrfeature.cpp
index fa9ad6d..a157574 100644
--- a/ogr/ogrfeature.cpp
+++ b/ogr/ogrfeature.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeature.cpp 25692 2013-03-01 15:16:20Z rouault $
+ * $Id: ogrfeature.cpp 27110 2014-03-28 21:29:20Z rouault $
  * 
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeature class implementation. 
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_p.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrfeature.cpp 25692 2013-03-01 15:16:20Z rouault $");
+CPL_CVSID("$Id: ogrfeature.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 /************************************************************************/
 /*                             OGRFeature()                             */
@@ -62,13 +63,14 @@ OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn )
     poDefn = poDefnIn;
 
     nFID = OGRNullFID;
-    
-    poGeometry = NULL;
 
     // Allocate array of fields and initialize them to the unset special value
     pauFields = (OGRField *) CPLMalloc( poDefn->GetFieldCount() *
                                         sizeof(OGRField) );
 
+    papoGeometries = (OGRGeometry **) CPLCalloc( poDefn->GetGeomFieldCount(),
+                                        sizeof(OGRGeometry*) );
+
     for( int i = 0; i < poDefn->GetFieldCount(); i++ )
     {
         pauFields[i].Set.nMarker1 = OGRUnsetMarker;
@@ -111,10 +113,10 @@ OGRFeatureH OGR_F_Create( OGRFeatureDefnH hDefn )
 OGRFeature::~OGRFeature()
 
 {
-    if( poGeometry != NULL )
-        delete poGeometry;
+    int i;
 
-    for( int i = 0; i < poDefn->GetFieldCount(); i++ )
+    int nFieldcount = poDefn->GetFieldCount();
+    for( i = 0; i < nFieldcount; i++ )
     {
         OGRFieldDefn    *poFDefn = poDefn->GetFieldDefn(i);
         
@@ -148,9 +150,16 @@ OGRFeature::~OGRFeature()
         }
     }
     
+    int nGeomFieldCount = poDefn->GetGeomFieldCount();
+    for( i = 0; i < nGeomFieldCount; i++ )
+    {
+        delete papoGeometries[i];
+    }
+    
     poDefn->Release();
 
     CPLFree( pauFields );
+    CPLFree( papoGeometries );
     CPLFree(m_pszStyleString);
     CPLFree(m_pszTmpFieldValue);
 }
@@ -289,12 +298,10 @@ OGRFeatureDefnH OGR_F_GetDefnRef( OGRFeatureH hFeat )
 OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
 
 {
-    delete poGeometry;
-    poGeometry = poGeomIn;
-
-    // I should be verifying that the geometry matches the defn's type.
-    
-    return OGRERR_NONE;
+    if( GetGeomFieldCount() > 0 )
+        return SetGeomFieldDirectly(0, poGeomIn);
+    else
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -352,16 +359,10 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
 OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
 
 {
-    delete poGeometry;
-
-    if( poGeomIn != NULL )
-        poGeometry = poGeomIn->clone();
+    if( GetGeomFieldCount() > 0 )
+        return SetGeomField(0, poGeomIn);
     else
-        poGeometry = NULL;
-
-    // I should be verifying that the geometry matches the defn's type.
-    
-    return OGRERR_NONE;
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -413,9 +414,27 @@ OGRErr OGR_F_SetGeometry( OGRFeatureH hFeat, OGRGeometryH hGeom )
 OGRGeometry *OGRFeature::StealGeometry()
 
 {
-    OGRGeometry *poReturn = poGeometry;
-    poGeometry = NULL;
-    return poReturn;
+    if( GetGeomFieldCount() > 0 )
+    {
+        OGRGeometry *poReturn = papoGeometries[0];
+        papoGeometries[0] = NULL;
+        return poReturn;
+    }
+    else
+        return NULL;
+}
+
+OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
+
+{
+    if( iGeomField >= 0 && iGeomField < GetGeomFieldCount() )
+    {
+        OGRGeometry *poReturn = papoGeometries[iGeomField];
+        papoGeometries[iGeomField] = NULL;
+        return poReturn;
+    }
+    else
+        return NULL;
 }
 
 /************************************************************************/
@@ -453,10 +472,21 @@ OGRGeometryH OGR_F_StealGeometry( OGRFeatureH hFeat )
  * \brief Fetch pointer to feature geometry.
  *
  * This method is the same as the C function OGR_F_GetGeometryRef().
+ * 
+ * Starting with GDAL 1.11, this is equivalent to calling
+ * OGRFeature::GetGeomFieldRef(0).
  *
  * @return pointer to internal feature geometry.  This object should
  * not be modified.
  */
+OGRGeometry *OGRFeature::GetGeometryRef()
+
+{
+    if( GetGeomFieldCount() > 0 )
+        return GetGeomFieldRef(0);
+    else
+        return NULL;
+}
 
 /************************************************************************/
 /*                        OGR_F_GetGeometryRef()                        */
@@ -480,6 +510,228 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
     return (OGRGeometryH) ((OGRFeature *) hFeat)->GetGeometryRef();
 }
 
+
+/************************************************************************/
+/*                           GetGeomFieldRef()                          */
+/************************************************************************/
+
+/**
+ * \brief Fetch pointer to feature geometry.
+ *
+ * This method is the same as the C function OGR_F_GetGeomFieldRef().
+ *
+ * @param iField geometry field to get.
+ *
+ * @return pointer to internal feature geometry.  This object should
+ * not be modified.
+ *
+ * @since GDAL 1.11
+ */
+OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
+
+{
+    if( iField < 0 || iField >= GetGeomFieldCount() )
+        return NULL;
+    else
+        return papoGeometries[iField];
+}
+
+/************************************************************************/
+/*                           GetGeomFieldRef()                          */
+/************************************************************************/
+
+/**
+ * \brief Fetch pointer to feature geometry.
+ *
+ * @param pszFName name of geometry field to get.
+ *
+ * @return pointer to internal feature geometry.  This object should
+ * not be modified.
+ *
+ * @since GDAL 1.11
+ */
+OGRGeometry *OGRFeature::GetGeomFieldRef(const char* pszFName)
+
+{
+    int iField = GetGeomFieldIndex(pszFName);
+    if( iField < 0 )
+        return NULL;
+    else
+        return papoGeometries[iField];
+}
+
+/************************************************************************/
+/*                       OGR_F_GetGeomFieldRef()                        */
+/************************************************************************/
+
+/**
+ * \brief Fetch an handle to feature geometry.
+ *
+ * This function is the same as the C++ method OGRFeature::GetGeomFieldRef().
+ *
+ * @param hFeat handle to the feature to get geometry from.
+ * @param iField geometry field to get.
+ * @return an handle to internal feature geometry.  This object should
+ * not be modified.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeometryH OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldRef", NULL );
+
+    return (OGRGeometryH) ((OGRFeature *) hFeat)->GetGeomFieldRef(iField);
+}
+
+/************************************************************************/
+/*                       SetGeomFieldDirectly()                         */
+/************************************************************************/
+
+/**
+ * \brief Set feature geometry of a specified geometry field.
+ *
+ * This method updates the features geometry, and operate exactly as
+ * SetGeomField(), except that this method assumes ownership of the
+ * passed geometry.
+ *
+ * This method is the same as the C function OGR_F_SetGeomFieldDirectly().
+ *
+ * @param iField geometry field to set.
+ * @param poGeomIn new geometry to apply to feature. Passing NULL value here
+ * is correct and it will result in deallocation of currently assigned geometry
+ * without assigning new one.
+ *
+ * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
+ * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
+ * OGRFeatureDefn (checking not yet implemented). 
+ *
+ * @since GDAL 1.11
+ */ 
+
+OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
+
+{
+    if( iField < 0 || iField >= GetGeomFieldCount() )
+        return OGRERR_FAILURE;
+
+    delete papoGeometries[iField];
+    papoGeometries[iField] = poGeomIn;
+
+    // I should be verifying that the geometry matches the defn's type.
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                     OGR_F_SetGeomFieldDirectly()                     */
+/************************************************************************/
+
+/**
+ * \brief Set feature geometry of a specified geometry field.
+ *
+ * This function updates the features geometry, and operate exactly as
+ * SetGeomField(), except that this function assumes ownership of the
+ * passed geometry.
+ *
+ * This function is the same as the C++ method 
+ * OGRFeature::SetGeomFieldDirectly.
+ *
+ * @param hFeat handle to the feature on which to apply the geometry.
+ * @param iField geometry field to set.
+ * @param hGeom handle to the new geometry to apply to feature.
+ *
+ * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
+ * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
+ * OGRFeatureDefn (checking not yet implemented).
+ *
+ * @since GDAL 1.11
+ */ 
+
+OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
+                                   OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomFieldDirectly", CE_Failure );
+
+    return ((OGRFeature *) hFeat)->SetGeomFieldDirectly(iField,
+                                                        (OGRGeometry *) hGeom);
+}
+
+/************************************************************************/
+/*                            SetGeomField()                            */
+/************************************************************************/
+
+/**
+ * \brief Set feature geometry of a specified geometry field.
+ *
+ * This method updates the features geometry, and operate exactly as
+ * SetGeomFieldDirectly(), except that this method does not assume ownership
+ * of the passed geometry, but instead makes a copy of it. 
+ *
+ * This method is the same as the C function OGR_F_SetGeomField().
+ *
+ * @param iField geometry field to set.
+ * @param poGeomIn new geometry to apply to feature. Passing NULL value here
+ * is correct and it will result in deallocation of currently assigned geometry
+ * without assigning new one.
+ *
+ * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
+ * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
+ * OGRFeatureDefn (checking not yet implemented).
+ *
+ * @since GDAL 1.11
+ */ 
+
+OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
+
+{
+    if( iField < 0 || iField >= GetGeomFieldCount() )
+        return OGRERR_FAILURE;
+
+    delete papoGeometries[iField];
+
+    if( poGeomIn != NULL )
+        papoGeometries[iField] = poGeomIn->clone();
+    else
+        papoGeometries[iField] = NULL;
+
+    // I should be verifying that the geometry matches the defn's type.
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        OGR_F_SetGeomField()                          */
+/************************************************************************/
+
+/**
+ * \brief Set feature geometry of a specified geometry field.
+ *
+ * This function updates the features geometry, and operate exactly as
+ * SetGeometryDirectly(), except that this function does not assume ownership
+ * of the passed geometry, but instead makes a copy of it. 
+ *
+ * This function is the same as the C++ OGRFeature::SetGeomField().
+ *
+ * @param hFeat handle to the feature on which new geometry is applied to.
+ * @param iField geometry field to set.
+ * @param hGeom handle to the new geometry to apply to feature.
+ *
+ * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
+ * the geometry type is illegal for the OGRFeatureDefn (checking not yet
+ * implemented). 
+ */ 
+
+OGRErr OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomField", CE_Failure );
+
+    return ((OGRFeature *) hFeat)->SetGeomField(iField, (OGRGeometry *) hGeom);
+}
+
 /************************************************************************/
 /*                               Clone()                                */
 /************************************************************************/
@@ -498,14 +750,17 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
 OGRFeature *OGRFeature::Clone()
 
 {
+    int i;
     OGRFeature  *poNew = new OGRFeature( poDefn );
 
-    poNew->SetGeometry( poGeometry );
-
-    for( int i = 0; i < poDefn->GetFieldCount(); i++ )
+    for( i = 0; i < poDefn->GetFieldCount(); i++ )
     {
         poNew->SetField( i, pauFields + i );
     }
+    for( i = 0; i < poDefn->GetGeomFieldCount(); i++ )
+    {
+        poNew->SetGeomField( i, papoGeometries[i] );
+    }
 
     if( GetStyleString() != NULL )
         poNew->SetStyleString(GetStyleString());
@@ -662,6 +917,143 @@ int OGR_F_GetFieldIndex( OGRFeatureH hFeat, const char *pszName )
     return ((OGRFeature *) hFeat)->GetFieldIndex( pszName );
 }
 
+
+/************************************************************************/
+/*                         GetGeomFieldCount()                          */
+/************************************************************************/
+
+/**
+ * \fn int OGRFeature::GetGeomFieldCount();
+ *
+ * \brief Fetch number of geometry fields on this feature.
+ * This will always be the same
+ * as the geometry field count for the OGRFeatureDefn.
+ *
+ * This method is the same as the C function OGR_F_GetGeomFieldCount().
+ *
+ * @return count of geometry fields.
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                      OGR_F_GetGeomFieldCount()                       */
+/************************************************************************/
+
+/**
+ * \brief Fetch number of geometry fields on this feature
+ * This will always be the same
+ * as the geometry field count for the OGRFeatureDefn.
+ *
+ * This function is the same as the C++ method OGRFeature::GetGeomFieldCount().
+ *
+ * @param hFeat handle to the feature to get the geometry fields count from.
+ * @return count of geometry fields.
+ *
+ * @since GDAL 1.11
+ */
+
+int OGR_F_GetGeomFieldCount( OGRFeatureH hFeat )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldCount", 0 );
+
+    return ((OGRFeature *) hFeat)->GetGeomFieldCount();
+}
+
+/************************************************************************/
+/*                        GetGeomFieldDefnRef()                         */
+/************************************************************************/
+
+/**
+ * \fn OGRGeomFieldDefn *OGRFeature::GetGeomFieldDefnRef( int iGeomField );
+ *
+ * \brief Fetch definition for this geometry field.
+ *
+ * This method is the same as the C function OGR_F_GetGeomFieldDefnRef().
+ *
+ * @param iGeomField the field to fetch, from 0 to GetGeomFieldCount()-1.
+ *
+ * @return the field definition (from the OGRFeatureDefn).  This is an
+ * internal reference, and should not be deleted or modified.
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                       OGR_F_GetGeomFieldDefnRef()                    */
+/************************************************************************/
+
+/**
+ * \brief Fetch definition for this geometry field.
+ *
+ * This function is the same as the C++ method OGRFeature::GetGeomFieldDefnRef().
+ *
+ * @param hFeat handle to the feature on which the field is found.
+ * @param i the field to fetch, from 0 to GetGeomFieldCount()-1.
+ *
+ * @return an handle to the field definition (from the OGRFeatureDefn).
+ * This is an internal reference, and should not be deleted or modified.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldDefnRef", NULL );
+
+    return (OGRGeomFieldDefnH) ((OGRFeature *) hFeat)->GetGeomFieldDefnRef(i);
+}
+
+/************************************************************************/
+/*                           GetGeomFieldIndex()                            */
+/************************************************************************/
+
+/**
+ * \fn int OGRFeature::GetGeomFieldIndex( const char * pszName );
+ * 
+ * \brief Fetch the geometry field index given geometry field name.
+ *
+ * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method. 
+ *
+ * This method is the same as the C function OGR_F_GetGeomFieldIndex().
+ *
+ * @param pszName the name of the geometry field to search for. 
+ *
+ * @return the geometry field index, or -1 if no matching geometry field is found.
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                       OGR_F_GetGeomFieldIndex()                      */
+/************************************************************************/
+
+/**
+ * \brief Fetch the geometry field index given geometry field name.
+ *
+ * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method. 
+ *
+ * This function is the same as the C++ method OGRFeature::GetGeomFieldIndex().
+ *
+ * @param hFeat handle to the feature on which the geometry field is found.
+ * @param pszName the name of the geometry field to search for. 
+ *
+ * @return the geometry field index, or -1 if no matching geometry field is found.
+ *
+ * @since GDAL 1.11
+ */
+
+int OGR_F_GetGeomFieldIndex( OGRFeatureH hFeat, const char *pszName )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldIndex", 0 );
+
+    return ((OGRFeature *) hFeat)->GetGeomFieldIndex( pszName );
+}
+
+
 /************************************************************************/
 /*                             IsFieldSet()                             */
 /************************************************************************/
@@ -678,7 +1070,7 @@ int OGR_F_GetFieldIndex( OGRFeatureH hFeat, const char *pszName )
  * @return TRUE if the field has been set, otherwise false.
  */
 
-int OGRFeature::IsFieldSet( int iField ) const
+int OGRFeature::IsFieldSet( int iField )
 
 {
     int iSpecialField = iField - poDefn->GetFieldCount();
@@ -692,16 +1084,16 @@ int OGRFeature::IsFieldSet( int iField ) const
 
           case SPF_OGR_GEOM_WKT:
           case SPF_OGR_GEOMETRY:
-            return poGeometry != NULL;
+            return GetGeomFieldCount() > 0 && papoGeometries[0] != NULL;
 
           case SPF_OGR_STYLE:
             return ((OGRFeature *)this)->GetStyleString() != NULL;
 
           case SPF_OGR_GEOM_AREA:
-            if( poGeometry == NULL )
+            if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return FALSE;
 
-            return OGR_G_Area((OGRGeometryH)poGeometry) != 0.0;
+            return OGR_G_Area((OGRGeometryH)papoGeometries[0]) != 0.0;
 
           default:
             return FALSE;
@@ -885,9 +1277,9 @@ int OGRFeature::GetFieldAsInteger( int iField )
             return GetFID();
 
         case SPF_OGR_GEOM_AREA:
-            if( poGeometry == NULL )
+            if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0;
-            return (int)OGR_G_Area((OGRGeometryH)poGeometry);
+            return (int)OGR_G_Area((OGRGeometryH)papoGeometries[0]);
 
         default:
             return 0;
@@ -975,9 +1367,9 @@ double OGRFeature::GetFieldAsDouble( int iField )
             return GetFID();
 
         case SPF_OGR_GEOM_AREA:
-            if( poGeometry == NULL )
+            if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0.0;
-            return OGR_G_Area((OGRGeometryH)poGeometry);
+            return OGR_G_Area((OGRGeometryH)papoGeometries[0]);
 
         default:
             return 0.0;
@@ -1073,8 +1465,8 @@ const char *OGRFeature::GetFieldAsString( int iField )
             return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
 
           case SPF_OGR_GEOMETRY:
-            if( poGeometry )
-                return poGeometry->getGeometryName();
+            if( GetGeomFieldCount() > 0 && papoGeometries[0] != NULL )
+                return papoGeometries[0]->getGeometryName();
             else
                 return "";
 
@@ -1086,21 +1478,21 @@ const char *OGRFeature::GetFieldAsString( int iField )
 
           case SPF_OGR_GEOM_WKT:
           {
-              if( poGeometry == NULL )
+              if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                   return "";
 
-              if (poGeometry->exportToWkt( &m_pszTmpFieldValue ) == OGRERR_NONE )
+              if (papoGeometries[0]->exportToWkt( &m_pszTmpFieldValue ) == OGRERR_NONE )
                   return m_pszTmpFieldValue;
               else
                   return "";
           }
 
           case SPF_OGR_GEOM_AREA:
-            if( poGeometry == NULL )
+            if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return "";
 
             snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%.16g", 
-                      OGR_G_Area((OGRGeometryH)poGeometry) );
+                      OGR_G_Area((OGRGeometryH)papoGeometries[0]) );
             return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
 
           default:
@@ -1508,7 +1900,7 @@ const double *OGR_F_GetFieldAsDoubleList( OGRFeatureH hFeat, int iField,
  * modified, or freed.  Its lifetime may be very brief.
  */
 
-char **OGRFeature::GetFieldAsStringList( int iField ) const
+char **OGRFeature::GetFieldAsStringList( int iField )
 
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
@@ -2631,12 +3023,26 @@ void OGRFeature::DumpReadable( FILE * fpOut, char** papszOptions )
         }
     }
 
-    if( poGeometry != NULL )
+    int nGeomFieldCount = GetGeomFieldCount();
+    if( nGeomFieldCount > 0 )
     {
         const char* pszDisplayGeometry =
                 CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
         if ( ! (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "NO") ) )
-            poGeometry->dumpReadable( fpOut, "  ", papszOptions );
+        {
+            for( int iField = 0; iField < nGeomFieldCount; iField++ )
+            {
+                OGRGeomFieldDefn    *poFDefn = poDefn->GetGeomFieldDefn(iField);
+
+                if( papoGeometries[iField] != NULL )
+                {
+                    fprintf( fpOut, "  " );
+                    if( strlen(poFDefn->GetNameRef()) > 0 && GetGeomFieldCount() > 1 )
+                        fprintf( fpOut, "%s = ", poFDefn->GetNameRef() );
+                    papoGeometries[iField]->dumpReadable( fpOut, "", papszOptions );
+                }
+            }
+        }
     }
 
     fprintf( fpOut, "\n" );
@@ -2912,15 +3318,22 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
         }
     }
 
-    if( GetGeometryRef() == NULL && poFeature->GetGeometryRef() != NULL )
-        return FALSE;
+    int nGeomFieldCount = GetGeomFieldCount();
+    for( i = 0; i < nGeomFieldCount; i ++ )
+    {
+        OGRGeometry* poThisGeom = GetGeomFieldRef(i);
+        OGRGeometry* poOtherGeom = poFeature->GetGeomFieldRef(i);
 
-    if( GetGeometryRef() != NULL && poFeature->GetGeometryRef() == NULL )
-        return FALSE;
+        if( poThisGeom == NULL && poOtherGeom != NULL )
+            return FALSE;
 
-    if( GetGeometryRef() != NULL && poFeature->GetGeometryRef() != NULL 
-        && (!GetGeometryRef()->Equals( poFeature->GetGeometryRef() ) ) )
-        return FALSE;
+        if( poThisGeom != NULL && poOtherGeom == NULL )
+            return FALSE;
+
+        if( poThisGeom != NULL && poOtherGeom != NULL 
+            && (!poThisGeom->Equals( poOtherGeom ) ) )
+            return FALSE;
+    }
 
     return TRUE;
 }
@@ -3088,14 +3501,41 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
 {
     OGRErr      eErr;
 
+    if( poSrcFeature == this )
+        return OGRERR_FAILURE;
+
     SetFID( OGRNullFID );
 
 /* -------------------------------------------------------------------- */
 /*      Set the geometry.                                               */
 /* -------------------------------------------------------------------- */
-    eErr = SetGeometry( poSrcFeature->GetGeometryRef() );
-    if( eErr != OGRERR_NONE )
-        return eErr;
+    if( GetGeomFieldCount() == 1 )
+    {
+        OGRGeomFieldDefn* poGFieldDefn = GetGeomFieldDefnRef(0);
+
+        int iSrc = poSrcFeature->GetGeomFieldIndex(
+                                    poGFieldDefn->GetNameRef());
+        if( iSrc >= 0 )
+            SetGeomField( 0, poSrcFeature->GetGeomFieldRef(iSrc) );
+        else
+            /* whatever the geometry field names are. For backward compatibility */
+            SetGeomField( 0, poSrcFeature->GetGeomFieldRef(0) );
+    }
+    else
+    {
+        int i;
+        for(i = 0; i < GetGeomFieldCount(); i++)
+        {
+            OGRGeomFieldDefn* poGFieldDefn = GetGeomFieldDefnRef(i);
+
+            int iSrc = poSrcFeature->GetGeomFieldIndex(
+                                        poGFieldDefn->GetNameRef());
+            if( iSrc >= 0 )
+                SetGeomField( i, poSrcFeature->GetGeomFieldRef(iSrc) );
+            else
+                SetGeomField( i, NULL );
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Copy feature style string.                                      */
@@ -3506,6 +3946,56 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
 }
 
 /************************************************************************/
+/*                        RemapGeomFields()                             */
+/*                                                                      */
+/*      This is used to transform a feature "in place" from one         */
+/*      feature defn to another with minimum work.                      */
+/************************************************************************/
+
+OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn, 
+                                    int *panRemapSource )
+
+{
+    int  iDstField;
+    OGRGeometry** papoNewGeomFields;
+
+    if( poNewDefn == NULL )
+        poNewDefn = poDefn;
+
+    papoNewGeomFields = (OGRGeometry **) CPLCalloc( poNewDefn->GetGeomFieldCount(), 
+                                           sizeof(OGRGeometry*) );
+
+    for( iDstField = 0; iDstField < poDefn->GetGeomFieldCount(); iDstField++ )
+    {
+        if( panRemapSource[iDstField] == -1 )
+        {
+            papoNewGeomFields[iDstField] = NULL;
+        }
+        else
+        {
+            papoNewGeomFields[iDstField] =
+                papoGeometries[panRemapSource[iDstField]];
+        }
+    }
+
+    /* 
+    ** We really should be freeing memory for old columns that
+    ** are no longer present.  We don't for now because it is a bit messy
+    ** and would take too long to test.  
+    */
+
+/* -------------------------------------------------------------------- */
+/*      Apply new definition and fields.                                */
+/* -------------------------------------------------------------------- */
+    CPLFree( papoGeometries );
+    papoGeometries = papoNewGeomFields;
+
+    poDefn = poNewDefn;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                         OGR_F_GetStyleTable()                        */
 /************************************************************************/
 
diff --git a/ogr/ogrfeaturedefn.cpp b/ogr/ogrfeaturedefn.cpp
index 94d0135..2e4abba 100644
--- a/ogr/ogrfeaturedefn.cpp
+++ b/ogr/ogrfeaturedefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturedefn.cpp 24286 2012-04-21 19:17:26Z rouault $
+ * $Id: ogrfeaturedefn.cpp 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeatureDefn class implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrfeaturedefn.cpp 24286 2012-04-21 19:17:26Z rouault $");
+CPL_CVSID("$Id: ogrfeaturedefn.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 /************************************************************************/
 /*                           OGRFeatureDefn()                           */
@@ -57,8 +58,9 @@ OGRFeatureDefn::OGRFeatureDefn( const char * pszName )
     nRefCount = 0;
     nFieldCount = 0;
     papoFieldDefn = NULL;
-    eGeomType = wkbUnknown;
-    bIgnoreGeometry = FALSE;
+    nGeomFieldCount = 1;
+    papoGeomFieldDefn = (OGRGeomFieldDefn**) CPLMalloc(sizeof(OGRGeomFieldDefn*));
+    papoGeomFieldDefn[0] = new OGRGeomFieldDefn("", wkbUnknown);
     bIgnoreStyle = FALSE;
 }
 
@@ -108,6 +110,13 @@ OGRFeatureDefn::~OGRFeatureDefn()
     }
 
     CPLFree( papoFieldDefn );
+
+    for( int i = 0; i < nGeomFieldCount; i++ )
+    {
+        delete papoGeomFieldDefn[i];
+    }
+
+    CPLFree( papoGeomFieldDefn );
 }
 
 /************************************************************************/
@@ -182,15 +191,21 @@ void OGR_FD_Release( OGRFeatureDefnH hDefn )
 OGRFeatureDefn *OGRFeatureDefn::Clone()
 
 {
+    int i;
     OGRFeatureDefn *poCopy;
 
     poCopy = new OGRFeatureDefn( GetName() );
 
-    poCopy->SetGeomType( GetGeomType() );
-
-    for( int i = 0; i < GetFieldCount(); i++ )
+    GetFieldCount();
+    for( i = 0; i < nFieldCount; i++ )
         poCopy->AddFieldDefn( GetFieldDefn( i ) );
 
+    /* There is a default geometry field created at OGRFeatureDefn instanciation */
+    poCopy->DeleteGeomFieldDefn(0);
+    GetGeomFieldCount();
+    for( i = 0; i < nGeomFieldCount; i++ )
+        poCopy->AddGeomFieldDefn( GetGeomFieldDefn( i ) );
+
     return poCopy;
 }
 
@@ -208,6 +223,10 @@ OGRFeatureDefn *OGRFeatureDefn::Clone()
  * @return the name.  This name is internal and should not be modified, or
  * freed.
  */
+const char * OGRFeatureDefn::GetName()
+{
+    return pszFeatureClassName;
+}
 
 /************************************************************************/
 /*                           OGR_FD_GetName()                           */
@@ -241,6 +260,11 @@ const char *OGR_FD_GetName( OGRFeatureDefnH hDefn )
  * @return count of fields.
  */
 
+int OGRFeatureDefn::GetFieldCount()
+{
+    return nFieldCount;
+}
+
 /************************************************************************/
 /*                        OGR_FD_GetFieldCount()                        */
 /************************************************************************/
@@ -281,7 +305,7 @@ int OGR_FD_GetFieldCount( OGRFeatureDefnH hDefn )
 OGRFieldDefn *OGRFeatureDefn::GetFieldDefn( int iField )
 
 {
-    if( iField < 0 || iField >= nFieldCount )
+    if( iField < 0 || iField >= GetFieldCount() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
         return NULL;
@@ -339,6 +363,7 @@ OGRFieldDefnH OGR_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField )
 void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
 
 {
+    GetFieldCount();
     papoFieldDefn = (OGRFieldDefn **)
         CPLRealloc( papoFieldDefn, sizeof(void*)*(nFieldCount+1) );
 
@@ -396,7 +421,7 @@ void OGR_FD_AddFieldDefn( OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField )
 OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
 
 {
-    if (iField < 0 || iField >= nFieldCount)
+    if (iField < 0 || iField >= GetFieldCount())
         return OGRERR_FAILURE;
 
     delete papoFieldDefn[iField];
@@ -467,7 +492,7 @@ OGRErr OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField )
 OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
 
 {
-    if (nFieldCount == 0)
+    if (GetFieldCount() == 0)
         return OGRERR_NONE;
 
     OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
@@ -518,6 +543,296 @@ OGRErr OGR_FD_ReorderFieldDefn( OGRFeatureDefnH hDefn, int* panMap )
     return ((OGRFeatureDefn *) hDefn)->ReorderFieldDefns( panMap );
 }
 
+
+/************************************************************************/
+/*                         GetGeomFieldCount()                          */
+/************************************************************************/
+
+/**
+ * \fn int OGRFeatureDefn::GetGeomFieldCount();
+ *
+ * \brief Fetch number of geometry fields on this feature.
+ *
+ * This method is the same as the C function OGR_FD_GetGeomFieldCount().
+ * @return count of geometry fields.
+ *
+ * @since GDAL 1.11
+ */
+int OGRFeatureDefn::GetGeomFieldCount()
+{
+    return nGeomFieldCount;
+}
+
+/************************************************************************/
+/*                      OGR_FD_GetGeomFieldCount()                      */
+/************************************************************************/
+
+/**
+ * \brief Fetch number of geometry fields on the passed feature definition.
+ *
+ * This function is the same as the C++ OGRFeatureDefn::GetGeomFieldCount().
+ *
+ * @param hDefn handle to the feature definition to get the fields count from.
+ * @return count of geometry fields.
+ *
+ * @since GDAL 1.11
+ */
+
+int OGR_FD_GetGeomFieldCount( OGRFeatureDefnH hDefn )
+
+{
+    return ((OGRFeatureDefn *) hDefn)->GetGeomFieldCount();
+}
+
+/************************************************************************/
+/*                           GetGeomFieldDefn()                         */
+/************************************************************************/
+
+/**
+ * \brief Fetch geometry field definition.
+ *
+ * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
+ *
+ * @param iGeomField the geometry field to fetch, between 0 and GetGeomFieldCount()-1.
+ *
+ * @return a pointer to an internal field definition object or NULL if invalid index.
+ * This object should not be modified or freed by the application.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn( int iGeomField )
+
+{
+    if( iGeomField < 0 || iGeomField >= GetGeomFieldCount() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iGeomField);
+        return NULL;
+    }
+
+    return papoGeomFieldDefn[iGeomField];
+}
+
+/************************************************************************/
+/*                      OGR_FD_GetGeomFieldDefn()                       */
+/************************************************************************/
+
+/**
+ * \brief Fetch geometry field definition of the passed feature definition.
+ *
+ * This function is the same as the C++ method 
+ * OGRFeatureDefn::GetGeomFieldDefn().
+ *
+ * @param hDefn handle to the feature definition to get the field definition
+ * from.
+ * @param iGeomField the geometry field to fetch, between 0 and GetGeomFieldCount()-1.
+ *
+ * @return an handle to an internal field definition object or NULL if invalid index.
+ * This object should not be modified or freed by the application.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
+
+{
+    return (OGRGeomFieldDefnH) ((OGRFeatureDefn *) hDefn)->GetGeomFieldDefn( iGeomField );
+}
+
+/************************************************************************/
+/*                          AddGeomFieldDefn()                          */
+/************************************************************************/
+
+/**
+ * \brief Add a new geometry field definition.
+ *
+ * To add a new geometry field definition to a layer definition, do not use this
+ * function directly, but use OGRLayer::CreateGeomField() instead.
+ * 
+ * This method does an internal copy of the passed geometry field definition,
+ * unless bCopy is set to FALSE (in which case it takes ownership of the
+ * field definition.
+ *
+ * This method should only be called while there are no OGRFeature
+ * objects in existance based on this OGRFeatureDefn.  The OGRGeomFieldDefn
+ * passed in is copied, and remains the responsibility of the caller.
+ *
+ * This method is the same as the C function OGR_FD_AddGeomFieldDefn().
+ *
+ * @param poNewDefn the definition of the new geometry field.
+ * @param bCopy whether poNewDefn should be copied.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGRFeatureDefn::AddGeomFieldDefn( OGRGeomFieldDefn * poNewDefn,
+                                       int bCopy )
+{
+    GetGeomFieldCount();
+    papoGeomFieldDefn = (OGRGeomFieldDefn **)
+        CPLRealloc( papoGeomFieldDefn, sizeof(void*)*(nGeomFieldCount+1) );
+
+    papoGeomFieldDefn[nGeomFieldCount] = (bCopy) ?
+        new OGRGeomFieldDefn( poNewDefn ) : poNewDefn;
+    nGeomFieldCount++;
+}
+
+/************************************************************************/
+/*                      OGR_FD_AddGeomFieldDefn()                       */
+/************************************************************************/
+
+/**
+ * \brief Add a new field definition to the passed feature definition.
+ *
+ * To add a new field definition to a layer definition, do not use this
+ * function directly, but use OGR_L_CreateGeomField() instead.
+ *
+ * This function  should only be called while there are no OGRFeature
+ * objects in existance based on this OGRFeatureDefn.  The OGRGeomFieldDefn
+ * passed in is copied, and remains the responsibility of the caller.
+ *
+ * This function is the same as the C++ method OGRFeatureDefn::AddGeomFieldDefn().
+ *
+ * @param hDefn handle to the feature definition to add the geometry field definition
+ * to.
+ * @param hNewGeomField handle to the new field definition.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn, OGRGeomFieldDefnH hNewGeomField )
+
+{
+    ((OGRFeatureDefn *) hDefn)->AddGeomFieldDefn( (OGRGeomFieldDefn *) hNewGeomField );
+}
+
+/************************************************************************/
+/*                         DeleteGeomFieldDefn()                        */
+/************************************************************************/
+
+/**
+ * \brief Delete an existing geometry field definition.
+ *
+ * To delete an existing field definition from a layer definition, do not use this
+ * function directly, but use OGRLayer::DeleteGeomField() instead.
+ *
+ * This method should only be called while there are no OGRFeature
+ * objects in existance based on this OGRFeatureDefn.
+ *
+ * This method is the same as the C function OGR_FD_DeleteGeomFieldDefn().
+ *
+ * @param iGeomField the index of the geometry field defintion.
+ * @return OGRERR_NONE in case of success.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRErr OGRFeatureDefn::DeleteGeomFieldDefn( int iGeomField )
+
+{
+    if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
+        return OGRERR_FAILURE;
+
+    delete papoGeomFieldDefn[iGeomField];
+    papoGeomFieldDefn[iGeomField] = NULL;
+
+    if (iGeomField < nGeomFieldCount - 1)
+    {
+        memmove(papoGeomFieldDefn + iGeomField,
+                papoGeomFieldDefn + iGeomField + 1,
+                (nGeomFieldCount - 1 - iGeomField) * sizeof(void*));
+    }
+
+    nGeomFieldCount--;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                     OGR_FD_DeleteGeomFieldDefn()                     */
+/************************************************************************/
+
+/**
+ * \brief Delete an existing geometry field definition.
+ *
+ * To delete an existing geometry field definition from a layer definition, do not use this
+ * function directly, but use OGR_L_DeleteGeomField() instead (*not implemented yet*)
+ *
+ * This method should only be called while there are no OGRFeature
+ * objects in existance based on this OGRFeatureDefn.
+ *
+ * This method is the same as the C++ method OGRFeatureDefn::DeleteGeomFieldDefn().
+ *
+ * @param hDefn handle to the feature definition.
+ * @param iGeomField the index of the geometry field defintion.
+ * @return OGRERR_NONE in case of success.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRErr OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
+
+{
+    return ((OGRFeatureDefn *) hDefn)->DeleteGeomFieldDefn( iGeomField );
+}
+
+
+/************************************************************************/
+/*                         GetGeomFieldIndex()                          */
+/************************************************************************/
+
+/**
+ * \brief Find geometry field by name.
+ *
+ * The geometry field index of the first geometry field matching the passed
+ * field name (case insensitively) is returned.
+ *
+ * This method is the same as the C function OGR_FD_GetGeomFieldIndex().
+ *
+ * @param pszGeomFieldName the geometry field name to search for.
+ *
+ * @return the geometry field index, or -1 if no match found.
+ */
+ 
+
+int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
+
+{
+    GetGeomFieldCount();
+    for( int i = 0; i < nGeomFieldCount; i++ )
+    {
+        if( EQUAL(pszGeomFieldName, GetGeomFieldDefn(i)->GetNameRef() ) )
+            return i;
+    }
+
+    return -1;
+}
+
+/************************************************************************/
+/*                      OGR_FD_GetGeomFieldIndex()                      */
+/************************************************************************/
+/**
+ * \brief Find geometry field by name.
+ *
+ * The geometry field index of the first geometry field matching the passed
+ * field name (case insensitively) is returned.
+ *
+ * This function is the same as the C++ method OGRFeatureDefn::GetGeomFieldIndex.
+ *
+ * @param hDefn handle to the feature definition to get field index from. 
+ * @param pszGeomFieldName the geometry field name to search for.
+ *
+ * @return the geometry field index, or -1 if no match found.
+ */
+
+int OGR_FD_GetGeomFieldIndex( OGRFeatureDefnH hDefn,
+                              const char *pszGeomFieldName )
+
+{
+    return ((OGRFeatureDefn *)hDefn)->GetGeomFieldIndex( pszGeomFieldName );
+}
+
+
 /************************************************************************/
 /*                            GetGeomType()                             */
 /************************************************************************/
@@ -534,10 +849,18 @@ OGRErr OGR_FD_ReorderFieldDefn( OGRFeatureDefnH hDefn, int* panMap )
  * type as 25D even if some or all geometries are in fact 25D.  A few (broken)
  * drivers return wkbPolygon for layers that also include wkbMultiPolygon.  
  *
+ * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->GetType().
+ *
  * This method is the same as the C function OGR_FD_GetGeomType().
  *
  * @return the base type for all geometry related to this definition.
  */
+OGRwkbGeometryType OGRFeatureDefn::GetGeomType()
+{
+    if( GetGeomFieldCount() == 0 )
+        return wkbNone;
+    return GetGeomFieldDefn(0)->GetType();
+}
 
 /************************************************************************/
 /*                         OGR_FD_GetGeomType()                         */
@@ -547,6 +870,8 @@ OGRErr OGR_FD_ReorderFieldDefn( OGRFeatureDefnH hDefn, int* panMap )
  *
  * This function is the same as the C++ method OGRFeatureDefn::GetGeomType().
  *
+ * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->GetType().
+ *
  * @param hDefn handle to the feature definition to get the geometry type from.
  * @return the base type for all geometry related to this definition.
  */
@@ -571,13 +896,26 @@ OGRwkbGeometryType OGR_FD_GetGeomType( OGRFeatureDefnH hDefn )
  *
  * This method is the same as the C function OGR_FD_SetGeomType().
  *
+ * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetType().
+ *
  * @param eNewType the new type to assign.
  */
 
 void OGRFeatureDefn::SetGeomType( OGRwkbGeometryType eNewType )
 
 {
-    eGeomType = eNewType;
+    if( GetGeomFieldCount() > 0 )
+    {
+        if( GetGeomFieldCount() == 1 && eNewType == wkbNone )
+            DeleteGeomFieldDefn(0);
+        else
+            GetGeomFieldDefn(0)->SetType(eNewType);
+    }
+    else if( eNewType != wkbNone )
+    {
+        OGRGeomFieldDefn oGeomFieldDefn( "", eNewType );
+        AddGeomFieldDefn(&oGeomFieldDefn);
+    }
 }
 
 /************************************************************************/
@@ -594,6 +932,8 @@ void OGRFeatureDefn::SetGeomType( OGRwkbGeometryType eNewType )
  *
  * This function is the same as the C++ method OGRFeatureDefn::SetGeomType().
  *
+ * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetType().
+ *
  * @param hDefn handle to the layer or feature definition to set the geometry
  * type to.
  * @param eType the new type to assign.
@@ -605,7 +945,6 @@ void OGR_FD_SetGeomType( OGRFeatureDefnH hDefn, OGRwkbGeometryType eType )
     ((OGRFeatureDefn *) hDefn)->SetGeomType( eType );
 }
 
-
 /************************************************************************/
 /*                             Reference()                              */
 /************************************************************************/
@@ -703,7 +1042,7 @@ int OGR_FD_Dereference( OGRFeatureDefnH hDefn )
  * This function is the same as the C++ method 
  * OGRFeatureDefn::GetReferenceCount().
  *
- * @param hDefn hanlde to the feature definition on witch OGRFeature are
+ * @param hDefn handle to the feature definition on witch OGRFeature are
  * based on. 
  * @return the current reference count.
  */
@@ -735,9 +1074,10 @@ int OGR_FD_GetReferenceCount( OGRFeatureDefnH hDefn )
 int OGRFeatureDefn::GetFieldIndex( const char * pszFieldName )
 
 {
+    GetFieldCount();
     for( int i = 0; i < nFieldCount; i++ )
     {
-        if( EQUAL(pszFieldName, papoFieldDefn[i]->GetNameRef() ) )
+        if( EQUAL(pszFieldName, GetFieldDefn(i)->GetNameRef() ) )
             return i;
     }
 
@@ -778,9 +1118,18 @@ int OGR_FD_GetFieldIndex( OGRFeatureDefnH hDefn, const char *pszFieldName )
  *
  * This method is the same as the C function OGR_FD_IsGeometryIgnored().
  *
+ * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->IsIgnored().
+ *
  * @return ignore state
  */
 
+int OGRFeatureDefn::IsGeometryIgnored()
+{
+    if( GetGeomFieldCount() == 0 )
+        return FALSE;
+    return GetGeomFieldDefn(0)->IsIgnored();
+}
+
 /************************************************************************/
 /*                      OGR_FD_IsGeometryIgnored()                      */
 /************************************************************************/
@@ -791,7 +1140,9 @@ int OGR_FD_GetFieldIndex( OGRFeatureDefnH hDefn, const char *pszFieldName )
  * This function is the same as the C++ method 
  * OGRFeatureDefn::IsGeometryIgnored().
  *
- * @param hDefn hanlde to the feature definition on witch OGRFeature are
+ * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->IsIgnored().
+ *
+ * @param hDefn handle to the feature definition on witch OGRFeature are
  * based on. 
  * @return ignore state
  */
@@ -812,9 +1163,17 @@ int OGR_FD_IsGeometryIgnored( OGRFeatureDefnH hDefn )
  *
  * This method is the same as the C function OGR_FD_SetGeometryIgnored().
  *
+ * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetIgnored().
+ *
  * @param bIgnore ignore state
  */
 
+void OGRFeatureDefn::SetGeometryIgnored( int bIgnore )
+{
+    if( GetGeomFieldCount() > 0 )
+        GetGeomFieldDefn(0)->SetIgnored(bIgnore);
+}
+
 /************************************************************************/
 /*                      OGR_FD_SetGeometryIgnored()                     */
 /************************************************************************/
@@ -825,7 +1184,9 @@ int OGR_FD_IsGeometryIgnored( OGRFeatureDefnH hDefn )
  * This function is the same as the C++ method 
  * OGRFeatureDefn::SetGeometryIgnored().
  *
- * @param hDefn hanlde to the feature definition on witch OGRFeature are
+ * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetIgnored().
+ *
+ * @param hDefn handle to the feature definition on witch OGRFeature are
  * based on. 
  * @param bIgnore ignore state
  */
@@ -893,7 +1254,7 @@ int OGR_FD_IsStyleIgnored( OGRFeatureDefnH hDefn )
  * This function is the same as the C++ method 
  * OGRFeatureDefn::SetStyleIgnored().
  *
- * @param hDefn hanlde to the feature definition on witch OGRFeature are
+ * @param hDefn handle to the feature definition on witch OGRFeature are
  * based on. 
  * @param bIgnore ignore state
  */
@@ -934,22 +1295,55 @@ void OGRFeatureDefn::DestroyFeatureDefn( OGRFeatureDefn *poDefn )
  * @return TRUE if the feature definition is identical to the other one.
  */
 
-int OGRFeatureDefn::IsSame( const OGRFeatureDefn * poOtherFeatureDefn ) const
+int OGRFeatureDefn::IsSame( OGRFeatureDefn * poOtherFeatureDefn )
 {
-    if (strcmp(pszFeatureClassName, poOtherFeatureDefn->pszFeatureClassName) == 0 &&
-        eGeomType == poOtherFeatureDefn->eGeomType &&
-        nFieldCount == poOtherFeatureDefn->nFieldCount)
+    if (strcmp(GetName(), poOtherFeatureDefn->GetName()) == 0 &&
+        GetFieldCount() == poOtherFeatureDefn->GetFieldCount() &&
+        GetGeomFieldCount() == poOtherFeatureDefn->GetGeomFieldCount())
     {
-        for(int i=0;i<nFieldCount;i++)
+        int i;
+        for(i=0;i<nFieldCount;i++)
         {
-            const OGRFieldDefn* poFldDefn = papoFieldDefn[i];
-            const OGRFieldDefn* poOtherFldDefn = poOtherFeatureDefn->papoFieldDefn[i];
+            const OGRFieldDefn* poFldDefn = GetFieldDefn(i);
+            const OGRFieldDefn* poOtherFldDefn = poOtherFeatureDefn->GetFieldDefn(i);
             if (!poFldDefn->IsSame(poOtherFldDefn))
             {
                 return FALSE;
             }
         }
+        for(i=0;i<nGeomFieldCount;i++)
+        {
+            OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(i);
+            OGRGeomFieldDefn* poOtherGFldDefn =
+                poOtherFeatureDefn->GetGeomFieldDefn(i);
+            if (!poGFldDefn->IsSame(poOtherGFldDefn))
+            {
+                return FALSE;
+            }
+        }
         return TRUE;
     }
     return FALSE;
 }
+
+/************************************************************************/
+/*                           OGR_FD_IsSame()                            */
+/************************************************************************/
+
+/**
+ * \brief Test if the feature definition is identical to the other one.
+ *
+ * @param hFDefn handle to the feature definition on witch OGRFeature are
+ * based on. 
+ * @param hOtherFDefn handle to the other feature definition to compare to.
+ * @return TRUE if the feature definition is identical to the other one.
+ *
+ * @since OGR 1.11
+ */
+
+int OGR_FD_IsSame( OGRFeatureDefnH hFDefn, OGRFeatureDefnH hOtherFDefn )
+{
+    VALIDATE_POINTER1( hFDefn, "OGR_FD_IsSame", FALSE );
+    VALIDATE_POINTER1( hOtherFDefn, "OGR_FD_IsSame", FALSE );
+    return ((OGRFeatureDefn*)hFDefn)->IsSame((OGRFeatureDefn*)hOtherFDefn);
+}
diff --git a/ogr/ogrfeaturequery.cpp b/ogr/ogrfeaturequery.cpp
index 9f13963..d08dd10 100644
--- a/ogr/ogrfeaturequery.cpp
+++ b/ogr/ogrfeaturequery.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturequery.cpp 24849 2012-08-25 12:22:05Z rouault $
+ * $Id: ogrfeaturequery.cpp 27044 2014-03-16 23:41:27Z rouault $
  * 
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of simple SQL WHERE style attributes queries
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "ogr_p.h"
 #include "ogr_attrind.h"
 
-CPL_CVSID("$Id: ogrfeaturequery.cpp 24849 2012-08-25 12:22:05Z rouault $");
+CPL_CVSID("$Id: ogrfeaturequery.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*     Support for special attributes (feature query and selection)     */
@@ -89,7 +90,8 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
     char        **papszFieldNames;
     swq_field_type *paeFieldTypes;
     int         iField;
-    int         nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT;
+    int         nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT +
+                              poDefn->GetGeomFieldCount();
 
     papszFieldNames = (char **) 
         CPLMalloc(sizeof(char *) * nFieldCount );
@@ -136,6 +138,17 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
         ++iField;
     }
 
+    for( iField = 0; iField < poDefn->GetGeomFieldCount(); iField++ )
+    {
+        OGRGeomFieldDefn    *poField = poDefn->GetGeomFieldDefn( iField );
+        int iDstField = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT + iField;
+
+        papszFieldNames[iDstField] = (char *) poField->GetNameRef();
+        if( *papszFieldNames[iDstField] == '\0' )
+            papszFieldNames[iDstField] = (char*) OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME;
+        paeFieldTypes[iDstField] = SWQ_GEOMETRY;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Try to parse.                                                   */
 /* -------------------------------------------------------------------- */
@@ -169,6 +182,13 @@ static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
     OGRFeature *poFeature = (OGRFeature *) pFeatureIn;
     swq_expr_node *poRetNode = NULL;
 
+    if( op->field_type == SWQ_GEOMETRY )
+    {
+        int iField = op->field_index - (poFeature->GetFieldCount() + SPECIAL_FIELD_COUNT);
+        poRetNode = new swq_expr_node( poFeature->GetGeomFieldRef(iField) );
+        return poRetNode;
+    }
+
     switch( op->field_type )
     {
       case SWQ_INTEGER:
@@ -181,7 +201,7 @@ static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
         poRetNode = new swq_expr_node( 
             poFeature->GetFieldAsDouble(op->field_index) );
         break;
-        
+
       default:
         poRetNode = new swq_expr_node( 
             poFeature->GetFieldAsString(op->field_index) );
diff --git a/ogr/ogrfeaturestyle.cpp b/ogr/ogrfeaturestyle.cpp
index f696947..50468ad 100644
--- a/ogr/ogrfeaturestyle.cpp
+++ b/ogr/ogrfeaturestyle.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturestyle.cpp 23051 2011-09-04 17:59:02Z winkey $
+ * $Id: ogrfeaturestyle.cpp 27071 2014-03-21 21:52:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Feature Representation string API
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000-2001, Stephane Villeneuve
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_featurestyle.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrfeaturestyle.cpp 23051 2011-09-04 17:59:02Z winkey $");
+CPL_CVSID("$Id: ogrfeaturestyle.cpp 27071 2014-03-21 21:52:46Z rouault $");
 
 CPL_C_START
 void OGRFeatureStylePuller() {}
@@ -785,6 +786,7 @@ OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
 OGRStyleTable::OGRStyleTable()
 {
     m_papszStyleTable = NULL;
+    iNextStyle = 0;
 }
 
 /************************************************************************/
@@ -923,6 +925,31 @@ GBool OGRStyleTable::AddStyle(const char *pszName, const char *pszStyleString)
     return FALSE;
 }
 
+/************************************************************************/
+/*                       OGR_STBL_AddStyle()                            */
+/************************************************************************/
+
+/**
+ * \brief Add a new style in the table.
+ * No comparison will be done on the
+ * Style string, only on the name.
+ * This function is the same as the C++ method OGRStyleTable::AddStyle().
+ *
+ * @param hStyleTable handle to the style table.
+ * @param pszName the name the style to add.
+ * @param pszStyleString the style string to add.
+ *
+ * @return TRUE on success, FALSE on error
+ */
+
+int OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
+                       const char *pszName, const char *pszStyleString)
+{
+    VALIDATE_POINTER1( hStyleTable, "OGR_STBL_AddStyle", FALSE );
+    
+    return ((OGRStyleTable *) hStyleTable)->AddStyle( pszName, pszStyleString );
+}
+
 /****************************************************************************/
 /*            GBool OGRStyleTable::RemoveStyle(char *pszName)               */
 /*                                                                          */
diff --git a/ogr/ogrfielddefn.cpp b/ogr/ogrfielddefn.cpp
index c56ceb5..19de781 100644
--- a/ogr/ogrfielddefn.cpp
+++ b/ogr/ogrfielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfielddefn.cpp 26202 2013-07-24 18:47:00Z rouault $
+ * $Id: ogrfielddefn.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFieldDefn class implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrfielddefn.cpp 26202 2013-07-24 18:47:00Z rouault $");
+CPL_CVSID("$Id: ogrfielddefn.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRFieldDefn()                            */
@@ -695,7 +696,7 @@ int OGR_Fld_IsIgnored( OGRFieldDefnH hDefn )
 /**
  * \brief Set whether this field should be omitted when fetching features
  *
- * This method is the same as the C function OGRFieldDefn::SetIgnored().
+ * This method is the same as the C++ method OGRFieldDefn::SetIgnored().
  *
  * @param hDefn handle to the field definition
  * @param ignore ignore state
diff --git a/ogr/ogrgeomediageometry.cpp b/ogr/ogrgeomediageometry.cpp
index 9d7d8f5..5211f2a 100644
--- a/ogr/ogrgeomediageometry.cpp
+++ b/ogr/ogrgeomediageometry.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeomediageometry.cpp 24656 2012-07-03 17:35:34Z rouault $
+ * $Id: ogrgeomediageometry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of geomedia geometry blobs
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogrgeomediageometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgeomediageometry.cpp 24656 2012-07-03 17:35:34Z rouault $");
+CPL_CVSID("$Id: ogrgeomediageometry.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define GEOMEDIA_POINT          0xC0
 #define GEOMEDIA_ORIENTED_POINT 0xC8
diff --git a/ogr/ogrgeomediageometry.h b/ogr/ogrgeomediageometry.h
index 1e7dc4a..efc906d 100644
--- a/ogr/ogrgeomediageometry.h
+++ b/ogr/ogrgeomediageometry.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeomediageometry.h 21557 2011-01-22 23:42:14Z rouault $
+ * $Id: ogrgeomediageometry.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of geomedia geometry blobs
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index 49a66b5..632bf8e 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometry.cpp 25268 2012-11-29 20:21:41Z rouault $
+ * $Id: ogrgeometry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements a few base methods on OGRGeometry.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,12 +35,12 @@
 #include "cpl_multiproc.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrgeometry.cpp 25268 2012-11-29 20:21:41Z rouault $");
+CPL_CVSID("$Id: ogrgeometry.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
 
 #ifdef HAVE_GEOS
-static void _GEOSErrorHandler(const char *fmt, ...)
+static void OGRGEOSErrorHandler(const char *fmt, ...)
 {
     va_list args;
 
@@ -48,7 +49,7 @@ static void _GEOSErrorHandler(const char *fmt, ...)
     va_end(args);
 }
 
-static void _GEOSWarningHandler(const char *fmt, ...)
+static void OGRGEOSWarningHandler(const char *fmt, ...)
 {
     va_list args;
 
@@ -334,20 +335,22 @@ OGRBoolean OGRGeometry::Intersects( OGRGeometry *poOtherGeom ) const
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hOtherGeosGeom = NULL;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     
     OGRBoolean bResult = FALSE;
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        if( GEOSIntersects( hThisGeosGeom, hOtherGeosGeom ) != 0 )
+        if( GEOSIntersects_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom ) != 0 )
             bResult = TRUE;
         else
             bResult = FALSE;
     }
 
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 #endif /* HAVE_GEOS */
@@ -564,6 +567,15 @@ OGRErr OGR_G_Transform( OGRGeometryH hGeom,
  * @return 0 for points, 1 for lines and 2 for surfaces.
  */
 
+int OGRGeometry::getIsoGeometryType() const
+{
+    int nGType = wkbFlatten(getGeometryType());
+
+    if ( getCoordinateDimension() == 3 )
+        nGType += 1000;
+
+    return nGType;
+}
 
 /************************************************************************/
 /*                  OGRGeometry::segmentize()                           */
@@ -962,7 +974,8 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
 
 /**
  * \fn OGRErr OGRGeometry::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                        unsigned char * pabyData ) const;
+                                        unsigned char * pabyData,
+                                        OGRwkbVariant eWkbVariant=wkbVariantOgc ) const
  *
  * \brief Convert a geometry into well known binary format.
  *
@@ -975,6 +988,11 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
  * @param pabyData a buffer into which the binary representation is
  *                      written.  This buffer must be at least
  *                      OGRGeometry::WkbSize() byte in size.
+ * @param eWkbVariant What standard to use when exporting geometries with 
+ *                      three dimensions (or more). The default wkbVariantOgc is 
+ *                      the historical OGR variant. wkbVariantIso is the 
+ *                      variant defined in ISO SQL/MM and adopted by OGC 
+ *                      for SFSQL 1.2.
  *
  * @return Currently OGRERR_NONE is always returned.
  */
@@ -1352,13 +1370,15 @@ OGRGeometry::IsValid(  ) const
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
     
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL  )
     {
-        bResult = GEOSisValid( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+        bResult = GEOSisValid_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -1423,13 +1443,15 @@ OGRGeometry::IsSimple(  ) const
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
     
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL  )
     {
-        bResult = GEOSisSimple( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+        bResult = GEOSisSimple_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -1494,13 +1516,15 @@ OGRGeometry::IsRing(  ) const
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
     
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL  )
     {
-        bResult = GEOSisRing( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+        bResult = GEOSisRing_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -1540,24 +1564,33 @@ int OGR_G_IsRing( OGRGeometryH hGeom )
 /*      OGR constants.                                                  */
 /************************************************************************/
 
+#define EQUALN_CST(var, cst) EQUALN(var, cst, strlen(cst))
+
 OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
 {
-    if ( EQUAL(pszGeomType, "POINT") )
-        return wkbPoint;
-    else if ( EQUAL(pszGeomType, "LINESTRING") )
-        return wkbLineString;
-    else if ( EQUAL(pszGeomType, "POLYGON") )
-        return wkbPolygon;
-    else if ( EQUAL(pszGeomType, "MULTIPOINT") )
-        return wkbMultiPoint;
-    else if ( EQUAL(pszGeomType, "MULTILINESTRING") )
-        return wkbMultiLineString;
-    else if ( EQUAL(pszGeomType, "MULTIPOLYGON") )
-        return wkbMultiPolygon;
-    else if ( EQUAL(pszGeomType, "GEOMETRYCOLLECTION") )
-        return wkbGeometryCollection;
+    unsigned int n25DBit = 0;
+    if( *pszGeomType != '\0' )
+    {
+        char ch = pszGeomType[strlen(pszGeomType)-1];
+        if( ch == 'z' || ch == 'Z' )
+            n25DBit = wkb25DBit;
+    }
+    if ( EQUALN_CST(pszGeomType, "POINT") )
+        return (OGRwkbGeometryType)(wkbPoint | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "LINESTRING") )
+        return (OGRwkbGeometryType)(wkbLineString | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "POLYGON") )
+        return (OGRwkbGeometryType)(wkbPolygon | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "MULTIPOINT") )
+        return (OGRwkbGeometryType)(wkbMultiPoint | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "MULTILINESTRING") )
+        return (OGRwkbGeometryType)(wkbMultiLineString | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "MULTIPOLYGON") )
+        return (OGRwkbGeometryType)(wkbMultiPolygon | n25DBit);
+    else if ( EQUALN_CST(pszGeomType, "GEOMETRYCOLLECTION") )
+        return (OGRwkbGeometryType)(wkbGeometryCollection | n25DBit);
     else
-        return wkbUnknown;
+        return (OGRwkbGeometryType)(wkbUnknown | n25DBit);
 }
 
 /************************************************************************/
@@ -1910,10 +1943,39 @@ int OGRGetGenerate_DB2_V72_BYTE_ORDER()
 }
 
 /************************************************************************/
+/*                          createGEOSContext()                         */
+/************************************************************************/
+
+GEOSContextHandle_t OGRGeometry::createGEOSContext()
+{
+#ifndef HAVE_GEOS
+    CPLError( CE_Failure, CPLE_NotSupported, 
+              "GEOS support not enabled." );
+    return NULL;
+#else
+    return initGEOS_r( OGRGEOSWarningHandler, OGRGEOSErrorHandler );
+#endif
+}
+
+/************************************************************************/
+/*                          freeGEOSContext()                           */
+/************************************************************************/
+
+void OGRGeometry::freeGEOSContext(GEOSContextHandle_t hGEOSCtxt)
+{
+#ifdef HAVE_GEOS
+    if( hGEOSCtxt != NULL )
+    {
+        finishGEOS_r( hGEOSCtxt );
+    }
+#endif
+}
+
+/************************************************************************/
 /*                            exportToGEOS()                            */
 /************************************************************************/
 
-GEOSGeom OGRGeometry::exportToGEOS() const
+GEOSGeom OGRGeometry::exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const
 
 {
 #ifndef HAVE_GEOS
@@ -1924,23 +1986,15 @@ GEOSGeom OGRGeometry::exportToGEOS() const
 
 #else
 
-    static void *hGEOSInitMutex = NULL;
-    static int bGEOSInitialized = FALSE;
-
-    CPLMutexHolderD( &hGEOSInitMutex );
-
-    if( !bGEOSInitialized )
-    {
-        bGEOSInitialized = TRUE;
-        initGEOS( _GEOSWarningHandler, _GEOSErrorHandler );
-    }
+    if( hGEOSCtxt == NULL )
+        return NULL;
 
     /* POINT EMPTY is exported to WKB as if it were POINT(0 0) */
     /* so that particular case is necessary */
     if (wkbFlatten(getGeometryType()) == wkbPoint &&
         nCoordDimension == 0)
     {
-        return GEOSGeomFromWKT("POINT EMPTY");
+        return GEOSGeomFromWKT_r(hGEOSCtxt, "POINT EMPTY");
     }
 
     GEOSGeom hGeom = NULL;
@@ -1950,7 +2004,7 @@ GEOSGeom OGRGeometry::exportToGEOS() const
     nDataSize = WkbSize();
     pabyData = (unsigned char *) CPLMalloc(nDataSize);
     if( exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
-        hGeom = GEOSGeomFromWKB_buf( pabyData, nDataSize );
+        hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
 
     CPLFree( pabyData );
 
@@ -1967,7 +2021,8 @@ GEOSGeom OGRGeometry::exportToGEOS() const
 /**
  * \brief Compute distance between two geometries.
  *
- * Returns the shortest distance between the two geometries. 
+ * Returns the shortest distance between the two geometries. The distance is
+ * expressed into the same unit as the coordinates of the geometries.
  *
  * This method is the same as the C function OGR_G_Distance().
  *
@@ -2002,19 +2057,21 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hThis = NULL;
     GEOSGeom hOther = NULL;
 
-    hOther = poOtherGeom->exportToGEOS();
-    hThis = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hOther = poOtherGeom->exportToGEOS(hGEOSCtxt);
+    hThis = exportToGEOS(hGEOSCtxt);
    
     int bIsErr = 0;
     double dfDistance = 0.0;
 
     if( hThis != NULL && hOther != NULL )
     {
-        bIsErr = GEOSDistance( hThis, hOther, &dfDistance );
+        bIsErr = GEOSDistance_r( hGEOSCtxt, hThis, hOther, &dfDistance );
     }
 
-    GEOSGeom_destroy( hThis );
-    GEOSGeom_destroy( hOther );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThis );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOther );
+    freeGEOSContext( hGEOSCtxt );
 
     if ( bIsErr > 0 ) 
     {
@@ -2033,7 +2090,8 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
 /**
  * \brief Compute distance between two geometries.
  *
- * Returns the shortest distance between the two geometries. 
+ * Returns the shortest distance between the two geometries. The distance is
+ * expressed into the same unit as the coordinates of the geometries.
  *
  * This function is the same as the C++ method OGRGeometry::Distance().
  *
@@ -2092,20 +2150,22 @@ OGRGeometry *OGRGeometry::ConvexHull() const
     GEOSGeom hGeosHull = NULL;
     OGRGeometry *poHullOGRGeom = NULL;
 
-    hGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hGeosGeom != NULL )
     {
-        hGeosHull = GEOSConvexHull( hGeosGeom );
-        GEOSGeom_destroy( hGeosGeom );
+        hGeosHull = GEOSConvexHull_r( hGEOSCtxt, hGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
 
         if( hGeosHull != NULL )
         {
-            poHullOGRGeom = OGRGeometryFactory::createFromGEOS(hGeosHull);
+            poHullOGRGeom = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosHull);
             if( poHullOGRGeom != NULL && getSpatialReference() != NULL )
                 poHullOGRGeom->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosHull);
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosHull);
         }
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return poHullOGRGeom;
 
@@ -2179,20 +2239,22 @@ OGRGeometry *OGRGeometry::Boundary() const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hGeosGeom != NULL )
     {
-        hGeosProduct = GEOSBoundary( hGeosGeom );
-        GEOSGeom_destroy( hGeosGeom );
+        hGeosProduct = GEOSBoundary_r( hGEOSCtxt, hGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
@@ -2284,7 +2346,8 @@ OGRGeometryH OGR_G_GetBoundary( OGRGeometryH hTarget )
  * If OGR is built without the GEOS library, this method will always fail, 
  * issuing a CPLE_NotSupported error. 
  *
- * @param dfDist the buffer distance to be applied. 
+ * @param dfDist the buffer distance to be applied. Should be expressed into
+ *               the same unit as the coordinates of the geometry.
  *
  * @param nQuadSegs the number of segments used to approximate a 90 degree (quadrant) of
  * curvature. 
@@ -2307,20 +2370,22 @@ OGRGeometry *OGRGeometry::Buffer( double dfDist, int nQuadSegs ) const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hGeosGeom != NULL )
     {
-        hGeosProduct = GEOSBuffer( hGeosGeom, dfDist, nQuadSegs );
-        GEOSGeom_destroy( hGeosGeom );
+        hGeosProduct = GEOSBuffer_r( hGEOSCtxt, hGeosGeom, dfDist, nQuadSegs );
+        GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
+    freeGEOSContext(hGEOSCtxt);
 
     return poOGRProduct;
 
@@ -2353,7 +2418,8 @@ OGRGeometry *OGRGeometry::Buffer( double dfDist, int nQuadSegs ) const
  * issuing a CPLE_NotSupported error. 
  *
  * @param hTarget the geometry.
- * @param dfDist the buffer distance to be applied. 
+ * @param dfDist the buffer distance to be applied. Should be expressed into
+ *               the same unit as the coordinates of the geometry.
  *
  * @param nQuadSegs the number of segments used to approximate a 90 degree
  * (quadrant) of curvature. 
@@ -2409,26 +2475,28 @@ OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        hGeosProduct = GEOSIntersection( hThisGeosGeom, hOtherGeosGeom );
+        hGeosProduct = GEOSIntersection_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
             {
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             }
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
@@ -2507,26 +2575,28 @@ OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        hGeosProduct = GEOSUnion( hThisGeosGeom, hOtherGeosGeom );
+        hGeosProduct = GEOSUnion_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
             {
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             }
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
@@ -2592,35 +2662,30 @@ OGRGeometry *OGRGeometry::UnionCascaded() const
     CPLError( CE_Failure, CPLE_NotSupported, 
               "GEOS support not enabled." );
     return NULL;
-
-/* GEOS >= 3.1.0 */
-#elif GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 1)
-
+#else
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSUnionCascaded( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+        hGeosProduct = GEOSUnionCascaded_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
-#else
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS >= 3.1.0 required for UnionCascaded() support." );
-    return NULL;
 #endif /* HAVE_GEOS */
 }
 
@@ -2691,26 +2756,28 @@ OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        hGeosProduct = GEOSDifference( hThisGeosGeom, hOtherGeosGeom );
+        hGeosProduct = GEOSDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
             {
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             }
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
@@ -2792,26 +2859,28 @@ OGRGeometry::SymDifference( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        hGeosProduct = GEOSSymDifference( hThisGeosGeom, hOtherGeosGeom );
+        hGeosProduct = GEOSSymDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGeosProduct);
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
             {
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             }
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return poOGRProduct;
 
@@ -2921,14 +2990,16 @@ OGRGeometry::Disjoint( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSDisjoint( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSDisjoint_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3001,15 +3072,17 @@ OGRGeometry::Touches( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSTouches( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSTouches_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3082,15 +3155,17 @@ OGRGeometry::Crosses( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSCrosses( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSCrosses_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3163,14 +3238,16 @@ OGRGeometry::Within( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSWithin( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSWithin_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3243,14 +3320,16 @@ OGRGeometry::Contains( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSContains( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSContains_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3324,14 +3403,16 @@ OGRGeometry::Overlaps( const OGRGeometry *poOtherGeom ) const
     GEOSGeom hOtherGeosGeom = NULL;
     OGRBoolean bResult = FALSE;
 
-    hThisGeosGeom = exportToGEOS();
-    hOtherGeosGeom = poOtherGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        bResult = GEOSOverlaps( hThisGeosGeom, hOtherGeosGeom );
+        bResult = GEOSOverlaps_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
     }
-    GEOSGeom_destroy( hThisGeosGeom );
-    GEOSGeom_destroy( hOtherGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+    freeGEOSContext( hGEOSCtxt );
 
     return bResult;
 
@@ -3453,26 +3534,34 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hOtherGeosGeom = NULL;
     
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL )
     {
-    	hOtherGeosGeom = GEOSGetCentroid( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+    	hOtherGeosGeom = GEOSGetCentroid_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hOtherGeosGeom == NULL )
+        {
+            freeGEOSContext( hGEOSCtxt );
             return OGRERR_FAILURE;
+        }
 
         OGRGeometry *poCentroidGeom =
-            OGRGeometryFactory::createFromGEOS( hOtherGeosGeom );
+            OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hOtherGeosGeom );
 
-        GEOSGeom_destroy( hOtherGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
 
         if (poCentroidGeom == NULL)
+        {
+            freeGEOSContext( hGEOSCtxt );
             return OGRERR_FAILURE;
+        }
         if (wkbFlatten(poCentroidGeom->getGeometryType()) != wkbPoint)
         {
             delete poCentroidGeom;
+            freeGEOSContext( hGEOSCtxt );
             return OGRERR_FAILURE;
         }
 
@@ -3492,10 +3581,12 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
 
         delete poCentroidGeom;
 
+        freeGEOSContext( hGEOSCtxt );
     	return OGRERR_NONE;
     }
     else
     {
+        freeGEOSContext( hGEOSCtxt );
     	return OGRERR_FAILURE;
     }
 
@@ -3588,36 +3679,46 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
     GEOSGeom hOtherGeosGeom = NULL;
     OGRGeometry* poThis = (OGRGeometry*) hGeom;
 
-    hThisGeosGeom = poThis->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
+    hThisGeosGeom = poThis->exportToGEOS(hGEOSCtxt);
  
     if( hThisGeosGeom != NULL )
     {
-        hOtherGeosGeom = GEOSPointOnSurface( hThisGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
+        hOtherGeosGeom = GEOSPointOnSurface_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hOtherGeosGeom == NULL )
+        {
+            OGRGeometry::freeGEOSContext( hGEOSCtxt );
             return NULL;
+        }
 
         OGRGeometry *poInsidePointGeom = (OGRGeometry *) 
-            OGRGeometryFactory::createFromGEOS( hOtherGeosGeom );
+            OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hOtherGeosGeom );
  
-        GEOSGeom_destroy( hOtherGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
 
         if (poInsidePointGeom == NULL)
+        {
+            OGRGeometry::freeGEOSContext( hGEOSCtxt );
             return NULL;
+        }
         if (wkbFlatten(poInsidePointGeom->getGeometryType()) != wkbPoint)
         {
             delete poInsidePointGeom;
+            OGRGeometry::freeGEOSContext( hGEOSCtxt );
             return NULL;
         }
 
         if( poInsidePointGeom != NULL && poThis->getSpatialReference() != NULL )
             poInsidePointGeom->assignSpatialReference(poThis->getSpatialReference());
 
+        OGRGeometry::freeGEOSContext( hGEOSCtxt );
         return (OGRGeometryH) poInsidePointGeom;
     }
     else
     {
+        OGRGeometry::freeGEOSContext( hGEOSCtxt );
         return NULL;
     }
 #endif
@@ -3653,32 +3754,28 @@ OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
               "GEOS support not enabled." );
     return NULL;
 
-/* GEOS >= 3.0.0 */
-#elif GEOS_CAPI_VERSION_MAJOR >= 2 || (GEOS_CAPI_VERSION_MAJOR == 1 && GEOS_CAPI_VERSION_MINOR >= 4)
-
+#else
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL ) 
     {
-        hGeosProduct = GEOSSimplify( hThisGeosGeom, dTolerance );
-        GEOSGeom_destroy( hThisGeosGeom );
+        hGeosProduct = GEOSSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS( hGeosProduct );
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
+    freeGEOSContext( hGEOSCtxt );
     return poOGRProduct;
 
-#else
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS >= 3.0.0 required for Simplify() support." );
-    return NULL;
 #endif /* HAVE_GEOS */
 
 }
@@ -3742,32 +3839,28 @@ OGRGeometry *OGRGeometry::SimplifyPreserveTopology(double dTolerance) const
               "GEOS support not enabled." );
     return NULL;
 
-/* GEOS >= 3.0.0 */
-#elif GEOS_CAPI_VERSION_MAJOR >= 2 || (GEOS_CAPI_VERSION_MAJOR == 1 && GEOS_CAPI_VERSION_MINOR >= 4)
-
+#else
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
-    hThisGeosGeom = exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSTopologyPreserveSimplify( hThisGeosGeom, dTolerance );
-        GEOSGeom_destroy( hThisGeosGeom );
+        hGeosProduct = GEOSTopologyPreserveSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS( hGeosProduct );
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosProduct );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
+    freeGEOSContext( hGEOSCtxt );
     return poOGRProduct;
 
-#else
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS >= 3.0.0 required for SimplifyPreserveTopology() support." );
-    return NULL;
 #endif /* HAVE_GEOS */
 
 }
@@ -3855,6 +3948,8 @@ OGRGeometry *OGRGeometry::Polygonize() const
     OGRGeometry *poPolygsOGRGeom = NULL;
     int bError = FALSE;
 
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+
     hGeosGeomList = new GEOSGeom [iCount];
     for ( int ig = 0; ig < iCount; ig++)
     {
@@ -3865,7 +3960,7 @@ OGRGeometry *OGRGeometry::Polygonize() const
             bError = TRUE;
         else
         {
-            hGeosGeom = poChild->exportToGEOS();
+            hGeosGeom = poChild->exportToGEOS(hGEOSCtxt);
             if( hGeosGeom == NULL)
                 bError = TRUE;
         }
@@ -3874,14 +3969,14 @@ OGRGeometry *OGRGeometry::Polygonize() const
 
     if( bError == FALSE )
     {
-        hGeosPolygs = GEOSPolygonize( hGeosGeomList, iCount );
+        hGeosPolygs = GEOSPolygonize_r( hGEOSCtxt, hGeosGeomList, iCount );
 
         if( hGeosPolygs != NULL )
         {
-            poPolygsOGRGeom = OGRGeometryFactory::createFromGEOS(hGeosPolygs);
+            poPolygsOGRGeom = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosPolygs);
             if( poPolygsOGRGeom != NULL && getSpatialReference() != NULL )
                 poPolygsOGRGeom->assignSpatialReference(getSpatialReference());
-            GEOSGeom_destroy( hGeosPolygs);
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosPolygs);
         }
     }
 
@@ -3889,9 +3984,10 @@ OGRGeometry *OGRGeometry::Polygonize() const
     {
         GEOSGeom hGeosGeom = *(hGeosGeomList + ig);
         if( hGeosGeom != NULL)
-            GEOSGeom_destroy( hGeosGeom );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
     }
     delete [] hGeosGeomList;
+    freeGEOSContext( hGEOSCtxt );
 
     return poPolygsOGRGeom;
 
@@ -3952,13 +4048,14 @@ void OGRGeometry::swapXY()
 /************************************************************************/
 
 /* GEOS >= 3.1.0 for prepared geometries */
-#if defined(HAVE_GEOS) && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 1))
+#if defined(HAVE_GEOS)
 #define HAVE_GEOS_PREPARED_GEOMETRY
 #endif
 
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
 struct _OGRPreparedGeometry
 {
+    GEOSContextHandle_t           hGEOSCtxt;
     GEOSGeom                      hGEOSGeom;
     const GEOSPreparedGeometry*   poPreparedGEOSGeom;
 };
@@ -3984,17 +4081,23 @@ int OGRHasPreparedGeometrySupport()
 OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
-    GEOSGeom hGEOSGeom = poGeom->exportToGEOS();
+    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
+    GEOSGeom hGEOSGeom = poGeom->exportToGEOS(hGEOSCtxt);
     if( hGEOSGeom == NULL )
+    {
+        OGRGeometry::freeGEOSContext( hGEOSCtxt );
         return NULL;
-    const GEOSPreparedGeometry* poPreparedGEOSGeom = GEOSPrepare(hGEOSGeom);
+    }
+    const GEOSPreparedGeometry* poPreparedGEOSGeom = GEOSPrepare_r(hGEOSCtxt, hGEOSGeom);
     if( poPreparedGEOSGeom == NULL )
     {
-        GEOSGeom_destroy( hGEOSGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hGEOSGeom );
+        OGRGeometry::freeGEOSContext( hGEOSCtxt );
         return NULL;
     }
 
     OGRPreparedGeometry* poPreparedGeom = new OGRPreparedGeometry;
+    poPreparedGeom->hGEOSCtxt = hGEOSCtxt;
     poPreparedGeom->hGEOSGeom = hGEOSGeom;
     poPreparedGeom->poPreparedGEOSGeom = poPreparedGEOSGeom;
 
@@ -4013,8 +4116,9 @@ void OGRDestroyPreparedGeometry( OGRPreparedGeometry* poPreparedGeom )
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     if( poPreparedGeom != NULL )
     {
-        GEOSPreparedGeom_destroy(poPreparedGeom->poPreparedGEOSGeom);
-        GEOSGeom_destroy( poPreparedGeom->hGEOSGeom );
+        GEOSPreparedGeom_destroy_r(poPreparedGeom->hGEOSCtxt, poPreparedGeom->poPreparedGEOSGeom);
+        GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, poPreparedGeom->hGEOSGeom );
+        OGRGeometry::freeGEOSContext( poPreparedGeom->hGEOSCtxt );
         delete poPreparedGeom;
     }
 #endif
@@ -4031,16 +4135,188 @@ int OGRPreparedGeometryIntersects( const OGRPreparedGeometry* poPreparedGeom,
     if( poPreparedGeom == NULL || poOtherGeom == NULL )
         return FALSE;
 
-    GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS();
+    GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
     if( hGEOSOtherGeom == NULL )
         return FALSE;
 
-    int bRet = GEOSPreparedIntersects(poPreparedGeom->poPreparedGEOSGeom,
-                                      hGEOSOtherGeom);
-    GEOSGeom_destroy( hGEOSOtherGeom );
+    int bRet = GEOSPreparedIntersects_r(poPreparedGeom->hGEOSCtxt,
+                                        poPreparedGeom->poPreparedGEOSGeom,
+                                        hGEOSOtherGeom);
+    GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, hGEOSOtherGeom );
 
     return bRet;
 #else
     return FALSE;
 #endif
 }
+
+/************************************************************************/
+/*                       OGRGeometryFromEWKB()                          */
+/************************************************************************/
+
+/* Flags for creating WKB format for PostGIS */
+#define WKBZOFFSET 0x80000000
+#define WKBMOFFSET 0x40000000
+#define WKBSRIDFLAG 0x20000000
+#define WKBBBOXFLAG 0x10000000
+
+OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID )
+
+{
+    OGRGeometry *poGeometry = NULL;
+    unsigned int ewkbFlags = 0;
+    
+    if (nLength < 5)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid EWKB content : %d bytes", nLength );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Detect XYZM variant of PostGIS EWKB                             */
+/*                                                                      */
+/*      OGR does not support parsing M coordinate,                      */
+/*      so we return NULL geometry.                                     */
+/* -------------------------------------------------------------------- */
+    memcpy(&ewkbFlags, pabyWKB+1, 4);
+    OGRwkbByteOrder eByteOrder = (pabyWKB[0] == 0 ? wkbXDR : wkbNDR);
+    if( OGR_SWAP( eByteOrder ) )
+        ewkbFlags= CPL_SWAP32(ewkbFlags);
+
+    if (ewkbFlags & WKBMOFFSET)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+            "Reading EWKB with 4-dimensional coordinates (XYZM) is not supported" );
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      PostGIS EWKB format includes an  SRID, but this won't be        */
+/*      understood by OGR, so if the SRID flag is set, we remove the    */
+/*      SRID (bytes at offset 5 to 8).                                  */
+/* -------------------------------------------------------------------- */
+    if( nLength > 9 &&
+        ((pabyWKB[0] == 0 /* big endian */ && (pabyWKB[1] & 0x20) )
+        || (pabyWKB[0] != 0 /* little endian */ && (pabyWKB[4] & 0x20))) )
+    {
+        if( pnSRID )
+        {
+            memcpy(pnSRID, pabyWKB+5, 4);
+            if( OGR_SWAP( eByteOrder ) )
+                *pnSRID = CPL_SWAP32(*pnSRID);
+        }
+        memmove( pabyWKB+5, pabyWKB+9, nLength-9 );
+        nLength -= 4;
+        if( pabyWKB[0] == 0 )
+            pabyWKB[1] &= (~0x20);
+        else
+            pabyWKB[4] &= (~0x20);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to ingest the geometry.                                     */
+/* -------------------------------------------------------------------- */
+    OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLength );
+
+    return poGeometry;
+}
+
+/************************************************************************/
+/*                     OGRGeometryFromHexEWKB()                         */
+/************************************************************************/
+
+OGRGeometry *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID )
+
+{
+    GByte   *pabyWKB;
+    int     nWKBLength=0;
+    OGRGeometry *poGeometry;
+
+    if( pszBytea == NULL )
+        return NULL;
+
+    pabyWKB = CPLHexToBinary(pszBytea, &nWKBLength);
+
+    poGeometry = OGRGeometryFromEWKB(pabyWKB, nWKBLength, pnSRID);
+
+    CPLFree(pabyWKB);
+
+    return poGeometry;
+}
+
+/************************************************************************/
+/*                       OGRGeometryToHexEWKB()                         */
+/************************************************************************/
+
+char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId )
+{
+    GByte       *pabyWKB;
+    char        *pszTextBuf;
+    char        *pszTextBufCurrent;
+    char        *pszHex;
+
+    int nWkbSize = poGeometry->WkbSize();
+    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
+
+    if( poGeometry->exportToWkb( wkbNDR, pabyWKB ) != OGRERR_NONE )
+    {
+        CPLFree( pabyWKB );
+        return CPLStrdup("");
+    }
+
+    /* When converting to hex, each byte takes 2 hex characters.  In addition
+       we add in 8 characters to represent the SRID integer in hex, and
+       one for a null terminator */
+
+    int pszSize = nWkbSize*2 + 8 + 1;
+    pszTextBuf = (char *) CPLMalloc(pszSize);
+    pszTextBufCurrent = pszTextBuf;
+
+    /* Convert the 1st byte, which is the endianess flag, to hex. */
+    pszHex = CPLBinaryToHex( 1, pabyWKB );
+    strcpy(pszTextBufCurrent, pszHex );
+    CPLFree ( pszHex );
+    pszTextBufCurrent += 2;
+
+    /* Next, get the geom type which is bytes 2 through 5 */
+    GUInt32 geomType;
+    memcpy( &geomType, pabyWKB+1, 4 );
+
+    /* Now add the SRID flag if an SRID is provided */
+    if (nSRSId > 0)
+    {
+        /* Change the flag to wkbNDR (little) endianess */
+        GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
+        /* Apply the flag */
+        geomType = geomType | nGSrsFlag;
+    }
+
+    /* Now write the geom type which is 4 bytes */
+    pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
+    strcpy(pszTextBufCurrent, pszHex );
+    CPLFree ( pszHex );
+    pszTextBufCurrent += 8;
+
+    /* Now include SRID if provided */
+    if (nSRSId > 0)
+    {
+        /* Force the srsid to wkbNDR (little) endianess */
+        GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
+        pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
+        strcpy(pszTextBufCurrent, pszHex );
+        CPLFree ( pszHex );
+        pszTextBufCurrent += 8;
+    }
+
+    /* Copy the rest of the data over - subtract
+       5 since we already copied 5 bytes above */
+    pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
+    strcpy(pszTextBufCurrent, pszHex );
+    CPLFree ( pszHex );
+
+    CPLFree( pabyWKB );
+
+    return pszTextBuf;
+}
diff --git a/ogr/ogrgeometrycollection.cpp b/ogr/ogrgeometrycollection.cpp
index 92cd98a..354dba2 100644
--- a/ogr/ogrgeometrycollection.cpp
+++ b/ogr/ogrgeometrycollection.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometrycollection.cpp 25426 2013-01-01 17:51:35Z rouault $
+ * $Id: ogrgeometrycollection.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRGeometryCollection class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeometrycollection.cpp 25426 2013-01-01 17:51:35Z rouault $");
+CPL_CVSID("$Id: ogrgeometrycollection.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       OGRGeometryCollection()                        */
@@ -399,18 +400,12 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
 /*      geometry type is between 0 and 255 so we only have to fetch     */
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
-    OGRwkbGeometryType eGeometryType;
 
-    if( eByteOrder == wkbNDR )
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[1];
-    }
-    else
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[4];
-    }
+    OGRBoolean b3D;
+    OGRwkbGeometryType eGeometryType;
+    OGRErr err = OGRReadWKBGeometryType( pabyData, &eGeometryType, &b3D );
 
-    if ( eGeometryType != wkbFlatten(getGeometryType()) )
+    if ( err != OGRERR_NONE || eGeometryType != wkbFlatten(getGeometryType()) )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
@@ -471,10 +466,9 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
             return OGRERR_CORRUPT_DATA;
 
         OGRwkbGeometryType eSubGeomType;
-        if( eSubGeomByteOrder == wkbNDR )
-            eSubGeomType = (OGRwkbGeometryType) pabySubData[1];
-        else
-            eSubGeomType = (OGRwkbGeometryType) pabySubData[4];
+        OGRBoolean bIs3D;
+        if ( OGRReadWKBGeometryType( pabySubData, &eSubGeomType, &bIs3D ) != OGRERR_NONE )
+            return OGRERR_FAILURE;
 
         if( eSubGeomType == wkbPoint ||
             eSubGeomType == wkbLineString ||
@@ -550,7 +544,8 @@ OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
 /************************************************************************/
 
 OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                            unsigned char * pabyData ) const
+                                            unsigned char * pabyData,
+                                            OGRwkbVariant eWkbVariant ) const
 
 {
     int         nOffset;
@@ -566,6 +561,9 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
     
+    if ( eWkbVariant == wkbVariantIso )
+        nGType = getIsoGeometryType();
+    
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
     else
@@ -950,6 +948,9 @@ OGRBoolean OGRGeometryCollection::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
+    if ( IsEmpty() && poOther->IsEmpty() )
+        return TRUE;
+
     if( getNumGeometries() != poOGC->getNumGeometries() )
         return FALSE;
     
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index a542e64..dd283ae 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometryfactory.cpp 25642 2013-02-12 10:57:34Z bishop $
+ * $Id: ogrgeometryfactory.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Factory for converting geometry to and from well known binary
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_p.h"
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 25642 2013-02-12 10:57:34Z bishop $");
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -118,10 +119,13 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      geometry type is between 0 and 255 so we only have to fetch     */
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
-    if( eByteOrder == wkbNDR )
-        eGeometryType = (OGRwkbGeometryType) pabyData[1];
-    else
-        eGeometryType = (OGRwkbGeometryType) pabyData[4];
+
+    OGRBoolean bIs3D;
+    OGRErr err = OGRReadWKBGeometryType( pabyData, &eGeometryType, &bIs3D );
+
+    if( err != OGRERR_NONE )
+        return err;
+
 
 /* -------------------------------------------------------------------- */
 /*      Instantiate a geometry of the appropriate type, and             */
@@ -520,10 +524,10 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
         if( poOldPoly->getExteriorRing() == NULL )
             continue;
 
-        poPolygon->addRing( poOldPoly->getExteriorRing() );
+        poPolygon->addRingDirectly( poOldPoly->stealExteriorRing() );
 
         for( iRing = 0; iRing < poOldPoly->getNumInteriorRings(); iRing++ )
-            poPolygon->addRing( poOldPoly->getInteriorRing( iRing ) );
+            poPolygon->addRingDirectly( poOldPoly->stealInteriorRing( iRing ) );
     }
     
     delete poGC;
@@ -995,7 +999,8 @@ typedef enum
 {
    METHOD_NORMAL,
    METHOD_SKIP,
-   METHOD_ONLY_CCW
+   METHOD_ONLY_CCW,
+   METHOD_CCW_INNER_JUST_AFTER_CW_OUTER
 } OrganizePolygonMethod;
 
 /**
@@ -1003,7 +1008,8 @@ typedef enum
  *
  * Analyse a set of rings (passed as simple polygons), and based on a 
  * geometric analysis convert them into a polygon with inner rings, 
- * or a MultiPolygon if dealing with more than one polygon.
+ * (or a MultiPolygon if dealing with more than one polygon) that follow the
+ * OGC Simple Feature specification.
  *
  * All the input geometries must be OGRPolygons with only a valid exterior
  * ring (at least 4 points) and no interior rings. 
@@ -1022,7 +1028,15 @@ typedef enum
  * to the option list (the result of the function will be a multi-polygon with all polygons
  * as toplevel polygons) or only make it analyze counterclockwise polygons by adding
  * METHOD=ONLY_CCW to the option list if you can assume that the outline
- * of holes is counterclockwise defined (this is the convention for shapefiles e.g.)
+ * of holes is counterclockwise defined (this is the convention for example in shapefiles,
+ * Personal Geodatabases or File Geodatabases).
+ *
+ * For FileGDB, in most cases, but not always, a faster method than ONLY_CCW can be used. It is
+ * CCW_INNER_JUST_AFTER_CW_OUTER. When using it, inner rings are assumed to be
+ * counterclockwise oriented, and following immediately the outer ring (clockwise
+ * oriented) that they belong to. If that assumption is not met, an inner ring
+ * could be attached to the wrong outer ring, so this method must be used
+ * with care.
  *
  * If the OGR_ORGANIZE_POLYGONS configuration option is defined, its value will override
  * the value of the METHOD option of papszOptions (usefull to modify the behaviour of the
@@ -1108,6 +1122,10 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         {
             method = METHOD_ONLY_CCW;
         }
+        else if (EQUAL(pszMethodValue, "CCW_INNER_JUST_AFTER_CW_OUTER"))
+        {
+            method = METHOD_CCW_INNER_JUST_AFTER_CW_OUTER;
+        }
         else if (!EQUAL(pszMethodValue, "DEFAULT"))
         {
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -1128,7 +1146,8 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             && ((OGRPolygon *) papoPolygons[i])->getNumInteriorRings() == 0
             && ((OGRPolygon *)papoPolygons[i])->getExteriorRing()->getNumPoints() >= 4)
         {
-            asPolyEx[i].dfArea = asPolyEx[i].poPolygon->get_Area();
+            if( method != METHOD_CCW_INNER_JUST_AFTER_CW_OUTER )
+                asPolyEx[i].dfArea = asPolyEx[i].poPolygon->get_Area();
             asPolyEx[i].poExteriorRing = asPolyEx[i].poPolygon->getExteriorRing();
             asPolyEx[i].poExteriorRing->getPoint(0, &asPolyEx[i].poAPoint);
             asPolyEx[i].bIsCW = asPolyEx[i].poExteriorRing->isClockwise();
@@ -1158,14 +1177,15 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
 
     /* If we are in ONLY_CCW mode and that we have found that there is only one outer ring, */
     /* then it is pretty easy : we can assume that all other rings are inside */
-    if (method == METHOD_ONLY_CCW && nCountCWPolygon == 1 && bUseFastVersion)
+    if ((method == METHOD_ONLY_CCW || method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER) &&
+        nCountCWPolygon == 1 && bUseFastVersion && !bNonPolygon )
     {
         geom = asPolyEx[indexOfCWPolygon].poPolygon;
         for(i=0; i<nPolygonCount; i++)
         {
             if (i != indexOfCWPolygon)
             {
-                ((OGRPolygon*)geom)->addRing(asPolyEx[i].poPolygon->getExteriorRing());
+                ((OGRPolygon*)geom)->addRingDirectly(asPolyEx[i].poPolygon->stealExteriorRing());
                 delete asPolyEx[i].poPolygon;
             }
         }
@@ -1175,6 +1195,55 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         return geom;
     }
 
+    if( method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER && !bNonPolygon && asPolyEx[0].bIsCW )
+    {
+        /* Inner rings are CCW oriented and follow immediately the outer */
+        /* ring (that is CW oriented) in which they are included */
+        OGRMultiPolygon* poMulti = NULL;
+        OGRPolygon* poCur = asPolyEx[0].poPolygon;
+        OGRGeometry* poRet = poCur;
+        /* We have already checked that the first ring is CW */
+        OGREnvelope* psEnvelope = &(asPolyEx[0].sEnvelope);
+        for(i=1;i<nPolygonCount;i++)
+        {
+            if( asPolyEx[i].bIsCW )
+            {
+                if( poMulti == NULL )
+                {
+                    poMulti = new OGRMultiPolygon();
+                    poRet = poMulti;
+                    poMulti->addGeometryDirectly(poCur);
+                }
+                poCur = asPolyEx[i].poPolygon;
+                poMulti->addGeometryDirectly(poCur);
+                psEnvelope = &(asPolyEx[i].sEnvelope);
+            }
+            else
+            {
+                poCur->addRingDirectly(asPolyEx[i].poPolygon->stealExteriorRing());
+                if(!(asPolyEx[i].poAPoint.getX() >= psEnvelope->MinX &&
+                     asPolyEx[i].poAPoint.getX() <= psEnvelope->MaxX &&
+                     asPolyEx[i].poAPoint.getY() >= psEnvelope->MinY &&
+                     asPolyEx[i].poAPoint.getY() <= psEnvelope->MaxY))
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Part %d does not respect CCW_INNER_JUST_AFTER_CW_OUTER rule", i);
+                }
+                delete asPolyEx[i].poPolygon;
+            }
+        }
+        delete [] asPolyEx;
+        if (pbIsValidGeometry)
+            *pbIsValidGeometry = TRUE;
+        return poRet;
+    }
+    else if( method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER && !bNonPolygon )
+    {
+        method = METHOD_ONLY_CCW;
+        for(i=0;i<nPolygonCount;i++)
+            asPolyEx[i].dfArea = asPolyEx[i].poPolygon->get_Area();
+    }
+
     /* Emits a warning if the number of parts is sufficiently big to anticipate for */
     /* very long computation time, and the user didn't specify an explicit method */
     if (nPolygonCount > N_CRITICAL_PART_NUMBER && method == METHOD_NORMAL && pszMethodValue == NULL)
@@ -1277,9 +1346,11 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             {
                 if (bUseFastVersion)
                 {
-                    /* Note that isPointInRing only test strict inclusion in the ring */
-                    if (asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint, FALSE))
+                    if( method == METHOD_ONLY_CCW && j == 0 )
                     {
+                        /* We are testing if a CCW ring is in the biggest CW ring */
+                        /* It *must* be inside as this is the last candidate, otherwise */
+                        /* the winding order rules is broken */
                         b_i_inside_j = TRUE;
                     }
                     else if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&asPolyEx[i].poAPoint, FALSE))
@@ -1290,22 +1361,56 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                         {
                             OGRPoint point;
                             asPolyEx[i].poExteriorRing->getPoint(k, &point);
-                            if (asPolyEx[j].poExteriorRing->isPointInRing(&point, FALSE))
+                            if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&point, FALSE))
+                            {
+                                /* If it is on the boundary of j, iterate again */ 
+                            }
+                            else if (asPolyEx[j].poExteriorRing->isPointInRing(&point, FALSE))
                             {
                                 /* If then point is strictly included in j, then i is considered inside j */
                                 b_i_inside_j = TRUE;
                                 break;
                             }
-                            else if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&point, FALSE))
-                            {
-                                /* If it is on the boundary of j, iterate again */ 
-                            }
-                            else
+                            else 
                             {
                                 /* If it is outside, then i cannot be inside j */
                                 break;
                             }
                         }
+                        if( !b_i_inside_j && k == nPoints && nPoints > 2 )
+                        {
+                            /* all points of i are on the boundary of j ... */
+                            /* take a point in the middle of a segment of i and */
+                            /* test it against j */
+                            for(k=0;k<nPoints-1;k++)
+                            {
+                                OGRPoint point1, point2, pointMiddle;
+                                asPolyEx[i].poExteriorRing->getPoint(k, &point1);
+                                asPolyEx[i].poExteriorRing->getPoint(k+1, &point2);
+                                pointMiddle.setX((point1.getX() + point2.getX()) / 2);
+                                pointMiddle.setY((point1.getY() + point2.getY()) / 2);
+                                if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&pointMiddle, FALSE))
+                                {
+                                    /* If it is on the boundary of j, iterate again */ 
+                                }
+                                else if (asPolyEx[j].poExteriorRing->isPointInRing(&pointMiddle, FALSE))
+                                {
+                                    /* If then point is strictly included in j, then i is considered inside j */
+                                    b_i_inside_j = TRUE;
+                                    break;
+                                }
+                                else 
+                                {
+                                    /* If it is outside, then i cannot be inside j */
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    /* Note that isPointInRing only test strict inclusion in the ring */
+                    else if (asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint, FALSE))
+                    {
+                        b_i_inside_j = TRUE;
                     }
                 }
                 else if (asPolyEx[j].poPolygon->Contains(asPolyEx[i].poPolygon))
@@ -1407,8 +1512,8 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         {
             if (asPolyEx[i].bIsTopLevel == FALSE)
             {
-                asPolyEx[i].poEnclosingPolygon->addRing(
-                    asPolyEx[i].poPolygon->getExteriorRing());
+                asPolyEx[i].poEnclosingPolygon->addRingDirectly(
+                    asPolyEx[i].poPolygon->stealExteriorRing());
                 delete asPolyEx[i].poPolygon;
             }
             else if (nCountTopLevel == 1)
@@ -1488,7 +1593,7 @@ OGRGeometry *OGRGeometryFactory::createFromGML( const char *pszData )
 /************************************************************************/
 
 OGRGeometry *
-OGRGeometryFactory::createFromGEOS( GEOSGeom geosGeom )
+OGRGeometryFactory::createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom geosGeom )
 
 {
 #ifndef HAVE_GEOS 
@@ -1504,19 +1609,19 @@ OGRGeometryFactory::createFromGEOS( GEOSGeom geosGeom )
     OGRGeometry *poGeometry = NULL;
 
     /* Special case as POINT EMPTY cannot be translated to WKB */
-    if (GEOSGeomTypeId(geosGeom) == GEOS_POINT &&
-        GEOSisEmpty(geosGeom))
+    if (GEOSGeomTypeId_r(hGEOSCtxt, geosGeom) == GEOS_POINT &&
+        GEOSisEmpty_r(hGEOSCtxt, geosGeom))
         return new OGRPoint();
 
 #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)
     /* GEOSGeom_getCoordinateDimension only available in GEOS 3.3.0 (unreleased at time of writing) */
-    int nCoordDim = GEOSGeom_getCoordinateDimension(geosGeom);
-    GEOSWKBWriter* wkbwriter = GEOSWKBWriter_create();
-    GEOSWKBWriter_setOutputDimension(wkbwriter, nCoordDim);
-    pabyBuf = GEOSWKBWriter_write( wkbwriter, geosGeom, &nSize );
-    GEOSWKBWriter_destroy(wkbwriter);
+    int nCoordDim = GEOSGeom_getCoordinateDimension_r(hGEOSCtxt, geosGeom);
+    GEOSWKBWriter* wkbwriter = GEOSWKBWriter_create_r(hGEOSCtxt);
+    GEOSWKBWriter_setOutputDimension_r(hGEOSCtxt, wkbwriter, nCoordDim);
+    pabyBuf = GEOSWKBWriter_write_r(hGEOSCtxt, wkbwriter, geosGeom, &nSize );
+    GEOSWKBWriter_destroy_r(hGEOSCtxt, wkbwriter);
 #else
-    pabyBuf = GEOSGeomToWKB_buf( geosGeom, &nSize );
+    pabyBuf = GEOSGeomToWKB_buf_r( hGEOSCtxt, geosGeom, &nSize );
 #endif
     if( pabyBuf == NULL || nSize == 0 )
     {
@@ -1534,7 +1639,7 @@ OGRGeometryFactory::createFromGEOS( GEOSGeom geosGeom )
     {
         /* Since GEOS 3.1.1, so we test 3.2.0 */
 #if GEOS_CAPI_VERSION_MAJOR >= 2 || (GEOS_CAPI_VERSION_MAJOR == 1 && GEOS_CAPI_VERSION_MINOR >= 6)
-        GEOSFree( pabyBuf );
+        GEOSFree_r( hGEOSCtxt, pabyBuf );
 #else
         free( pabyBuf );
 #endif
@@ -1546,18 +1651,6 @@ OGRGeometryFactory::createFromGEOS( GEOSGeom geosGeom )
 }
 
 /************************************************************************/
-/*                       getGEOSGeometryFactory()                       */
-/************************************************************************/
-
-void *OGRGeometryFactory::getGEOSGeometryFactory() 
-
-{
-    // XXX - mloskot - What to do with this call
-    // after GEOS C++ API has been stripped?
-    return NULL;
-}
-
-/************************************************************************/
 /*                              haveGEOS()                              */
 /************************************************************************/
 
@@ -2543,6 +2636,11 @@ OGR_G_ApproximateArcAngles(
  * consumed and a new one returned (or potentially the same one).
  *
  * @param poGeom the input geometry - ownership is passed to the method.
+ * @param bOnlyInOrder flag that, if set to FALSE, indicate that the order of
+ *                     points in a linestring might be reversed if it enables
+ *                     to match the extremity of another linestring. If set
+ *                     to TRUE, the start of a linestring must match the end
+ *                     of another linestring.
  * @return new geometry.
  */
 
diff --git a/ogr/ogrgeomfielddefn.cpp b/ogr/ogrgeomfielddefn.cpp
new file mode 100644
index 0000000..fb89508
--- /dev/null
+++ b/ogr/ogrgeomfielddefn.cpp
@@ -0,0 +1,494 @@
+/******************************************************************************
+ * $Id: ogrgeomfielddefn.cpp 27110 2014-03-28 21:29:20Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  The OGRGeomFieldDefn class implementation.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_feature.h"
+#include "ogr_api.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrgeomfielddefn.cpp 27110 2014-03-28 21:29:20Z rouault $");
+
+/************************************************************************/
+/*                         OGRGeomFieldDefn()                           */
+/************************************************************************/
+
+/**
+ * \brief Constructor.
+ *
+ * @param pszNameIn the name of the new field.
+ * @param eGeomTypeIn the type of the new field.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefn::OGRGeomFieldDefn( const char * pszNameIn,
+                                    OGRwkbGeometryType eGeomTypeIn )
+
+{
+    Initialize( pszNameIn, eGeomTypeIn );
+}
+
+/************************************************************************/
+/*                          OGRGeomFieldDefn()                          */
+/************************************************************************/
+
+/**
+ * \brief Constructor.
+ *
+ * Create by cloning an existing geometry field definition.
+ *
+ * @param poPrototype the geometry field definition to clone.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefn::OGRGeomFieldDefn( OGRGeomFieldDefn *poPrototype )
+
+{
+    Initialize( poPrototype->GetNameRef(), poPrototype->GetType() );
+    SetSpatialRef( poPrototype->GetSpatialRef() );
+}
+
+/************************************************************************/
+/*                           OGR_GFld_Create()                          */
+/************************************************************************/
+/**
+ * \brief Create a new field geometry definition.
+ *
+ * This function is the same as the CPP method OGRGeomFieldDefn::OGRGeomFieldDefn().
+ *
+ * @param pszName the name of the new field definition.
+ * @param eType the type of the new field definition.
+ * @return handle to the new field definition.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRGeomFieldDefnH OGR_GFld_Create( const char *pszName,
+                                   OGRwkbGeometryType eType )
+
+{
+    return (OGRGeomFieldDefnH) (new OGRGeomFieldDefn(pszName,eType));
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+void OGRGeomFieldDefn::Initialize( const char * pszNameIn,
+                                   OGRwkbGeometryType eTypeIn )
+
+{
+    pszName = CPLStrdup( pszNameIn );
+    eGeomType = eTypeIn;
+    poSRS = NULL;
+    bIgnore = FALSE;
+}
+
+/************************************************************************/
+/*                         ~OGRGeomFieldDefn()                          */
+/************************************************************************/
+
+OGRGeomFieldDefn::~OGRGeomFieldDefn()
+
+{
+    CPLFree( pszName );
+
+    if( NULL != poSRS )
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                         OGR_GFld_Destroy()                           */
+/************************************************************************/
+/**
+ * \brief Destroy a geometry field definition.
+ *
+ * @param hDefn handle to the geometry field definition to destroy.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_GFld_Destroy( OGRGeomFieldDefnH hDefn )
+
+{
+    VALIDATE_POINTER0( hDefn, "OGR_GFld_Destroy" );
+    delete (OGRGeomFieldDefn *) hDefn;
+}
+
+/************************************************************************/
+/*                              SetName()                               */
+/************************************************************************/
+
+/**
+ * \brief Reset the name of this field.
+ *
+ * This method is the same as the C function OGR_GFld_SetName().
+ *
+ * @param pszNameIn the new name to apply.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGRGeomFieldDefn::SetName( const char * pszNameIn )
+
+{
+    CPLFree( pszName );
+    pszName = CPLStrdup( pszNameIn );
+}
+
+/************************************************************************/
+/*                         OGR_GFld_SetName()                           */
+/************************************************************************/
+/**
+ * \brief Reset the name of this field.
+ *
+ * This function is the same as the CPP method OGRGeomFieldDefn::SetName().
+ *
+ * @param hDefn handle to the geometry field definition to apply the new name to.
+ * @param pszName the new name to apply.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_GFld_SetName( OGRGeomFieldDefnH hDefn, const char *pszName )
+
+{
+    VALIDATE_POINTER0( hDefn, "OGR_GFld_SetName" );
+    ((OGRGeomFieldDefn *) hDefn)->SetName( pszName );
+}
+
+/************************************************************************/
+/*                             GetNameRef()                             */
+/************************************************************************/
+
+/**
+ * \fn const char *OGRGeomFieldDefn::GetNameRef();
+ *
+ * \brief Fetch name of this field.
+ *
+ * This method is the same as the C function OGR_GFld_GetNameRef().
+ *
+ * @return pointer to an internal name string that should not be freed or
+ * modified.
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                        OGR_GFld_GetNameRef()                         */
+/************************************************************************/
+/**
+ * \brief Fetch name of this field.
+ *
+ * This function is the same as the CPP method OGRGeomFieldDefn::GetNameRef().
+ *
+ * @param hDefn handle to the geometry field definition.
+ * @return the name of the geometry field definition.
+ *
+ * @since GDAL 1.11
+ */
+
+const char *OGR_GFld_GetNameRef( OGRGeomFieldDefnH hDefn )
+
+{
+    VALIDATE_POINTER1( hDefn, "OGR_GFld_GetNameRef", "" );
+    return ((OGRGeomFieldDefn *) hDefn)->GetNameRef();
+}
+
+/************************************************************************/
+/*                              GetType()                               */
+/************************************************************************/
+
+/**
+ * \fn OGRwkbGeometryType OGRGeomFieldDefn::GetType();
+ *
+ * \brief Fetch geometry type of this field.
+ *
+ * This method is the same as the C function OGR_GFld_GetType().
+ *
+ * @return field geometry type.
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                          OGR_GFld_GetType()                          */
+/************************************************************************/
+/**
+ * \brief Fetch geometry type of this field.
+ *
+ * This function is the same as the CPP method OGRGeomFieldDefn::GetType().
+ *
+ * @param hDefn handle to the geometry field definition to get type from.
+ * @return field geometry type.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRwkbGeometryType OGR_GFld_GetType( OGRGeomFieldDefnH hDefn )
+
+{
+    VALIDATE_POINTER1( hDefn, "OGR_GFld_GetType", wkbUnknown );
+    return ((OGRGeomFieldDefn *) hDefn)->GetType();
+}
+
+/************************************************************************/
+/*                              SetType()                               */
+/************************************************************************/
+
+/**
+ * \fn void OGRGeomFieldDefn::SetType( OGRwkbGeometryType eType );
+ *
+ * \brief Set the geometry type of this field.
+ * This should never be done to an OGRGeomFieldDefn
+ * that is already part of an OGRFeatureDefn.
+ *
+ * This method is the same as the C function OGR_GFld_SetType().
+ *
+ * @param eType the new field geometry type.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGRGeomFieldDefn::SetType( OGRwkbGeometryType eTypeIn )
+
+{
+    eGeomType = eTypeIn;
+}
+
+/************************************************************************/
+/*                          OGR_GFld_SetType()                          */
+/************************************************************************/
+/**
+ * \brief Set the geometry type of this field.
+ * This should never be done to an OGRGeomFieldDefn
+ * that is already part of an OGRFeatureDefn.
+ *
+ * This function is the same as the CPP method OGRGeomFieldDefn::SetType().
+ *
+ * @param hDefn handle to the geometry field definition to set type to.
+ * @param eType the new field geometry type.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_GFld_SetType( OGRGeomFieldDefnH hDefn, OGRwkbGeometryType eType )
+
+{
+    VALIDATE_POINTER0( hDefn, "OGR_GFld_SetType" );
+    ((OGRGeomFieldDefn *) hDefn)->SetType( eType );
+}
+
+/************************************************************************/
+/*                             IsIgnored()                              */
+/************************************************************************/
+
+/**
+ * \fn int OGRGeomFieldDefn::IsIgnored();
+ *
+ * \brief Return whether this field should be omitted when fetching features
+ *
+ * This method is the same as the C function OGR_GFld_IsIgnored().
+ *
+ * @return ignore state
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                         OGR_GFld_IsIgnored()                         */
+/************************************************************************/
+
+/**
+ * \brief Return whether this field should be omitted when fetching features
+ *
+ * This method is the same as the C++ method OGRGeomFieldDefn::IsIgnored().
+ *
+ * @param hDefn handle to the geometry field definition
+ * @return ignore state
+ *
+ * @since GDAL 1.11
+ */
+
+int OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn )
+{
+    VALIDATE_POINTER1( hDefn, "OGR_GFld_IsIgnored", FALSE );
+    return ((OGRGeomFieldDefn *) hDefn)->IsIgnored();
+}
+
+/************************************************************************/
+/*                            SetIgnored()                              */
+/************************************************************************/
+
+/**
+ * \fn void OGRGeomFieldDefn::SetIgnored( int ignore );
+ *
+ * \brief Set whether this field should be omitted when fetching features
+ *
+ * This method is the same as the C function OGR_GFld_SetIgnored().
+ *
+ * @param ignore ignore state
+ *
+ * @since GDAL 1.11
+ */
+
+/************************************************************************/
+/*                        OGR_GFld_SetIgnored()                         */
+/************************************************************************/
+
+/**
+ * \brief Set whether this field should be omitted when fetching features
+ *
+ * This method is the same as the C++ method OGRGeomFieldDefn::SetIgnored().
+ *
+ * @param hDefn handle to the geometry field definition
+ * @param ignore ignore state
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_GFld_SetIgnored( OGRGeomFieldDefnH hDefn, int ignore )
+{
+    VALIDATE_POINTER0( hDefn, "OGR_GFld_SetIgnored" );
+    ((OGRGeomFieldDefn *) hDefn)->SetIgnored( ignore );
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+/**
+ * \brief Fetch spatial reference system of this field.
+ *
+ * This method is the same as the C function OGR_GFld_GetSpatialRef().
+ *
+ * @return field spatial reference system.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRSpatialReference* OGRGeomFieldDefn::GetSpatialRef()
+{
+    return poSRS;
+}
+
+/************************************************************************/
+/*                       OGR_GFld_GetSpatialRef()                       */
+/************************************************************************/
+
+/**
+ * \brief Fetch spatial reference system of this field.
+ *
+ * This function is the same as the C++ method OGRGeomFieldDefn::GetSpatialRef().
+ *
+ * @param hDefn handle to the geometry field definition
+ *
+ * @return field spatial reference system.
+ *
+ * @since GDAL 1.11
+ */
+
+OGRSpatialReferenceH OGR_GFld_GetSpatialRef( OGRGeomFieldDefnH hDefn )
+{
+    VALIDATE_POINTER1( hDefn, "OGR_GFld_GetSpatialRef", NULL );
+    return (OGRSpatialReferenceH) ((OGRGeomFieldDefn *) hDefn)->GetSpatialRef();
+}
+
+/************************************************************************/
+/*                           SetSpatialRef()                            */
+/************************************************************************/
+
+/**
+ * \brief Set the spatial reference of this field.
+ *
+ * This method is the same as the C function OGR_GFld_SetSpatialRef().
+ *
+ * This method drops the reference of the previously set SRS object and
+ * acquires a new reference on the passed object (if non-NULL).
+ *
+ * @param poSRSIn the new SRS to apply.
+ *
+ * @since GDAL 1.11
+ */
+void OGRGeomFieldDefn::SetSpatialRef(OGRSpatialReference* poSRSIn)
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+    poSRS = poSRSIn;
+    if( poSRS != NULL )
+        poSRS->Reference();
+}
+
+/************************************************************************/
+/*                       OGR_GFld_SetSpatialRef()                       */
+/************************************************************************/
+
+/**
+ * \brief Set the spatial reference of this field.
+ *
+ * This function is the same as the C++ method OGRGeomFieldDefn::SetSpatialRef().
+ *
+ * This function drops the reference of the previously set SRS object and
+ * acquires a new reference on the passed object (if non-NULL).
+ *
+ * @param hDefn handle to the geometry field definition
+ * @param hSRS the new SRS to apply.
+ *
+ * @since GDAL 1.11
+ */
+
+void OGR_GFld_SetSpatialRef( OGRGeomFieldDefnH hDefn, OGRSpatialReferenceH hSRS )
+{
+    VALIDATE_POINTER0( hDefn, "OGR_GFld_SetSpatialRef" );
+    ((OGRGeomFieldDefn *) hDefn)->SetSpatialRef( (OGRSpatialReference*) hSRS );
+}
+
+/************************************************************************/
+/*                             IsSame()                                 */
+/************************************************************************/
+
+/**
+ * \brief Test if the geometry field definition is identical to the other one.
+ *
+ * @param poOtherFieldDefn the other field definition to compare to.
+ * @return TRUE if the geometry field definition is identical to the other one.
+ *
+ * @since GDAL 1.11
+ */
+
+int OGRGeomFieldDefn::IsSame( OGRGeomFieldDefn * poOtherFieldDefn )
+{
+    if( !(strcmp(GetNameRef(), poOtherFieldDefn->GetNameRef()) == 0 &&
+                 GetType() == poOtherFieldDefn->GetType()) )
+        return FALSE;
+    OGRSpatialReference* poMySRS = GetSpatialRef();
+    OGRSpatialReference* poOtherSRS = poOtherFieldDefn->GetSpatialRef();
+    return ((poMySRS == poOtherSRS) ||
+            (poMySRS != NULL && poOtherSRS != NULL &&
+             poMySRS->IsSame(poOtherSRS)));
+}
diff --git a/ogr/ogrlinearring.cpp b/ogr/ogrlinearring.cpp
index 7b1e3ae..231713e 100644
--- a/ogr/ogrlinearring.cpp
+++ b/ogr/ogrlinearring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinearring.cpp 24520 2012-05-30 21:30:11Z rouault $
+ * $Id: ogrlinearring.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLinearRing geometry class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrlinearring.cpp 24520 2012-05-30 21:30:11Z rouault $");
+CPL_CVSID("$Id: ogrlinearring.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRLinearRing()                            */
@@ -62,7 +63,7 @@ OGRLinearRing::OGRLinearRing( OGRLinearRing * poSrcRing )
         return;
     }
 
-    setNumPoints( poSrcRing->getNumPoints() );
+    setNumPoints( poSrcRing->getNumPoints(), FALSE );
 
     memcpy( paoPoints, poSrcRing->paoPoints,
             sizeof(OGRRawPoint) * getNumPoints() );
@@ -118,11 +119,13 @@ OGRErr OGRLinearRing::importFromWkb( unsigned char *pabyData, int nSize )
 /************************************************************************/
 
 OGRErr OGRLinearRing::exportToWkb( OGRwkbByteOrder eByteOrder, 
-                                   unsigned char * pabyData ) const
+                                   unsigned char * pabyData,
+                                   OGRwkbVariant eWkbVariant ) const
 
 {
     (void) eByteOrder;
     (void) pabyData;
+    (void) eWkbVariant;
 
     return OGRERR_UNSUPPORTED_OPERATION;
 }
@@ -169,7 +172,7 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
     }
 
     /* (Re)Allocation of paoPoints buffer. */
-    setNumPoints( nNewNumPoints );
+    setNumPoints( nNewNumPoints, FALSE );
 
     if( b3D )
         Make3D();
@@ -351,6 +354,14 @@ int OGRLinearRing::isClockwise() const
                paoPoints[i].x > paoPoints[v].x ) )
         {
             v = i;
+            bUseFallback = FALSE;
+        }
+        else if ( paoPoints[i].y == paoPoints[v].y &&
+                  paoPoints[i].x == paoPoints[v].x )
+        {
+            /* Two vertex with same coordinates are the lowest rightmost */
+            /* vertex! We cannot use that point as the pivot (#5342) */
+            bUseFallback = TRUE;
         }
     }
 
@@ -530,17 +541,18 @@ OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelo
     // test if ray starting from given point crosses segment (p - 1, p)
     int iNumCrossings = 0;
 
+    double prev_diff_x = getX(0) - dfTestX;
+    double prev_diff_y = getY(0) - dfTestY;
+
     for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ ) 
     {
-        const int iPointPrev = iPoint - 1;
-
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
 
-        const double x2 = getX(iPointPrev) - dfTestX;
-        const double y2 = getY(iPointPrev) - dfTestY;
+        const double x2 = prev_diff_x;
+        const double y2 = prev_diff_y;
 
-        if( ( ( y1 > 0 ) && ( y2 <= 0 ) ) || ( ( y2 > 0 ) && ( y1 <= 0 ) ) ) 
+        if( ( ( y1 > 0 ) && ( y2 <= 0 ) ) || ( ( y2 > 0 ) && ( y1 <= 0 ) ) )
         {
             // Check if ray intersects with segment of the ring
             const double dfIntersection = ( x1 * y2 - x2 * y1 ) / (y2 - y1);
@@ -550,6 +562,9 @@ OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelo
                 iNumCrossings++;
             }
         }
+
+        prev_diff_x = x1;
+        prev_diff_y = y1;
     }
 
     // If iNumCrossings number is even, given point is outside the ring,
@@ -579,38 +594,44 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
     const double dfTestY = poPoint->getY();
 
     // Fast test if point is inside extent of the ring
-    OGREnvelope extent;
-    getEnvelope(&extent);
-    if ( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
-         && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
+    if( bTestEnvelope )
     {
-        return 0;
+        OGREnvelope extent;
+        getEnvelope(&extent);
+        if ( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
+            && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
+        {
+            return 0;
+        }
     }
 
+    double prev_diff_x = getX(0) - dfTestX;
+    double prev_diff_y = getY(0) - dfTestY;
+
     for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ ) 
     {
-        const int iPointPrev = iPoint - 1;
-
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
 
-        const double x2 = getX(iPointPrev) - dfTestX;
-        const double y2 = getY(iPointPrev) - dfTestY;
-
-        /* If iPoint and iPointPrev are the same, go on */
-        if (x1 == x2 && y1 == y2)
-        {
-            continue;
-        }
+        const double x2 = prev_diff_x;
+        const double y2 = prev_diff_y;
 
         /* If the point is on the segment, return immediatly */
         /* FIXME? If the test point is not exactly identical to one of */
         /* the vertices of the ring, but somewhere on a segment, there's */
         /* little chance that we get 0. So that should be tested against some epsilon */
+
         if ( x1 * y2 - x2 * y1 == 0 )
         {
-            return 1;
+            /* If iPoint and iPointPrev are the same, go on */
+            if( !(x1 == x2 && y1 == y2) )
+            {
+                return 1;
+            }
         }
+
+        prev_diff_x = x1;
+        prev_diff_y = y1;
     }
 
     return 0;
diff --git a/ogr/ogrlinestring.cpp b/ogr/ogrlinestring.cpp
index dde9324..cbed43d 100644
--- a/ogr/ogrlinestring.cpp
+++ b/ogr/ogrlinestring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinestring.cpp 24519 2012-05-30 21:28:53Z rouault $
+ * $Id: ogrlinestring.cpp 27111 2014-03-28 21:34:19Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLineString geometry class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +31,9 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 #include <assert.h>
+#include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrlinestring.cpp 24519 2012-05-30 21:28:53Z rouault $");
+CPL_CVSID("$Id: ogrlinestring.cpp 27111 2014-03-28 21:34:19Z rouault $");
 
 /************************************************************************/
 /*                           OGRLineString()                            */
@@ -69,12 +71,13 @@ OGRLineString::~OGRLineString()
 OGRwkbGeometryType OGRLineString::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( nCoordDimension == 3 )
         return wkbLineString25D;
     else
         return wkbLineString;
 }
 
+
 /************************************************************************/
 /*                            flattenTo2D()                             */
 /************************************************************************/
@@ -297,7 +300,7 @@ double OGRLineString::getZ( int iVertex ) const
  * @param nNewPointCount the new number of points for geometry.
  */
 
-void OGRLineString::setNumPoints( int nNewPointCount )
+void OGRLineString::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
 {
     if( nNewPointCount == 0 )
@@ -324,7 +327,8 @@ void OGRLineString::setNumPoints( int nNewPointCount )
         }
         paoPoints = paoNewPoints;
         
-        memset( paoPoints + nPointCount,
+        if( bZeroizeNewContent )
+            memset( paoPoints + nPointCount,
                 0, sizeof(OGRRawPoint) * (nNewPointCount - nPointCount) );
         
         if( getCoordinateDimension() == 3 )
@@ -338,7 +342,8 @@ void OGRLineString::setNumPoints( int nNewPointCount )
                 return;
             }
             padfZ = padfNewZ;
-            memset( padfZ + nPointCount, 0,
+            if( bZeroizeNewContent )
+                memset( padfZ + nPointCount, 0,
                     sizeof(double) * (nNewPointCount - nPointCount) );
         }
     }
@@ -433,6 +438,26 @@ void OGRLineString::setPoint( int iPoint, double xIn, double yIn )
 }
 
 /************************************************************************/
+/*                                setZ()                                */
+/************************************************************************/
+
+void OGRLineString::setZ( int iPoint, double zIn )
+{
+    if( getCoordinateDimension() == 2 )
+        Make3D();
+
+    if( iPoint >= nPointCount )
+    {
+        setNumPoints( iPoint+1 );
+        if (nPointCount < iPoint + 1)
+            return;
+    }
+
+    if( padfZ )
+        padfZ[iPoint] = zIn;
+}
+
+/************************************************************************/
 /*                              addPoint()                              */
 /************************************************************************/
 
@@ -507,7 +532,7 @@ void OGRLineString::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
                                double * padfZ )
 
 {
-    setNumPoints( nPointsIn );
+    setNumPoints( nPointsIn, FALSE );
     if (nPointCount < nPointsIn)
         return;
 
@@ -563,7 +588,7 @@ void OGRLineString::setPoints( int nPointsIn, double * padfX, double * padfY,
 /* -------------------------------------------------------------------- */
 /*      Assign values.                                                  */
 /* -------------------------------------------------------------------- */
-    setNumPoints( nPointsIn );
+    setNumPoints( nPointsIn, FALSE );
     if (nPointCount < nPointsIn)
         return;
 
@@ -751,7 +776,7 @@ void OGRLineString::addSubLineString( const OGRLineString *poOtherLine,
     int nOldPoints = nPointCount;
     int nPointsToAdd = ABS(nEndVertex-nStartVertex) + 1;
 
-    setNumPoints( nPointsToAdd + nOldPoints );
+    setNumPoints( nPointsToAdd + nOldPoints, FALSE );
     if (nPointCount < nPointsToAdd + nOldPoints)
         return;
 
@@ -826,21 +851,11 @@ OGRErr OGRLineString::importFromWkb( unsigned char * pabyData,
 /*      geometry type is between 0 and 255 so we only have to fetch     */
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
+    OGRBoolean bIs3D;
     OGRwkbGeometryType eGeometryType;
-    int bIs3D = FALSE;
+    OGRErr err = OGRReadWKBGeometryType( pabyData, &eGeometryType, &bIs3D );
 
-    if( eByteOrder == wkbNDR )
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[1];
-        bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
-    }
-    else
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[4];
-        bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
-    }
-
-    if( eGeometryType != wkbLineString )
+    if( err != OGRERR_NONE || eGeometryType != wkbLineString )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
@@ -869,7 +884,7 @@ OGRErr OGRLineString::importFromWkb( unsigned char * pabyData,
         return OGRERR_NOT_ENOUGH_DATA;
     }
 
-    setNumPoints( nNewNumPoints );
+    setNumPoints( nNewNumPoints, FALSE );
     if (nPointCount < nNewNumPoints)
         return OGRERR_FAILURE;
     
@@ -926,7 +941,8 @@ OGRErr OGRLineString::importFromWkb( unsigned char * pabyData,
 /************************************************************************/
 
 OGRErr  OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
-                               unsigned char * pabyData ) const
+                                    unsigned char * pabyData,
+                                    OGRwkbVariant eWkbVariant ) const
 
 {
 /* -------------------------------------------------------------------- */
@@ -938,6 +954,9 @@ OGRErr  OGRLineString::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      Set the geometry feature type.                                  */
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
+
+    if ( eWkbVariant == wkbVariantIso )
+        nGType = getIsoGeometryType();
     
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
@@ -1123,7 +1142,7 @@ OGRErr OGRLineString::exportToWkt( char ** ppszDstText ) const
 /* -------------------------------------------------------------------- */
 /*      Handle special empty case.                                      */
 /* -------------------------------------------------------------------- */
-    if( nPointCount == 0 )
+    if( IsEmpty() )
     {
         CPLString osEmpty;
         osEmpty.Printf("%s EMPTY",getGeometryName());
@@ -1279,6 +1298,265 @@ void OGRLineString::Value( double dfDistance, OGRPoint * poPoint ) const
 }
 
 /************************************************************************/
+/*                              Project()                               */
+/*                                                                      */
+/* Return distance of point projected on line from origin of this line  */
+/************************************************************************/
+
+/**
+* \brief Project point on linestring.
+*
+* The input point projeted on linestring. This is the shortest distance 
+* from point to the linestring. The distance from begin of linestring to
+* the point projection returned.
+*
+* This method is built on the GEOS library (GEOS >= 3.2.0), check it for the 
+* definition of the geometry operation.
+* If OGR is built without the GEOS library, this method will always return -1,
+* issuing a CPLE_NotSupported error.
+*
+* @return a distance from the begin of the linestring to the projected point.
+*
+* @since OGR 1.11.0
+*/
+
+/* GEOS >= 3.2.0 for project capabilty */
+#if defined(HAVE_GEOS)
+#if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2)
+#define HAVE_GEOS_PROJECT
+#endif
+#endif
+
+
+double OGRLineString::Project(const OGRPoint *poPoint) const
+
+{
+    double dfResult = -1;
+#ifndef HAVE_GEOS_PROJECT
+
+
+    CPLError(CE_Failure, CPLE_NotSupported,
+        "GEOS support not enabled.");
+    return dfResult;
+
+#else
+    GEOSGeom hThisGeosGeom = NULL;
+    GEOSGeom hPointGeosGeom = NULL;
+
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    hPointGeosGeom = poPoint->exportToGEOS(hGEOSCtxt);
+    if (hThisGeosGeom != NULL && hPointGeosGeom != NULL)
+    {
+        dfResult = GEOSProject_r(hGEOSCtxt, hThisGeosGeom, hPointGeosGeom);
+    }
+    GEOSGeom_destroy_r(hGEOSCtxt, hThisGeosGeom);
+    GEOSGeom_destroy_r(hGEOSCtxt, hPointGeosGeom);
+    freeGEOSContext(hGEOSCtxt);
+
+    return dfResult;
+
+#endif /* HAVE_GEOS */
+}
+
+/************************************************************************/
+/*                            getSubLine()                              */
+/*                                                                      */
+/*  Extracts a portion of this OGRLineString into a new OGRLineString   */
+/************************************************************************/
+
+
+/**
+* \brief Get the portion of linestring.
+*
+* The portion of the linestring extracted to new one. The input distances 
+* (maybe present as ratio of length of linestring) set begin and end of
+* extracted portion.
+*
+* @param dfDistanceFrom The distance from the origin of linestring, where the subline should begins
+* @param dfDistanceTo The distance from the origin of linestring, where the subline should ends
+* @param bAsRatio The flag indicating that distances are the ratio of the linestring length.
+*
+* @return a newly allocated linestring now owned by the caller, or NULL on failure.
+*
+* @since OGR 1.11.0
+*/
+
+
+OGRLineString* OGRLineString::getSubLine(double dfDistanceFrom, double dfDistanceTo, int bAsRatio) const
+
+{
+    OGRLineString       *poNewLineString;
+    double      dfLength = 0;
+    int         i;
+
+    poNewLineString = new OGRLineString();
+
+    poNewLineString->assignSpatialReference(getSpatialReference());
+    //poNewLineString->setPoints(nPointCount, paoPoints, padfZ);
+    poNewLineString->setCoordinateDimension(getCoordinateDimension());
+
+    double dfLen = get_Length();
+    if (bAsRatio == TRUE)
+    {
+        //convert to real distance
+        dfDistanceFrom *= dfLen;
+        dfDistanceTo *= dfLen;
+    }
+
+    if (dfDistanceFrom < 0)
+        dfDistanceFrom = 0;
+    if (dfDistanceTo > dfLen)
+        dfDistanceTo = dfLen;
+
+    if ( dfDistanceFrom > dfDistanceTo || dfDistanceFrom >= dfLen)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Input distances are invalid.");
+
+        return NULL;
+    }
+
+    //get first point
+
+    if (dfDistanceFrom == 0)
+    {
+        if (getCoordinateDimension() == 3)
+            poNewLineString->addPoint(paoPoints[0].x, paoPoints[0].y, padfZ[0]);
+        else
+            poNewLineString->addPoint(paoPoints[0].x, paoPoints[0].y);
+
+        i = 0;
+    }
+    else
+    {
+        for (i = 0; i < nPointCount - 1; i++)
+        {
+            double      dfDeltaX, dfDeltaY, dfSegLength;
+
+            dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
+            dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
+            dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+
+            double dfX, dfY, dfRatio;
+
+            if (dfSegLength > 0)
+            {
+                if ((dfLength <= dfDistanceFrom) && ((dfLength + dfSegLength) >=
+                    dfDistanceFrom))
+                {
+                    dfRatio = (dfDistanceFrom - dfLength) / dfSegLength;
+
+                    dfX = paoPoints[i].x * (1 - dfRatio)
+                        + paoPoints[i + 1].x * dfRatio;
+                    dfY = paoPoints[i].y * (1 - dfRatio)
+                        + paoPoints[i + 1].y * dfRatio;
+
+                    if (getCoordinateDimension() == 3)
+                    {
+                        poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
+                        + padfZ[i+1] * dfRatio);
+                    }
+                    else
+                    {
+                        poNewLineString->addPoint(dfX, dfY);
+                    }
+                    
+                    //check if dfDistanceTo is in same segment
+                    if ((dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
+                        dfDistanceTo))
+                    {
+                        dfRatio = (dfDistanceTo - dfLength) / dfSegLength;
+
+                        dfX = paoPoints[i].x * (1 - dfRatio)
+                            + paoPoints[i + 1].x * dfRatio;
+                        dfY = paoPoints[i].y * (1 - dfRatio)
+                            + paoPoints[i + 1].y * dfRatio;
+
+                        if (getCoordinateDimension() == 3)
+                        {
+                            poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
+                                + padfZ[i + 1] * dfRatio);
+                        }
+                        else
+                        {
+                            poNewLineString->addPoint(dfX, dfY);
+                        }
+
+                        if (poNewLineString->getNumPoints() < 2)
+                        {
+                            delete poNewLineString;
+                            poNewLineString = NULL;
+                        }
+
+                        return poNewLineString;
+                    }
+                    i++;
+                    dfLength += dfSegLength;
+                    break;
+                }
+
+                dfLength += dfSegLength;
+            }
+        }
+    }
+
+    //add points
+    for (; i < nPointCount - 1; i++)
+    {
+        double      dfDeltaX, dfDeltaY, dfSegLength;
+
+        if (getCoordinateDimension() == 3)
+            poNewLineString->addPoint(paoPoints[i].x, paoPoints[i].y, padfZ[i]);
+        else
+            poNewLineString->addPoint(paoPoints[i].x, paoPoints[i].y);
+
+        dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
+        dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
+        dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+
+        double dfX, dfY, dfRatio;
+
+        if (dfSegLength > 0)
+        {
+            if ((dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
+                dfDistanceTo))
+            {
+                dfRatio = (dfDistanceTo - dfLength) / dfSegLength;
+
+                dfX = paoPoints[i].x * (1 - dfRatio)
+                    + paoPoints[i + 1].x * dfRatio;
+                dfY = paoPoints[i].y * (1 - dfRatio)
+                    + paoPoints[i + 1].y * dfRatio;
+
+                if (getCoordinateDimension() == 3)
+                    poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
+                    + padfZ[i + 1] * dfRatio);
+                else
+                    poNewLineString->addPoint(dfX, dfY);
+
+                return poNewLineString;
+            }
+
+            dfLength += dfSegLength;
+        }
+    }
+
+
+    if (getCoordinateDimension() == 3)
+        poNewLineString->addPoint(paoPoints[nPointCount - 1].x, paoPoints[nPointCount - 1].y, padfZ[nPointCount - 1]);
+    else
+        poNewLineString->addPoint(paoPoints[nPointCount - 1].x, paoPoints[nPointCount - 1].y);
+
+    if (poNewLineString->getNumPoints() < 2)
+    {
+        delete poNewLineString;
+        poNewLineString = NULL;
+    }
+
+    return poNewLineString;
+}
+
+/************************************************************************/
 /*                            getEnvelope()                             */
 /************************************************************************/
 
@@ -1287,7 +1565,7 @@ void OGRLineString::getEnvelope( OGREnvelope * psEnvelope ) const
 {
     double      dfMinX, dfMinY, dfMaxX, dfMaxY;
 
-    if( nPointCount == 0 )
+    if( IsEmpty() )
     {
         psEnvelope->MinX = 0;
         psEnvelope->MaxX = 0;
@@ -1329,7 +1607,7 @@ void OGRLineString::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
     double      dfMinZ, dfMaxZ;
 
-    if( nPointCount == 0 || padfZ == NULL )
+    if( IsEmpty() || padfZ == NULL )
     {
         psEnvelope->MinZ = 0;
         psEnvelope->MaxZ = 0;
@@ -1365,6 +1643,9 @@ OGRBoolean OGRLineString::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
+    if( IsEmpty() && poOther->IsEmpty() )
+        return TRUE;
+    
     // we should eventually test the SRS.
 
     if( getNumPoints() != poOLine->getNumPoints() )
@@ -1522,6 +1803,7 @@ void OGRLineString::segmentize( double dfMaxLength )
     double* padfNewZ = NULL;
     int nNewPointCount = 0;
     double dfSquareMaxLength = dfMaxLength * dfMaxLength;
+    const int nCoordinateDimension = getCoordinateDimension();
 
     for( i = 0; i < nPointCount; i++ )
     {
@@ -1529,7 +1811,7 @@ void OGRLineString::segmentize( double dfMaxLength )
             OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + 1));
         paoNewPoints[nNewPointCount] = paoPoints[i];
 
-        if( getCoordinateDimension() == 3 )
+        if( nCoordinateDimension == 3 )
         {
             padfNewZ = (double *)
                 OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + 1));
@@ -1551,7 +1833,7 @@ void OGRLineString::segmentize( double dfMaxLength )
 
             paoNewPoints = (OGRRawPoint *)
                 OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + nIntermediatePoints));
-            if( getCoordinateDimension() == 3 )
+            if( nCoordinateDimension == 3 )
             {
                 padfNewZ = (double *)
                     OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + nIntermediatePoints));
@@ -1561,10 +1843,10 @@ void OGRLineString::segmentize( double dfMaxLength )
             {
                 paoNewPoints[nNewPointCount + j - 1].x = paoPoints[i].x + j * dfX / (nIntermediatePoints + 1);
                 paoNewPoints[nNewPointCount + j - 1].y = paoPoints[i].y + j * dfY / (nIntermediatePoints + 1);
-                if( getCoordinateDimension() == 3 )
+                if( nCoordinateDimension == 3 )
                 {
                     /* No interpolation */
-                    padfNewZ[nNewPointCount + j - 1] = 0;
+                    padfNewZ[nNewPointCount + j - 1] = padfZ[i];
                 }
             }
 
@@ -1576,7 +1858,7 @@ void OGRLineString::segmentize( double dfMaxLength )
     paoPoints = paoNewPoints;
     nPointCount = nNewPointCount;
 
-    if( getCoordinateDimension() == 3 )
+    if( nCoordinateDimension == 3 )
     {
         OGRFree(padfZ);
         padfZ = padfNewZ;
diff --git a/ogr/ogrmultilinestring.cpp b/ogr/ogrmultilinestring.cpp
index aea7bc7..0815586 100644
--- a/ogr/ogrmultilinestring.cpp
+++ b/ogr/ogrmultilinestring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultilinestring.cpp 25426 2013-01-01 17:51:35Z rouault $
+ * $Id: ogrmultilinestring.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiLineString class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultilinestring.cpp 25426 2013-01-01 17:51:35Z rouault $");
+CPL_CVSID("$Id: ogrmultilinestring.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRMultiLineString()                          */
diff --git a/ogr/ogrmultipoint.cpp b/ogr/ogrmultipoint.cpp
index cd273f3..4a13e85 100644
--- a/ogr/ogrmultipoint.cpp
+++ b/ogr/ogrmultipoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultipoint.cpp 25426 2013-01-01 17:51:35Z rouault $
+ * $Id: ogrmultipoint.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPoint class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_p.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrmultipoint.cpp 25426 2013-01-01 17:51:35Z rouault $");
+CPL_CVSID("$Id: ogrmultipoint.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRMultiPoint()                            */
diff --git a/ogr/ogrmultipolygon.cpp b/ogr/ogrmultipolygon.cpp
index 4db7876..913a781 100644
--- a/ogr/ogrmultipolygon.cpp
+++ b/ogr/ogrmultipolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultipolygon.cpp 25426 2013-01-01 17:51:35Z rouault $
+ * $Id: ogrmultipolygon.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPolygon class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultipolygon.cpp 25426 2013-01-01 17:51:35Z rouault $");
+CPL_CVSID("$Id: ogrmultipolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRMultiPolygon()                           */
diff --git a/ogr/ogrpgeogeometry.cpp b/ogr/ogrpgeogeometry.cpp
index 7107f81..523208b 100644
--- a/ogr/ogrpgeogeometry.cpp
+++ b/ogr/ogrpgeogeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.cpp 25499 2013-01-13 22:07:12Z rouault $
+ * $Id: ogrpgeogeometry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -9,6 +9,7 @@
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_p.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpgeogeometry.cpp 25499 2013-01-13 22:07:12Z rouault $");
+CPL_CVSID("$Id: ogrpgeogeometry.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define SHPP_TRISTRIP   0
 #define SHPP_TRIFAN     1
@@ -45,6 +46,166 @@ CPL_CVSID("$Id: ogrpgeogeometry.cpp 25499 2013-01-13 22:07:12Z rouault $");
 
 
 /************************************************************************/
+/*                  OGRCreateFromMultiPatchPart()                       */
+/************************************************************************/
+
+void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
+                                 OGRPolygon*& poLastPoly,
+                                 int nPartType,
+                                 int nPartPoints,
+                                 double* padfX,
+                                 double* padfY,
+                                 double* padfZ)
+{
+    nPartType &= 0xf;
+
+    if( nPartType == SHPP_TRISTRIP )
+    {
+        int iBaseVert;
+
+        if( poLastPoly != NULL )
+        {
+            poMP->addGeometryDirectly( poLastPoly );
+            poLastPoly = NULL;
+        }
+
+        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
+        {
+            OGRPolygon *poPoly = new OGRPolygon();
+            OGRLinearRing *poRing = new OGRLinearRing();
+            int iSrcVert = iBaseVert;
+
+            poRing->setPoint( 0,
+                            padfX[iSrcVert],
+                            padfY[iSrcVert],
+                            padfZ[iSrcVert] );
+            poRing->setPoint( 1,
+                            padfX[iSrcVert+1],
+                            padfY[iSrcVert+1],
+                            padfZ[iSrcVert+1] );
+
+            poRing->setPoint( 2,
+                            padfX[iSrcVert+2],
+                            padfY[iSrcVert+2],
+                            padfZ[iSrcVert+2] );
+            poRing->setPoint( 3,
+                            padfX[iSrcVert],
+                            padfY[iSrcVert],
+                            padfZ[iSrcVert] );
+
+            poPoly->addRingDirectly( poRing );
+            poMP->addGeometryDirectly( poPoly );
+        }
+    }
+    else if( nPartType == SHPP_TRIFAN )
+    {
+        int iBaseVert;
+
+        if( poLastPoly != NULL )
+        {
+            poMP->addGeometryDirectly( poLastPoly );
+            poLastPoly = NULL;
+        }
+
+        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
+        {
+            OGRPolygon *poPoly = new OGRPolygon();
+            OGRLinearRing *poRing = new OGRLinearRing();
+            int iSrcVert = iBaseVert;
+
+            poRing->setPoint( 0,
+                            padfX[0],
+                            padfY[0],
+                            padfZ[0] );
+            poRing->setPoint( 1,
+                            padfX[iSrcVert+1],
+                            padfY[iSrcVert+1],
+                            padfZ[iSrcVert+1] );
+
+            poRing->setPoint( 2,
+                            padfX[iSrcVert+2],
+                            padfY[iSrcVert+2],
+                            padfZ[iSrcVert+2] );
+            poRing->setPoint( 3,
+                            padfX[0],
+                            padfY[0],
+                            padfZ[0] );
+
+            poPoly->addRingDirectly( poRing );
+            poMP->addGeometryDirectly( poPoly );
+        }
+    }
+    else if( nPartType == SHPP_OUTERRING
+            || nPartType == SHPP_INNERRING
+            || nPartType == SHPP_FIRSTRING
+            || nPartType == SHPP_RING )
+    {
+        if( poLastPoly != NULL
+            && (nPartType == SHPP_OUTERRING
+                || nPartType == SHPP_FIRSTRING) )
+        {
+            poMP->addGeometryDirectly( poLastPoly );
+            poLastPoly = NULL;
+        }
+
+        if( poLastPoly == NULL )
+            poLastPoly = new OGRPolygon();
+
+        OGRLinearRing *poRing = new OGRLinearRing;
+
+        poRing->setPoints( nPartPoints,
+                            padfX,
+                            padfY,
+                            padfZ );
+
+        poRing->closeRings();
+
+        poLastPoly->addRingDirectly( poRing );
+    }
+    else if ( nPartType == SHPP_TRIANGLES )
+    {
+        int iBaseVert;
+
+        if( poLastPoly != NULL )
+        {
+            poMP->addGeometryDirectly( poLastPoly );
+            poLastPoly = NULL;
+        }
+
+        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
+        {
+            OGRPolygon *poPoly = new OGRPolygon();
+            OGRLinearRing *poRing = new OGRLinearRing();
+            int iSrcVert = iBaseVert;
+
+            poRing->setPoint( 0,
+                            padfX[iSrcVert],
+                            padfY[iSrcVert],
+                            padfZ[iSrcVert] );
+            poRing->setPoint( 1,
+                            padfX[iSrcVert+1],
+                            padfY[iSrcVert+1],
+                            padfZ[iSrcVert+1] );
+
+            poRing->setPoint( 2,
+                            padfX[iSrcVert+2],
+                            padfY[iSrcVert+2],
+                            padfZ[iSrcVert+2] );
+            poRing->setPoint( 3,
+                            padfX[iSrcVert],
+                            padfY[iSrcVert],
+                            padfZ[iSrcVert] );
+
+            poPoly->addRingDirectly( poRing );
+            poMP->addGeometryDirectly( poPoly );
+        }
+    }
+    else
+        CPLDebug( "OGR", "Unrecognised parttype %d, ignored.",
+                nPartType );
+}
+
+/************************************************************************/
 /*                     OGRCreateFromMultiPatch()                        */
 /*                                                                      */
 /*      Translate a multipatch representation to an OGR geometry        */
@@ -85,152 +246,13 @@ static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
             nPartStart = panPartStart[iPart];
         }
 
-        panPartType[iPart] &= 0xf;
-
-        if( panPartType[iPart] == SHPP_TRISTRIP )
-        {
-            int iBaseVert;
-
-            if( poLastPoly != NULL )
-            {
-                poMP->addGeometryDirectly( poLastPoly );
-                poLastPoly = NULL;
-            }
-
-            for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
-            {
-                OGRPolygon *poPoly = new OGRPolygon();
-                OGRLinearRing *poRing = new OGRLinearRing();
-                int iSrcVert = iBaseVert + nPartStart;
-
-                poRing->setPoint( 0,
-                                padfX[iSrcVert],
-                                padfY[iSrcVert],
-                                padfZ[iSrcVert] );
-                poRing->setPoint( 1,
-                                padfX[iSrcVert+1],
-                                padfY[iSrcVert+1],
-                                padfZ[iSrcVert+1] );
-
-                poRing->setPoint( 2,
-                                padfX[iSrcVert+2],
-                                padfY[iSrcVert+2],
-                                padfZ[iSrcVert+2] );
-                poRing->setPoint( 3,
-                                padfX[iSrcVert],
-                                padfY[iSrcVert],
-                                padfZ[iSrcVert] );
-
-                poPoly->addRingDirectly( poRing );
-                poMP->addGeometryDirectly( poPoly );
-            }
-        }
-        else if( panPartType[iPart] == SHPP_TRIFAN )
-        {
-            int iBaseVert;
-
-            if( poLastPoly != NULL )
-            {
-                poMP->addGeometryDirectly( poLastPoly );
-                poLastPoly = NULL;
-            }
-
-            for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
-            {
-                OGRPolygon *poPoly = new OGRPolygon();
-                OGRLinearRing *poRing = new OGRLinearRing();
-                int iSrcVert = iBaseVert + nPartStart;
-
-                poRing->setPoint( 0,
-                                padfX[nPartStart],
-                                padfY[nPartStart],
-                                padfZ[nPartStart] );
-                poRing->setPoint( 1,
-                                padfX[iSrcVert+1],
-                                padfY[iSrcVert+1],
-                                padfZ[iSrcVert+1] );
-
-                poRing->setPoint( 2,
-                                padfX[iSrcVert+2],
-                                padfY[iSrcVert+2],
-                                padfZ[iSrcVert+2] );
-                poRing->setPoint( 3,
-                                padfX[nPartStart],
-                                padfY[nPartStart],
-                                padfZ[nPartStart] );
-
-                poPoly->addRingDirectly( poRing );
-                poMP->addGeometryDirectly( poPoly );
-            }
-        }
-        else if( panPartType[iPart] == SHPP_OUTERRING
-                || panPartType[iPart] == SHPP_INNERRING
-                || panPartType[iPart] == SHPP_FIRSTRING
-                || panPartType[iPart] == SHPP_RING )
-        {
-            if( poLastPoly != NULL
-                && (panPartType[iPart] == SHPP_OUTERRING
-                    || panPartType[iPart] == SHPP_FIRSTRING) )
-            {
-                poMP->addGeometryDirectly( poLastPoly );
-                poLastPoly = NULL;
-            }
-
-            if( poLastPoly == NULL )
-                poLastPoly = new OGRPolygon();
-
-            OGRLinearRing *poRing = new OGRLinearRing;
-
-            poRing->setPoints( nPartPoints,
-                                padfX + nPartStart,
-                                padfY + nPartStart,
-                                padfZ + nPartStart );
-
-            poRing->closeRings();
-
-            poLastPoly->addRingDirectly( poRing );
-        }
-        else if ( panPartType[iPart] == SHPP_TRIANGLES )
-        {
-            int iBaseVert;
-
-            if( poLastPoly != NULL )
-            {
-                poMP->addGeometryDirectly( poLastPoly );
-                poLastPoly = NULL;
-            }
-
-            for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
-            {
-                OGRPolygon *poPoly = new OGRPolygon();
-                OGRLinearRing *poRing = new OGRLinearRing();
-                int iSrcVert = iBaseVert + nPartStart;
-
-                poRing->setPoint( 0,
-                                padfX[iSrcVert],
-                                padfY[iSrcVert],
-                                padfZ[iSrcVert] );
-                poRing->setPoint( 1,
-                                padfX[iSrcVert+1],
-                                padfY[iSrcVert+1],
-                                padfZ[iSrcVert+1] );
-
-                poRing->setPoint( 2,
-                                padfX[iSrcVert+2],
-                                padfY[iSrcVert+2],
-                                padfZ[iSrcVert+2] );
-                poRing->setPoint( 3,
-                                padfX[iSrcVert],
-                                padfY[iSrcVert],
-                                padfZ[iSrcVert] );
-
-                poPoly->addRingDirectly( poRing );
-                poMP->addGeometryDirectly( poPoly );
-            }
-        }
-        else
-            CPLDebug( "OGR", "Unrecognised parttype %d, ignored.",
-                    panPartType[iPart] );
+        OGRCreateFromMultiPatchPart(poMP,
+                                    poLastPoly,
+                                    panPartType[iPart],
+                                    nPartPoints,
+                                    padfX + nPartStart,
+                                    padfY + nPartStart,
+                                    padfZ + nPartStart);
     }
 
     if( poLastPoly != NULL )
@@ -850,6 +872,233 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
 
 /************************************************************************/
+/*                   OGRWriteMultiPatchToShapeBin()                     */
+/************************************************************************/
+
+OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom, 
+                                     GByte **ppabyShape,
+                                     int *pnBytes )
+{
+    if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiPolygon )
+        return OGRERR_UNSUPPORTED_OPERATION;
+    
+    poGeom->closeRings();
+    OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
+    int nParts = 0;
+    int* panPartStart = NULL;
+    int* panPartType = NULL;
+    int nPoints = 0;
+    OGRRawPoint* poPoints = NULL;
+    double* padfZ = NULL;
+    int nBeginLastPart = 0;
+
+    for( int j = 0; j < poMPoly->getNumGeometries(); j++ )
+    {
+        OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(j));
+        int nRings = poPoly->getNumInteriorRings() + 1;
+
+        /* Skip empties */
+        if ( poPoly->IsEmpty() ) 
+            continue;
+
+        OGRLinearRing *poRing = poPoly->getExteriorRing();
+        if( nRings == 1 && poRing->getNumPoints() == 4 )
+        {
+            if( nParts > 0 &&
+                ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
+                 panPartType[nParts-1] == SHPP_TRIFAN) &&
+                poRing->getX(0) == poPoints[nBeginLastPart].x &&
+                poRing->getY(0) == poPoints[nBeginLastPart].y &&
+                poRing->getZ(0) == padfZ[nBeginLastPart] &&
+                poRing->getX(1) == poPoints[nPoints-1].x &&
+                poRing->getY(1) == poPoints[nPoints-1].y &&
+                poRing->getZ(1) == padfZ[nPoints-1] )
+            {
+                panPartType[nParts-1] = SHPP_TRIFAN;
+
+                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
+                                            (nPoints + 1) * sizeof(OGRRawPoint));
+                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 1) * sizeof(double));
+                poPoints[nPoints].x = poRing->getX(2);
+                poPoints[nPoints].y = poRing->getY(2);
+                padfZ[nPoints] = poRing->getZ(2);
+                nPoints ++;
+            }
+            else if( nParts > 0 &&
+                ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
+                 panPartType[nParts-1] == SHPP_TRISTRIP) &&
+                poRing->getX(0) == poPoints[nPoints-2].x &&
+                poRing->getY(0) == poPoints[nPoints-2].y &&
+                poRing->getZ(0) == padfZ[nPoints-2] &&
+                poRing->getX(1) == poPoints[nPoints-1].x &&
+                poRing->getY(1) == poPoints[nPoints-1].y &&
+                poRing->getZ(1) == padfZ[nPoints-1] )
+            {
+                panPartType[nParts-1] = SHPP_TRISTRIP;
+
+                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
+                                            (nPoints + 1) * sizeof(OGRRawPoint));
+                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 1) * sizeof(double));
+                poPoints[nPoints].x = poRing->getX(2);
+                poPoints[nPoints].y = poRing->getY(2);
+                padfZ[nPoints] = poRing->getZ(2);
+                nPoints ++;
+            }
+            else
+            {
+                if( nParts == 0 || panPartType[nParts-1] != SHPP_TRIANGLES )
+                {
+                    nBeginLastPart = nPoints;
+
+                    panPartStart = (int*)CPLRealloc(panPartStart, (nParts + 1) * sizeof(int));
+                    panPartType = (int*)CPLRealloc(panPartType, (nParts + 1) * sizeof(int));
+                    panPartStart[nParts] = nPoints;
+                    panPartType[nParts] = SHPP_TRIANGLES;
+                    nParts ++;
+                }
+
+                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
+                                        (nPoints + 3) * sizeof(OGRRawPoint));
+                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 3) * sizeof(double));
+                for(int i=0;i<3;i++)
+                {
+                    poPoints[nPoints+i].x = poRing->getX(i);
+                    poPoints[nPoints+i].y = poRing->getY(i);
+                    padfZ[nPoints+i] = poRing->getZ(i);
+                }
+                nPoints += 3;
+            }
+        }
+        else
+        {
+            panPartStart = (int*)CPLRealloc(panPartStart, (nParts + nRings) * sizeof(int));
+            panPartType = (int*)CPLRealloc(panPartType, (nParts + nRings) * sizeof(int));
+
+            for ( int i = 0; i < nRings; i++ )
+            {
+                panPartStart[nParts + i] = nPoints;
+                if ( i == 0 )
+                {
+                    poRing = poPoly->getExteriorRing();
+                    panPartType[nParts + i] = SHPP_OUTERRING;
+                }
+                else
+                {
+                    poRing = poPoly->getInteriorRing(i-1);
+                    panPartType[nParts + i] = SHPP_INNERRING;
+                }
+                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
+                        (nPoints + poRing->getNumPoints()) * sizeof(OGRRawPoint));
+                padfZ = (double*)CPLRealloc(padfZ,
+                        (nPoints + poRing->getNumPoints()) * sizeof(double));
+                for( int k = 0; k < poRing->getNumPoints(); k++ )
+                {
+                    poPoints[nPoints+k].x = poRing->getX(k);
+                    poPoints[nPoints+k].y = poRing->getY(k);
+                    padfZ[nPoints+k] = poRing->getZ(k);
+                }
+                nPoints += poRing->getNumPoints();
+            }
+
+            nParts += nRings;
+        }
+    }
+
+    int nShpSize = 4; /* All types start with integer type number */
+    nShpSize += 16 * 2; /* xy bbox */ 
+    nShpSize += 4; /* nparts */
+    nShpSize += 4; /* npoints */
+    nShpSize += 4 * nParts; /* panPartStart[nparts] */
+    nShpSize += 4 * nParts; /* panPartType[nparts] */
+    nShpSize += 8 * 2 * nPoints; /* xy points */
+    nShpSize += 16; /* z bbox */
+    nShpSize += 8 * nPoints; /* z points */
+
+    *pnBytes = nShpSize;
+    *ppabyShape = (GByte*) CPLMalloc(nShpSize);
+
+    GByte* pabyPtr = *ppabyShape;
+
+    /* Write in the type number and advance the pointer */
+    GUInt32 nGType = CPL_LSBWORD32( SHPT_MULTIPATCH );
+    memcpy( pabyPtr, &nGType, 4 );
+    pabyPtr += 4;
+
+    OGREnvelope3D envelope;
+    poGeom->getEnvelope(&envelope);
+    memcpy( pabyPtr, &(envelope.MinX), 8 );
+    memcpy( pabyPtr+8, &(envelope.MinY), 8 );
+    memcpy( pabyPtr+8+8, &(envelope.MaxX), 8 );
+    memcpy( pabyPtr+8+8+8, &(envelope.MaxY), 8 );
+
+    int i;
+    /* Swap box if needed. Shape doubles are always LSB */
+    if( OGR_SWAP( wkbNDR ) )
+    {
+        for ( i = 0; i < 4; i++ )
+            CPL_SWAPDOUBLE( pabyPtr + 8*i );
+    }
+    pabyPtr += 32;
+
+    /* Write in the part count */
+    GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
+    memcpy( pabyPtr, &nPartsLsb, 4 );
+    pabyPtr += 4;
+
+    /* Write in the total point count */
+    GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
+    memcpy( pabyPtr, &nPointsLsb, 4 );
+    pabyPtr += 4;
+
+    for( i = 0; i < nParts; i ++ )
+    {
+        int nPartStart = CPL_LSBWORD32(panPartStart[i]);
+        memcpy( pabyPtr, &nPartStart, 4 );
+        pabyPtr += 4;
+    }
+    for( i = 0; i < nParts; i ++ )
+    {
+        int nPartType = CPL_LSBWORD32(panPartType[i]);
+        memcpy( pabyPtr, &nPartType, 4 );
+        pabyPtr += 4;
+    }
+
+    memcpy(pabyPtr, poPoints, 2 * 8 * nPoints);
+    /* Swap box if needed. Shape doubles are always LSB */
+    if( OGR_SWAP( wkbNDR ) )
+    {
+        for ( i = 0; i < 2 * nPoints; i++ )
+            CPL_SWAPDOUBLE( pabyPtr + 8*i );
+    }
+    pabyPtr += 2 * 8 * nPoints;
+
+    memcpy( pabyPtr, &(envelope.MinZ), 8 );
+    memcpy( pabyPtr+8, &(envelope.MaxZ), 8 );
+    if( OGR_SWAP( wkbNDR ) )
+    {
+        for ( i = 0; i < 2; i++ )
+            CPL_SWAPDOUBLE( pabyPtr + 8*i );
+    }
+    pabyPtr += 16;
+    
+    memcpy(pabyPtr, padfZ, 8 * nPoints);
+    /* Swap box if needed. Shape doubles are always LSB */
+    if( OGR_SWAP( wkbNDR ) )
+    {
+        for ( i = 0; i < nPoints; i++ )
+            CPL_SWAPDOUBLE( pabyPtr + 8*i );
+    }
+    pabyPtr +=  8 * nPoints;
+    
+    CPLFree(panPartStart);
+    CPLFree(panPartType);
+    CPLFree(poPoints);
+    CPLFree(padfZ);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                      OGRCreateFromShapeBin()                         */
 /*                                                                      */
 /*      Translate shapefile binary representation to an OGR             */
@@ -1026,8 +1275,8 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         if (nRequiredSize > nBytes)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
-                     nPoints, nParts, nBytes, nSHPType);
+                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d, nRequiredSize=%d",
+                     nPoints, nParts, nBytes, nSHPType, nRequiredSize);
             return OGRERR_FAILURE;
         }
 
diff --git a/ogr/ogrpgeogeometry.h b/ogr/ogrpgeogeometry.h
index cd2f188..7b7b22b 100644
--- a/ogr/ogrpgeogeometry.h
+++ b/ogr/ogrpgeogeometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.h 22525 2011-06-11 02:18:49Z rburhum $
+ * $Id: ogrpgeogeometry.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -72,6 +73,13 @@
 #define ESRI_LAYERGEOMTYPE_POLYGON       4
 #define ESRI_LAYERGEOMTYPE_MULTIPATCH    9
 
+void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
+                                 OGRPolygon*& poLastPoly,
+                                 int nPartType,
+                                 int nPartPoints,
+                                 double* padfX,
+                                 double* padfY,
+                                 double* padfZ);
 
 OGRErr CPL_DLL OGRCreateFromShapeBin( GByte *pabyShape,
                               OGRGeometry **ppoGeom,
@@ -81,5 +89,8 @@ OGRErr CPL_DLL OGRWriteToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes );
 
+OGRErr CPL_DLL OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom, 
+                           GByte **ppabyShape,
+                           int *pnBytes );
 
 #endif
diff --git a/ogr/ogrpoint.cpp b/ogr/ogrpoint.cpp
index f4121cf..49a11c5 100644
--- a/ogr/ogrpoint.cpp
+++ b/ogr/ogrpoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpoint.cpp 22448 2011-05-28 18:49:54Z rouault $
+ * $Id: ogrpoint.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The Point geometry class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,10 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpoint.cpp 22448 2011-05-28 18:49:54Z rouault $");
+/* for std::numeric_limits */
+#include <limits>
+
+CPL_CVSID("$Id: ogrpoint.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                              OGRPoint()                              */
@@ -129,10 +133,10 @@ int OGRPoint::getDimension() const
 OGRwkbGeometryType OGRPoint::getGeometryType() const
 
 {
-    if( nCoordDimension < 3 )
-        return wkbPoint;
-    else
+    if( nCoordDimension == 3 )
         return wkbPoint25D;
+    else
+        return wkbPoint;
 }
 
 /************************************************************************/
@@ -214,27 +218,18 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
 /*      geometry type is between 0 and 255 so we only have to fetch     */
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
+    OGRBoolean bIs3D;
     OGRwkbGeometryType eGeometryType;
-    int                bIs3D;
-    
-    if( eByteOrder == wkbNDR )
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[1];
-        bIs3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
-    }
-    else
-    {
-        eGeometryType = (OGRwkbGeometryType) pabyData[4];
-        bIs3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
-    }
+    OGRErr err = OGRReadWKBGeometryType( pabyData, &eGeometryType, &bIs3D );
 
-    if( eGeometryType != wkbPoint )
+    if( err != OGRERR_NONE || eGeometryType != wkbPoint )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
 /*      Get the vertex.                                                 */
 /* -------------------------------------------------------------------- */
-    memcpy( &x, pabyData + 5, 16 );
+    memcpy( &x, pabyData + 5,     8 );
+    memcpy( &y, pabyData + 5 + 8, 8 );
     
     if( OGR_SWAP( eByteOrder ) )
     {
@@ -270,7 +265,8 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
 /************************************************************************/
 
 OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
-                               unsigned char * pabyData ) const
+                               unsigned char * pabyData,
+                               OGRwkbVariant eWkbVariant ) const
 
 {
 /* -------------------------------------------------------------------- */
@@ -283,6 +279,9 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
     
+    if ( eWkbVariant == wkbVariantIso )
+        nGType = getIsoGeometryType();
+    
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
     else
@@ -293,11 +292,22 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
-    memcpy( pabyData+5, &x, 16 );
 
-    if( nCoordDimension == 3 )
+    if ( IsEmpty() && eWkbVariant == wkbVariantIso )
+    {
+        double dNan = std::numeric_limits<double>::quiet_NaN();
+        memcpy( pabyData+5, &dNan, 8 );
+        memcpy( pabyData+5+8, &dNan, 8 );
+        if( nCoordDimension == 3 )
+            memcpy( pabyData+5+16, &dNan, 8 );
+    }
+    else
     {
-        memcpy( pabyData + 5 + 16, &z, 8 );
+        memcpy( pabyData+5, &x, 16 );
+        if( nCoordDimension == 3 )
+        {
+            memcpy( pabyData + 5 + 16, &z, 8 );
+        }
     }
     
 /* -------------------------------------------------------------------- */
@@ -464,7 +474,7 @@ OGRErr OGRPoint::exportToWkt( char ** ppszDstText ) const
     char        szTextEquiv[140];
     char        szCoordinate[80];
 
-    if (nCoordDimension == 0)
+    if ( IsEmpty() )
         *ppszDstText = CPLStrdup( "POINT EMPTY" );
     else
     {
@@ -571,6 +581,9 @@ OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
+    if ( IsEmpty() && poOther->IsEmpty() )
+        return TRUE;
+
     // we should eventually test the SRS.
     
     if( poOPoint->getX() != getX()
diff --git a/ogr/ogrpolygon.cpp b/ogr/ogrpolygon.cpp
index 9ab981e..76f7ebc 100644
--- a/ogr/ogrpolygon.cpp
+++ b/ogr/ogrpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpolygon.cpp 24895 2012-09-02 18:12:08Z rouault $
+ * $Id: ogrpolygon.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRPolygon geometry class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "ogr_geos.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrpolygon.cpp 24895 2012-09-02 18:12:08Z rouault $");
+CPL_CVSID("$Id: ogrpolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                             OGRPolygon()                             */
@@ -106,12 +107,13 @@ void OGRPolygon::empty()
 OGRwkbGeometryType OGRPolygon::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( nCoordDimension == 3 )
         return wkbPolygon25D;
     else
         return wkbPolygon;
 }
 
+
 /************************************************************************/
 /*                            getDimension()                            */
 /************************************************************************/
@@ -182,6 +184,28 @@ const OGRLinearRing *OGRPolygon::getExteriorRing() const
 }
 
 /************************************************************************/
+/*                          stealExteriorRing()                         */
+/************************************************************************/
+
+/**
+ * \brief "Steal" reference to external polygon ring.
+ *
+ * After the call to that function, only call to stealInteriorRing() or
+ * destruction of the OGRPolygon is valid. Other operations may crash.
+ *
+ * @return pointer to external ring.  May be NULL if the OGRPolygon is empty.
+ */
+
+OGRLinearRing *OGRPolygon::stealExteriorRing()
+{
+    if( nRingCount == 0 )
+        return NULL;
+    OGRLinearRing *poRet = papoRings[0];
+    papoRings[0] = NULL;
+    return poRet;
+}
+
+/************************************************************************/
 /*                        getNumInteriorRings()                         */
 /************************************************************************/
 
@@ -220,7 +244,7 @@ int OGRPolygon::getNumInteriorRings() const
  *
  * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
  *
- * @return pointer to external ring.  May be NULL if the OGRPolygon is empty.
+ * @return pointer to interior ring.  May be NULL.
  */
 
 OGRLinearRing *OGRPolygon::getInteriorRing( int iRing )
@@ -242,6 +266,29 @@ const OGRLinearRing *OGRPolygon::getInteriorRing( int iRing ) const
 }
 
 /************************************************************************/
+/*                          stealInteriorRing()                         */
+/************************************************************************/
+
+/**
+ * \brief "Steal" reference to indicated interior ring.
+ *
+ * After the call to that function, only call to stealInteriorRing() or
+ * destruction of the OGRPolygon is valid. Other operations may crash.
+ *
+ * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
+ * @return pointer to interior ring.  May be NULL.
+ */
+
+OGRLinearRing *OGRPolygon::stealInteriorRing(int iRing)
+{
+    if( iRing < 0 || iRing >= nRingCount-1 )
+        return NULL;
+    OGRLinearRing *poRet = papoRings[iRing+1];
+    papoRings[iRing+1] = NULL;
+    return poRet;
+}
+
+/************************************************************************/
 /*                              addRing()                               */
 /************************************************************************/
 
@@ -337,7 +384,7 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
 
 {
     OGRwkbByteOrder     eByteOrder;
-    int                 nDataOffset, b3D;
+    int                 nDataOffset;
     
     if( nSize < 9 && nSize != -1 )
         return OGRERR_NOT_ENOUGH_DATA;
@@ -354,28 +401,20 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
 /*      geometry type is between 0 and 255 so we only have to fetch     */
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
-#ifdef DEBUG
+
+    OGRBoolean b3D;
     OGRwkbGeometryType eGeometryType;
-    
-    if( eByteOrder == wkbNDR )
-        eGeometryType = (OGRwkbGeometryType) pabyData[1];
-    else
-        eGeometryType = (OGRwkbGeometryType) pabyData[4];
+    OGRErr err = OGRReadWKBGeometryType( pabyData, &eGeometryType, &b3D );
 
-    if( eGeometryType != wkbPolygon )
+    if( err != OGRERR_NONE || eGeometryType != wkbPolygon )
         return OGRERR_CORRUPT_DATA;
-#endif    
-
-    if( eByteOrder == wkbNDR )
-        b3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
-    else
-        b3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
 
     if( b3D )
         nCoordDimension = 3;
     else
         nCoordDimension = 2;
 
+
 /* -------------------------------------------------------------------- */
 /*      Do we already have some rings?                                  */
 /* -------------------------------------------------------------------- */
@@ -456,7 +495,8 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
 /************************************************************************/
 
 OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                 unsigned char * pabyData ) const
+                                 unsigned char * pabyData,
+                                 OGRwkbVariant eWkbVariant ) const
 
 {
     int         nOffset;
@@ -471,6 +511,9 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      Set the geometry feature type.                                  */
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
+
+    if ( eWkbVariant == wkbVariantIso )
+        nGType = getIsoGeometryType();
     
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
@@ -722,8 +765,8 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText ) const
 /* -------------------------------------------------------------------- */
 /*      If we have no valid exterior ring, return POLYGON EMPTY.        */
 /* -------------------------------------------------------------------- */
-    if (getExteriorRing() == NULL ||
-        getExteriorRing()->IsEmpty())
+    if (getExteriorRing() == NULL || 
+        getExteriorRing()->IsEmpty() )
     {
         *ppszDstText = CPLStrdup("POLYGON EMPTY");
         return OGRERR_NONE;
@@ -810,7 +853,7 @@ error:
 int OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
 
 {
-    if( poPoint == NULL )
+    if( poPoint == NULL || poPoint->IsEmpty() )
         return OGRERR_FAILURE;
 
     OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
@@ -934,6 +977,9 @@ OGRBoolean OGRPolygon::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
+    if ( IsEmpty() && poOther->IsEmpty() )
+        return TRUE;
+
     if( getNumInteriorRings() != poOPoly->getNumInteriorRings() )
         return FALSE;
 
@@ -1075,7 +1121,7 @@ void OGRPolygon::setCoordinateDimension( int nNewDimension )
 OGRBoolean OGRPolygon::IsEmpty(  ) const
 {
     for( int iRing = 0; iRing < nRingCount; iRing++ )
-        if (papoRings[iRing]->IsEmpty() == FALSE)
+        if ( papoRings[iRing]->IsEmpty() == FALSE )
             return FALSE;
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/GNUmakefile b/ogr/ogrsf_frmts/GNUmakefile
index 4736930..f3f8585 100644
--- a/ogr/ogrsf_frmts/GNUmakefile
+++ b/ogr/ogrsf_frmts/GNUmakefile
@@ -6,7 +6,7 @@ SUBDIRS-yes	:= \
 	mitab ntf gpx rec s57 sdts shape tiger vrt \
 	geoconcept xplane georss gtm dxf pgdump gpsbabel \
 	sua openair pds htf aeronavfaa edigeo svg idrisi \
-	arcgen segukooa segy
+	arcgen segukooa segy sxf openfilegdb wasp
 
 SUBDIRS-$(HAVE_DODS)	+= dods
 SUBDIRS-$(HAVE_DWGDIRECT) += dxfdwg
@@ -16,7 +16,7 @@ SUBDIRS-$(HAVE_IDB)	+= idb
 SUBDIRS-$(HAVE_XERCES)	+= ili
 SUBDIRS-$(HAVE_NAS)	+= nas
 SUBDIRS-$(HAVE_MYSQL)	+= mysql
-SUBDIRS-$(ODBC_SETTING)	+= odbc pgeo mssqlspatial geomedia
+SUBDIRS-$(ODBC_SETTING)	+= odbc pgeo mssqlspatial geomedia walk
 SUBDIRS-$(HAVE_OGDI)	+= ogdi
 SUBDIRS-$(HAVE_OCI)	+= oci
 SUBDIRS-$(HAVE_OGR_PG)	+= pg
@@ -30,12 +30,16 @@ SUBDIRS-$(HAVE_LIBKML)  += libkml
 SUBDIRS-$(CURL_SETTING) += wfs
 SUBDIRS-$(MDB_ENABLED)  += mdb
 SUBDIRS-$(CURL_SETTING) += gft
+SUBDIRS-$(CURL_SETTING) += gme
 SUBDIRS-$(CURL_SETTING) += couchdb
 SUBDIRS-$(HAVE_FREEXL)  += xls
 SUBDIRS-$(HAVE_EXPAT)   += ods
 SUBDIRS-$(HAVE_EXPAT)   += xlsx
 SUBDIRS-$(CURL_SETTING) += elastic
+SUBDIRS-$(HAVE_SQLITE)	+= gpkg
 SUBDIRS-$(HAVE_SQLITE)	+= osm
+SUBDIRS-$(HAVE_SOSI)	+= sosi
+SUBDIRS-$(CURL_SETTING) += cartodb
 
 ifeq ($(PCIDSK_SETTING),internal)
 SUBDIRS-yes  += pcidsk
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
index 1484fee..241314e 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
+++ b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_aeronavfaa.h 21376 2011-01-02 18:28:40Z rouault $
+ * $Id: ogr_aeronavfaa.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Definition of classes for OGR AeronavFAA driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -81,9 +81,6 @@ protected:
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
index b0c7d17..f9963cf 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograeronavfaadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
+ * $Id: ograeronavfaadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograeronavfaadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
+CPL_CVSID("$Id: ograeronavfaadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      OGRAeronavFAADataSource()                       */
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
index 00fe26a..ab4886b 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograeronavfaadriver.cpp 21372 2011-01-01 23:53:54Z rouault $
+ * $Id: ograeronavfaadriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_aeronavfaa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograeronavfaadriver.cpp 21372 2011-01-01 23:53:54Z rouault $");
+CPL_CVSID("$Id: ograeronavfaadriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // g++ ogr/ogrsf_frmts/aeronavfaa/*.cpp -Wall -g -fPIC -shared -o ogr_AeronavFAA.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/aernovfaa -Iogr/ogrsf_frmts
 
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
index 3b0cb2f..1297cd6 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograeronavfaalayer.cpp 21376 2011-01-02 18:28:40Z rouault $
+ * $Id: ograeronavfaalayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAALayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograeronavfaalayer.cpp 21376 2011-01-02 18:28:40Z rouault $");
+CPL_CVSID("$Id: ograeronavfaalayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRAeronavFAALayer()                          */
@@ -52,6 +52,7 @@ OGRAeronavFAALayer::OGRAeronavFAALayer( VSILFILE* fp, const char* pszLayerName )
 
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
index 2744246..b3de804 100644
--- a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
+++ b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_arcgen.h 23148 2011-10-01 11:55:08Z rouault $
+ * $Id: ogr_arcgen.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Definition of classes for OGR .arcgen driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -59,9 +59,6 @@ class OGRARCGENLayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
-
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
index ee3d65d..2a48219 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograrcgendatasource.cpp 25447 2013-01-04 20:30:09Z rouault $
+ * $Id: ograrcgendatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograrcgendatasource.cpp 25447 2013-01-04 20:30:09Z rouault $");
+CPL_CVSID("$Id: ograrcgendatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRARCGENDataSource()                          */
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
index 7fbd735..a5afdc7 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograrcgendriver.cpp 23148 2011-10-01 11:55:08Z rouault $
+ * $Id: ograrcgendriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_arcgen.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograrcgendriver.cpp 23148 2011-10-01 11:55:08Z rouault $");
+CPL_CVSID("$Id: ograrcgendriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRARCGEN();
 
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
index b04f47e..e6d7e9b 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ograrcgenlayer.cpp 23148 2011-10-01 11:55:08Z rouault $
+ * $Id: ograrcgenlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograrcgenlayer.cpp 23148 2011-10-01 11:55:08Z rouault $");
+CPL_CVSID("$Id: ograrcgenlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRARCGENLayer()                             */
diff --git a/ogr/ogrsf_frmts/bna/ogr_bna.h b/ogr/ogrsf_frmts/bna/ogr_bna.h
index b00b6eb..6737bd7 100644
--- a/ogr/ogrsf_frmts/bna/ogr_bna.h
+++ b/ogr/ogrsf_frmts/bna/ogr_bna.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_bna.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_bna.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BNA Translator
  * Purpose:  Definition of classes for OGR .bna driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
index 414f903..75664b0 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrbnadatasource.cpp 23244 2011-10-16 21:52:16Z rouault $
+ * $Id: ogrbnadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNADataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
index 3874dfc..167b2cf 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
index 2f00959..2c1197c 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrbnalayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
+ * $Id: ogrbnalayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNALayer class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
index 8cd4753..f26452a 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrbnaparser.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrbnaparser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  BNA Parser
  * Purpose:  Parse a BNA record
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/cartodb/GNUmakefile b/ogr/ogrsf_frmts/cartodb/GNUmakefile
new file mode 100644
index 0000000..98e725e
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrcartodbdriver.o ogrcartodbdatasource.o ogrcartodblayer.o ogrcartodbtablelayer.o ogrcartodbresultlayer.o
+
+CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../..$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_cartodb.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/cartodb/drv_cartodb.html b/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
new file mode 100644
index 0000000..c907228
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
@@ -0,0 +1,125 @@
+<html>
+<head>
+<title>CartoDB</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>CartoDB</h1>
+
+(GDAL/OGR >= 1.11)<p>
+
+This driver can connect to the services implementing the CartoDB API.
+GDAL/OGR must be built with Curl support in order to the
+CartoDB driver to be compiled.<p>
+
+The driver supports read and write operations.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a CartoDB datasource is : <pre>CartoDB:[account_name]</pre><p>
+
+Additionnal optional parameters can be specified after the ':' sign.
+Currently the following one is supported :<p>
+
+<ul>
+<li> <b>tables=table_name1[,table_name2]*</b>: A list of table names.
+This is necessary when you need to access to public tables for example.
+</ul>
+
+If several parameters are specified, they must be separated by a space.<p>
+
+<h2>Configuration options</h2>
+
+The following configuration options are available :
+<ul>
+<li>CARTODB_API_URL: defaults to https://[account_name].cartodb.com/api/v2/sql.
+Can be used to point to another server.</li>
+<li>CARTODB_HTTPS: can be set to NO to use http:// protocol instead of
+https:// (only if CARTODB_API_URL is not defined).</li>
+<li>CARTODB_API_KEY: see following paragraph.</li>
+</ul>
+
+
+<h2>Authentication</h2>
+
+Most operations, in particular write operations, require an authenticated
+access. The only exception is read-only access to public tables.<p>
+
+Authenticated access is obtained by specifying the API key given in the
+management interface of the CartoDB service. It is specified with the
+CARTODB_API_KEY configuration option.<p>
+
+<h2>Geometry</h2>
+
+The OGR driver will report as many geometry fields as available in the
+layer (except the 'the_geom_webmercator' field), following RFC 41.
+
+<h2>Filtering</h2>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to
+the server. It also makes the same for attribute
+filters set with SetAttributeFilter().<p>
+
+<h2>Paging</h2>
+
+Features are retrieved from the server by chunks of 500 by default.
+This number can be altered with the CARTODB_PAGE_SIZE
+configuration option.<p>
+
+<h2>Write support</h2>
+
+Table creation and deletion is possible.<p>
+
+Write support is only enabled when the datasource is opened in update mode.<p>
+
+The mapping between the operations of the CartoDB service and the OGR concepts is the following :
+<ul>
+<li>OGRFeature::CreateFeature() <==> INSERT operation</li>
+<li>OGRFeature::SetFeature() <==> UPDATE operation</li>
+<li>OGRFeature::DeleteFeature() <==> DELETE operation</li>
+<li>OGRDataSource::CreateLayer() <==> CREATE TABLE operation</li>
+<li>OGRDataSource::DeleteLayer() <==> DROP TABLE operation</li>
+</ul>
+
+When inserting a new feature with CreateFeature(), and if the command is successfull, OGR will fetch the
+returned rowid and use it as the OGR FID.<p>
+
+<h2>Write support and OGR transactions</h2>
+
+The above operations are by default issued to the server synchronously with the OGR API call. This however
+can cause performance penalties when issuing a lot of commands due to many client/server exchanges.<p>
+
+It is possible to surround the CreateFeature() operation between OGRLayer::StartTransaction() and OGRLayer::CommitTransaction().
+The operations will be stored into memory and only executed at the time CommitTransaction() is called.<p>
+
+<h2>SQL</h2>
+
+SQL commands provided to the OGRDataSource::ExecuteSQL() call are executed on the server side, unless the OGRSQL
+dialect is specified. You can use the full power of PostgreSQL + PostGIS SQL
+capabilities.<p>
+
+<h2>Examples</h2>
+
+<li>
+Acceccing data from a public table:
+<pre>
+ogrinfo -ro "CartoDB:gdalautotest2 tables=tm_world_borders_simpl_0_3"
+</pre>
+<p>
+
+<li>
+Creating and populating a table from a shapefile:
+<pre>
+ogr2ogr --config CARTODB_API_KEY abcdefghijklmnopqrstuvw -f CartoDB "CartoDB:myaccount" myshapefile.shp
+</pre>
+<p>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="http://developers.cartodb.com/documentation/apis-overview.htmll">CartoDB API overview</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/cartodb/makefile.vc b/ogr/ogrsf_frmts/cartodb/makefile.vc
new file mode 100644
index 0000000..c9f07e4
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/makefile.vc
@@ -0,0 +1,16 @@
+
+OBJ	=	ogrcartodbdriver.obj ogrcartodbdatasource.obj ogrcartodblayer.obj ogrcartodbtablelayer.obj ogrcartodbresultlayer.obj
+
+EXTRAFLAGS =	-I.. -I..\.. -I..\geojson\libjson
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h b/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
new file mode 100644
index 0000000..df86ade
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
@@ -0,0 +1,237 @@
+/******************************************************************************
+ * $Id: ogr_cartodb.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CARTODB Translator
+ * Purpose:  Definition of classes for OGR CartoDB driver.
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_CARTODB_H_INCLUDED
+#define _OGR_CARTODB_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_http.h"
+
+#include <vector>
+#include <json.h>
+
+json_object* OGRCARTODBGetSingleRow(json_object* poObj);
+CPLString OGRCARTODBEscapeIdentifier(const char* pszStr);
+CPLString OGRCARTODBEscapeLiteral(const char* pszStr);
+
+/************************************************************************/
+/*                      OGRCartoDBGeomFieldDefn                         */
+/************************************************************************/
+
+class OGRCartoDBGeomFieldDefn: public OGRGeomFieldDefn
+{
+    public:
+        int nSRID;
+
+        OGRCartoDBGeomFieldDefn(const char* pszName, OGRwkbGeometryType eType) :
+                OGRGeomFieldDefn(pszName, eType), nSRID(0)
+        {
+        }
+};
+
+/************************************************************************/
+/*                           OGRCARTODBLayer                            */
+/************************************************************************/
+class OGRCARTODBDataSource;
+
+class OGRCARTODBLayer : public OGRLayer
+{
+protected:
+    OGRCARTODBDataSource* poDS;
+
+    OGRFeatureDefn      *poFeatureDefn;
+    OGRSpatialReference *poSRS;
+    CPLString            osBaseSQL;
+    CPLString            osFIDColName;
+
+    int                  bEOF;
+    int                  nFetchedObjects;
+    int                  iNextInFetchedObjects;
+    int                  iNext;
+    json_object         *poCachedObj;
+
+    OGRFeature          *GetNextRawFeature();
+    OGRFeature          *BuildFeature(json_object* poRowObj);
+
+    void                 EstablishLayerDefn(const char* pszLayerName);
+    OGRSpatialReference *GetSRS(const char* pszGeomCol, int *pnSRID);
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol) = 0;
+
+  public:
+                         OGRCARTODBLayer(OGRCARTODBDataSource* poDS);
+                        ~OGRCARTODBLayer();
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual int                 TestCapability( const char * );
+
+    int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("CARTODB_PAGE_SIZE", "500")); }
+};
+
+
+/************************************************************************/
+/*                        OGRCARTODBTableLayer                          */
+/************************************************************************/
+
+class OGRCARTODBTableLayer : public OGRCARTODBLayer
+{
+    CPLString           osName;
+    CPLString           osQuery;
+    CPLString           osWHERE;
+
+    int                 bInTransaction;
+    CPLString           osTransactionSQL;
+    long                nNextFID;
+
+    void                BuildWhere();
+
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+
+  public:
+                         OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS, const char* pszName);
+                        ~OGRCARTODBTableLayer();
+
+    virtual const char*         GetName() { return osName.c_str(); }
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual int                 GetFeatureCount( int bForce = TRUE );
+    virtual OGRFeature         *GetFeature( long nFeatureId );
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+
+    virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      SetFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( long nFID );
+
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+    
+    virtual OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+};
+
+/************************************************************************/
+/*                       OGRCARTODBResultLayer                          */
+/************************************************************************/
+
+class OGRCARTODBResultLayer : public OGRCARTODBLayer
+{
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+
+  public:
+                        OGRCARTODBResultLayer( OGRCARTODBDataSource* poDS,
+                                               const char * pszRawStatement );
+    virtual             ~OGRCARTODBResultLayer();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+};
+
+/************************************************************************/
+/*                           OGRCARTODBDataSource                       */
+/************************************************************************/
+
+class OGRCARTODBDataSource : public OGRDataSource
+{
+    char*               pszName;
+    char*               pszAccount;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    int                 bReadWrite;
+
+    int                 bUseHTTPS;
+
+    CPLString           osAPIKey;
+
+    int                 bMustCleanPersistant;
+
+    int                 FetchSRSId( OGRSpatialReference * poSRS );
+
+  public:
+                        OGRCARTODBDataSource();
+                        ~OGRCARTODBDataSource();
+
+    int                 Open( const char * pszFilename,
+                              int bUpdate );
+
+    virtual const char* GetName() { return pszName; }
+
+    virtual int         GetLayerCount() { return nLayers; }
+    virtual OGRLayer*   GetLayer( int );
+    virtual OGRLayer    *GetLayerByName(const char *);
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRLayer   *CreateLayer( const char *pszName,
+                                     OGRSpatialReference *poSpatialRef = NULL,
+                                     OGRwkbGeometryType eGType = wkbUnknown,
+                                     char ** papszOptions = NULL );
+    virtual OGRErr      DeleteLayer(int);
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+    const char*                 GetAPIURL() const;
+    int                         IsReadWrite() const { return bReadWrite; }
+    char**                      AddHTTPOptions(char** papszOptions = NULL);
+    json_object*                RunSQL(const char* pszUnescapedSQL);
+
+    int                         IsAuthenticatedConnection() { return osAPIKey.size() != 0; }
+};
+
+/************************************************************************/
+/*                           OGRCARTODBDriver                           */
+/************************************************************************/
+
+class OGRCARTODBDriver : public OGRSFDriver
+{
+  public:
+                ~OGRCARTODBDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+
+    virtual int                 TestCapability( const char * ) { return FALSE; }
+};
+
+#endif /* ndef _OGR_CARTODB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
new file mode 100644
index 0000000..b443134
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
@@ -0,0 +1,641 @@
+/******************************************************************************
+ * $Id: ogrcartodbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CartoDB Translator
+ * Purpose:  Implements OGRCARTODBDataSource class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_cartodb.h"
+
+CPL_CVSID("$Id: ogrcartodbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/************************************************************************/
+/*                        OGRCARTODBDataSource()                        */
+/************************************************************************/
+
+OGRCARTODBDataSource::OGRCARTODBDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+    pszAccount = NULL;
+
+    bReadWrite = FALSE;
+    bUseHTTPS = FALSE;
+
+    bMustCleanPersistant = FALSE;
+}
+
+/************************************************************************/
+/*                       ~OGRCARTODBDataSource()                        */
+/************************************************************************/
+
+OGRCARTODBDataSource::~OGRCARTODBDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (bMustCleanPersistant)
+    {
+        char** papszOptions = CSLAddString(NULL, CPLSPrintf("CLOSE_PERSISTENT=CARTODB:%p", this));
+        CPLHTTPFetch( GetAPIURL(), papszOptions);
+        CSLDestroy(papszOptions);
+    }
+
+    CPLFree( pszName );
+    CPLFree( pszAccount );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCARTODBDataSource::TestCapability( const char * pszCap )
+
+{
+    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRCARTODBDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRCARTODBDataSource::GetLayerByName(const char * pszLayerName)
+{
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
+    return poLayer;
+}
+
+/************************************************************************/
+/*                     OGRCARTODBGetOptionValue()                       */
+/************************************************************************/
+
+CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
+                               const char* pszOptionName)
+{
+    CPLString osOptionName(pszOptionName);
+    osOptionName += "=";
+    const char* pszOptionValue = strstr(pszFilename, osOptionName);
+    if (!pszOptionValue)
+        return "";
+
+    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
+    if (pszSpace)
+        osOptionValue.resize(pszSpace - osOptionValue.c_str());
+    return osOptionValue;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRCARTODBDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (!EQUALN(pszFilename, "CARTODB:", strlen("CARTODB:")))
+        return FALSE;
+
+    bReadWrite = bUpdateIn;
+
+    pszName = CPLStrdup( pszFilename );
+    pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
+    char* pchSpace = strchr(pszAccount, ' ');
+    if( pchSpace )
+        *pchSpace = '\0';
+
+    osAPIKey = CPLGetConfigOption("CARTODB_API_KEY", "");
+
+    CPLString osTables = OGRCARTODBGetOptionValue(pszFilename, "tables");
+
+    bUseHTTPS = CSLTestBoolean(CPLGetConfigOption("CARTODB_HTTPS", "YES"));
+
+    if (osTables.size() != 0)
+    {
+        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
+        for(int i=0;papszTables && papszTables[i];i++)
+        {
+            papoLayers = (OGRLayer**) CPLRealloc(
+                papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+            papoLayers[nLayers ++] = new OGRCARTODBTableLayer(this, papszTables[i]);
+        }
+        CSLDestroy(papszTables);
+        return TRUE;
+    }
+    
+    if( osAPIKey.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "When not specifying tables option, CARTODB_API_KEY must be defined");
+        return FALSE;
+    }
+
+    json_object* poObj = RunSQL("SELECT CDB_UserTables()");
+    if( poObj == NULL )
+        return FALSE;
+    json_object* poRows = json_object_object_get(poObj, "rows");
+    if( poRows == NULL || json_object_get_type(poRows) != json_type_array)
+    {
+        json_object_put(poObj);
+        return FALSE;
+    }
+    for(int i=0; i < json_object_array_length(poRows); i++)
+    {
+        json_object* poTableNameObj = json_object_array_get_idx(poRows, i);
+        if( poTableNameObj != NULL &&
+            json_object_get_type(poTableNameObj) == json_type_object )
+        {
+            json_object* poVal = json_object_object_get(poTableNameObj, "cdb_usertables");
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                papoLayers = (OGRLayer**) CPLRealloc(
+                    papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+                papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
+                            this, json_object_get_string(poVal));
+            }
+        }
+    }
+    json_object_put(poObj);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetAPIURL()                               */
+/************************************************************************/
+
+const char* OGRCARTODBDataSource::GetAPIURL() const
+{
+    const char* pszAPIURL = CPLGetConfigOption("CARTODB_API_URL", NULL);
+    if (pszAPIURL)
+        return pszAPIURL;
+    else if (bUseHTTPS)
+        return CPLSPrintf("https://%s.cartodb.com/api/v2/sql", pszAccount);
+    else
+        return CPLSPrintf("http://%s.cartodb.com/api/v2/sql", pszAccount);
+}
+
+/************************************************************************/
+/*                             FetchSRSId()                             */
+/************************************************************************/
+
+int OGRCARTODBDataSource::FetchSRSId( OGRSpatialReference * poSRS )
+
+{
+    const char*         pszAuthorityName;
+
+    if( poSRS == NULL )
+        return 0;
+
+    OGRSpatialReference oSRS(*poSRS);
+    poSRS = NULL;
+
+    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+
+    if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
+    {
+/* -------------------------------------------------------------------- */
+/*      Try to identify an EPSG code                                    */
+/* -------------------------------------------------------------------- */
+        oSRS.AutoIdentifyEPSG();
+
+        pszAuthorityName = oSRS.GetAuthorityName(NULL);
+        if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
+        {
+            const char* pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
+            if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
+            {
+                /* Import 'clean' SRS */
+                oSRS.importFromEPSG( atoi(pszAuthorityCode) );
+
+                pszAuthorityName = oSRS.GetAuthorityName(NULL);
+            }
+        }
+    }
+/* -------------------------------------------------------------------- */
+/*      Check whether the EPSG authority code is already mapped to a    */
+/*      SRS ID.                                                         */
+/* -------------------------------------------------------------------- */
+    if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+    {
+        int             nAuthorityCode;
+
+        /* For the root authority name 'EPSG', the authority code
+         * should always be integral
+         */
+        nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
+
+        return nAuthorityCode;
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                           CreateLayer()                              */
+/************************************************************************/
+
+OGRLayer   *OGRCARTODBDataSource::CreateLayer( const char *pszName,
+                                           OGRSpatialReference *poSpatialRef,
+                                           OGRwkbGeometryType eGType,
+                                           char ** papszOptions )
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we already have this layer?  If so, should we blow it        */
+/*      away?                                                           */
+/* -------------------------------------------------------------------- */
+    int iLayer;
+
+    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( EQUAL(pszName,papoLayers[iLayer]->GetName()) )
+        {
+            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
+                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
+            {
+                DeleteLayer( iLayer );
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Layer %s already exists, CreateLayer failed.\n"
+                          "Use the layer creation option OVERWRITE=YES to "
+                          "replace it.",
+                          pszName );
+                return NULL;
+            }
+        }
+    }
+
+    int nSRID = 0;
+    if( poSpatialRef != NULL )
+        nSRID = FetchSRSId( poSpatialRef );
+
+    CPLString osGeomType;
+    if( eGType != wkbNone )
+    {
+        osGeomType = OGRToOGCGeomType(eGType);
+        if( eGType & wkb25DBit )
+            osGeomType += "Z";
+    }
+
+    CPLString osSQL;
+    osSQL.Printf("CREATE TABLE %s ( %s SERIAL, ",
+                 OGRCARTODBEscapeIdentifier(pszName).c_str(),
+                 "cartodb_id");
+    if( osGeomType.size() > 0 )
+    {
+        osSQL += CPLSPrintf("%s GEOMETRY(%s, %d), %s GEOMETRY(%s, %d),",
+                 "the_geom",
+                 osGeomType.c_str(),
+                 nSRID,
+                 "the_geom_webmercator",
+                 osGeomType.c_str(),
+                 3857);
+    }
+    osSQL += CPLSPrintf("PRIMARY KEY (%s) )", "cartodb_id");
+
+    osSQL += ";";
+    osSQL += CPLSPrintf("DROP SEQUENCE IF EXISTS %s",
+                        OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str());
+    osSQL += ";";
+    osSQL += CPLSPrintf("CREATE SEQUENCE %s START 1",
+                        OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str());
+    osSQL += ";";
+    osSQL += CPLSPrintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT nextval('%s')",
+                        pszName,
+                        "cartodb_id",
+                        OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str());
+
+    json_object* poObj = RunSQL(osSQL);
+    if( poObj == NULL )
+        return NULL;
+    json_object_put(poObj);
+
+    OGRCARTODBTableLayer* poLayer = new OGRCARTODBTableLayer(this, pszName);
+    papoLayers = (OGRLayer**) CPLRealloc(
+                    papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( iLayer < 0 || iLayer >= nLayers )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Layer %d not in legal range of 0 to %d.",
+                  iLayer, nLayers-1 );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLString osLayerName = papoLayers[iLayer]->GetLayerDefn()->GetName();
+
+    CPLDebug( "CARTODB", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete papoLayers[iLayer];
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
+             sizeof(void *) * (nLayers - iLayer - 1) );
+    nLayers--;
+
+    if (osLayerName.size() == 0)
+        return OGRERR_NONE;
+
+    CPLString osSQL;
+    osSQL.Printf("DROP TABLE %s",
+                 OGRCARTODBEscapeIdentifier(osLayerName).c_str());
+
+    json_object* poObj = RunSQL(osSQL);
+    if( poObj == NULL )
+        return OGRERR_FAILURE;
+    json_object_put(poObj);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          AddHTTPOptions()                            */
+/************************************************************************/
+
+char** OGRCARTODBDataSource::AddHTTPOptions(char** papszOptions)
+{
+    bMustCleanPersistant = TRUE;
+
+    return CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CARTODB:%p", this));
+}
+
+/************************************************************************/
+/*                               RunSQL()                               */
+/************************************************************************/
+
+json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
+{
+    CPLString osSQL("POSTFIELDS=q=");
+    /* Do post escaping */
+    for(int i=0;pszUnescapedSQL[i] != 0;i++)
+    {
+        const int ch = ((unsigned char*)pszUnescapedSQL)[i];
+        if (ch != '&' && ch >= 32 && ch < 128)
+            osSQL += (char)ch;
+        else
+            osSQL += CPLSPrintf("%%%02X", ch);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Provide the API Key                                             */
+/* -------------------------------------------------------------------- */
+    if( osAPIKey.size() )
+    {
+        osSQL += "&api_key=";
+        osSQL += osAPIKey;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collection the header options and execute request.              */
+/* -------------------------------------------------------------------- */
+    char** papszOptions = CSLAddString(AddHTTPOptions(), osSQL);
+    CPLHTTPResult * psResult = CPLHTTPFetch( GetAPIURL(), papszOptions);
+    CSLDestroy(papszOptions);
+
+/* -------------------------------------------------------------------- */
+/*      Check for some error conditions and report.  HTML Messages      */
+/*      are transformed info failure.                                   */
+/* -------------------------------------------------------------------- */
+    if (psResult && psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "CARTODB", "RunSQL HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "HTML error page returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult && psResult->pszErrBuf != NULL) 
+    {
+        CPLDebug( "CARTODB", "RunSQL Error Message:%s", psResult->pszErrBuf );
+    }
+    else if (psResult && psResult->nStatus != 0) 
+    {
+        CPLDebug( "CARTODB", "RunSQL Error Status:%d", psResult->nStatus );
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    
+    if( strlen((const char*)psResult->pabyData) < 1000 )
+        CPLDebug( "CARTODB", "RunSQL Response:%s", psResult->pabyData );
+    
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "JSON parsing error: %s (at offset %d)",
+                    json_tokener_errors[jstok->err], jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( poObj != NULL )
+    {
+        if( json_object_get_type(poObj) == json_type_object )
+        {
+            json_object* poError = json_object_object_get(poObj, "error");
+            if( poError != NULL && json_object_get_type(poError) == json_type_array &&
+                json_object_array_length(poError) > 0 )
+            {
+                poError = json_object_array_get_idx(poError, 0);
+                if( poError != NULL && json_object_get_type(poError) == json_type_string )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, 
+                            "Error returned by server : %s", json_object_get_string(poError));
+                    json_object_put(poObj);
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                        OGRCARTODBGetSingleRow()                      */
+/************************************************************************/
+
+json_object* OGRCARTODBGetSingleRow(json_object* poObj)
+{
+    if( poObj == NULL )
+    {
+        return NULL;
+    }
+
+    json_object* poRows = json_object_object_get(poObj, "rows");
+    if( poRows == NULL ||
+        json_object_get_type(poRows) != json_type_array ||
+        json_object_array_length(poRows) != 1 )
+    {
+        json_object_put(poObj);
+        return NULL;
+    }
+
+    json_object* poRowObj = json_object_array_get_idx(poRows, 0);
+    if( poRowObj == NULL || json_object_get_type(poRowObj) != json_type_object )
+    {
+        json_object_put(poObj);
+        return NULL;
+    }
+
+    return poRowObj;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRCARTODBDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect )
+
+{
+    /* Skip leading spaces */
+    while(*pszSQLCommand == ' ')
+        pszSQLCommand ++;
+
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+        
+        for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+        {
+            if( EQUAL(papoLayers[iLayer]->GetName(), 
+                      pszLayerName ))
+            {
+                DeleteLayer( iLayer );
+                break;
+            }
+        }
+        return NULL;
+    }
+
+    OGRCARTODBResultLayer* poLayer = new OGRCARTODBResultLayer( this, pszSQLCommand );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+
+    CPLErrorReset();
+    poLayer->GetLayerDefn();
+    if( CPLGetLastErrorNo() != 0 )
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRCARTODBDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
new file mode 100644
index 0000000..8ec2e0e
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * $Id: ogrcartodbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CartoDB Translator
+ * Purpose:  Implements OGRCARTODBDriver.
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_cartodb.h"
+
+// g++ -g -Wall -fPIC -shared -o ogr_CARTODB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/cartodb ogr/ogrsf_frmts/cartodb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson 
+
+CPL_CVSID("$Id: ogrcartodbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+extern "C" void RegisterOGRCartoDB();
+
+/************************************************************************/
+/*                        ~OGRCARTODBDriver()                           */
+/************************************************************************/
+
+OGRCARTODBDriver::~OGRCARTODBDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRCARTODBDriver::GetName()
+
+{
+    return "CartoDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRCARTODBDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRCARTODBDataSource   *poDS = new OGRCARTODBDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         RegisterOGRCARTODB()                         */
+/************************************************************************/
+
+void RegisterOGRCartoDB()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRCARTODBDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
new file mode 100644
index 0000000..012154e
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
@@ -0,0 +1,426 @@
+/******************************************************************************
+ * $Id: ogrcartodblayer.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CartoDB Translator
+ * Purpose:  Implements OGRCARTODBLayer class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_cartodb.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrcartodblayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/************************************************************************/
+/*                         OGRCARTODBLayer()                            */
+/************************************************************************/
+
+OGRCARTODBLayer::OGRCARTODBLayer(OGRCARTODBDataSource* poDS)
+
+{
+    this->poDS = poDS;
+
+    poSRS = NULL;
+
+    poFeatureDefn = NULL;
+    
+    poCachedObj = NULL;
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                         ~OGRCARTODBLayer()                           */
+/************************************************************************/
+
+OGRCARTODBLayer::~OGRCARTODBLayer()
+
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRCARTODBLayer::ResetReading()
+
+{
+    if( poCachedObj != NULL )
+        json_object_put(poCachedObj);
+    poCachedObj = NULL;
+    bEOF = FALSE;
+    nFetchedObjects = -1;
+    iNextInFetchedObjects = 0;
+    iNext = 0;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRCARTODBLayer::GetLayerDefn()
+{
+    CPLAssert(poFeatureDefn);
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           BuildFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRCARTODBLayer::BuildFeature(json_object* poRowObj)
+{
+    OGRFeature* poFeature = NULL;
+    if( poRowObj != NULL &&
+        json_object_get_type(poRowObj) == json_type_object )
+    {
+        poFeature = new OGRFeature(poFeatureDefn);
+
+        if( osFIDColName.size() )
+        {
+            json_object* poVal = json_object_object_get(poRowObj, osFIDColName);
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_int )
+            {
+                poFeature->SetFID(json_object_get_int64(poVal));
+            }
+        }
+        else
+        {
+            poFeature->SetFID(iNext);
+        }
+
+        for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+        {
+            json_object* poVal = json_object_object_get(poRowObj,
+                            poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+                {
+                    int nYear, nMonth, nDay, nHour, nMinute, nTZ;
+                    float fSecond;
+                    if( OGRParseXMLDateTime( json_object_get_string(poVal),
+                                  &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ) )
+                    {
+                        poFeature->SetField(i, nYear, nMonth, nDay, nHour, nMinute, (int)fSecond, nTZ);
+                    }
+                }
+                else
+                {
+                    poFeature->SetField(i, json_object_get_string(poVal));
+                }
+            }
+            else if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_int )
+            {
+                poFeature->SetField(i, (int)json_object_get_int64(poVal));
+            }
+            else if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_double )
+            {
+                poFeature->SetField(i, json_object_get_double(poVal));
+            }
+        }
+
+        for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
+        {
+            OGRGeomFieldDefn* poGeomFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
+            json_object* poVal = json_object_object_get(poRowObj,
+                            poGeomFldDefn->GetNameRef());
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                OGRGeometry* poGeom = OGRGeometryFromHexEWKB(
+                                        json_object_get_string(poVal), NULL);
+                if( poGeom != NULL )
+                    poGeom->assignSpatialReference(poGeomFldDefn->GetSpatialRef());
+                poFeature->SetGeomFieldDirectly(i, poGeom);
+            }
+        }
+    }
+    return poFeature;
+}
+
+/************************************************************************/
+/*                        GetNextRawFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRCARTODBLayer::GetNextRawFeature()
+{
+    if( bEOF ) 
+        return NULL;
+
+    if( iNextInFetchedObjects >= nFetchedObjects )
+    {
+        if( nFetchedObjects > 0 && nFetchedObjects < GetFeaturesToFetch() )
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        CPLString osSQL = osBaseSQL;
+        if( osSQL.ifind(" LIMIT ") == std::string::npos )
+        {
+            osSQL += " LIMIT ";
+            osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
+            osSQL += " OFFSET ";
+            osSQL += CPLSPrintf("%d", iNext);
+        }
+        json_object* poObj = poDS->RunSQL(osSQL);
+        if( poObj == NULL )
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+        json_object* poRows = json_object_object_get(poObj, "rows");
+        if( poRows == NULL ||
+            json_object_get_type(poRows) != json_type_array ||
+            json_object_array_length(poRows) == 0 )
+        {
+            json_object_put(poObj);
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        if( poCachedObj != NULL )
+            json_object_put(poCachedObj);
+        poCachedObj = poObj;
+
+        nFetchedObjects = json_object_array_length(poRows);
+        iNextInFetchedObjects = 0;
+    }
+
+    json_object* poRows = json_object_object_get(poCachedObj, "rows");
+    json_object* poRowObj = json_object_array_get_idx(poRows, iNextInFetchedObjects);
+
+    iNextInFetchedObjects ++;
+
+    OGRFeature* poFeature = BuildFeature(poRowObj);
+    iNext ++;
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRCARTODBLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    GetLayerDefn();
+
+    while(TRUE)
+    {
+        poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+            return NULL;
+
+        if((m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            return poFeature;
+        }
+        else
+            delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCARTODBLayer::TestCapability( const char * pszCap )
+
+{
+    if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          EstablishLayerDefn()                        */
+/************************************************************************/
+
+void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName)
+{
+    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType(wkbNone);
+
+    CPLString osSQL;
+    size_t nPos = osBaseSQL.ifind(" LIMIT ");
+    if( nPos != std::string::npos )
+    {
+        osSQL = osBaseSQL;
+        size_t nSize = osSQL.size();
+        for(size_t i = nPos + strlen(" LIMIT "); i < nSize; i++)
+        {
+            if( osSQL[i] == ' ' )
+                break;
+            osSQL[i] = '0';
+        }
+    }
+    else
+        osSQL.Printf("%s LIMIT 0", osBaseSQL.c_str());
+    json_object* poObj = poDS->RunSQL(osSQL);
+    if( poObj == NULL )
+    {
+        return;
+    }
+
+    json_object* poFields = json_object_object_get(poObj, "fields");
+    if( poFields == NULL || json_object_get_type(poFields) != json_type_object)
+    {
+        json_object_put(poObj);
+        return;
+    }
+
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC( poFields, it )
+    {
+        const char* pszColName = it.key;
+        if( it.val != NULL && json_object_get_type(it.val) == json_type_object)
+        {
+            json_object* poType = json_object_object_get(it.val, "type");
+            if( poType != NULL && json_object_get_type(poType) == json_type_string )
+            {
+                const char* pszType = json_object_get_string(poType);
+                CPLDebug("CARTODB", "%s : %s", pszColName, pszType);
+                if( EQUAL(pszType, "string") )
+                {
+                    OGRFieldDefn oFieldDefn(pszColName, OFTString);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+                else if( EQUAL(pszType, "number") )
+                {
+                    if( !EQUAL(pszColName, "cartodb_id") )
+                    {
+                        OGRFieldDefn oFieldDefn(pszColName, OFTReal);
+                        poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                    }
+                    else
+                        osFIDColName = pszColName;
+                }
+                else if( EQUAL(pszType, "date") )
+                {
+                    if( !EQUAL(pszColName, "created_at") &&
+                        !EQUAL(pszColName, "updated_at") )
+                    {
+                        OGRFieldDefn oFieldDefn(pszColName, OFTDateTime);
+                        poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                    }
+                }
+                else if( EQUAL(pszType, "geometry") )
+                {
+                    if( !EQUAL(pszColName, "the_geom_webmercator") )
+                    {
+                        OGRCartoDBGeomFieldDefn *poFieldDefn =
+                            new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
+                        poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
+                        OGRSpatialReference* poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
+                        if( poSRS != NULL )
+                        {
+                            poFeatureDefn->GetGeomFieldDefn(
+                                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+                            poSRS->Release();
+                        }
+                    }
+                }
+                else
+                {
+                    CPLDebug("CARTODB", "Unhandled type: %s", pszType);
+                }
+            }
+            else if( poType != NULL && json_object_get_type(poType) == json_type_int )
+            {
+                /* FIXME? manual creations of geometry columns return integer types */
+                OGRCartoDBGeomFieldDefn *poFieldDefn =
+                    new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
+                poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
+                OGRSpatialReference* poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
+                if( poSRS != NULL )
+                {
+                    poFeatureDefn->GetGeomFieldDefn(
+                        poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+                    poSRS->Release();
+                }
+            }
+        }
+    }
+    json_object_put(poObj);
+}
+
+/************************************************************************/
+/*                               GetSRS()                               */
+/************************************************************************/
+
+OGRSpatialReference* OGRCARTODBLayer::GetSRS(const char* pszGeomCol,
+                                             int *pnSRID)
+{
+    json_object* poObj = poDS->RunSQL(GetSRS_SQL(pszGeomCol));
+    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return NULL;
+    }
+
+    json_object* poSRID = json_object_object_get(poRowObj, "srid");
+    if( poSRID != NULL && json_object_get_type(poSRID) == json_type_int )
+    {
+        *pnSRID = json_object_get_int(poSRID);
+    }
+
+    json_object* poSRTEXT = json_object_object_get(poRowObj, "srtext");
+    OGRSpatialReference* poSRS = NULL;
+    if( poSRTEXT != NULL && json_object_get_type(poSRTEXT) == json_type_string )
+    {
+        const char* pszSRTEXT = json_object_get_string(poSRTEXT);
+        poSRS = new OGRSpatialReference();
+        char* pszTmp = (char* )pszSRTEXT;
+        if( poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+    json_object_put(poObj);
+
+    return poSRS;
+}
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
new file mode 100644
index 0000000..0951196
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * $Id
+ *
+ * Project:  CartoDB Translator
+ * Purpose:  Implements OGRCARTODBResultLayer class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_cartodb.h"
+
+CPL_CVSID("$Id");
+
+/************************************************************************/
+/*                          OGRCARTODBResultLayer()                     */
+/************************************************************************/
+
+OGRCARTODBResultLayer::OGRCARTODBResultLayer( OGRCARTODBDataSource* poDS,
+                                              const char * pszRawQueryIn ) :
+                                              OGRCARTODBLayer(poDS)
+{
+    osBaseSQL = pszRawQueryIn;
+}
+
+/************************************************************************/
+/*                       ~OGRCARTODBResultLayer()                       */
+/************************************************************************/
+
+OGRCARTODBResultLayer::~OGRCARTODBResultLayer()
+
+{
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRCARTODBResultLayer::GetLayerDefn()
+{
+    if( poFeatureDefn != NULL )
+        return poFeatureDefn;
+
+    EstablishLayerDefn("result");
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                             GetSRS_SQL()                             */
+/************************************************************************/
+
+CPLString OGRCARTODBResultLayer::GetSRS_SQL(const char* pszGeomCol)
+{
+    CPLString osSQL;
+    CPLString osLimitedSQL;
+
+    size_t nPos = osBaseSQL.ifind(" LIMIT ");
+    if( nPos != std::string::npos )
+    {
+        osLimitedSQL = osBaseSQL;
+        size_t nSize = osLimitedSQL.size();
+        for(size_t i = nPos + strlen(" LIMIT "); i < nSize; i++)
+        {
+            if( osLimitedSQL[i] == ' ' && osLimitedSQL[i-1] == '0')
+            {
+                osLimitedSQL[i-1] = '1';
+                break;
+            }
+            osLimitedSQL[i] = '0';
+        }
+    }
+    else
+        osLimitedSQL.Printf("%s LIMIT 1", osBaseSQL.c_str());
+
+    /* Assuming that the SRID of the first non-NULL geometry applies */
+    /* to geometries of all rows. */
+    osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
+                "(SELECT ST_SRID(%s) FROM (%s) ogr_subselect)",
+                OGRCARTODBEscapeIdentifier(pszGeomCol).c_str(),
+                osLimitedSQL.c_str());
+
+    return osSQL;
+}
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
new file mode 100644
index 0000000..c5734e3
--- /dev/null
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
@@ -0,0 +1,953 @@
+/******************************************************************************
+ * $Id: ogrcartodbtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CartoDB Translator
+ * Purpose:  Implements OGRCARTODBTableLayer class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_cartodb.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrcartodbtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/************************************************************************/
+/*                    OGRCARTODBEscapeIdentifier( )                     */
+/************************************************************************/
+
+CPLString OGRCARTODBEscapeIdentifier(const char* pszStr)
+{
+    CPLString osStr;
+
+    osStr += "\"";
+
+    char ch;
+    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    {
+        if (ch == '"')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    osStr += "\"";
+
+    return osStr;
+}
+
+/************************************************************************/
+/*                    OGRCARTODBEscapeLiteral( )                        */
+/************************************************************************/
+
+CPLString OGRCARTODBEscapeLiteral(const char* pszStr)
+{
+    CPLString osStr;
+
+    char ch;
+    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    {
+        if (ch == '\'')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    return osStr;
+}
+
+/************************************************************************/
+/*                        OGRCARTODBTableLayer()                        */
+/************************************************************************/
+
+OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS,
+                                           const char* pszName) :
+                                           OGRCARTODBLayer(poDS)
+
+{
+    osName = pszName;
+    bInTransaction = FALSE;
+    nNextFID = -1;
+}
+
+/************************************************************************/
+/*                    ~OGRCARTODBTableLayer()                           */
+/************************************************************************/
+
+OGRCARTODBTableLayer::~OGRCARTODBTableLayer()
+
+{
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefn()
+{
+    if( poFeatureDefn != NULL )
+        return poFeatureDefn;
+
+    osBaseSQL.Printf("SELECT * FROM %s",
+                     OGRCARTODBEscapeIdentifier(osName).c_str());
+    EstablishLayerDefn(osName);
+    if( osFIDColName.size() > 0 )
+    {
+        osBaseSQL.Printf("SELECT * FROM %s ORDER BY %s ASC",
+                         OGRCARTODBEscapeIdentifier(osName).c_str(),
+                         OGRCARTODBEscapeIdentifier(osFIDColName).c_str());
+    }
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    GetLayerDefn();
+
+    if( pszQuery == NULL )
+        osQuery = "";
+    else
+    {
+        osQuery = pszQuery;
+    }
+
+    BuildWhere();
+
+    ResetReading();
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRCARTODBTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
+
+    if( InstallFilter( poGeomIn ) )
+    {
+        BuildWhere();
+
+        ResetReading();
+    }
+}
+
+/************************************************************************/
+/*                          StartTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::StartTransaction()
+
+{
+    bInTransaction = TRUE;
+    osTransactionSQL = "";
+    nNextFID = -1;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::CommitTransaction()
+
+{
+    OGRErr eRet = OGRERR_NONE;
+
+    if( bInTransaction && osTransactionSQL.size() > 0 )
+    {
+        eRet = OGRERR_FAILURE;
+        osTransactionSQL = "BEGIN;" + osTransactionSQL + "COMMIT;";
+        json_object* poObj = poDS->RunSQL(osTransactionSQL);
+        if( poObj != NULL )
+        {
+            eRet = OGRERR_NONE;
+            json_object_put(poObj);
+        }
+    }
+
+    bInTransaction = FALSE;
+    osTransactionSQL = "";
+    nNextFID = -1;
+    return eRet;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::RollbackTransaction()
+
+{
+    bInTransaction = FALSE;
+    osTransactionSQL = "";
+    nNextFID = -1;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
+
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+
+    const char* pszFieldType = "VARCHAR";
+    switch( poFieldIn->GetType() )
+    {
+        case OFTInteger:
+            pszFieldType = "INTEGER";
+            break;
+        case OFTReal:
+            pszFieldType = "FLOAT8";
+            break;
+        case OFTDate:
+            pszFieldType = "date";
+            break;
+        case OFTTime:
+            pszFieldType = "time";
+            break;
+        case OFTDateTime:
+            pszFieldType = "timestamp with time zone";
+            break;
+        default:
+            break;
+    }
+
+    CPLString osSQL;
+    osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
+                  OGRCARTODBEscapeIdentifier(osName).c_str(),
+                  OGRCARTODBEscapeIdentifier(poFieldIn->GetNameRef()).c_str(),
+                  pszFieldType );
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    if( poObj == NULL )
+        return OGRERR_FAILURE;
+    json_object_put(poObj);
+
+    poFeatureDefn->AddFieldDefn( poFieldIn );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::CreateFeature( OGRFeature *poFeature )
+
+{
+    int i;
+    
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    CPLString osSQL;
+
+    int bHasJustGotNextFID = FALSE;
+    if( bInTransaction && nNextFID < 0 && osFIDColName.size() )
+    {
+        osSQL.Printf("SELECT nextval('%s') AS nextid",
+                     OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
+
+        json_object* poObj = poDS->RunSQL(osSQL);
+        json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+        if( poRowObj != NULL )
+        {
+            json_object* poID = json_object_object_get(poRowObj, "nextid");
+            if( poID != NULL && json_object_get_type(poID) == json_type_int )
+            {
+                nNextFID = json_object_get_int64(poID);
+                bHasJustGotNextFID = TRUE;
+            }
+        }
+
+        if( poObj != NULL )
+            json_object_put(poObj);
+    }
+
+    osSQL.Printf("INSERT INTO %s ", OGRCARTODBEscapeIdentifier(osName).c_str());
+    int bMustComma = FALSE;
+    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    {
+        if( !poFeature->IsFieldSet(i) )
+            continue;
+
+        if( bMustComma )
+            osSQL += ", ";
+        else
+        {
+            osSQL += "(";
+            bMustComma = TRUE;
+        }
+
+        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+    }
+
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    {
+        if( poFeature->GetGeomFieldRef(i) == NULL )
+            continue;
+
+        if( bMustComma )
+            osSQL += ", ";
+        else
+        {
+            osSQL += "(";
+            bMustComma = TRUE;
+        }
+
+        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+    }
+    
+    if( osFIDColName.size() && (poFeature->GetFID() != OGRNullFID || nNextFID >= 0) )
+    {
+        if( bMustComma )
+            osSQL += ", ";
+        else
+        {
+            osSQL += "(";
+            bMustComma = TRUE;
+        }
+
+        osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+    }
+
+    if( !bMustComma )
+        osSQL += " DEFAULT VALUES";
+    else
+    {
+        osSQL += ") VALUES (";
+        
+        bMustComma = FALSE;
+        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        {
+            if( !poFeature->IsFieldSet(i) )
+                continue;
+        
+            if( bMustComma )
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+            
+            if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTString )
+            {
+                osSQL += "'";
+                osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+                osSQL += "'";
+            }
+            else
+                osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+        }
+        
+        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        {
+            OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+            if( poGeom == NULL )
+                continue;
+        
+            if( bMustComma )
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+
+            OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
+                (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
+            int nSRID = poGeomFieldDefn->nSRID;
+            if( nSRID == 0 )
+                nSRID = 4326;
+            char* pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID);
+            osSQL += "'";
+            osSQL += pszEWKB;
+            osSQL += "'";
+            CPLFree(pszEWKB);
+        }
+
+        if( osFIDColName.size() && nNextFID >= 0 )
+        {
+            if( bMustComma )
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+
+            if( bHasJustGotNextFID )
+            {
+                osSQL += CPLSPrintf("%ld", nNextFID);
+            }
+            else
+            {
+                osSQL += CPLSPrintf("nextval('%s')",
+                        OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
+            }
+            poFeature->SetFID(nNextFID);
+            nNextFID ++;
+        }
+        else if( osFIDColName.size() && poFeature->GetFID() != OGRNullFID )
+        {
+            if( bMustComma )
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+
+            osSQL += CPLSPrintf("%ld", poFeature->GetFID());
+        }
+
+        osSQL += ")";
+    }
+
+    if( bInTransaction )
+    {
+        osTransactionSQL += osSQL;
+        osTransactionSQL += ";";
+        return OGRERR_NONE;
+    }
+    
+    if( osFIDColName.size() )
+    {
+        osSQL += " RETURNING ";
+        osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+
+        json_object* poObj = poDS->RunSQL(osSQL);
+        json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+        if( poRowObj == NULL )
+        {
+            if( poObj != NULL )
+                json_object_put(poObj);
+            return OGRERR_FAILURE;
+        }
+
+        json_object* poID = json_object_object_get(poRowObj, "cartodb_id");
+        if( poID != NULL && json_object_get_type(poID) == json_type_int )
+        {
+            poFeature->SetFID(json_object_get_int64(poID));
+        }
+
+        if( poObj != NULL )
+            json_object_put(poObj);
+
+        return OGRERR_NONE;
+    }
+    else
+    {
+        OGRErr eRet = OGRERR_FAILURE;
+        json_object* poObj = poDS->RunSQL(osSQL);
+        if( poObj != NULL )
+        {
+            json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+            if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
+            {
+                int nTotalRows = json_object_get_int(poTotalRows);
+                if( nTotalRows == 1 )
+                {
+                    eRet = OGRERR_NONE;
+                }
+            }
+            json_object_put(poObj);
+        }
+
+        return eRet;
+    }
+}
+
+/************************************************************************/
+/*                            SetFeature()                              */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::SetFeature( OGRFeature *poFeature )
+
+{
+    int i;
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeature->GetFID() == OGRNullFID)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FID required on features given to SetFeature()." );
+        return OGRERR_FAILURE;
+    }
+    
+    CPLString osSQL;
+    osSQL.Printf("UPDATE %s SET ", OGRCARTODBEscapeIdentifier(osName).c_str());
+    int bMustComma = FALSE;
+    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    {
+        if( bMustComma )
+            osSQL += ", ";
+        else
+            bMustComma = TRUE;
+
+        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        osSQL += " = ";
+
+        if( !poFeature->IsFieldSet(i) )
+        {
+            osSQL += "NULL";
+        }
+        else if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTString )
+        {
+            osSQL += "'";
+            osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+            osSQL += "'";
+        }
+        else
+            osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+    }
+
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    {
+        if( bMustComma )
+            osSQL += ", ";
+        else
+            bMustComma = TRUE;
+
+        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+        osSQL += " = ";
+
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom == NULL )
+        {
+            osSQL += "NULL";
+        }
+        else
+        {
+            OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
+                (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
+            int nSRID = poGeomFieldDefn->nSRID;
+            if( nSRID == 0 )
+                nSRID = 4326;
+            char* pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID);
+            osSQL += "'";
+            osSQL += pszEWKB;
+            osSQL += "'";
+            CPLFree(pszEWKB);
+        }
+    }
+
+    osSQL += CPLSPrintf(" WHERE %s = %ld",
+                    OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                    poFeature->GetFID());
+    
+    if( bInTransaction )
+    {
+        osTransactionSQL += osSQL;
+        osTransactionSQL += ";";
+        return OGRERR_NONE;
+    }
+
+    OGRErr eRet = OGRERR_FAILURE;
+    json_object* poObj = poDS->RunSQL(osSQL);
+    if( poObj != NULL )
+    {
+        json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+        if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
+        {
+            int nTotalRows = json_object_get_int(poTotalRows);
+            if( nTotalRows == 1 )
+            {
+                eRet = OGRERR_NONE;
+            }
+        }
+        json_object_put(poObj);
+    }
+
+    return eRet;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::DeleteFeature( long nFID )
+
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+    
+    if( osFIDColName.size() == 0 )
+        return OGRERR_FAILURE;
+    
+    CPLString osSQL;
+    osSQL.Printf("DELETE FROM %s WHERE %s = %ld",
+                    OGRCARTODBEscapeIdentifier(osName).c_str(),
+                    OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                    nFID);
+    
+    if( bInTransaction )
+    {
+        osTransactionSQL += osSQL;
+        osTransactionSQL += ";";
+        return OGRERR_NONE;
+    }
+    
+    OGRErr eRet = OGRERR_FAILURE;
+    json_object* poObj = poDS->RunSQL(osSQL);
+    if( poObj != NULL )
+    {
+        json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+        if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
+        {
+            int nTotalRows = json_object_get_int(poTotalRows);
+            if( nTotalRows == 1 )
+            {
+                eRet = OGRERR_NONE;
+            }
+        }
+        json_object_put(poObj);
+    }
+
+    return eRet;
+}
+
+/************************************************************************/
+/*                             GetSRS_SQL()                             */
+/************************************************************************/
+
+CPLString OGRCARTODBTableLayer::GetSRS_SQL(const char* pszGeomCol)
+{
+    CPLString osSQL;
+
+    if( poDS->IsAuthenticatedConnection() )
+    {
+        /* Find_SRID needs access to geometry_columns table, whhose access */
+        /* is restricted to authenticated connections. */
+        osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
+                    "(SELECT Find_SRID('public', '%s', '%s'))",
+                    OGRCARTODBEscapeLiteral(osName).c_str(),
+                    OGRCARTODBEscapeLiteral(pszGeomCol).c_str());
+    }
+    else
+    {
+        /* Assuming that the SRID of the first non-NULL geometry applies */
+        /* to geometries of all rows. */
+        osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
+                    "(SELECT ST_SRID(%s) FROM %s WHERE %s IS NOT NULL LIMIT 1)",
+                    OGRCARTODBEscapeIdentifier(pszGeomCol).c_str(),
+                    OGRCARTODBEscapeIdentifier(osName).c_str(),
+                    OGRCARTODBEscapeIdentifier(pszGeomCol).c_str());
+    }
+
+    return osSQL;
+}
+
+/************************************************************************/
+/*                             BuildWhere()                             */
+/*                                                                      */
+/*      Build the WHERE statement appropriate to the current set of     */
+/*      criteria (spatial and attribute queries).                       */
+/************************************************************************/
+
+void OGRCARTODBTableLayer::BuildWhere()
+
+{
+    osWHERE = "";
+
+    if( m_poFilterGeom != NULL &&
+        m_iGeomFieldFilter >= 0 &&
+        m_iGeomFieldFilter < poFeatureDefn->GetGeomFieldCount() )
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        CPLString osGeomColumn(poFeatureDefn->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
+
+        char szBox3D_1[128];
+        char szBox3D_2[128];
+        char* pszComma;
+
+        snprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
+        while((pszComma = strchr(szBox3D_1, ',')) != NULL)
+            *pszComma = '.';
+        snprintf(szBox3D_2, sizeof(szBox3D_2), "%.18g %.18g", sEnvelope.MaxX, sEnvelope.MaxY);
+        while((pszComma = strchr(szBox3D_2, ',')) != NULL)
+            *pszComma = '.';
+        osWHERE.Printf("WHERE %s && 'BOX3D(%s, %s)'::box3d",
+                       OGRCARTODBEscapeIdentifier(osGeomColumn).c_str(),
+                       szBox3D_1, szBox3D_2 );
+    }
+
+    if( strlen(osQuery) > 0 )
+    {
+        if( strlen(osWHERE) == 0 )
+            osWHERE = "WHERE ";
+        else
+            osWHERE += " AND ";
+        osWHERE += osQuery;
+    }
+
+    osBaseSQL.Printf("SELECT * FROM %s",
+                     OGRCARTODBEscapeIdentifier(osName).c_str());
+    if( osWHERE.size() )
+    {
+        osBaseSQL += " ";
+        osBaseSQL += osWHERE;
+    }
+}
+
+/************************************************************************/
+/*                              GetFeature()                            */
+/************************************************************************/
+
+OGRFeature* OGRCARTODBTableLayer::GetFeature( long nFeatureId )
+{
+    GetLayerDefn();
+    
+    if( osFIDColName.size() == 0 )
+        return OGRCARTODBLayer::GetFeature(nFeatureId);
+
+    CPLString osSQL(CPLSPrintf("SELECT * FROM %s WHERE %s = %ld",
+                               OGRCARTODBEscapeIdentifier(osName).c_str(),
+                               OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                               nFeatureId));
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return OGRCARTODBLayer::GetFeature(nFeatureId);
+    }
+
+    OGRFeature* poFeature = BuildFeature(poRowObj);
+    json_object_put(poObj);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRCARTODBTableLayer::GetFeatureCount(int bForce)
+{
+    GetLayerDefn();
+
+    CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
+                               OGRCARTODBEscapeIdentifier(osName).c_str()));
+    if( osWHERE.size() )
+    {
+        osSQL += " ";
+        osSQL += osWHERE;
+    }
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return OGRCARTODBLayer::GetFeatureCount(bForce);
+    }
+
+    json_object* poCount = json_object_object_get(poRowObj, "count");
+    if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
+    {
+        json_object_put(poObj);
+        return OGRCARTODBLayer::GetFeatureCount(bForce);
+    }
+
+    int nRet = (int)json_object_get_int64(poCount);
+
+    json_object_put(poObj);
+
+    return nRet;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      For PostGIS use internal Extend(geometry) function              */
+/*      in other cases we use standard OGRLayer::GetExtent()            */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
+{
+    CPLString   osSQL;
+
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    OGRGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->GetGeomFieldDefn(iGeomField);
+
+    /* Do not take the spatial filter into account */
+    osSQL.Printf( "SELECT ST_Extent(%s) FROM %s",
+                  OGRCARTODBEscapeIdentifier(poGeomFieldDefn->GetNameRef()).c_str(),
+                  OGRCARTODBEscapeIdentifier(osName).c_str());
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    if( poRowObj != NULL )
+    {
+        json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
+        if( poExtent != NULL && json_object_get_type(poExtent) == json_type_string )
+        {
+            const char* pszBox = json_object_get_string(poExtent);
+            const char * ptr, *ptrEndParenthesis;
+            char szVals[64*6+6];
+
+            ptr = strchr(pszBox, '(');
+            if (ptr)
+                ptr ++;
+            if (ptr == NULL ||
+                (ptrEndParenthesis = strchr(ptr, ')')) == NULL ||
+                ptrEndParenthesis - ptr > (int)(sizeof(szVals) - 1))
+            {
+                CPLError( CE_Failure, CPLE_IllegalArg,
+                            "Bad extent representation: '%s'", pszBox);
+
+                json_object_put(poObj);
+                return OGRERR_FAILURE;
+            }
+
+            strncpy(szVals,ptr,ptrEndParenthesis - ptr);
+            szVals[ptrEndParenthesis - ptr] = '\0';
+
+            char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);
+            int nTokenCnt = 4;
+
+            if ( CSLCount(papszTokens) != nTokenCnt )
+            {
+                CPLError( CE_Failure, CPLE_IllegalArg,
+                            "Bad extent representation: '%s'", pszBox);
+                CSLDestroy(papszTokens);
+
+                json_object_put(poObj);
+                return OGRERR_FAILURE;
+            }
+
+            // Take X,Y coords
+            // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
+            // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
+            // =>   X2 index calculated as nTokenCnt/2
+            //      Y2 index caluclated as nTokenCnt/2+1
+            
+            psExtent->MinX = CPLAtof( papszTokens[0] );
+            psExtent->MinY = CPLAtof( papszTokens[1] );
+            psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
+            psExtent->MaxY = CPLAtof( papszTokens[nTokenCnt/2+1] );
+
+            CSLDestroy(papszTokens);
+
+            json_object_put(poObj);
+            return OGRERR_NONE;
+        }
+    }
+
+    if( poObj != NULL )
+        json_object_put(poObj);
+
+    if( iGeomField == 0 )
+        return OGRLayer::GetExtent( psExtent, bForce );
+    else
+        return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return TRUE;
+    if( EQUAL(pszCap, OLCFastGetExtent) )
+        return TRUE;
+    if( EQUAL(pszCap, OLCRandomRead) )
+    {
+        GetLayerDefn();
+        return osFIDColName.size() != 0;
+    }
+
+    if( EQUAL(pszCap,OLCSequentialWrite)
+     || EQUAL(pszCap,OLCRandomWrite)
+     || EQUAL(pszCap,OLCDeleteFeature)
+     || EQUAL(pszCap,OLCCreateField) )
+    {
+        return poDS->IsReadWrite();
+    }
+
+    if( EQUAL(pszCap,OLCTransactions) )
+        return TRUE;
+
+    return OGRCARTODBLayer::TestCapability(pszCap);
+}
diff --git a/ogr/ogrsf_frmts/couchdb/GNUmakefile b/ogr/ogrsf_frmts/couchdb/GNUmakefile
index 415513e..53a6a9b 100644
--- a/ogr/ogrsf_frmts/couchdb/GNUmakefile
+++ b/ogr/ogrsf_frmts/couchdb/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrcouchdbdriver.o ogrcouchdbdatasource.o ogrcouchdblayer.o ogrcouchdbtablelayer.o ogrcouchdbrowslayer.o
 
-CPPFLAGS	:=	-I.. -I../.. -I../geojson -I../geojson/jsonc $(GDAL_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../geojson $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/couchdb/makefile.vc b/ogr/ogrsf_frmts/couchdb/makefile.vc
index a839631..38224d2 100644
--- a/ogr/ogrsf_frmts/couchdb/makefile.vc
+++ b/ogr/ogrsf_frmts/couchdb/makefile.vc
@@ -1,6 +1,6 @@
 
 OBJ	=	ogrcouchdbdriver.obj ogrcouchdbdatasource.obj ogrcouchdblayer.obj ogrcouchdbtablelayer.obj ogrcouchdbrowslayer.obj
-EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\jsonc
+EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\libjson
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
index f3988dd..774106e 100644
--- a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
+++ b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_couchdb.h 23324 2011-11-05 16:17:33Z rouault $
+ * $Id: ogr_couchdb.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Definition of classes for OGR CouchDB / GeoCouch driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
-#include "json.h"
+#include <json.h>
 
 #include <vector>
 #include <map>
@@ -94,8 +94,6 @@ protected:
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference*GetSpatialRef();
-
     virtual CouchDBLayerType    GetLayerType() = 0;
 
     virtual OGRErr              SetNextByIndex( long nIndex );
@@ -189,8 +187,6 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference*GetSpatialRef();
-
     void                        SetInfoAfterCreation(OGRwkbGeometryType eGType,
                                              OGRSpatialReference* poSRSIn,
                                              int nUpdateSeqIn,
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
index 9f1ed66..a7ae260 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrcouchdbdatasource.cpp 25698 2013-03-02 18:53:07Z rouault $
+ * $Id: ogrcouchdbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_couchdb.h"
 #include "swq.h"
 
-CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 25698 2013-03-02 18:53:07Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRCouchDBDataSource()                        */
@@ -543,7 +543,10 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                                           const char *pszDialect )
 
 {
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand,
                                           poSpatialFilter,
                                           pszDialect );
@@ -948,7 +951,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
                 const swq_operation *op = swq_op_registrar::GetOperator(
                     (swq_op) psColDef->col_func );
                 oFDefn.SetName( CPLSPrintf( "%s_%s",
-                                            op->osName.c_str(),
+                                            op->pszName,
                                             psColDef->field_name ) );
             }
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
index 686e0ef..8951c1e 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrcouchdbdriver.cpp 22229 2011-04-25 17:44:28Z rouault $
+ * $Id: ogrcouchdbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 
 // g++ -g -Wall -fPIC -shared -o ogr_CouchDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/couchdb ogr/ogrsf_frmts/couchdb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/jsonc
 
-CPL_CVSID("$Id: ogrcouchdbdriver.cpp 22229 2011-04-25 17:44:28Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRCouchDB();
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
index 1e69f00..a1156e5 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrcouchdblayer.cpp 22283 2011-05-01 22:14:25Z rouault $
+ * $Id: ogrcouchdblayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,11 +28,10 @@
  ****************************************************************************/
 
 #include "ogr_couchdb.h"
-#include "json_object_private.h" // json_object_iter, complete type required
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 
-CPL_CVSID("$Id: ogrcouchdblayer.cpp 22283 2011-05-01 22:14:25Z rouault $");
+CPL_CVSID("$Id: ogrcouchdblayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRCouchDBLayer()                             */
@@ -181,17 +180,6 @@ int OGRCouchDBLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                          GetSpatialRef()                             */
-/************************************************************************/
-
-OGRSpatialReference* OGRCouchDBLayer::GetSpatialRef()
-{
-    GetLayerDefn();
-
-    return poSRS;
-}
-
-/************************************************************************/
 /*                         TranslateFeature()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
index daa5a7b..c9a5a32 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrcouchdbrowslayer.cpp 22252 2011-04-28 20:59:51Z rouault $
+ * $Id: ogrcouchdbrowslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBRowsLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_couchdb.h"
 
-CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 22252 2011-04-28 20:59:51Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRCouchDBRowsLayer()                        */
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
index f070bda..c586430 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrcouchdbtablelayer.cpp 23437 2011-11-28 23:03:56Z rouault $
+ * $Id: ogrcouchdbtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBTableLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,12 +30,11 @@
 #include "ogr_couchdb.h"
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonwriter.h"
-#include "json_object_private.h" // json_object_iter, complete type required
 #include "swq.h"
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 23437 2011-11-28 23:03:56Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       OGRCouchDBTableLayer()                         */
@@ -1736,17 +1735,6 @@ void OGRCouchDBTableLayer::SetInfoAfterCreation(OGRwkbGeometryType eGType,
 }
 
 /************************************************************************/
-/*                          GetSpatialRef()                             */
-/************************************************************************/
-
-OGRSpatialReference* OGRCouchDBTableLayer::GetSpatialRef()
-{
-    LoadMetadata();
-
-    return poSRS;
-}
-
-/************************************************************************/
 /*                     OGRCouchDBIsNumericObject()                      */
 /************************************************************************/
 
@@ -1888,6 +1876,8 @@ void OGRCouchDBTableLayer::LoadMetadata()
         poFeatureDefn->Reference();
 
         poFeatureDefn->SetGeomType(eGeomType);
+        if( poFeatureDefn->GetGeomFieldCount() != 0 ) 
+            poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
         OGRFieldDefn oFieldId("_id", OFTString);
         poFeatureDefn->AddFieldDefn(&oFieldId);
diff --git a/ogr/ogrsf_frmts/csv/ogr_csv.h b/ogr/ogrsf_frmts/csv/ogr_csv.h
index 8637e5e..d307fd6 100644
--- a/ogr/ogrsf_frmts/csv/ogr_csv.h
+++ b/ogr/ogrsf_frmts/csv/ogr_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csv.h 25806 2013-03-26 18:30:18Z warmerdam $
+ * $Id: ogr_csv.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Definition of classes for OGR .csv driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004,  Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -72,8 +73,9 @@ class OGRCSVLayer : public OGRLayer
     int                 bWriteBOM;
     char                chDelimiter;
 
-    int                 iWktGeomReadField;
+    int*                panGeomFieldIndex;
     int                 bFirstFeatureAppendedDuringSession;
+    int                 bHiddenWKTColumn;
 
     /*http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm specific */
     int                 iNfdcLatitudeS, iNfdcLongitudeS;
@@ -103,11 +105,14 @@ class OGRCSVLayer : public OGRLayer
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE );
 
     virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 
     void                SetCRLF(int);
-    void                SetWriteGeometry(OGRCSVGeometryFormat eGeometryFormat);
+    void                SetWriteGeometry(OGRwkbGeometryType eGType,
+                                         OGRCSVGeometryFormat eGeometryFormat);
     void                SetCreateCSVT(int bCreateCSVT);
     void                SetWriteBOM(int bWriteBOM);
 
@@ -130,6 +135,8 @@ class OGRCSVDataSource : public OGRDataSource
     int                 bUpdate;
 
     CPLString           osDefaultCSVName;
+    
+    int                 bEnableGeometryFields;
 
   public:
                         OGRCSVDataSource();
@@ -158,6 +165,8 @@ class OGRCSVDataSource : public OGRDataSource
     void                SetDefaultCSVName( const char *pszName ) 
         { osDefaultCSVName = pszName; }
 
+    void                EnableGeometryFields() { bEnableGeometryFields = TRUE; }
+
     static CPLString    GetRealExtension(CPLString osFilename);
 };
 
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
index a10c8c0..7b1b99d 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdatasource.cpp 25354 2012-12-27 10:26:34Z rouault $
+ * $Id: ogrcsvdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDataSource class
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_csv.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: ogrcsvdatasource.cpp 25354 2012-12-27 10:26:34Z rouault $");
+CPL_CVSID("$Id: ogrcsvdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRCSVDataSource()                          */
@@ -48,6 +49,7 @@ OGRCSVDataSource::OGRCSVDataSource()
     pszName = NULL;
 
     bUpdate = FALSE;
+    bEnableGeometryFields = FALSE;
 }
 
 /************************************************************************/
@@ -75,6 +77,8 @@ int OGRCSVDataSource::TestCapability( const char * pszCap )
         return bUpdate;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return bUpdate;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return bUpdate && bEnableGeometryFields;
     else
         return FALSE;
 }
@@ -592,11 +596,15 @@ OGRCSVDataSource::CreateLayer( const char *pszLayerName,
 /*      Should we write the geometry ?                                  */
 /* -------------------------------------------------------------------- */
     const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
-    if (pszGeometry != NULL)
+    if( bEnableGeometryFields )
+    {
+        papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT);
+    }
+    else if (pszGeometry != NULL)
     {
         if (EQUAL(pszGeometry, "AS_WKT"))
         {
-            papoLayers[nLayers-1]->SetWriteGeometry(OGR_CSV_GEOM_AS_WKT);
+            papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT);
         }
         else if (EQUAL(pszGeometry, "AS_XYZ") ||
                  EQUAL(pszGeometry, "AS_XY") ||
@@ -604,7 +612,8 @@ OGRCSVDataSource::CreateLayer( const char *pszLayerName,
         {
             if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint)
             {
-                papoLayers[nLayers-1]->SetWriteGeometry(EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
+                papoLayers[nLayers-1]->SetWriteGeometry(eGType,
+                                                        EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
                                                         EQUAL(pszGeometry, "AS_XY") ?  OGR_CSV_GEOM_AS_XY :
                                                                                        OGR_CSV_GEOM_AS_YX);
             }
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
index 5c15e29..ed47887 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdriver.cpp 23830 2012-01-30 23:07:44Z rouault $
+ * $Id: ogrcsvdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDriver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_csv.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrcsvdriver.cpp 23830 2012-01-30 23:07:44Z rouault $");
+CPL_CVSID("$Id: ogrcsvdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRCSVDriver()                            */
@@ -141,6 +142,10 @@ OGRDataSource *OGRCSVDriver::CreateDataSource( const char * pszName,
 
     if( osDirName != pszName )
         poDS->SetDefaultCSVName( CPLGetFilename(pszName) );
+    
+    const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
+    if (pszGeometry != NULL && EQUAL(pszGeometry, "AS_WKT"))
+        poDS->EnableGeometryFields();
 
     return poDS;
 }
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
index c53c87e..66ce065 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 26200 2013-07-24 10:05:16Z rouault $
+ * $Id: ogrcsvlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcsvlayer.cpp 26200 2013-07-24 10:05:16Z rouault $");
+CPL_CVSID("$Id: ogrcsvlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 
@@ -165,8 +166,7 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter, int bDontHonourStr
     {
         for( ; pszWorkLine[i] != '\0'; i++ )
         {
-            if( pszWorkLine[i] == '\"'
-                && (i == 0 || pszWorkLine[i-1] != '\\') )
+            if( pszWorkLine[i] == '\"' )
                 nCount++;
         }
 
@@ -213,7 +213,7 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
 {
     fpCSV = fp;
 
-    iWktGeomReadField = -1;
+    panGeomFieldIndex = NULL;
     iNfdcLatitudeS = iNfdcLongitudeS = -1;
     iLatitudeField = iLongitudeField = -1;
     this->bInWriteMode = bInWriteMode;
@@ -222,6 +222,7 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
     this->chDelimiter = chDelimiter;
 
     bFirstFeatureAppendedDuringSession = TRUE;
+    bHiddenWKTColumn = FALSE;
     bUseCRLF = FALSE;
     bNeedRewindBeforeRead = FALSE;
     eGeometryFormat = OGR_CSV_GEOM_NONE;
@@ -405,6 +406,11 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
         }
     }
     
+    panGeomFieldIndex = (int*) CPLCalloc(nFieldCount, sizeof(int));
+    for( iField = 0; iField < nFieldCount; iField++ )
+    {
+        panGeomFieldIndex[iField] = -1;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Build field definitions.                                        */
@@ -484,12 +490,43 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
                 CPLError(CE_Warning, CPLE_NotSupported, "Unknown type : %s", papszFieldTypes[iField]);
         }
 
-        if( EQUAL(oField.GetNameRef(),"WKT")
-            && oField.GetType() == OFTString 
-            && iWktGeomReadField == -1 )
+        if( (EQUAL(oField.GetNameRef(),"WKT") ||
+             EQUALN(oField.GetNameRef(),"_WKT", 4) )
+            && oField.GetType() == OFTString )
         {
-            iWktGeomReadField = iField;
-            poFeatureDefn->SetGeomType( wkbUnknown );
+            eGeometryFormat = OGR_CSV_GEOM_AS_WKT;
+
+            const char* pszFieldName = oField.GetNameRef();
+            panGeomFieldIndex[iField] = poFeatureDefn->GetGeomFieldCount();
+            OGRGeomFieldDefn oGeomFieldDefn(
+                EQUAL(pszFieldName,"WKT") ? "" : CPLSPrintf("geom_%s", pszFieldName),
+                wkbUnknown );
+
+            /* Usefull hack for RFC 41 testing */
+            const char* pszEPSG = strstr(pszFieldName, "_EPSG_");
+            if( pszEPSG != NULL )
+            {
+                int nEPSGCode = atoi(pszEPSG + strlen("_EPSG_"));
+                OGRSpatialReference* poSRS = new OGRSpatialReference();
+                poSRS->importFromEPSG(nEPSGCode);
+                oGeomFieldDefn.SetSpatialRef(poSRS);
+                poSRS->Release();
+            }
+
+            if( strstr(pszFieldName, "_POINT") )
+                oGeomFieldDefn.SetType(wkbPoint);
+            else if( strstr(pszFieldName, "_LINESTRING") )
+                oGeomFieldDefn.SetType(wkbLineString);
+            else if( strstr(pszFieldName, "_POLYGON") )
+                oGeomFieldDefn.SetType(wkbPolygon);
+            else if( strstr(pszFieldName, "_MULTIPOINT") )
+                oGeomFieldDefn.SetType(wkbMultiPoint);
+            else if( strstr(pszFieldName, "_MULTILINESTRING") )
+                oGeomFieldDefn.SetType(wkbMultiLineString);
+            else if( strstr(pszFieldName, "_MULTIPOLYGON") )
+                oGeomFieldDefn.SetType(wkbMultiPolygon);
+
+            poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
         }
 
         /*http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm specific */
@@ -596,6 +633,8 @@ OGRCSVLayer::~OGRCSVLayer()
     if (bNew && bInWriteMode)
         WriteHeader();
 
+    CPLFree( panGeomFieldIndex );
+
     poFeatureDefn->Release();
     CPLFree(pszFilename);
 
@@ -665,16 +704,24 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
     
     for( iAttr = 0; !bIsEurostatTSV && iAttr < nAttrCount; iAttr++)
     {
-        if( iAttr == iWktGeomReadField && papszTokens[iAttr][0] != '\0' )
+        int iGeom = panGeomFieldIndex[iAttr];
+        if( iGeom >= 0 && papszTokens[iAttr][0] != '\0'&&
+            !(poFeatureDefn->GetGeomFieldDefn(iGeom)->IsIgnored()) )
         {
             char *pszWKT = papszTokens[iAttr];
             OGRGeometry *poGeom = NULL;
 
             if( OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom )
                 == OGRERR_NONE )
-                poFeature->SetGeometryDirectly( poGeom );
+            {
+                poGeom->assignSpatialReference(
+                    poFeatureDefn->GetGeomFieldDefn(iGeom)->GetSpatialRef());
+                poFeature->SetGeomFieldDirectly( iGeom, poGeom );
+            }
         }
 
+        if( poFeatureDefn->GetFieldDefn(iAttr)->IsIgnored() )
+            continue;
         OGRFieldType eFieldType = poFeatureDefn->GetFieldDefn(iAttr)->GetType();
         if ( eFieldType == OFTReal || eFieldType == OFTInteger )
         {
@@ -718,7 +765,8 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
             }
             for( int iSubAttr = 0; iSubAttr < nEurostatDims; iSubAttr ++ )
             {
-                poFeature->SetField( iSubAttr, papszDims[iSubAttr] );
+                if( !poFeatureDefn->GetFieldDefn(iSubAttr)->IsIgnored() )
+                    poFeature->SetField( iSubAttr, papszDims[iSubAttr] );
             }
             CSLDestroy(papszDims);
         }
@@ -730,11 +778,13 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                  ( eType == CPL_VALUE_INTEGER ||
                    eType == CPL_VALUE_REAL ) )
             {
-                poFeature->SetField( nEurostatDims + 2 * (iAttr - 1), papszVals[0] );
+                if( !poFeatureDefn->GetFieldDefn(nEurostatDims + 2 * (iAttr - 1))->IsIgnored() )
+                    poFeature->SetField( nEurostatDims + 2 * (iAttr - 1), papszVals[0] );
             }
             if( CSLCount(papszVals) == 2 )
             {
-                poFeature->SetField( nEurostatDims + 2 * (iAttr - 1) + 1, papszVals[1] );
+                if( !poFeatureDefn->GetFieldDefn(nEurostatDims + 2 * (iAttr - 1) + 1)->IsIgnored() )
+                    poFeature->SetField( nEurostatDims + 2 * (iAttr - 1) + 1, papszVals[1] );
             }
             CSLDestroy(papszVals);
         }
@@ -757,7 +807,8 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
         double dfLat = atof(papszTokens[iNfdcLatitudeS]) / 3600;
         if (strchr(papszTokens[iNfdcLatitudeS], 'S'))
             dfLat *= -1;
-        poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
+        if( !(poFeatureDefn->GetGeomFieldDefn(0)->IsIgnored()) )
+            poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -778,7 +829,8 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
         {
             double dfLon = atof(papszTokens[iLongitudeField]);
             double dfLat = atof(papszTokens[iLatitudeField]);
-            poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
+            if( !(poFeatureDefn->GetGeomFieldDefn(0)->IsIgnored()) )
+                poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
         }
     }
 
@@ -818,7 +870,7 @@ OGRFeature *OGRCSVLayer::GetNextFeature()
             break;
 
         if( (m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
             break;
@@ -840,6 +892,10 @@ int OGRCSVLayer::TestCapability( const char * pszCap )
         return bInWriteMode;
     else if( EQUAL(pszCap,OLCCreateField) )
         return bNew && !bHasFieldNames;
+    else if( EQUAL(pszCap,OLCCreateGeomField) )
+        return bNew && !bHasFieldNames && eGeometryFormat == OGR_CSV_GEOM_AS_WKT;
+    else if( EQUAL(pszCap,OLCIgnoreFields) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -855,7 +911,7 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
 /*      If we have already written our field names, then we are not     */
 /*      allowed to add new fields.                                      */
 /* -------------------------------------------------------------------- */
-    if( bHasFieldNames || !bNew )
+    if( !TestCapability(OLCCreateField) )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Unable to create new fields after first feature written.");
@@ -867,6 +923,11 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
 /* -------------------------------------------------------------------- */
     if( poFeatureDefn->GetFieldIndex( poNewField->GetNameRef() ) != -1 )
     {
+        if( poFeatureDefn->GetGeomFieldIndex( poNewField->GetNameRef() ) != -1 )
+            return OGRERR_NONE;
+        if( poFeatureDefn->GetGeomFieldIndex( CPLSPrintf("geom_%s", poNewField->GetNameRef()) ) != -1 )
+            return OGRERR_NONE;
+
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create field %s, but a field with this name already exists.",
                   poNewField->GetNameRef() );
@@ -909,9 +970,48 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
 /* -------------------------------------------------------------------- */
     poFeatureDefn->AddFieldDefn( poNewField );
 
+    panGeomFieldIndex = (int*) CPLRealloc(panGeomFieldIndex,
+                                sizeof(int) * poFeatureDefn->GetFieldCount());
+    panGeomFieldIndex[poFeatureDefn->GetFieldCount() - 1] = -1;
+
     return OGRERR_NONE;
 }
 
+
+/************************************************************************/
+/*                          CreateGeomField()                           */
+/************************************************************************/
+
+OGRErr OGRCSVLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                     int bApproxOK )
+
+{
+    if( !TestCapability(OLCCreateGeomField) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create new fields after first feature written.");
+        return OGRERR_FAILURE;
+    }
+
+    poFeatureDefn->AddGeomFieldDefn( poGeomField );
+
+    const char* pszName = poGeomField->GetNameRef();
+    if( EQUALN(pszName, "geom_", strlen("geom_")) )
+        pszName += strlen("geom_");
+    if( !EQUAL(pszName, "WKT") && !EQUALN(pszName, "_WKT", 4) )
+        pszName = CPLSPrintf("_WKT%s", pszName);
+
+    OGRFieldDefn oRegularFieldDefn( pszName, OFTString );
+    poFeatureDefn->AddFieldDefn( &oRegularFieldDefn );
+
+    panGeomFieldIndex = (int*) CPLRealloc(panGeomFieldIndex,
+                                sizeof(int) * poFeatureDefn->GetFieldCount());
+    panGeomFieldIndex[poFeatureDefn->GetFieldCount() - 1] =
+        poFeatureDefn->GetGeomFieldCount() - 1;
+
+    return OGRERR_FAILURE;
+}
+
 /************************************************************************/
 /*                            WriteHeader()                             */
 /*                                                                      */
@@ -964,17 +1064,7 @@ OGRErr OGRCSVLayer::WriteHeader()
             VSIFWriteL("\xEF\xBB\xBF", 1, 3, fpCSV);
         }
 
-        if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
-        {
-            if (fpCSV) VSIFPrintfL( fpCSV, "%s", "WKT");
-            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "String");
-            if (poFeatureDefn->GetFieldCount() > 0)
-            {
-                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
-                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
-            }
-        }
-        else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
+        if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
         {
             if (fpCSV) VSIFPrintfL( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter);
             if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real,Real");
@@ -1005,11 +1095,17 @@ OGRErr OGRCSVLayer::WriteHeader()
             }
         }
 
+        if( bHiddenWKTColumn )
+        {
+            if (fpCSV) VSIFPrintfL( fpCSV, "%s", "WKT" );
+            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "String");
+        }
+
         for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
         {
             char *pszEscaped;
 
-            if( iField > 0 )
+            if( iField > 0 || bHiddenWKTColumn )
             {
                 if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                 if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
@@ -1048,7 +1144,8 @@ OGRErr OGRCSVLayer::WriteHeader()
 
         /* The CSV driver will not recognize single column tables, so add */
         /* a fake second blank field */
-        if( poFeatureDefn->GetFieldCount() == 1 )
+        if( poFeatureDefn->GetFieldCount() == 1 ||
+            (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn) )
         {
             if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
         }
@@ -1137,23 +1234,7 @@ OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )
 /* -------------------------------------------------------------------- */
 /*      Write out the geometry                                          */
 /* -------------------------------------------------------------------- */
-    if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
-    {
-        OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
-        char* pszWKT = NULL;
-        if (poGeom && poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
-        {
-            VSIFPrintfL( fpCSV, "\"%s\"", pszWKT);
-        }
-        else
-        {
-            VSIFPrintfL( fpCSV, "\"\"");
-        }
-        CPLFree(pszWKT);
-        if (poFeatureDefn->GetFieldCount() > 0)
-            VSIFPrintfL( fpCSV, "%c", chDelimiter);
-    }
-    else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ ||
+    if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ ||
              eGeometryFormat == OGR_CSV_GEOM_AS_XY ||
              eGeometryFormat == OGR_CSV_GEOM_AS_YX)
     {
@@ -1188,17 +1269,55 @@ OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Write out all the field values.                                 */
+/*      Special case to deal with hidden "WKT" geometry column          */
 /* -------------------------------------------------------------------- */
     int bNonEmptyLine = FALSE;
+
+    if( bHiddenWKTColumn )
+    {
+        char *pszEscaped;
+        OGRGeometry     *poGeom = poNewFeature->GetGeomFieldRef(0);
+        if (poGeom && poGeom->exportToWkt(&pszEscaped) == OGRERR_NONE)
+        {
+            char* pszNew = CPLStrdup(CPLSPrintf("\"%s\"", pszEscaped));
+            CPLFree(pszEscaped);
+            pszEscaped = pszNew;
+        }
+        else
+            pszEscaped = CPLStrdup("");
+
+        int nLen = (int)strlen(pszEscaped);
+        bNonEmptyLine |= (nLen != 0);
+        VSIFWriteL( pszEscaped, 1, nLen, fpCSV );
+        CPLFree( pszEscaped );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write out all the field values.                                 */
+/* -------------------------------------------------------------------- */
+
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         char *pszEscaped;
         
-        if( iField > 0 )
+        if( iField > 0 || bHiddenWKTColumn )
             VSIFPrintfL( fpCSV, "%c", chDelimiter );
-        
-        if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
+
+        if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT &&
+            panGeomFieldIndex[iField] >= 0 )
+        {
+            int iGeom = panGeomFieldIndex[iField];
+            OGRGeometry     *poGeom = poNewFeature->GetGeomFieldRef(iGeom);
+            if (poGeom && poGeom->exportToWkt(&pszEscaped) == OGRERR_NONE)
+            {
+                char* pszNew = CPLStrdup(CPLSPrintf("\"%s\"", pszEscaped));
+                CPLFree(pszEscaped);
+                pszEscaped = pszNew;
+            }
+            else
+                pszEscaped = CPLStrdup("");
+        }
+        else if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
         {
             pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
             /* Use point as decimal separator */
@@ -1219,7 +1338,8 @@ OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )
         CPLFree( pszEscaped );
     }
 
-    if(  poFeatureDefn->GetFieldCount() == 1 && !bNonEmptyLine )
+    if( (poFeatureDefn->GetFieldCount() == 1 ||
+         (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn)) && !bNonEmptyLine )
         VSIFPrintfL( fpCSV, "%c", chDelimiter );
 
     if( bUseCRLF )
@@ -1243,9 +1363,22 @@ void OGRCSVLayer::SetCRLF( int bNewValue )
 /*                       SetWriteGeometry()                             */
 /************************************************************************/
 
-void OGRCSVLayer::SetWriteGeometry(OGRCSVGeometryFormat eGeometryFormat)
+void OGRCSVLayer::SetWriteGeometry(OGRwkbGeometryType eGType,
+                                   OGRCSVGeometryFormat eGeometryFormat)
 {
     this->eGeometryFormat = eGeometryFormat;
+    if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT && eGType != wkbNone )
+    {
+        OGRGeomFieldDefn oGFld("WKT", eGType);
+        bHiddenWKTColumn = TRUE;
+        /* We don't use CreateGeomField() since we don't want to generate */
+        /* a geometry field in first position, as it confuses applications */
+        /* (such as MapServer <= 6.4) that assume that the first regular field */
+        /* they add will be at index 0 */
+        poFeatureDefn->AddGeomFieldDefn( &oGFld );
+    }
+    else
+        poFeatureDefn->SetGeomType( eGType );
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
index 249ade0..2ac49da 100644
--- a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnwrite.cpp 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: dgnwrite.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access functions related to writing DGN elements.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnwrite.cpp 25340 2012-12-21 20:30:21Z rouault $");
+CPL_CVSID("$Id: dgnwrite.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint, 
                            unsigned char *pabyTarget );
@@ -1073,7 +1074,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
     }
     else
     {
-        memcpy( psArc->quat, panQuaternion, sizeof(long)*4 );
+        memcpy( psArc->quat, panQuaternion, sizeof(int)*4 );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1294,7 +1295,7 @@ DGNCreateConeElem( DGNHandle hDGN,
     memset( psCone->quat, 0, sizeof(int) * 4 );
     if( panQuaternion != NULL )
     {
-        memcpy( psCone->quat, panQuaternion, sizeof(long)*4 );
+        memcpy( psCone->quat, panQuaternion, sizeof(int)*4 );
     }
     else {
       psCone->quat[0] = 1 << 31;
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
index 02e16d7..eec9496 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdgnlayer.cpp 24142 2012-03-19 20:27:18Z warmerdam $
+ * $Id: ogrdgnlayer.cpp 26929 2014-02-11 20:45:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRDGNLayer class.
@@ -31,8 +31,9 @@
 #include "cpl_conv.h"
 #include "ogr_featurestyle.h"
 #include "ogr_api.h"
+#include <list>
 
-CPL_CVSID("$Id: ogrdgnlayer.cpp 24142 2012-03-19 20:27:18Z warmerdam $");
+CPL_CVSID("$Id: ogrdgnlayer.cpp 26929 2014-02-11 20:45:17Z rouault $");
 
 /************************************************************************/
 /*                           OGRDGNLayer()                              */
@@ -1055,9 +1056,52 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     {
         OGRPolygon *poPoly = ((OGRPolygon *) poGeom);
 
-        // Ignore all but the exterior ring. 
-        papsGroup = LineStringToElementGroup( poPoly->getExteriorRing(),
-                                              DGNT_SHAPE );
+        DGNElemCore **papsGroupExt = LineStringToElementGroup(
+                poPoly->getExteriorRing(), DGNT_SHAPE);
+
+        int innerRingsCnt = poPoly->getNumInteriorRings();
+
+        if (innerRingsCnt > 0) {
+            CPLDebug("InnerRings", "there are %d inner rings", innerRingsCnt);
+            std::list<DGNElemCore*> dgnElements;
+
+            for (i = 0; papsGroupExt[i] != NULL; i++) {
+                dgnElements.push_back(papsGroupExt[i]);
+            }
+            CPLFree(papsGroupExt);
+
+            // get all interior rings and create complex group shape
+            for (int iRing = 0; iRing < innerRingsCnt; iRing++) {
+                DGNElemCore **papsGroupInner = LineStringToElementGroup(
+                        poPoly->getInteriorRing(iRing), DGNT_SHAPE);
+                papsGroupInner[0]->properties |= DGNPF_HOLE;
+                DGNUpdateElemCoreExtended(hDGN, papsGroupInner[0]);
+                for (i = 0; papsGroupInner[i] != NULL; i++) {
+                    dgnElements.push_back(papsGroupInner[i]);
+                }
+                CPLFree(papsGroupInner);
+            }
+            int index = 1;
+            papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),
+                    dgnElements.size() + 2);
+            for (std::list<DGNElemCore*>::iterator list_iter =
+                    dgnElements.begin(); list_iter != dgnElements.end();
+                    list_iter++) {
+                papsGroup[index++] = *list_iter;
+            }
+
+            //papsGroup[0] = DGNCreateComplexHeaderFromGroup( hDGN, DGNT_COMPLEX_SHAPE_HEADER, dgnElements.size(), papsGroup+1);
+            DGNPoint asPoints[1];
+            asPoints[0].x = 0;
+            asPoints[0].y = 0;
+            asPoints[0].z = 0;
+            papsGroup[0] = DGNCreateCellHeaderFromGroup(hDGN, "", 1, NULL,
+                    dgnElements.size(), papsGroup + 1, asPoints + 0, 1.0, 1.0,
+                    0.0);
+            DGNAddShapeFillInfo(hDGN, papsGroup[0], 6);
+        } else {
+            papsGroup = papsGroupExt;
+        }
     }
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon 
              || wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint
@@ -1093,15 +1137,17 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     int nColor = poFeature->GetFieldAsInteger( "ColorIndex" );
     int nWeight = poFeature->GetFieldAsInteger( "Weight" );
     int nStyle = poFeature->GetFieldAsInteger( "Style" );
+    int nMSLink = poFeature->GetFieldAsInteger( "MSLink" );
 
     nLevel = MAX(0,MIN(63,nLevel));
     nColor = MAX(0,MIN(255,nColor));
     nWeight = MAX(0,MIN(31,nWeight));
     nStyle = MAX(0,MIN(7,nStyle));
+    nMSLink = MAX(0,MIN(4294967295,nMSLink));
 
     DGNUpdateElemCore( hDGN, papsGroup[0], nLevel, nGraphicGroup, nColor, 
                        nWeight, nStyle );
-    
+    DGNAddMSLink( hDGN, papsGroup[0], DGNLT_ODBC, 0, nMSLink );
 /* -------------------------------------------------------------------- */
 /*      Write to file.                                                  */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
index c555ff7..1ab4590 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodsdatasource.cpp 20634 2010-09-16 22:02:29Z rouault $
+ * $Id: ogrdodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodsdatasource.cpp 20634 2010-09-16 22:02:29Z rouault $");
+CPL_CVSID("$Id: ogrdodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /************************************************************************/
 /*                         OGRDODSDataSource()                          */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dwg/ogr_dwg.h b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
index a8c2713..934db88 100644
--- a/ogr/ogrsf_frmts/dwg/ogr_dwg.h
+++ b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
@@ -132,6 +132,7 @@ class OGRDWGLayer : public OGRLayer
     OGRFeature *        TranslateLINE( OdDbEntityPtr poEntity );
     OGRFeature *        TranslateLWPOLYLINE( OdDbEntityPtr poEntity );
     OGRFeature *        Translate2DPOLYLINE( OdDbEntityPtr poEntity );
+    OGRFeature *        Translate3DPOLYLINE( OdDbEntityPtr poEntity );
     OGRFeature *        TranslateELLIPSE( OdDbEntityPtr poEntity );
     OGRFeature *        TranslateARC( OdDbEntityPtr poEntity );
     OGRFeature *        TranslateMTEXT( OdDbEntityPtr poEntity );
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
index c8cbf38..5ca9853 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
+ * $Id: ogrdwg_hatch.cpp 26672 2013-11-28 13:10:36Z rouault $
  *
  * Project:  DWG Translator
  * Purpose:  Implements translation support for HATCH elements as part
@@ -41,7 +41,7 @@
 #include "Ge/GeCircArc2d.h"
 #include "Ge/GeEllipArc2d.h"
 
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdwg_hatch.cpp 26672 2013-11-28 13:10:36Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -191,20 +191,18 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
         {
             OdGeCircArc2d* poCircArc = (OdGeCircArc2d*) poEdge;
             OdGePoint2d oCenter = poCircArc->center();
-            double dfStartAngle = poCircArc->endAng() * 180 / PI;
-            double dfEndAngle = poCircArc->startAng() * 180 / PI;
+            double dfStartAngle = poCircArc->startAng() * 180 / PI;
+            double dfEndAngle = poCircArc->endAng() * 180 / PI;
             
             if( !poCircArc->isClockWise() )
             {
                 dfStartAngle *= -1;
                 dfEndAngle *= -1;
-//                double dfTemp = dfStartAngle;
-//                dfStartAngle = dfEndAngle;
-//                dfEndAngle = dfTemp;
             }
-
-            if( dfStartAngle > dfEndAngle )
+            else if( dfStartAngle > dfEndAngle )
+            {
                 dfEndAngle += 360.0;
+            }
 
             OGRLineString *poLS = (OGRLineString *) 
                 OGRGeometryFactory::approximateArcAngles( 
@@ -225,8 +223,18 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
 
             dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / PI;
 
-            dfStartAng = -1 * poArc->endAng()*180/PI;
-            dfEndAng = -1 * poArc->startAng()*180/PI;
+            dfStartAng = poArc->startAng()*180/PI;
+            dfEndAng = poArc->endAng()*180/PI;
+ 
+            if( !poArc->isClockWise() )
+            {
+                dfStartAng *= -1;
+                dfEndAng *= -1;
+            }
+            else if( dfStartAng > dfEndAng )
+            {
+                dfEndAng += 360.0;
+            }
 
             OGRLineString *poLS = (OGRLineString *) 
                 OGRGeometryFactory::approximateArcAngles( 
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
index ab179dd..c401a0f 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
@@ -53,7 +53,8 @@ OGRDWGDriver::OGRDWGDriver()
 OGRDWGDriver::~OGRDWGDriver()
 
 {
-    if( bInitialized )
+    if( bInitialized && !CSLTestBoolean(
+            CPLGetConfigOption("IN_GDAL_GLOBAL_DESTRUCTOR", "NO")) )
     {
         bInitialized = FALSE;
         odUninitialize();
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
index 452659f..110462e 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
@@ -34,6 +34,8 @@
 
 #include "DbPolyline.h"
 #include "Db2dPolyline.h"
+#include "Db3dPolyline.h"
+#include "Db3dPolylineVertex.h"
 #include "DbLine.h"
 #include "DbPoint.h"
 #include "DbEllipse.h"
@@ -756,6 +758,39 @@ OGRFeature *OGRDWGLayer::Translate2DPOLYLINE( OdDbEntityPtr poEntity )
 }
 
 /************************************************************************/
+/*                        Translate3DPOLYLINE()                         */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::Translate3DPOLYLINE( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDb3dPolylinePtr poPL = OdDb3dPolyline::cast( poEntity );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Create a polyline geometry from the vertices.                   */
+/* -------------------------------------------------------------------- */
+    OGRLineString *poLS = new OGRLineString();
+    OdDbObjectIteratorPtr poIter = poPL->vertexIterator();
+
+    while( !poIter->done() )
+    {
+        OdDb3dPolylineVertexPtr poVertex = poIter->entity();
+        OdGePoint3d oPoint = poVertex->position();
+        poLS->addPoint( oPoint.x, oPoint.y, oPoint.z );
+        poIter->step();
+    }
+
+    poFeature->SetGeometryDirectly( poLS );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
 /*                           TranslateLINE()                            */
 /************************************************************************/
 
@@ -1312,6 +1347,10 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
         {
             poFeature = Translate2DPOLYLINE( poEntity );
         }
+        else if( EQUAL(pszEntityClassName,"AcDb3dPolyline") )
+        {
+            poFeature = Translate3DPOLYLINE( poEntity );
+        }
         else if( EQUAL(pszEntityClassName,"AcDbEllipse") )
         {
             poFeature = TranslateELLIPSE( poEntity );
diff --git a/ogr/ogrsf_frmts/dxf/drv_dxf.html b/ogr/ogrsf_frmts/dxf/drv_dxf.html
index 699fba3..e234d8c 100644
--- a/ogr/ogrsf_frmts/dxf/drv_dxf.html
+++ b/ogr/ogrsf_frmts/dxf/drv_dxf.html
@@ -33,8 +33,8 @@ The following element types are supported:<p>
 <li> POINT: Produces a simple point geometry feature.
 <li> MTEXT, TEXT: Produces a point feature with LABEL style information.
 <li> LINE, POLYLINE, LWPOLYLINE: translated as a LINESTRING or POLYGON 
-depending on whether it is closed. Rounded polylines (those with their 
-vertices' budge attributes set) will be tesselated.
+depending on whether it is closed. Rounded polylines (those with their 
+vertices' budge attributes set) will be tesselated.
 Single-vertex polylines are translated to POINT.
 <li> CIRCLE, ELLIPSE, ARC:  Translated as a LINESTRING, tesselating the 
 arc into line segments. 
@@ -161,7 +161,7 @@ INSERT entities as INSERT entities rather than exploding them.<p>
 
 <h3>Layer Definitions</h3>
 
-When writing entities, if populated the LayerName field is used to set the 
+When writing entities, if populated the Layer field is used to set the 
 written entities layer.  If the layer is not already defined in the template
 header then a new layer definition will be introduced, copied from the 
 definition of the default layer ("0"). 
diff --git a/ogr/ogrsf_frmts/dxf/ogr_dxf.h b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
index 4514b7f..63350b0 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_dxf.h
+++ b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dxf.h 25811 2013-03-29 22:16:56Z rouault $
+ * $Id: ogr_dxf.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Definition of classes for OGR .dxf driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009,  Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -115,11 +116,13 @@ class OGRDXFLayer : public OGRLayer
     OGRFeature *        TranslateELLIPSE();
     OGRFeature *        TranslateARC();
     OGRFeature *        TranslateSPLINE();
+    OGRFeature *        Translate3DFACE();
     OGRFeature *        TranslateINSERT();
     OGRFeature *        TranslateMTEXT();
     OGRFeature *        TranslateTEXT();
     OGRFeature *        TranslateDIMENSION();
     OGRFeature *        TranslateHATCH();
+    OGRFeature *        TranslateSOLID();
 
     void                FormatDimension( CPLString &osText, double dfValue );
     OGRErr              CollectBoundaryPath( OGRGeometryCollection * );
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
index 626a312..87d9e49 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
+ * $Id: ogrdxf_dimension.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for DIMENSION elements as a part
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdxf_dimension.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
index f55943d..17c4081 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
+ * $Id: ogrdxf_hatch.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for HATCH elements as part
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 
 #include "ogrdxf_polyline_smooth.h"
 
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdxf_hatch.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -102,6 +103,14 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
     OGRGeometry* poFinalGeom = (OGRGeometry *)
         OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
                                   TRUE, TRUE, 0.0000001, &eErr );
+    if( eErr != OGRERR_NONE )
+    {
+        delete poFinalGeom;
+        OGRMultiLineString* poMLS = new OGRMultiLineString();
+        for(int i=0;i<oGC.getNumGeometries();i++)
+            poMLS->addGeometry(oGC.getGeometryRef(i));
+        poFinalGeom = poMLS;
+    }
 
     ApplyOCSTransformer( poFinalGeom );
     poFeature->SetGeometryDirectly( poFinalGeom );
@@ -215,22 +224,22 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             double dfEndY;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
-                dfStartX = atof(szLineBuf);
+                dfStartX = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
-                dfStartY = atof(szLineBuf);
+                dfStartY = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 11 )
-                dfEndX = atof(szLineBuf);
+                dfEndX = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 21 )
-                dfEndY = atof(szLineBuf);
+                dfEndY = CPLAtof(szLineBuf);
             else
                 break;
 
@@ -254,27 +263,27 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             int    bCounterClockwise = FALSE;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
-                dfCenterX = atof(szLineBuf);
+                dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
-                dfCenterY = atof(szLineBuf);
+                dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 40 )
-                dfRadius = atof(szLineBuf);
+                dfRadius = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 50 )
-                dfStartAngle = -1 * atof(szLineBuf);
+                dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 51 )
-                dfEndAngle = -1 * atof(szLineBuf);
+                dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
 
@@ -283,16 +292,14 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             else if (nCode >= 0)
                 poDS->UnreadValue();
 
+            if( dfStartAngle > dfEndAngle )
+                dfEndAngle += 360.0;
             if( bCounterClockwise )
             {
-                double dfTemp = dfStartAngle;
-                dfStartAngle = dfEndAngle;
-                dfEndAngle = dfTemp;
+                dfStartAngle *= -1; 
+                dfEndAngle *= -1; 
             }
 
-            if( dfStartAngle > dfEndAngle )
-                dfEndAngle += 360.0;
-
             OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles( 
                 dfCenterX, dfCenterY, 0.0,
                 dfRadius, dfRadius, 0.0,
@@ -319,37 +326,37 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             int    bCounterClockwise = FALSE;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
-                dfCenterX = atof(szLineBuf);
+                dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
-                dfCenterY = atof(szLineBuf);
+                dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 11 )
-                dfMajorX = atof(szLineBuf);
+                dfMajorX = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 21 )
-                dfMajorY = atof(szLineBuf);
+                dfMajorY = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 40 )
-                dfRatio = atof(szLineBuf) / 100.0;
+                dfRatio = CPLAtof(szLineBuf) / 100.0;
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 50 )
-                dfStartAngle = -1 * atof(szLineBuf);
+                dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
             if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 51 )
-                dfEndAngle = -1 * atof(szLineBuf);
+                dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
 
@@ -358,16 +365,14 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             else if (nCode >= 0)
                 poDS->UnreadValue();
 
+            if( dfStartAngle > dfEndAngle )
+                dfEndAngle += 360.0;
             if( bCounterClockwise )
             {
-                double dfTemp = dfStartAngle;
-                dfStartAngle = dfEndAngle;
-                dfEndAngle = dfTemp;
+                dfStartAngle *= -1; 
+                dfEndAngle *= -1; 
             }
 
-            if( dfStartAngle > dfEndAngle )
-                dfEndAngle += 360.0;
-
             dfMajorRadius = sqrt( dfMajorX * dfMajorX + dfMajorY * dfMajorY );
             dfMinorRadius = dfMajorRadius * dfRatio;
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
index 74a054b..f950d3b 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
@@ -262,6 +262,8 @@ void DXFSmoothPolyline::EmitArc
     if(!bClockwise && (ogrArcStartAngle < ogrArcEndAngle))
         ogrArcEndAngle = -180.0 + (linedir * a);
 
+    if(bClockwise && (ogrArcStartAngle > ogrArcEndAngle)) 
+        ogrArcEndAngle += 360.0; 
 
 /* -------------------------------------------------------------------- */
 /*      Flip arc's rotation if necessary.                               */
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
index 36f65c0..d433800 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfdatasource.cpp 25811 2013-03-29 22:16:56Z rouault $
+ * $Id: ogrdxfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDataSource class
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfdatasource.cpp 25811 2013-03-29 22:16:56Z rouault $");
+CPL_CVSID("$Id: ogrdxfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRDXFDataSource()                          */
@@ -134,17 +135,27 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
         return FALSE;
 
     if( ReadValue( szLineBuf ) != 2 
-        || (!EQUAL(szLineBuf,"HEADER") && !EQUAL(szLineBuf,"ENTITIES")) )
+        || (!EQUAL(szLineBuf,"HEADER") && !EQUAL(szLineBuf,"ENTITIES") && !EQUAL(szLineBuf,"TABLES")) )
         return FALSE;
 
     if( EQUAL(szLineBuf,"ENTITIES") )
         bEntitiesOnly = TRUE;
 
+    /* Some files might have no header but begin directly with a TABLES section */
+    else if( EQUAL(szLineBuf,"TABLES") )
+    {
+        if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
+            osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
+
+        ReadTablesSection();
+        ReadValue(szLineBuf);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Process the header, picking up a few useful pieces of           */
 /*      information.                                                    */
 /* -------------------------------------------------------------------- */
-    if( !bEntitiesOnly )
+    else /* if( EQUAL(szLineBuf,"HEADER") ) */
     {
         ReadHeaderSection();
         ReadValue(szLineBuf);
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
index 549c640..51b3f53 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxflayer.cpp 25030 2012-10-02 22:08:36Z rouault $
+ * $Id: ogrdxflayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +31,9 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 #include "ogrdxf_polyline_smooth.h"
+#include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 25030 2012-10-02 22:08:36Z rouault $");
+CPL_CVSID("$Id: ogrdxflayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -1454,6 +1456,267 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
 }
 
 /************************************************************************/
+/*                          Translate3DFACE()                           */
+/************************************************************************/
+
+OGRFeature *OGRDXFLayer::Translate3DFACE()
+
+{
+    char szLineBuf[257];
+    int nCode;
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0;
+    double dfX2 = 0.0, dfY2 = 0.0, dfZ2 = 0.0;
+    double dfX3 = 0.0, dfY3 = 0.0, dfZ3 = 0.0;
+    double dfX4 = 0.0, dfY4 = 0.0, dfZ4 = 0.0;
+
+/* -------------------------------------------------------------------- */
+/*      Process values.                                                 */
+/* -------------------------------------------------------------------- */
+    while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
+    {
+        switch( nCode )
+        {
+          case 10:
+            dfX1 = CPLAtof(szLineBuf);
+            break;
+
+          case 11:
+            dfX2 = CPLAtof(szLineBuf);
+            break;
+
+          case 12:
+            dfX3 = CPLAtof(szLineBuf);
+            break;
+
+          case 13:
+            dfX4 = CPLAtof(szLineBuf);
+            break;
+
+          case 20:
+            dfY1 = CPLAtof(szLineBuf);
+            break;
+
+          case 21:
+            dfY2 = CPLAtof(szLineBuf);
+            break;
+
+          case 22:
+            dfY3 = CPLAtof(szLineBuf);
+            break;
+
+          case 23:
+            dfY4 = CPLAtof(szLineBuf);
+            break;
+
+          case 30:
+            dfZ1 = CPLAtof(szLineBuf);
+            break;
+
+          case 31:
+            dfZ2 = CPLAtof(szLineBuf);
+            break;
+
+          case 32:
+            dfZ3 = CPLAtof(szLineBuf);
+            break;
+
+          case 33:
+            dfZ4 = CPLAtof(szLineBuf);
+            break;
+
+          default:
+            TranslateGenericProperty( poFeature, nCode, szLineBuf );
+            break;
+        }
+    }
+
+    if( nCode == 0 )
+        poDS->UnreadValue();
+
+/* -------------------------------------------------------------------- */
+/*      Create geometry                                                 */
+/* -------------------------------------------------------------------- */
+    OGRPolygon *poPoly = new OGRPolygon();
+    OGRLinearRing* poLR = new OGRLinearRing();
+    poLR->addPoint( dfX1, dfY1, dfZ1 );
+    poLR->addPoint( dfX2, dfY2, dfZ2 );
+    poLR->addPoint( dfX3, dfY3, dfZ3 );
+    if( dfX4 != dfX3 || dfY4 != dfY3 || dfZ4 != dfZ3 )
+        poLR->addPoint( dfX4, dfY4, dfZ4 );
+    poPoly->addRingDirectly(poLR);
+    poPoly->closeRings();
+
+    ApplyOCSTransformer( poLR );
+    poFeature->SetGeometryDirectly( poPoly );
+
+    /* PrepareLineStyle( poFeature ); */
+
+    return poFeature;
+}
+
+/* -------------------------------------------------------------------- */
+/*      Distance                                                        */
+/*                                                                      */
+/*      Calculate distance between two points                           */
+/* -------------------------------------------------------------------- */
+
+static double Distance(double dX0, double dY0, double dX1, double dY1) {
+    return sqrt((dX1 - dX0) * (dX1 - dX0) + (dY1 - dY0) * (dY1 - dY0));
+}
+
+/* -------------------------------------------------------------------- */
+/*      AddEdgesByNearest                                               */
+/*                                                                      */
+/*      Order and add SOLID edges to geometry collection                */
+/* -------------------------------------------------------------------- */
+
+static void AddEdgesByNearest(OGRGeometryCollection* poCollection, OGRLineString *poLS,
+        OGRLineString *poLS4, double dfX2, double dfY2, double dfX3,
+        double dfY3, double dfX4, double dfY4) {
+    OGRLineString *poLS2 = new OGRLineString();
+    OGRLineString *poLS3 = new OGRLineString();
+    poLS->addPoint(dfX2, dfY2);
+    poCollection->addGeometryDirectly(poLS);
+    poLS2->addPoint(dfX2, dfY2);
+    double dTo3 = Distance(dfX2, dfY2, dfX3, dfY3);
+    double dTo4 = Distance(dfX2, dfY2, dfX4, dfY4);
+    if (dTo3 <= dTo4) {
+        poLS2->addPoint(dfX3, dfY3);
+        poCollection->addGeometryDirectly(poLS2);
+        poLS3->addPoint(dfX3, dfY3);
+        poLS3->addPoint(dfX4, dfY4);
+        poCollection->addGeometryDirectly(poLS3);
+        poLS4->addPoint(dfX4, dfY4);
+    } else {
+        poLS2->addPoint(dfX4, dfY4);
+        poCollection->addGeometryDirectly(poLS2);
+        poLS3->addPoint(dfX4, dfY4);
+        poLS3->addPoint(dfX3, dfY3);
+        poCollection->addGeometryDirectly(poLS3);
+        poLS4->addPoint(dfX3, dfY3);
+    }
+}
+
+/************************************************************************/
+/*                           TranslateSOLID()                           */
+/************************************************************************/
+
+OGRFeature *OGRDXFLayer::TranslateSOLID()
+
+{
+    CPLDebug("SOLID", "translating solid");
+    char szLineBuf[257];
+    int nCode;
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    double dfX1 = 0.0, dfY1 = 0.0;
+    double dfX2 = 0.0, dfY2 = 0.0;
+    double dfX3 = 0.0, dfY3 = 0.0;
+    double dfX4 = 0.0, dfY4 = 0.0;
+
+    while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0) {
+        switch (nCode) {
+        case 10:
+            dfX1 = CPLAtof(szLineBuf);
+            break;
+
+        case 20:
+            dfY1 = CPLAtof(szLineBuf);
+            break;
+
+        case 30:
+            break;
+
+        case 11:
+            dfX2 = CPLAtof(szLineBuf);
+            break;
+
+        case 21:
+            dfY2 = CPLAtof(szLineBuf);
+            break;
+
+        case 31:
+            break;
+
+        case 12:
+            dfX3 = CPLAtof(szLineBuf);
+            break;
+
+        case 22:
+            dfY3 = CPLAtof(szLineBuf);
+            break;
+
+        case 32:
+            break;
+
+        case 13:
+            dfX4 = CPLAtof(szLineBuf);
+            break;
+
+        case 23:
+            dfY4 = CPLAtof(szLineBuf);
+            break;
+
+        case 33:
+            break;
+
+        default:
+            TranslateGenericProperty(poFeature, nCode, szLineBuf);
+            break;
+        }
+    }
+
+    CPLDebug("Corner coordinates are", "%f,%f,%f,%f,%f,%f,%f,%f", dfX1, dfY1,
+            dfX2, dfY2, dfX3, dfY3, dfX4, dfY4);
+
+    OGRGeometryCollection* poCollection = NULL;
+    poCollection = new OGRGeometryCollection();
+
+    OGRLineString *poLS = new OGRLineString();
+    poLS->addPoint(dfX1, dfY1);
+
+    // corners in SOLID can be in any order, so we need to order them for
+    // creating edges for polygon
+
+    double dTo2 = Distance(dfX1, dfY1, dfX2, dfY2);
+    double dTo3 = Distance(dfX1, dfY1, dfX3, dfY3);
+    double dTo4 = Distance(dfX1, dfY1, dfX4, dfY4);
+
+    OGRLineString *poLS4 = new OGRLineString();
+
+    if (dTo2 <= dTo3 && dTo2 <= dTo4) {
+        AddEdgesByNearest(poCollection, poLS, poLS4, dfX2, dfY2, dfX3, dfY3,
+                dfX4, dfY4);
+    } else if (dTo3 <= dTo2 && dTo3 <= dTo4) {
+        AddEdgesByNearest(poCollection, poLS, poLS4, dfX3, dfY3, dfX2, dfY2,
+                dfX4, dfY4);
+    } else /* if (dTo4 <= dTo2 && dTo4 <= dTo3) */ {
+        AddEdgesByNearest(poCollection, poLS, poLS4, dfX4, dfY4, dfX3, dfY3,
+                dfX2, dfY2);
+    }
+    poLS4->addPoint(dfX1, dfY1);
+    poCollection->addGeometryDirectly(poLS4);
+    OGRErr eErr;
+
+    OGRGeometry* poFinalGeom = (OGRGeometry *) OGRBuildPolygonFromEdges(
+            (OGRGeometryH) poCollection, TRUE, TRUE, 0, &eErr);
+
+    delete poCollection;
+
+    ApplyOCSTransformer(poFinalGeom);
+
+    poFeature->SetGeometryDirectly(poFinalGeom);
+
+    if (nCode == 0)
+        poDS->UnreadValue();
+
+    // Set style pen color
+    PrepareLineStyle(poFeature);
+
+    return poFeature;
+}
+
+/************************************************************************/
 /*                      GeometryInsertTransformer                       */
 /************************************************************************/
 
@@ -1764,6 +2027,10 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
         {
             poFeature = TranslateSPLINE();
         }
+        else if( EQUAL(szLineBuf,"3DFACE") )
+        {
+            poFeature = Translate3DFACE();
+        }
         else if( EQUAL(szLineBuf,"INSERT") )
         {
             poFeature = TranslateINSERT();
@@ -1776,6 +2043,10 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
         {
             poFeature = TranslateHATCH();
         }
+        else if( EQUAL(szLineBuf,"SOLID") )
+        {
+            poFeature = TranslateSOLID();
+        }
         else
         {
             if( oIgnoredEntities.count(szLineBuf) == 0 )
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
index 512e4b5..6cd13de 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfwriterds.cpp 24359 2012-05-01 17:01:22Z rouault $
+ * $Id: ogrdxfwriterds.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterDS - the OGRDataSource class used for
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfwriterds.cpp 24359 2012-05-01 17:01:22Z rouault $");
+CPL_CVSID("$Id: ogrdxfwriterds.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRDXFWriterDS()                          */
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
index 4f97149..7c9000e 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfwriterlayer.cpp 26373 2013-08-26 19:51:18Z rouault $
+ * $Id: ogrdxfwriterlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterLayer - the OGRLayer class used for
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_featurestyle.h"
 
-CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 26373 2013-08-26 19:51:18Z rouault $");
+CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
diff --git a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
index a7254c4..7ed2b9d 100644
--- a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
+++ b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_edigeo.h 23423 2011-11-26 18:40:30Z rouault $
+ * $Id: ogr_edigeo.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Definition of classes for OGR .edigeo driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -73,8 +73,6 @@ class OGREDIGEOLayer : public OGRLayer
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
     virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
 
 
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
index 037cbd3..2e2844f 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z rouault $
+ * $Id: ogredigeodatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z rouault $");
+CPL_CVSID("$Id: ogredigeodatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef M_PI
 # define M_PI  3.1415926535897932384626433832795
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
index a056b11..355be16 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogredigeodriver.cpp 21630 2011-02-06 13:08:20Z rouault $
+ * $Id: ogredigeodriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_edigeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogredigeodriver.cpp 21630 2011-02-06 13:08:20Z rouault $");
+CPL_CVSID("$Id: ogredigeodriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGREDIGEO();
 
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
index ae511ab..a0b988a 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogredigeolayer.cpp 22195 2011-04-17 18:21:14Z rouault $
+ * $Id: ogredigeolayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEOLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogredigeolayer.cpp 22195 2011-04-17 18:21:14Z rouault $");
+CPL_CVSID("$Id: ogredigeolayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGREDIGEOLayer()                            */
@@ -54,6 +54,8 @@ OGREDIGEOLayer::OGREDIGEOLayer( OGREDIGEODataSource* poDS,
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eType );
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/elastic/GNUmakefile b/ogr/ogrsf_frmts/elastic/GNUmakefile
index faef692..5dbbfc1 100644
--- a/ogr/ogrsf_frmts/elastic/GNUmakefile
+++ b/ogr/ogrsf_frmts/elastic/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrelasticdriver.o ogrelasticdatasource.o ogrelasticlayer.o
 
-CPPFLAGS	:=	-I.. -I../.. -I../geojson -I../geojson/jsonc $(GDAL_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/elastic/makefile.vc b/ogr/ogrsf_frmts/elastic/makefile.vc
index 9b94572..0b84247 100644
--- a/ogr/ogrsf_frmts/elastic/makefile.vc
+++ b/ogr/ogrsf_frmts/elastic/makefile.vc
@@ -1,6 +1,6 @@
 
 OBJ	=	ogrelasticdriver.obj ogrelasticdatasource.obj ogrelasticlayer.obj
-EXTRAFLAGS =	-DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC) -I.. -I..\..  -I..\geojson -I..\geojson\jsonc
+EXTRAFLAGS =	-DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC) -I.. -I..\..  -I..\geojson -I..\geojson\libjson
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/elastic/ogr_elastic.h b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
index 5871229..7ba1a02 100644
--- a/ogr/ogrsf_frmts/elastic/ogr_elastic.h
+++ b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_elastic.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_elastic.h 26464 2013-09-13 21:06:03Z rouault $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -66,8 +66,6 @@ public:
 
     int TestCapability(const char *);
 
-    OGRSpatialReference *GetSpatialRef();
-
     int GetFeatureCount(int bForce);
 
     void PushIndex();
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
index ff60e95..424219c 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrelasticdatasource.cpp 23848 2012-01-31 20:49:42Z rouault $
+ * $Id: ogrelasticdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Adam Estrada
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "cpl_csv.h"
 #include "cpl_http.h"
 
-CPL_CVSID("$Id: ogrelasticdatasource.cpp 23848 2012-01-31 20:49:42Z rouault $");
+CPL_CVSID("$Id: ogrelasticdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRElasticDataSource()                        */
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
index 04c9794..ad412e3 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrelasticlayer.cpp 23836 2012-01-31 19:32:04Z rouault $
+ * $Id: ogrelasticlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Adam Estrada
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,9 +33,9 @@
 #include "cpl_minixml.h"
 #include "ogr_api.h"
 #include "ogr_p.h"
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 
-CPL_CVSID("$Id: ogrelasticlayer.cpp 23836 2012-01-31 19:32:04Z rouault $");
+CPL_CVSID("$Id: ogrelasticlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRElasticLayer()                          */
@@ -70,6 +71,8 @@ OGRElasticLayer::OGRElasticLayer(const char* pszFilename,
     if (poSRS)
         poSRS->Reference();
 
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+
     ResetReading();
     return;
 }
@@ -117,14 +120,6 @@ OGRFeature *OGRElasticLayer::GetNextFeature() {
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRElasticLayer::GetSpatialRef() {
-    return poSRS;
-}
-
-/************************************************************************/
 /*                            AppendGroup()                             */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
index bc9c0c7..d6f639a 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDatasource.cpp 26310 2013-08-13 19:54:26Z rouault $
+ * $Id: FGdbDatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR Datasource.
@@ -9,6 +9,7 @@
  ******************************************************************************
  * Copyright (c) 2010, Ragi Yaser Burhum
  * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,8 +35,9 @@
 #include "cpl_string.h"
 #include "gdal.h"
 #include "FGdbUtils.h"
+#include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: FGdbDatasource.cpp 26310 2013-08-13 19:54:26Z rouault $");
+CPL_CVSID("$Id: FGdbDatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 using std::vector;
 using std::wstring;
@@ -46,7 +48,7 @@ using std::wstring;
 
 FGdbDataSource::FGdbDataSource(FGdbDriver* poDriver):
 OGRDataSource(),
-m_poDriver(poDriver), m_pszName(0), m_pGeodatabase(NULL)
+m_poDriver(poDriver), m_pszName(0), m_pGeodatabase(NULL), m_bUpdate(false)
 {
 }
 
@@ -56,6 +58,8 @@ m_poDriver(poDriver), m_pszName(0), m_pGeodatabase(NULL)
 
 FGdbDataSource::~FGdbDataSource()
 {
+    CPLMutexHolderOptionalLockD(m_poDriver->GetMutex());
+
     size_t count = m_layers.size();
     for(size_t i = 0; i < count; ++i )
         delete m_layers[i];
@@ -73,6 +77,7 @@ int FGdbDataSource::Open(Geodatabase* pGeodatabase, const char * pszNewName, int
 {
     m_pszName = CPLStrdup( pszNewName );
     m_pGeodatabase = pGeodatabase;
+    m_bUpdate = bUpdate;
 
     std::vector<std::wstring> typesRequested;
 
@@ -104,14 +109,14 @@ bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
             GDBDebug(hr, "Error opening " + WStringToString(layers[i]) + ". Skipping it");
             continue;
         }
-        FGdbLayer* pLayer = new FGdbLayer;
+        FGdbLayer* pLayer = new FGdbLayer();
         if (!pLayer->Initialize(this, pTable, layers[i], type))
         {
             delete pLayer;
             return GDBErr(hr, "Error initializing OGRLayer for " + WStringToString(layers[i]));
         }
 
-        m_layers.push_back(pLayer);
+        m_layers.push_back(new OGRMutexedLayer(pLayer, TRUE, m_poDriver->GetMutex()));
     }
     return true;
 }
@@ -248,16 +253,21 @@ bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
 
 OGRErr FGdbDataSource::DeleteLayer( int iLayer )
 {
+    if( !m_bUpdate )
+        return OGRERR_FAILURE;
+
     if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
         return OGRERR_FAILURE;
+    
+    FGdbLayer* poBaseLayer = (FGdbLayer*) m_layers[iLayer]->GetBaseLayer();
 
     // Fetch FGDBAPI Table before deleting OGR layer object
 
-    Table* pTable = m_layers[iLayer]->GetTable();
+    Table* pTable = poBaseLayer->GetTable();
 
-    std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
-    std::wstring strPath = m_layers[iLayer]->GetTablePath();
-    std::wstring strType = m_layers[iLayer]->GetType();
+    std::string name = poBaseLayer->GetLayerDefn()->GetName();
+    std::wstring strPath = poBaseLayer->GetTablePath();
+    std::wstring strType = poBaseLayer->GetType();
 
     // delete OGR layer
     delete m_layers[iLayer];
@@ -286,10 +296,10 @@ OGRErr FGdbDataSource::DeleteLayer( int iLayer )
 int FGdbDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
+        return m_bUpdate;
 
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return TRUE;
+        return m_bUpdate;
 
     return FALSE;
 }
@@ -321,16 +331,21 @@ FGdbDataSource::CreateLayer( const char * pszLayerName,
                               OGRwkbGeometryType eType,
                               char ** papszOptions )
 {
-    FGdbLayer* pLayer = new FGdbLayer;
+    if( !m_bUpdate )
+        return NULL;
+
+    FGdbLayer* pLayer = new FGdbLayer();
     if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
     {
         delete pLayer;
         return NULL;
     }
+    
+    OGRMutexedLayer* pMutexedLayer = new OGRMutexedLayer(pLayer, TRUE, m_poDriver->GetMutex());
 
-    m_layers.push_back(pLayer);
+    m_layers.push_back(pMutexedLayer);
 
-    return pLayer;  
+    return pMutexedLayer;  
 }
 
 
@@ -409,7 +424,10 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
                                        const char *pszDialect )
 
 {
-    if ( pszDialect != NULL && EQUAL(pszDialect, "OGRSQL") )
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand,
                                           poSpatialFilter,
                                           pszDialect );
@@ -419,9 +437,10 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
     if (EQUALN(pszSQLCommand, "GetLayerDefinition ", strlen("GetLayerDefinition ")))
     {
-        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
-        if (poLayer)
+        OGRMutexedLayer* poMutexedLayer = (OGRMutexedLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
+        if (poMutexedLayer)
         {
+            FGdbLayer* poLayer = (FGdbLayer*) poMutexedLayer->GetBaseLayer();
             char* pszVal = NULL;
             poLayer->GetLayerXML(&pszVal);
             OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerDefinition", pszVal );
@@ -437,9 +456,10 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
     if (EQUALN(pszSQLCommand, "GetLayerMetadata ", strlen("GetLayerMetadata ")))
     {
-        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
-        if (poLayer)
+        OGRMutexedLayer* poMutexedLayer = (OGRMutexedLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
+        if (poMutexedLayer)
         {
+            FGdbLayer* poLayer = (FGdbLayer*) poMutexedLayer->GetBaseLayer();
             char* pszVal = NULL;
             poLayer->GetLayerMetadataXML(&pszVal);
             OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerMetadata", pszVal );
@@ -479,7 +499,8 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 
     if( EQUALN(pszSQLCommand, "SELECT ", 7) )
     {
-        return new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
+        OGRLayer* pLayer = new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
+        return new OGRMutexedLayer(pLayer, TRUE, m_poDriver->GetMutex());
     }
     else
     {
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
index 335fa37..a79692a 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDriver.cpp 26310 2013-08-13 19:54:26Z rouault $
+ * $Id: FGdbDriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR driver.
@@ -9,6 +9,7 @@
  ******************************************************************************
  * Copyright (c) 2010, Ragi Yaser Burhum
  * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,16 +33,17 @@
 #include "ogr_fgdb.h"
 #include "cpl_conv.h"
 #include "FGdbUtils.h"
+#include "cpl_multiproc.h"
+#include "ogrmutexeddatasource.h"
 
-CPL_CVSID("$Id: FGdbDriver.cpp 26310 2013-08-13 19:54:26Z rouault $");
+CPL_CVSID("$Id: FGdbDriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRFileGDB();
 
 /************************************************************************/
 /*                            FGdbDriver()                              */
 /************************************************************************/
-FGdbDriver::FGdbDriver():
-OGRSFDriver()
+FGdbDriver::FGdbDriver(): OGRSFDriver(), hMutex(NULL)
 {
 }
 
@@ -51,6 +53,9 @@ OGRSFDriver()
 FGdbDriver::~FGdbDriver()
 
 {
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    hMutex = NULL;
 }
 
 
@@ -89,6 +94,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
         return NULL;
     }
 
+    CPLMutexHolderD(&hMutex);
     Geodatabase* pGeoDatabase = NULL;
 
     FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename];
@@ -126,7 +132,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
         return NULL;
     }
     else
-        return pDS;
+        return new OGRMutexedDataSource(pDS, TRUE, hMutex);
 }
 
 /***********************************************************************/
@@ -142,6 +148,8 @@ OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
     int bUpdate = TRUE; // If we're creating, we must be writing.
     VSIStatBuf stat;
 
+    CPLMutexHolderD(&hMutex);
+
     /* We don't support options yet, so warn if they send us some */
     if ( papszOptions )
     {
@@ -191,7 +199,7 @@ OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
         return NULL;
     }
     else
-        return pDS;
+        return new OGRMutexedDataSource(pDS, TRUE, hMutex);
 }
 
 /***********************************************************************/
@@ -200,6 +208,8 @@ OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
 
 void FGdbDriver::Release(const char* pszName)
 {
+    CPLMutexHolderOptionalLockD(hMutex);
+
     FGdbDatabaseConnection* pConnection = oMapConnections[pszName];
     if( pConnection != NULL )
     {
@@ -238,6 +248,7 @@ int FGdbDriver::TestCapability( const char * pszCap )
 
 OGRErr FGdbDriver::DeleteDataSource( const char *pszDataSource )
 {
+    CPLMutexHolderD(&hMutex);
 
     std::wstring wstr = StringToWString(pszDataSource);
 
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
index 997134f..2a75f81 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: FGdbLayer.cpp 25208 2012-11-05 18:34:41Z rouault $
+* $Id: FGdbLayer.cpp 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Implements FileGDB OGR layer.
@@ -9,6 +9,7 @@
 ******************************************************************************
 * Copyright (c) 2010, Ragi Yaser Burhum
 * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #include "FGdbUtils.h"
 #include "cpl_minixml.h" // the only way right now to extract schema information
 
-CPL_CVSID("$Id: FGdbLayer.cpp 25208 2012-11-05 18:34:41Z rouault $");
+CPL_CVSID("$Id: FGdbLayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 using std::string;
 using std::wstring;
@@ -134,6 +135,8 @@ FGdbLayer::FGdbLayer():
     m_bLayerEnvelopeValid = false;
     m_bLayerJustCreated = false;
 #endif
+    m_papszOptions = NULL;
+    m_bCreateMultipatch = FALSE;
 }
 
 /************************************************************************/
@@ -163,6 +166,10 @@ FGdbLayer::~FGdbLayer()
         m_pOGRFilterGeometry = NULL;
     }
     
+    for(size_t i = 0; i < m_apoByteArrays.size(); i++ )
+        delete m_apoByteArrays[i];
+
+    CSLDestroy(m_papszOptions);
 }
 
 #ifdef EXTENT_WORKAROUND
@@ -347,6 +354,9 @@ OGRErr FGdbLayer::CreateFeature( OGRFeature *poFeature )
     Row fgdb_row;
     fgdbError hr;
 
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     if (m_bBulkLoadAllowed < 0)
         m_bBulkLoadAllowed = CSLTestBoolean(CPLGetConfigOption("FGDB_BULK_LOAD", "NO"));
 
@@ -420,6 +430,7 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
     int nFieldCount = poFeatureDefn->GetFieldCount();
 
     /* Copy the OGR visible fields (everything except geometry and FID) */
+    int nCountBinaryField = 0;
     for( int i = 0; i < nFieldCount; i++ )
     {
         std::string field_name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
@@ -479,15 +490,18 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
         {
             /* Strings we convert to wstring */
             std::string fldvalue = poFeature->GetFieldAsString(i);
-            std::wstring wfldvalue = StringToWString(fldvalue);
             if( strFieldType == "esriFieldTypeString" )
+            {
+                std::wstring wfldvalue = StringToWString(fldvalue);
                 hr = fgdb_row.SetString(wfield_name, wfldvalue);
+            }
             // Apparently, esriFieldTypeGlobalID can not be set, but is
             // initialized by the FileGDB SDK itself.
             else if( strFieldType == "esriFieldTypeGUID" /*||
                      strFieldType == "esriFieldTypeGlobalID" */ )
             {
                 Guid guid;
+                std::wstring wfldvalue = StringToWString(fldvalue);
                 if( FAILED(hr = guid.FromString(wfldvalue)) )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
@@ -499,6 +513,10 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
                     hr = fgdb_row.SetGUID(wfield_name, guid);
                 }
             }
+            else if( strFieldType == "esriFieldTypeXML"  )
+            {
+                hr = fgdb_row.SetXML(wfield_name, fldvalue);
+            }
             else
                 hr = 0;
         }
@@ -515,20 +533,23 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
         else if ( nOGRFieldType == OFTBinary )
         {
             /* Binary data */
-            ByteArray fgdb_bytearray;
             int bytesize;
             GByte *bytes = poFeature->GetFieldAsBinary(i, &bytesize);
             if ( bytesize )
             {
-                fgdb_bytearray.Allocate(bytesize);
-                memcpy(fgdb_bytearray.byteArray, bytes, bytesize);
-                fgdb_bytearray.inUseLength = bytesize;
-                hr = fgdb_row.SetBinary(wfield_name, fgdb_bytearray);
+                /* This is annoying but SetBinary() doesn't keep the binary */
+                /* content. The ByteArray object must still be alive at */
+                /* the time Insert() is called */
+                m_apoByteArrays[nCountBinaryField]->Allocate(bytesize);
+                memcpy(m_apoByteArrays[nCountBinaryField]->byteArray, bytes, bytesize);
+                m_apoByteArrays[nCountBinaryField]->inUseLength = bytesize;
+                hr = fgdb_row.SetBinary(wfield_name, *(m_apoByteArrays[nCountBinaryField]));
             }
             else
             {
                 hr = fgdb_row.SetNull(wfield_name);
             }
+            nCountBinaryField ++;
         }
         else
         {
@@ -565,7 +586,16 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
             /* Write geometry to a buffer */
             GByte *pabyShape = NULL;
             int nShapeSize = 0;
-            OGRErr err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
+            OGRErr err;
+
+            if( m_bCreateMultipatch && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
+            {
+                err = OGRWriteMultiPatchToShapeBin( poGeom, &pabyShape, &nShapeSize );
+            }
+            else
+            {
+                err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
+            }
             if ( err != OGRERR_NONE )
                 return err;
 
@@ -634,6 +664,9 @@ OGRErr FGdbLayer::DeleteFeature( long nFID )
     EnumRows       enumRows;
     Row            row;
 
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     EndBulkLoad();
 
     if (GetRow(enumRows, row, nFID) != OGRERR_NONE)
@@ -659,6 +692,9 @@ OGRErr FGdbLayer::SetFeature( OGRFeature* poFeature )
     EnumRows       enumRows;
     Row            row;
 
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     if( poFeature->GetFID() == OGRNullFID )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -705,6 +741,31 @@ char* FGdbLayer::CreateFieldDefn(OGRFieldDefn& oField,
         return NULL;
     }
 
+    const char* pszColumnTypes = CSLFetchNameValue(m_papszOptions, "COLUMN_TYPES");
+    if( pszColumnTypes != NULL )
+    {
+        char** papszTokens = CSLTokenizeString2(pszColumnTypes, ",", 0);
+        const char* pszFieldType = CSLFetchNameValue(papszTokens, fieldname.c_str());
+        if( pszFieldType != NULL )
+        {
+            OGRFieldType fldtypeCheck;
+            if( GDBToOGRFieldType(pszFieldType, &fldtypeCheck) )
+            {
+                if( fldtypeCheck != fldtype )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not consistant with OGR data type",
+                         fieldname.c_str(), pszFieldType, pszFieldType);
+                }
+                else
+                    gdbFieldType = pszFieldType;
+            }
+            else
+                CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not recognized",
+                         fieldname.c_str(), pszFieldType, pszFieldType);
+        }
+        CSLDestroy(papszTokens);
+    }
+
     if (fieldname_clean.size() != 0)
     {
         oField.SetName(fieldname_clean.c_str());
@@ -816,6 +877,9 @@ OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
     std::string fieldname_clean;
     std::string gdbFieldType;
 
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     char* defn_str = CreateFieldDefn(oField, bApproxOK,
                                      fieldname_clean, gdbFieldType);
     if (defn_str == NULL)
@@ -838,6 +902,9 @@ OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
 
     m_vOGRFieldToESRIField.push_back(StringToWString(fieldname_clean));
     m_vOGRFieldToESRIFieldType.push_back( gdbFieldType );
+    
+    if( oField.GetType() == OFTBinary )
+        m_apoByteArrays.push_back(new ByteArray());
 
     /* All done and happy */
     return OGRERR_NONE;
@@ -850,6 +917,10 @@ OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
 
 OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
 {
+
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     if (iFieldToDelete < 0 || iFieldToDelete >= m_pFeatureDefn->GetFieldCount())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -883,6 +954,10 @@ OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
 
 OGRErr FGdbLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
 {
+
+    if( !m_pDS->GetUpdate() )
+        return OGRERR_FAILURE;
+
     if (iFieldToAlter < 0 || iFieldToAlter >= m_pFeatureDefn->GetFieldCount())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -1353,6 +1428,13 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
         }
         if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z) )
             return GDBErr(-1, "Unable to map OGR type to ESRI type");
+
+        if( wkbFlatten(eType) == wkbMultiPolygon &&
+            CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "CREATE_MULTIPATCH", "NO")) )
+        {
+            esri_type = "esriGeometryMultiPatch";
+            has_z = true;
+        }
     }
 
     m_bLaunderReservedKeywords = CSLFetchBoolean( papszOptions, "LAUNDER_RESERVED_KEYWORDS", TRUE) == TRUE;
@@ -1514,6 +1596,9 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
         return GDBErr(hr, "Failed at creating table for " + table_path);
     }
 
+    m_papszOptions = CSLDuplicate(papszOptions);
+    m_bCreateMultipatch = CSLTestBoolean(CSLFetchNameValueDef(m_papszOptions, "CREATE_MULTIPATCH", "NO"));
+
     /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
     return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
 }
@@ -1617,6 +1702,12 @@ bool FGdbLayer::Initialize(FGdbDataSource* pParentDataSource, Table* pTable,
     }
     CPLDestroyXMLNode( psRoot );
 
+    if( m_pFeatureDefn->GetGeomFieldCount() != 0 )
+    {
+        m_pFeatureDefn->GetGeomFieldDefn(0)->SetName(m_strShapeFieldName.c_str());
+        m_pFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_pSRS);
+    }
+
     if (abort)
         return false;
 
@@ -1880,6 +1971,8 @@ bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
 
             m_vOGRFieldToESRIField.push_back(StringToWString(fieldName));
             m_vOGRFieldToESRIFieldType.push_back( fieldType );
+            if( ogrType == OFTBinary )
+                m_apoByteArrays.push_back(new ByteArray());
 
         }
     }
@@ -1934,6 +2027,9 @@ void FGdbLayer::ResetReading()
 
 void FGdbLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
 {
+    if( !InstallFilter(pOGRGeom) )
+        return;
+
     if (m_pOGRFilterGeometry)
     {
         OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
@@ -2027,7 +2123,8 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
     ShapeBuffer gdbGeometry;
     // Row::GetGeometry() will fail with -2147467259 for NULL geometries
     // Row::GetGeometry() will fail with -2147219885 for tables without a geometry field
-    if (!FAILED(hr = pRow->GetGeometry(gdbGeometry)))
+    if (!m_pFeatureDefn->IsGeometryIgnored() &&
+        !FAILED(hr = pRow->GetGeometry(gdbGeometry)))
     {
         OGRGeometry* pOGRGeo = NULL;
 
@@ -2052,6 +2149,12 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
 
     for (size_t i = 0; i < mappedFieldCount; ++i)
     {
+        OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(i);
+        // The IsNull() and GetXXX() API are very slow when there are a 
+        // big number of fields, for example with Tiger database.
+        if (poFieldDefn->IsIgnored() )
+            continue;
+
         const wstring & wstrFieldName = m_vOGRFieldToESRIField[i];
         const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
 
@@ -2074,7 +2177,7 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
         // NOTE: This switch statement needs to be kept in sync with GDBToOGRFieldType utility function
         //       since we are only checking for types we mapped in that utility function
 
-        switch (m_pFeatureDefn->GetFieldDefn(i)->GetType())
+        switch (poFieldDefn->GetType())
         {
 
             case OFTInteger:
@@ -2133,7 +2236,8 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
             case OFTString:
             {
                 wstring val;
-                
+                std::string strValue;
+
                 if( strFieldType == "esriFieldTypeGlobalID" )
                 {
                     Guid guid;
@@ -2145,6 +2249,7 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
                         foundBadColumn = true;
                         continue;
                     }
+                    strValue = WStringToString(val);
                 }
                 else if( strFieldType == "esriFieldTypeGUID" )
                 {
@@ -2157,6 +2262,17 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
                         foundBadColumn = true;
                         continue;
                     }
+                    strValue = WStringToString(val);
+                }
+                else if( strFieldType == "esriFieldTypeXML" )
+                {
+                    if (FAILED(hr = pRow->GetXML(wstrFieldName, strValue)))
+                    {
+                        GDBErr(hr, "Failed to determine XML value for column " +
+                            WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
                 }
                 else
                 {
@@ -2167,28 +2283,27 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
                         foundBadColumn = true;
                         continue;
                     }
+                    strValue = WStringToString(val);
                 }
 
-                pOutFeature->SetField(i, WStringToString(val).c_str());
+                pOutFeature->SetField(i, strValue.c_str());
             }
             break;
 
-            /* TODO: Need to get test dataset to implement these leave it as NULL for now
             case OFTBinary:
             {
                 ByteArray binaryBuf;
 
                 if (FAILED(hr = pRow->GetBinary(wstrFieldName, binaryBuf)))
-                {
-                GDBErr(hr, "Failed to determine binary value for column " + WStringToString(wstrFieldName));
-                foundBadColumn = true;
-                continue;
+                    {
+                    GDBErr(hr, "Failed to determine binary value for column " + WStringToString(wstrFieldName));
+                    foundBadColumn = true;
+                    continue;
                 }
 
                 pOutFeature->SetField(i, (int)binaryBuf.inUseLength, (GByte*)binaryBuf.byteArray);
             }
             break;
-            */
 
             case OFTDateTime:
             {
@@ -2283,7 +2398,33 @@ int FGdbLayer::GetFeatureCount( int bForce )
     EndBulkLoad();
 
     if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0)
-        return OGRLayer::GetFeatureCount(bForce);
+    {
+        ResetReading();
+        if (m_pEnumRows == NULL)
+            return 0;
+
+        int nFeatures = 0;
+        while( TRUE )
+        {
+            long hr;
+
+            Row row;
+
+            if (FAILED(hr = m_pEnumRows->Next(row)))
+            {
+                GDBErr(hr, "Failed fetching features");
+                return 0;
+            }
+
+            if (hr != S_OK)
+            {
+                break;
+            }
+            nFeatures ++;
+        }
+        ResetReading();
+        return nFeatures;
+    }
 
     if (FAILED(hr = m_pTable->GetRowCount(rowCount)))
     {
@@ -2291,26 +2432,6 @@ int FGdbLayer::GetFeatureCount( int bForce )
         return 0;
     }
 
-#if 0
-  Row            row;
-  EnumRows       enumRows;
-
-  if (FAILED(hr = m_pTable->Search(StringToWString(m_strOIDFieldName), L"", true, enumRows)))
-  {
-    GDBErr(hr, "Failed counting rows");
-    return -1;
-  }
-
-  while (S_OK == (hr = enumRows.Next(row)))
-    ++rowCount;
-
-  if (FAILED(hr))
-  {
-    GDBErr(hr, "Failed counting rows (during fetch)");
-    return -1;
-  }
-#endif
-
     return static_cast<int>(rowCount);
 }
 
@@ -2324,7 +2445,21 @@ OGRErr FGdbLayer::GetExtent (OGREnvelope* psExtent, int bForce)
 {
     if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0 ||
         m_strShapeFieldName.size() == 0)
-        return OGRLayer::GetExtent(psExtent, bForce);
+    {
+        int* pabSaveFieldIgnored = new int[m_pFeatureDefn->GetFieldCount()];
+        for(int i=0;i<m_pFeatureDefn->GetFieldCount();i++)
+        {
+            pabSaveFieldIgnored[i] = m_pFeatureDefn->GetFieldDefn(i)->IsIgnored();
+            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(TRUE);
+        }
+        OGRErr eErr = OGRLayer::GetExtent(psExtent, bForce);
+        for(int i=0;i<m_pFeatureDefn->GetFieldCount();i++)
+        {
+            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(pabSaveFieldIgnored[i]);
+        }
+        delete[] pabSaveFieldIgnored;
+        return eErr;
+    }
 
     long hr;
     Envelope envelope;
@@ -2482,29 +2617,29 @@ int FGdbLayer::TestCapability( const char* pszCap )
         return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.size() == 0;
 
     else if (EQUAL(pszCap,OLCCreateField)) /* CreateField() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 
     else if (EQUAL(pszCap,OLCSequentialWrite)) /* CreateFeature() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 
     else if (EQUAL(pszCap,OLCStringsAsUTF8)) /* Native UTF16, converted to UTF8 */
         return TRUE;
 
     else if (EQUAL(pszCap,OLCReorderFields)) /* TBD ReorderFields() */
-        return FALSE;
+        return m_pDS->GetUpdate();
 
     else if (EQUAL(pszCap,OLCDeleteFeature)) /* DeleteFeature() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 
     else if (EQUAL(pszCap,OLCRandomWrite)) /* SetFeature() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 
     else if (EQUAL(pszCap,OLCDeleteField)) /* DeleteField() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 
 #ifdef AlterFieldDefn_implemented_but_not_working
     else if (EQUAL(pszCap,OLCAlterFieldDefn)) /* AlterFieldDefn() */
-        return TRUE;
+        return m_pDS->GetUpdate();
 #endif
 
     else if (EQUAL(pszCap,OLCFastSetNextByIndex)) /* TBD FastSetNextByIndex() */
@@ -2512,7 +2647,10 @@ int FGdbLayer::TestCapability( const char* pszCap )
 
     else if (EQUAL(pszCap,OLCTransactions)) /* TBD Start/End Transactions() */
         return FALSE;
-        
+
+    else if( EQUAL(pszCap,OLCIgnoreFields) )
+        return TRUE;
+
     else 
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
index 2bc2ec3..5add04b 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
@@ -5,7 +5,7 @@
 * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
 *
 ******************************************************************************
-* Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
index d763b40..08185ef 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: FGdbUtils.cpp 23984 2012-02-15 05:19:25Z rcoup $
+* $Id: FGdbUtils.cpp 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Different utility functions used in FileGDB OGR driver.
@@ -9,6 +9,7 @@
 ******************************************************************************
 * Copyright (c) 2010, Ragi Yaser Burhum
 * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include "ogr_api.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: FGdbUtils.cpp 23984 2012-02-15 05:19:25Z rcoup $");
+CPL_CVSID("$Id: FGdbUtils.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 using std::string;
 
@@ -370,35 +371,46 @@ bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precisi
 {
     *precision = 0;
 
+    /* Width (Length in FileGDB terms) based on FileGDB_API/samples/XMLsamples/OneOfEachFieldType.xml */
+    /* Length is in bytes per doc of FileGDB_API/xmlResources/FileGDBAPI.xsd */
     if(gdbType == "esriFieldTypeSmallInteger" )
     {
         *width = 2;
     }
     else if(gdbType == "esriFieldTypeInteger" )
     {
-        *width = 12;
+        *width = 4;
     }
     else if(gdbType == "esriFieldTypeSingle" )
     {
-        *width = 12;
-        *precision = 5;
+        *width = 4;
+        *precision = 5; // FIXME ?
     }
     else if(gdbType == "esriFieldTypeDouble" )
     {
-        *width = 24;
-        *precision = 15;
+        *width = 8;
+        *precision = 15; // FIXME ?
     }
-    else if(gdbType == "esriFieldTypeString" )
+    else if(gdbType == "esriFieldTypeString" ||
+            gdbType == "esriFieldTypeXML")
     {
-        *width = 2147483647;
+        *width = atoi(CPLGetConfigOption("FGDB_STRING_WIDTH", "65536"));
     }
     else if(gdbType == "esriFieldTypeDate" )
     {
-        *width = 32;
+        *width = 8;
     }
     else if(gdbType == "esriFieldTypeOID" )
     {
-        *width = 15;
+        *width = 4;
+    }
+    else if(gdbType == "esriFieldTypeGUID" )
+    {
+        *width = 16;
+    }
+    else if(gdbType == "esriFieldTypeBlob" )
+    {
+        *width = 0;
     }
     else
     {
diff --git a/ogr/ogrsf_frmts/filegdb/GNUmakefile b/ogr/ogrsf_frmts/filegdb/GNUmakefile
index de3a4ee..6bfd44e 100644
--- a/ogr/ogrsf_frmts/filegdb/GNUmakefile
+++ b/ogr/ogrsf_frmts/filegdb/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	FGdbDatasource.o FGdbDriver.o FGdbLayer.o FGdbUtils.o FGdbResultLayer.o 
 
-CPPFLAGS	:=	$(GDAL_INCLUDE) $(FGDB_INC) $(CPPFLAGS)
+CPPFLAGS	:=	-I../generic $(GDAL_INCLUDE) $(FGDB_INC) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
index cbfe352..150905d 100644
--- a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
+++ b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
@@ -9,12 +9,14 @@
 
 <p>The FileGDB driver provides read and write access to File Geodatabases (.gdb directories) created by ArcGIS 10 and above.</p>
 
+<p>Note : starting with OGR 1.11, the <a href="drv_openfilegdb.html">OpenFileGDB driver</a> driver exists as an alternative built-in 
+i.e. not depending on a third-party library) read-only driver.</p>
 
 <h2>Requirements</h2>
 
 <p>
 	<ul>
-		<li><a href="http://resources.arcgis.com/content/geodatabases/10.0/file-gdb-api">FileGDB API SDK</a></li>
+		<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">FileGDB API SDK</a></li>
         <li>OGR >= 1.9.0</li>
 	</ul>
 </p>
@@ -56,6 +58,7 @@ respectively the definition and metadata of a FileGDB table as XML content.
 			<li>For geographic coordinate systems: XORIGIN=-400, YORIGIN=-400, XYSCALE=1000000000</li>
 			<li>For projected coordinate systems: XYSCALE=10000 for the default XYTOLERANCE of 0.001m. XORIGIN and YORIGIN change based on the coordinate system, but the OGR default of -2147483647 is suitable with the default XYSCALE for all coordinate systems.</li></ul></p></li>
 	<li><b>XML_DEFINITION</b> : (GDAL >= 1.10) When this option is set, its value will be used as the XML definition to create the new table. The root node of such a XML definition must be a <esri:DataElement> element conformant to FileGDBAPI.xsd</li>
+    <li><b>CREATE_MULTIPATCH</b>=YES : (GDAL >= 1.11) When this option is set, geometries of layers of type MultiPolygon will be written as MultiPatch</li>
 </ul>
 
 <h2>Examples</h2>
@@ -91,7 +94,8 @@ respectively the definition and metadata of a FileGDB table as XML content.
 <h2>Links</h2>
 
 <ul>
-<li><a href="http://resources.arcgis.com/content/geodatabases/10.0/file-gdb-api">ESRI File Geodatabase API Page</a></li>
+<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">ESRI File Geodatabase API Page</a></li>
+<li><a href="drv_openfilegdb.html">OpenFileGDB driver</a>, not depending on a third-party library/SDK</li>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/filegdb/makefile.vc b/ogr/ogrsf_frmts/filegdb/makefile.vc
index ad6e85f..7f6ff7e 100644
--- a/ogr/ogrsf_frmts/filegdb/makefile.vc
+++ b/ogr/ogrsf_frmts/filegdb/makefile.vc
@@ -1,5 +1,5 @@
 OBJ     =       FGdbDriver.obj FGdbDatasource.obj FGdbLayer.obj FGdbUtils.obj FGdbResultLayer.obj
-EXTRAFLAGS =	-I.. -I..\.. -I$(FGDB_INC)
+EXTRAFLAGS =	-I.. -I..\generic -I..\.. -I$(FGDB_INC)
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
index d2d7582..9904938 100644
--- a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
+++ b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: ogr_fgdb.h 26310 2013-08-13 19:54:26Z rouault $
+* $Id: ogr_fgdb.h 27044 2014-03-16 23:41:27Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Standard includes and class definitions ArcObjects OGR driver.
@@ -7,6 +7,7 @@
 *
 ******************************************************************************
 * Copyright (c) 2009, Ragi Yaser Burhum
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -32,6 +33,7 @@
 
 #include <vector>
 #include "ogrsf_frmts.h"
+#include "ogrmutexedlayer.h"
 
 /* GDAL string utilities */
 #include "cpl_string.h"
@@ -59,6 +61,8 @@
 /* The ESRI FGDB API namespace */
 using namespace FileGDBAPI;
 
+class FGdbDriver;
+
 /************************************************************************/
 /*                           FGdbBaseLayer                              */
 /************************************************************************/
@@ -109,9 +113,14 @@ class FGdbLayer : public FGdbBaseLayer
   bool                UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom);
 #endif
 
+  std::vector<ByteArray*> m_apoByteArrays;
   OGRErr              PopulateRowWithFeature( Row& row, OGRFeature *poFeature );
   OGRErr              GetRow( EnumRows& enumRows, Row& row, long nFID );
 
+  char              **m_papszOptions;
+  
+  int                 m_bCreateMultipatch;
+
   char*               CreateFieldDefn(OGRFieldDefn& oField,
                                       int bApproxOK,
                                       std::string& fieldname_clean,
@@ -129,7 +138,6 @@ public:
 
   // virtual const char *GetName();
   virtual const char* GetFIDColumn() { return m_strOIDFieldName.c_str(); }
-  virtual const char* GetGeometryColumn() { return m_strShapeFieldName.c_str(); }
 
   virtual void        ResetReading();
   virtual OGRFeature* GetNextFeature();
@@ -161,8 +169,6 @@ public:
 //  virtual OGRErr        RollbackTransaction( );
 
   OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
-	
-  virtual OGRSpatialReference *GetSpatialRef() { return m_pSRS; }
 
   virtual int         TestCapability( const char * );
 
@@ -213,8 +219,6 @@ public:
 
   OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
 
-  //virtual OGRSpatialReference *GetSpatialRef() { return m_pSRS; }
-
   virtual int         TestCapability( const char * );
 
 protected:
@@ -226,7 +230,6 @@ protected:
 /************************************************************************/
 /*                           FGdbDataSource                            */
 /************************************************************************/
-class FGdbDriver;
 
 class FGdbDataSource : public OGRDataSource
 {
@@ -254,6 +257,7 @@ public:
   int TestCapability( const char * );
 
   Geodatabase* GetGDB() { return m_pGeodatabase; }
+  bool         GetUpdate() { return m_bUpdate; }
 
   /*
   protected:
@@ -268,8 +272,9 @@ protected:
 
   FGdbDriver* m_poDriver;
   char* m_pszName;
-  std::vector <FGdbLayer*> m_layers;
+  std::vector <OGRMutexedLayer*> m_layers;
   Geodatabase* m_pGeodatabase;
+  bool m_bUpdate;
 
 };
 
@@ -290,6 +295,7 @@ public:
 class FGdbDriver : public OGRSFDriver
 {
   std::map<CPLString, FGdbDatabaseConnection*> oMapConnections;
+  void* hMutex;
 
 public:
   FGdbDriver();
@@ -302,6 +308,7 @@ public:
   virtual OGRErr DeleteDataSource( const char *pszDataSource );
 
   void Release(const char* pszName);
+  void* GetMutex() { return hMutex; }
 
 private:
 
diff --git a/ogr/ogrsf_frmts/fme/GNUmakefile b/ogr/ogrsf_frmts/fme/GNUmakefile
index 5b30d73..54d30ed 100644
--- a/ogr/ogrsf_frmts/fme/GNUmakefile
+++ b/ogr/ogrsf_frmts/fme/GNUmakefile
@@ -6,7 +6,7 @@ OBJ	=	ogrfmecacheindex.o ogrfmedatasource.o ogrfmedriver.o \
 		ogrfmelayer.o ogrfmelayercached.o ogrfmelayerdb.o \
 		fme2ogr_utils.o
 
-CPPFLAGS	+=	-I.. -I../.. $(FME_INCLUDE) \
+CPPFLAGS	+=	-I.. -I../.. $(GDAL_INCLUDE) $(FME_INCLUDE) \
 		-DSUPPORT_INDIRECT_FMEDLL -DSUPPORT_PERSISTENT_CACHE
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/generic/GNUmakefile b/ogr/ogrsf_frmts/generic/GNUmakefile
index c0029c6..7c6d5fd 100644
--- a/ogr/ogrsf_frmts/generic/GNUmakefile
+++ b/ogr/ogrsf_frmts/generic/GNUmakefile
@@ -5,7 +5,8 @@ include ../../../GDALmake.opt
 OBJ	=	ogrsfdriverregistrar.o ogrlayer.o ogrdatasource.o \
 		ogrsfdriver.o ogrregisterall.o ogr_gensql.o \
 		ogr_attrind.o ogr_miattrind.o ogrlayerdecorator.o \
-		ogrwarpedlayer.o ogrunionlayer.o ogrlayerpool.o
+		ogrwarpedlayer.o ogrunionlayer.o ogrlayerpool.o \
+		ogrmutexedlayer.o ogrmutexeddatasource.o
 
 BASEFORMATS = \
 	-DAVCBIN_ENABLED \
@@ -43,7 +44,10 @@ BASEFORMATS = \
 	-DIDRISI_ENABLED \
 	-DARCGEN_ENABLED \
 	-DSEGUKOOA_ENABLED \
-	-DSEGY_ENABLED
+	-DSEGY_ENABLED \
+	-DSXF_ENABLED \
+	-DOPENFILEGDB_ENABLED \
+	-DWASP_ENABLED
 
 CXXFLAGS :=     $(CXXFLAGS) -DINST_DATA=\"$(INST_DATA)\" $(BASEFORMATS)
 
@@ -135,6 +139,10 @@ ifeq ($(HAVE_PANORAMA),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DPANORAMA_ENABLED
 endif
 
+ifeq ($(HAVE_SOSI),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DSOSI_ENABLED
+endif
+
 ifeq ($(HAVE_SQLITE),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DVFK_ENABLED
 endif
@@ -156,6 +164,10 @@ CXXFLAGS :=	$(CXXFLAGS) -DGFT_ENABLED
 endif
 
 ifeq ($(CURL_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DGME_ENABLED
+endif
+
+ifeq ($(CURL_SETTING),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DCOUCHDB_ENABLED
 endif
 
@@ -183,6 +195,14 @@ ifneq ($(LIBZ_SETTING),no)
 CXXFLAGS :=	$(CXXFLAGS) -DPDF_ENABLED
 endif
 
+ifeq ($(ODBC_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DWALK_ENABLED
+endif
+
+ifeq ($(CURL_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DCARTODB_ENABLED
+endif
+
 CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/generic/makefile.vc b/ogr/ogrsf_frmts/generic/makefile.vc
index 4875411..f247a16 100644
--- a/ogr/ogrsf_frmts/generic/makefile.vc
+++ b/ogr/ogrsf_frmts/generic/makefile.vc
@@ -2,19 +2,20 @@
 OBJ	=	ogrsfdriverregistrar.obj ogrlayer.obj ogr_gensql.obj \
 		ogrdatasource.obj ogrsfdriver.obj ogrregisterall.obj \
 		ogr_attrind.obj ogr_miattrind.obj ogrlayerdecorator.obj \
-		ogrwarpedlayer.obj ogrunionlayer.obj ogrlayerpool.obj
+		ogrwarpedlayer.obj ogrunionlayer.obj ogrlayerpool.obj \
+		ogrmutexedlayer.obj ogrmutexeddatasource.obj
 
 
 GDAL_ROOT	=	..\..\..
 
-BASEFORMATS = -DSHAPE_ENABLED -DTAB_ENABLED -DNTF_ENABLED -DSDTS_ENABLED -DTIGER_ENABLED -DS57_ENABLED -DDGN_ENABLED -DVRT_ENABLED -DAVCBIN_ENABLED -DREC_ENABLED -DMEM_ENABLED -DCSV_ENABLED -DGML_ENABLED -DGMT_ENABLED -DBNA_ENABLED -DKML_ENABLED -DGEOJSON_ENABLED -DGPX_ENABLED -DGEOCONCEPT_ENABLED -DXPLANE_ENABLED -DGEORSS_ENABLED -DGTM_ENABLED -DDXF_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED -DEDIGEO_ENABL [...]
+BASEFORMATS = -DSHAPE_ENABLED -DTAB_ENABLED -DNTF_ENABLED -DSDTS_ENABLED -DTIGER_ENABLED -DS57_ENABLED -DDGN_ENABLED -DVRT_ENABLED -DAVCBIN_ENABLED -DREC_ENABLED -DMEM_ENABLED -DCSV_ENABLED -DGML_ENABLED -DGMT_ENABLED -DBNA_ENABLED -DKML_ENABLED -DGEOJSON_ENABLED -DGPX_ENABLED -DGEOCONCEPT_ENABLED -DXPLANE_ENABLED -DGEORSS_ENABLED -DGTM_ENABLED -DDXF_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED -DEDIGEO_ENABL [...]
 
 EXTRAFLAGS =	-I.. -I..\.. $(OGDIDEF) $(FMEDEF) $(OCIDEF) $(PGDEF) \
 		$(ODBCDEF) $(SQLITEDEF) $(MYSQLDEF) $(ILIDEF) $(DWGDEF) \
 		$(SDEDEF) $(BASEFORMATS) $(IDBDEF) $(NASDEF) $(DODSDEF) \
 		$(PCIDSKDEF) $(LIBKMLDEF) $(WFSDEF) $(SOSIDEF) $(GFTDEF) \
 		$(COUCHDBDEF) $(FGDBDEF) $(XLSDEF) $(ODSDEF) $(XLSXDEF) $(INGRESDEF) \
-		$(ELASTICDEF) $(OSMDEF) $(VFKDEF)
+		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODBDEF) $(GMEDEF)
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
@@ -31,7 +32,7 @@ OGDIDEF	=	-DOGDI_ENABLED
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DMSSQLSPATIAL_ENABLED -DGEOMEDIA_ENABLED
+ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DMSSQLSPATIAL_ENABLED -DGEOMEDIA_ENABLED -DWALK_ENABLED
 !ENDIF
 
 !IFDEF PG_LIB
@@ -141,6 +142,14 @@ OSMDEF	=	-DOSM_ENABLED
 VFKDEF	=	-DVFK_ENABLED
 !ENDIF
 
+!IFDEF CURL_LIB
+CARTODBDEF = -DCARTODB_ENABLED
+!ENDIF
+
+!IFDEF CURL_LIB
+GMEDEF = -DGME_ENABLED
+!ENDIF
+
 default:	$(OBJ)
 
 clean:
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
index bfa03c4..e8f3cf4 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gensql.cpp 24289 2012-04-22 09:53:41Z rouault $
+ * $Id: ogr_gensql.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGenSQLResultsLayer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,11 +32,26 @@
 #include "ogr_p.h"
 #include "ogr_gensql.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+#include "cpl_time.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogr_gensql.cpp 24289 2012-04-22 09:53:41Z rouault $");
+CPL_CVSID("$Id: ogr_gensql.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
+class OGRGenSQLGeomFieldDefn: public OGRGeomFieldDefn
+{
+    public:
+        OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn* poGeomFieldDefn) :
+            OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
+                             poGeomFieldDefn->GetType()), bForceGeomType(FALSE)
+        {
+            SetSpatialRef(poGeomFieldDefn->GetSpatialRef());
+        }
+
+        int bForceGeomType;
+};
+
 /************************************************************************/
 /*               OGRGenSQLResultsLayerHasSpecialField()                 */
 /************************************************************************/
@@ -48,7 +64,8 @@ int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
     {
         if (expr->table_index == 0)
         {
-            return expr->field_index >= nMinIndexForSpecialField;
+            return expr->field_index >= nMinIndexForSpecialField &&
+                   expr->field_index < nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
         }
     }
     else if (expr->eNodeType == SNT_OPERATION)
@@ -86,6 +103,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
     nNextIndexFID = 0;
     nExtraDSCount = 0;
     papoExtraDS = NULL;
+    panGeomFieldToSrcGeomField = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Identify all the layers involved in the SELECT.                 */
@@ -157,28 +175,29 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
         this->pszWHERE = NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Now that we have poSrcLayer, we can install a spatial filter    */
-/*      if there is one.                                                */
-/* -------------------------------------------------------------------- */
-    if( poSpatFilter != NULL )
-        SetSpatialFilter( poSpatFilter );
-
-/* -------------------------------------------------------------------- */
 /*      Prepare a feature definition based on the query.                */
 /* -------------------------------------------------------------------- */
     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
 
     poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
+    poDefn->SetGeomType(wkbNone);
     poDefn->Reference();
 
     iFIDFieldIndex = poSrcDefn->GetFieldCount();
 
+    /* + 1 since we can add an implicit geometry field */
+    panGeomFieldToSrcGeomField = (int*) CPLMalloc(sizeof(int) * (1 + psSelectInfo->result_columns));
+
     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     {
         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
         OGRFieldDefn oFDefn( "", OFTInteger );
+        OGRGeomFieldDefn oGFDefn( "", wkbUnknown );
         OGRFieldDefn *poSrcFDefn = NULL;
+        OGRGeomFieldDefn *poSrcGFDefn = NULL;
+        int bIsGeometry = FALSE;
         OGRFeatureDefn *poLayerDefn = NULL;
+        int iSrcGeomField = -1;
 
         if( psColDef->table_index != -1 )
             poLayerDefn = 
@@ -187,18 +206,38 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
         if( psColDef->field_index > -1 
             && poLayerDefn != NULL
             && psColDef->field_index < poLayerDefn->GetFieldCount() )
+        {
             poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
+        }
+
+        if( poLayerDefn != NULL &&
+            IS_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index) )
+        {
+            bIsGeometry = TRUE;
+            iSrcGeomField =
+                ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index);
+            poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
+        }
+
+        if( psColDef->target_type == SWQ_GEOMETRY )
+            bIsGeometry = TRUE;
+
+        if( psColDef->col_func == SWQCF_COUNT )
+            bIsGeometry = FALSE;
 
-        if( strlen(psColDef->field_name) == 0 )
+        if( strlen(psColDef->field_name) == 0 && !bIsGeometry )
         {
             CPLFree( psColDef->field_name );
             psColDef->field_name = (char *) CPLMalloc(40);
-            sprintf( psColDef->field_name, "FIELD_%d", iField+1 );
+            sprintf( psColDef->field_name, "FIELD_%d", poDefn->GetFieldCount()+1 );
         }
 
         if( psColDef->field_alias != NULL )
         {
-            oFDefn.SetName(psColDef->field_alias);
+            if( bIsGeometry )
+                oGFDefn.SetName(psColDef->field_alias);
+            else
+                oFDefn.SetName(psColDef->field_alias);
         }
         else if( psColDef->col_func != SWQCF_NONE )
         {
@@ -206,23 +245,40 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
                 (swq_op) psColDef->col_func );
 
             oFDefn.SetName( CPLSPrintf( "%s_%s",
-                                        op->osName.c_str(),
+                                        op->pszName,
                                         psColDef->field_name ) );
         }
         else
-            oFDefn.SetName( psColDef->field_name );
+        {
+            if( bIsGeometry )
+                oGFDefn.SetName(psColDef->field_name);
+            else
+                oFDefn.SetName( psColDef->field_name );
+        }
 
         if( psColDef->col_func == SWQCF_COUNT )
             oFDefn.SetType( OFTInteger );
         else if( poSrcFDefn != NULL )
         {
-            oFDefn.SetType( poSrcFDefn->GetType() );
-            if( psColDef->col_func != SWQCF_AVG )
+            if( psColDef->col_func != SWQCF_AVG ||
+                psColDef->field_type == SWQ_DATE ||
+                psColDef->field_type == SWQ_TIME ||
+                psColDef->field_type == SWQ_TIMESTAMP )
+                oFDefn.SetType( poSrcFDefn->GetType() );
+            else
+                oFDefn.SetType( OFTReal );
+            if( psColDef->col_func != SWQCF_AVG &&
+                psColDef->col_func != SWQCF_SUM )
             {
                 oFDefn.SetWidth( poSrcFDefn->GetWidth() );
                 oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
             }
         }
+        else if( poSrcGFDefn != NULL )
+        {
+            oGFDefn.SetType( poSrcGFDefn->GetType() );
+            oGFDefn.SetSpatialRef( poSrcGFDefn->GetSpatialRef() );
+        }
         else if ( psColDef->field_index >= iFIDFieldIndex )
         {
             switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
@@ -281,6 +337,8 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
           case SWQ_TIME:
             oFDefn.SetType( OFTTime );
             break;
+          case SWQ_GEOMETRY:
+            break;
 
           default:
             CPLAssert( FALSE );
@@ -298,10 +356,88 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
             oFDefn.SetPrecision( psColDef->field_precision );
         }
 
-        poDefn->AddFieldDefn( &oFDefn );
+        if( bIsGeometry )
+        {
+            panGeomFieldToSrcGeomField[poDefn->GetGeomFieldCount()] = iSrcGeomField;
+            /* Hack while drivers haven't been updated so that */
+            /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == poSrcLayer->GetSpatialRef() */
+            if( iSrcGeomField == 0 &&
+                poSrcDefn->GetGeomFieldCount() == 1 &&
+                oGFDefn.GetSpatialRef() == NULL )
+            {
+                oGFDefn.SetSpatialRef(poSrcLayer->GetSpatialRef());
+            }
+            int bForceGeomType = FALSE;
+            if( psColDef->eGeomType != wkbUnknown )
+            {
+                oGFDefn.SetType( psColDef->eGeomType );
+                bForceGeomType = TRUE;
+            }
+            if( psColDef->nSRID > 0 )
+            {
+                OGRSpatialReference* poSRS = new OGRSpatialReference();
+                if( poSRS->importFromEPSG( psColDef->nSRID ) == OGRERR_NONE )
+                {
+                    oGFDefn.SetSpatialRef( poSRS );
+                }
+                poSRS->Release();
+            }
+
+            OGRGenSQLGeomFieldDefn* poMyGeomFieldDefn =
+                new OGRGenSQLGeomFieldDefn(&oGFDefn);
+            poMyGeomFieldDefn->bForceGeomType = bForceGeomType;
+            poDefn->AddGeomFieldDefn( poMyGeomFieldDefn, FALSE );
+        }
+        else
+            poDefn->AddFieldDefn( &oFDefn );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add implicit geometry field.                                    */
+/* -------------------------------------------------------------------- */
+    if( psSelectInfo->query_mode == SWQM_RECORDSET &&
+        poDefn->GetGeomFieldCount() == 0 &&
+        poSrcDefn->GetGeomFieldCount() == 1 )
+    {
+        psSelectInfo->result_columns++;
+
+        psSelectInfo->column_defs = (swq_col_def *) 
+            CPLRealloc( psSelectInfo->column_defs, sizeof(swq_col_def) * psSelectInfo->result_columns );
+
+        swq_col_def *col_def = psSelectInfo->column_defs + psSelectInfo->result_columns - 1;
+
+        memset( col_def, 0, sizeof(swq_col_def) );
+        const char* pszName = poSrcDefn->GetGeomFieldDefn(0)->GetNameRef();
+        if( *pszName != '\0' )
+            col_def->field_name = CPLStrdup( pszName );
+        else
+            col_def->field_name = CPLStrdup( OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME );
+        col_def->field_alias = NULL;
+        col_def->table_index = 0;
+        col_def->field_index = GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcDefn, 0);
+        col_def->field_type = SWQ_GEOMETRY;
+        col_def->target_type = SWQ_GEOMETRY;
+
+        panGeomFieldToSrcGeomField[poDefn->GetGeomFieldCount()] = 0;
+
+        OGRGenSQLGeomFieldDefn* poMyGeomFieldDefn =
+            new OGRGenSQLGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
+        poDefn->AddGeomFieldDefn( poMyGeomFieldDefn, FALSE );
+
+        /* Hack while drivers haven't been updated so that */
+        /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == poSrcLayer->GetSpatialRef() */
+        if( poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == NULL )
+        {
+            poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSrcLayer->GetSpatialRef());
+        }
     }
 
-    poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
+/* -------------------------------------------------------------------- */
+/*      Now that we have poSrcLayer, we can install a spatial filter    */
+/*      if there is one.                                                */
+/* -------------------------------------------------------------------- */
+    if( poSpatFilter != NULL )
+        SetSpatialFilter( 0, poSpatFilter );
 
     ResetReading();
 
@@ -334,6 +470,7 @@ OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
     papoTableLayers = NULL;
              
     CPLFree( panFIDIndex );
+    CPLFree( panGeomFieldToSrcGeomField );
 
     delete poSummaryFeature;
     delete (swq_select *) pSelectInfo;
@@ -407,6 +544,42 @@ void OGRGenSQLResultsLayer::ClearFilters()
 }
 
 /************************************************************************/
+/*                    MustEvaluateSpatialFilterOnGenSQL()               */
+/************************************************************************/
+
+int OGRGenSQLResultsLayer::MustEvaluateSpatialFilterOnGenSQL()
+{
+    int bEvaluateSpatialFilter = FALSE;
+    if( m_poFilterGeom != NULL &&
+        m_iGeomFieldFilter >= 0 &&
+        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
+    {
+        int iSrcGeomField = panGeomFieldToSrcGeomField[m_iGeomFieldFilter];
+        if( iSrcGeomField < 0 )
+            bEvaluateSpatialFilter = TRUE;
+    }
+    return bEvaluateSpatialFilter;
+}
+
+/************************************************************************/
+/*                       ApplyFiltersToSource()                         */
+/************************************************************************/
+
+void OGRGenSQLResultsLayer::ApplyFiltersToSource()
+{
+    poSrcLayer->SetAttributeFilter( pszWHERE );
+    if( m_iGeomFieldFilter >= 0 &&
+        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
+    {
+        int iSrcGeomField = panGeomFieldToSrcGeomField[m_iGeomFieldFilter];
+        if( iSrcGeomField >= 0 )
+            poSrcLayer->SetSpatialFilter( iSrcGeomField, m_poFilterGeom );
+    }
+
+    poSrcLayer->ResetReading();
+}
+
+/************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
 
@@ -417,10 +590,7 @@ void OGRGenSQLResultsLayer::ResetReading()
 
     if( psSelectInfo->query_mode == SWQM_RECORDSET )
     {
-        poSrcLayer->SetAttributeFilter( pszWHERE );
-        poSrcLayer->SetSpatialFilter( m_poFilterGeom );
-        
-        poSrcLayer->ResetReading();
+        ApplyFiltersToSource();
     }
 
     nNextIndexFID = 0;
@@ -457,31 +627,36 @@ OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex )
 /*                             GetExtent()                              */
 /************************************************************************/
 
-OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent, 
+OGRErr OGRGenSQLResultsLayer::GetExtent( int iGeomField,
+                                         OGREnvelope *psExtent, 
                                          int bForce )
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
 
-    if( psSelectInfo->query_mode == SWQM_RECORDSET )
-        return poSrcLayer->GetExtent( psExtent, bForce );
-    else
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
         return OGRERR_FAILURE;
-}
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef() 
-
-{
-    swq_select *psSelectInfo = (swq_select *) pSelectInfo;
+    }
 
-    if( psSelectInfo->query_mode != SWQM_RECORDSET )
-        return NULL;
+    if( psSelectInfo->query_mode == SWQM_RECORDSET )
+    {
+        int iSrcGeomField = panGeomFieldToSrcGeomField[iGeomField];
+        if( iSrcGeomField >= 0 )
+            return poSrcLayer->GetExtent( iSrcGeomField, psExtent, bForce );
+        else if( iGeomField == 0 )
+            return OGRLayer::GetExtent( psExtent, bForce );
+        else
+            return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
+    }
     else
-        return poSrcLayer->GetSpatialRef();
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -509,7 +684,7 @@ int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
     }
     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
         return 1;
-    else if( m_poAttrQuery == NULL )
+    else if( m_poAttrQuery == NULL && !MustEvaluateSpatialFilterOnGenSQL() )
         return poSrcLayer->GetFeatureCount( bForce );
     else
         return OGRLayer::GetFeatureCount( bForce );
@@ -556,14 +731,19 @@ int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node* expr)
 {
     if (expr->eNodeType == SNT_COLUMN)
     {
-        if( expr->table_index != -1 && expr->field_index != -1 )
+        if( expr->table_index == 0 && expr->field_index != -1 )
         {
             OGRLayer* poLayer = papoTableLayers[expr->table_index];
             int nSpecialFieldIdx = expr->field_index -
                             poLayer->GetLayerDefn()->GetFieldCount();
-            return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
-                   nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
-                   nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
+            if( nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
+                nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
+                nSpecialFieldIdx == SPF_OGR_GEOM_AREA )
+                return TRUE;
+            if( expr->field_index ==
+                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0) )
+                return TRUE;
+            return FALSE;
         }
     }
     else if (expr->eNodeType == SNT_OPERATION)
@@ -596,10 +776,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /*      Ensure our query parameters are in place on the source          */
 /*      layer.  And initialize reading.                                 */
 /* -------------------------------------------------------------------- */
-    poSrcLayer->SetAttributeFilter(pszWHERE);
-    poSrcLayer->SetSpatialFilter( m_poFilterGeom );
-        
-    poSrcLayer->ResetReading();
+    ApplyFiltersToSource();
 
 /* -------------------------------------------------------------------- */
 /*      Ignore geometry reading if no spatial filter in place and that  */
@@ -614,7 +791,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-            if (psColDef->table_index != -1 && psColDef->field_index != -1)
+            if (psColDef->table_index == 0 && psColDef->field_index != -1)
             {
                 OGRLayer* poLayer = papoTableLayers[psColDef->table_index];
                 int nSpecialFieldIdx = psColDef->field_index -
@@ -626,6 +803,12 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                     bFoundGeomExpr = TRUE;
                     break;
                 }
+                if( psColDef->field_index ==
+                        GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0) )
+                {
+                    bFoundGeomExpr = TRUE;
+                    break;
+                }
             }
             if (psColDef->expr != NULL && ContainGeomSpecialField(psColDef->expr))
             {
@@ -670,6 +853,16 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                 /* psColDef->field_index can be -1 in the case of a COUNT(*) */
                 if (psColDef->field_index < 0)
                     pszError = swq_select_summarize( psSelectInfo, iField, "" );
+                else if (IS_GEOM_FIELD_INDEX(poSrcLayer->GetLayerDefn(), psColDef->field_index) )
+                {
+                    int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
+                            poSrcLayer->GetLayerDefn(), psColDef->field_index);
+                    OGRGeometry* poGeom = poSrcFeature->GetGeomFieldRef(iSrcGeomField);
+                    if( poGeom != NULL )
+                        pszError = swq_select_summarize( psSelectInfo, iField, "" );
+                    else
+                        pszError = NULL;
+                }
                 else if (poSrcFeature->IsFieldSet(psColDef->field_index))
                     pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
                                                 psColDef->field_index ) );
@@ -735,12 +928,43 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                 swq_summary *psSummary = psSelectInfo->column_summary + iField;
 
                 if( psColDef->col_func == SWQCF_AVG )
-                    poSummaryFeature->SetField( iField,
-                                            psSummary->sum / psSummary->count );
+                {
+                    if( psColDef->field_type == SWQ_DATE ||
+                        psColDef->field_type == SWQ_TIME ||
+                        psColDef->field_type == SWQ_TIMESTAMP)
+                    {
+                        struct tm brokendowntime;
+                        CPLUnixTimeToYMDHMS((GIntBig)(psSummary->sum / psSummary->count), &brokendowntime);
+                        poSummaryFeature->SetField( iField,
+                                                    brokendowntime.tm_year + 1900,
+                                                    brokendowntime.tm_mon + 1,
+                                                    brokendowntime.tm_mday,
+                                                    brokendowntime.tm_hour,
+                                                    brokendowntime.tm_min,
+                                                    brokendowntime.tm_sec, 0);
+                    }
+                    else
+                        poSummaryFeature->SetField( iField,
+                                                    psSummary->sum / psSummary->count );
+                }
                 else if( psColDef->col_func == SWQCF_MIN )
-                    poSummaryFeature->SetField( iField, psSummary->min );
+                {
+                    if( psColDef->field_type == SWQ_DATE ||
+                        psColDef->field_type == SWQ_TIME ||
+                        psColDef->field_type == SWQ_TIMESTAMP)
+                        poSummaryFeature->SetField( iField, psSummary->szMin );
+                    else
+                        poSummaryFeature->SetField( iField, psSummary->min );
+                }
                 else if( psColDef->col_func == SWQCF_MAX )
-                    poSummaryFeature->SetField( iField, psSummary->max );
+                {
+                    if( psColDef->field_type == SWQ_DATE ||
+                        psColDef->field_type == SWQ_TIME ||
+                        psColDef->field_type == SWQ_TIMESTAMP)
+                        poSummaryFeature->SetField( iField, psSummary->szMax );
+                    else
+                        poSummaryFeature->SetField( iField, psSummary->max );
+                }
                 else if( psColDef->col_func == SWQCF_COUNT )
                     poSummaryFeature->SetField( iField, psSummary->count );
                 else if( psColDef->col_func == SWQCF_SUM )
@@ -812,6 +1036,20 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
                 poFeature->GetFieldAsDouble(op->field_index) );
         break;
         
+      case SWQ_GEOMETRY:
+        if( poFeature == NULL )
+        {
+            poRetNode = new swq_expr_node( (OGRGeometry*) NULL );
+        }
+        else
+        {
+            int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
+                poFeature->GetDefnRef(), op->field_index);
+            poRetNode = new swq_expr_node(
+                poFeature->GetGeomFieldRef(iSrcGeomField) );
+        }
+        break;
+
       default:
         if( poFeature == NULL 
             || !poFeature->IsFieldSet(op->field_index) )
@@ -937,20 +1175,27 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 
     poDstFeat->SetFID( poSrcFeat->GetFID() );
 
-    poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
-
     poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
 
 /* -------------------------------------------------------------------- */
 /*      Evaluate fields that are complex expressions.                   */
 /* -------------------------------------------------------------------- */
+    int iRegularField = 0;
+    int iGeomField = 0;
     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     {
         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
         swq_expr_node *poResult;
 
         if( psColDef->field_index != -1 )
+        {
+            if( psColDef->field_type == SWQ_GEOMETRY ||
+                psColDef->target_type == SWQ_GEOMETRY )
+                iGeomField++;
+            else
+                iRegularField++;
             continue;
+        }
 
         poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher, 
                                              (void *) &apoFeatures );
@@ -963,6 +1208,10 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 
         if( poResult->is_null )
         {
+            if( poResult->field_type == SWQ_GEOMETRY )
+                iGeomField++;
+            else
+                iRegularField++;
             delete poResult;
             continue;
         }
@@ -970,15 +1219,53 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
         switch( poResult->field_type )
         {
           case SWQ_INTEGER:
-            poDstFeat->SetField( iField, poResult->int_value );
+            poDstFeat->SetField( iRegularField++, poResult->int_value );
             break;
             
           case SWQ_FLOAT:
-            poDstFeat->SetField( iField, poResult->float_value );
+            poDstFeat->SetField( iRegularField++, poResult->float_value );
             break;
             
+          case SWQ_GEOMETRY:
+          {
+            OGRGenSQLGeomFieldDefn* poGeomFieldDefn =
+                (OGRGenSQLGeomFieldDefn*) poDstFeat->GetGeomFieldDefnRef(iGeomField);
+            if( poGeomFieldDefn->bForceGeomType &&
+                poResult->geometry_value != NULL )
+            {
+                OGRwkbGeometryType eCurType =
+                    wkbFlatten(poResult->geometry_value->getGeometryType());
+                OGRwkbGeometryType eReqType =
+                    wkbFlatten(poGeomFieldDefn->GetType());
+                if( eCurType == wkbPolygon && eReqType == wkbMultiPolygon )
+                {
+                    poResult->geometry_value = (OGRGeometry*)
+                        OGR_G_ForceToMultiPolygon( (OGRGeometryH) poResult->geometry_value );
+                }
+                else if( (eCurType == wkbMultiPolygon || eCurType == wkbGeometryCollection) &&
+                         eReqType == wkbPolygon )
+                {
+                    poResult->geometry_value = (OGRGeometry*)
+                        OGR_G_ForceToPolygon( (OGRGeometryH) poResult->geometry_value );
+                }
+                else if( eCurType == wkbLineString && eReqType == wkbMultiLineString )
+                {
+                    poResult->geometry_value = (OGRGeometry*)
+                        OGR_G_ForceToMultiLineString( (OGRGeometryH) poResult->geometry_value );
+                }
+                else if( (eCurType == wkbMultiLineString || eCurType == wkbGeometryCollection) &&
+                         eReqType == wkbLineString )
+                {
+                    poResult->geometry_value = (OGRGeometry*)
+                        OGR_G_ForceToLineString( (OGRGeometryH) poResult->geometry_value );
+                }
+            }
+            poDstFeat->SetGeomField( iGeomField++, poResult->geometry_value );
+            break;
+          }
+            
           default:
-            poDstFeat->SetField( iField, poResult->string_value );
+            poDstFeat->SetField( iRegularField++, poResult->string_value );
             break;
         }
 
@@ -988,51 +1275,73 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 /* -------------------------------------------------------------------- */
 /*      Copy fields from primary record to the destination feature.     */
 /* -------------------------------------------------------------------- */
+    iRegularField = 0;
+    iGeomField = 0;
     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     {
         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
 
         if( psColDef->table_index != 0 )
+        {
+            if( psColDef->field_type == SWQ_GEOMETRY ||
+                psColDef->target_type == SWQ_GEOMETRY )
+                iGeomField++;
+            else
+                iRegularField++;
             continue;
+        }
 
-        if ( psColDef->field_index >= iFIDFieldIndex &&
-            psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
+        if( IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(), psColDef->field_index) )
+        {
+            int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
+                poSrcFeat->GetDefnRef(), psColDef->field_index);
+            poDstFeat->SetGeomField( iGeomField ++,
+                                     poSrcFeat->GetGeomFieldRef(iSrcGeomField) );
+        }
+        else if( psColDef->field_index >= iFIDFieldIndex &&
+                 psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
         {
             switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
             {
               case SWQ_INTEGER:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
                 break;
               case SWQ_FLOAT:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
                 break;
               default:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
             }
+            iRegularField ++;
         }
         else
         {
             switch (psColDef->target_type)
             {
               case SWQ_INTEGER:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
                 break;
 
               case SWQ_FLOAT:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
                 break;
               
               case SWQ_STRING:
               case SWQ_TIMESTAMP:
               case SWQ_DATE:
               case SWQ_TIME:
-                poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
+                poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
                 break;
+                
+              case SWQ_GEOMETRY:
+                  CPLAssert(0);
+                  break;
 
               default:
-                poDstFeat->SetField( iField,
+                poDstFeat->SetField( iRegularField,
                          poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
             }
+            iRegularField ++;
         }
     }
 
@@ -1050,14 +1359,21 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             continue;
 
         // Copy over selected field values. 
+        iRegularField = 0;
         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-            
+
+            if( psColDef->field_type == SWQ_GEOMETRY ||
+                psColDef->target_type == SWQ_GEOMETRY )
+                continue;
+
             if( psColDef->table_index == psJoinInfo->secondary_table )
-                poDstFeat->SetField( iField,
+                poDstFeat->SetField( iRegularField,
                                      poJoinFeature->GetRawFieldRef( 
                                          psColDef->field_index ) );
+
+            iRegularField ++;
         }
 
         delete poJoinFeature;
@@ -1084,6 +1400,8 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
         return GetFeature( nNextIndexFID++ );
 
+    int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
+
 /* -------------------------------------------------------------------- */
 /*      Handle ordered sets.                                            */
 /* -------------------------------------------------------------------- */
@@ -1107,8 +1425,10 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
         if( poFeature == NULL )
             return NULL;
 
-        if( m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature ) )
+        if( (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) &&
+            (!bEvaluateSpatialFilter ||
+             FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) )) )
             return poFeature;
 
         delete poFeature;
@@ -1518,7 +1838,12 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
         OGRFieldDefn *poFDefn;
 
-        if( psKeyDef->field_index >= iFIDFieldIndex )
+        if( psKeyDef->field_index >= iFIDFieldIndex + SPECIAL_FIELD_COUNT )
+        {
+            CPLAssert( FALSE );
+            return 0;
+        }
+        else if( psKeyDef->field_index >= iFIDFieldIndex )
             poFDefn = NULL;
         else
             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
@@ -1718,8 +2043,11 @@ OGRErr OGRGenSQLResultsLayer::SetAttributeFilter( const char* pszAttributeFilter
 /*                       SetSpatialFilter()                             */
 /************************************************************************/
 
-void OGRGenSQLResultsLayer::SetSpatialFilter( OGRGeometry * poGeom )
+void OGRGenSQLResultsLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
 {
     InvalidateOrderByIndex();
-    OGRLayer::SetSpatialFilter(poGeom);
+    if( iGeomField == 0 )
+        OGRLayer::SetSpatialFilter(poGeom);
+    else
+        OGRLayer::SetSpatialFilter(iGeomField, poGeom);
 }
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.h b/ogr/ogrsf_frmts/generic/ogr_gensql.h
index 4c43034..ca64375 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.h
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gensql.h 24634 2012-07-01 14:39:00Z rouault $
+ * $Id: ogr_gensql.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of ExecuteSQL().
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,6 +35,16 @@
 #include "swq.h"
 #include "cpl_hash_set.h"
 
+#define GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poFDefn, iGeom) \
+    ((poFDefn)->GetFieldCount() + SPECIAL_FIELD_COUNT + (iGeom))
+
+#define IS_GEOM_FIELD_INDEX(poFDefn, idx) \
+    (((idx) >= (poFDefn)->GetFieldCount() + SPECIAL_FIELD_COUNT) && \
+     ((idx) < (poFDefn)->GetFieldCount() + SPECIAL_FIELD_COUNT + (poFDefn)->GetGeomFieldCount()))
+
+#define ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poFDefn, idx) \
+    ((idx) - ((poFDefn)->GetFieldCount() + SPECIAL_FIELD_COUNT))
+
 /************************************************************************/
 /*                        OGRGenSQLResultsLayer                         */
 /************************************************************************/
@@ -52,6 +63,8 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     OGRFeatureDefn *poDefn;
 
     int         PrepareSummary();
+    
+    int        *panGeomFieldToSrcGeomField;
 
     int         nIndexSize;
     long       *panFIDIndex;
@@ -72,6 +85,7 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     int         Compare( OGRField *pasFirst, OGRField *pasSecond );
 
     void        ClearFilters();
+    void        ApplyFiltersToSource();
 
     void        FindAndSetIgnoredFields();
     void        ExploreExprForIgnoredFields(swq_expr_node* expr, CPLHashSet* hSet);
@@ -80,6 +94,8 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     int         ContainGeomSpecialField(swq_expr_node* expr);
 
     void        InvalidateOrderByIndex();
+    
+    int         MustEvaluateSpatialFilterOnGenSQL();
 
   public:
                 OGRGenSQLResultsLayer( OGRDataSource *poSrcDS, 
@@ -98,14 +114,14 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
 
     virtual OGRFeatureDefn *GetLayerDefn();
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual int         GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
 
     virtual int         TestCapability( const char * );
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
     virtual OGRErr      SetAttributeFilter( const char * );
 };
 
diff --git a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
index e1f39eb..f59fcfc 100644
--- a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_miattrind.cpp 20104 2010-07-18 17:34:53Z tamas $
+ * $Id: ogr_miattrind.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements interface to MapInfo .ID files used as attribute
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "mitab/mitab_priv.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogr_miattrind.cpp 20104 2010-07-18 17:34:53Z tamas $");
+CPL_CVSID("$Id: ogr_miattrind.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRMIAttrIndex                            */
diff --git a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
index 8c59bbb..31b9a68 100644
--- a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdatasource.cpp 24813 2012-08-20 21:08:33Z rouault $
+ * $Id: ogrdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,7 +41,7 @@
 #include "../sqlite/ogrsqliteexecutesql.h"
 #endif
 
-CPL_CVSID("$Id: ogrdatasource.cpp 24813 2012-08-20 21:08:33Z rouault $");
+CPL_CVSID("$Id: ogrdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRDataSource()                           */
@@ -265,8 +266,16 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
     }
 
     CPLErrorReset();
-    poDstLayer = CreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
-                              poSrcDefn->GetGeomType(), papszOptions );
+    if( poSrcDefn->GetGeomFieldCount() > 1 &&
+        TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+    {
+        poDstLayer = CreateLayer( pszNewName, NULL, wkbNone, papszOptions );
+    }
+    else
+    {
+        poDstLayer = CreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
+                                  poSrcDefn->GetGeomType(), papszOptions );
+    }
     
     if( poDstLayer == NULL )
         return NULL;
@@ -327,6 +336,19 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Create geometry fields.                                         */
+/* -------------------------------------------------------------------- */
+    if( poSrcDefn->GetGeomFieldCount() > 1 &&
+        TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+    {
+        int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
+        for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
+        {
+            poDstLayer->CreateGeomField( poSrcDefn->GetGeomFieldDefn(iField) );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Check if the destination layer supports transactions and set a  */
 /*      default number of features in a single transaction.             */
 /* -------------------------------------------------------------------- */
@@ -361,6 +383,7 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
                       "Unable to translate feature %ld from layer %s.\n",
                       poFeature->GetFID(), poSrcDefn->GetName() );
             OGRFeature::DestroyFeature( poFeature );
+            CPLFree(panMap);
             return poDstLayer;
         }
 
@@ -372,6 +395,7 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
         if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
         {
             OGRFeature::DestroyFeature( poDstFeature );
+            CPLFree(panMap);
             return poDstLayer;
         }
 
@@ -406,10 +430,10 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
 
             if( papoDstFeature[nFeatCount]->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
             {
-                OGRFeature::DestroyFeature( poFeature );
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to translate feature %ld from layer %s.\n",
                           poFeature->GetFID(), poSrcDefn->GetName() );
+                OGRFeature::DestroyFeature( poFeature );
                 bStopTransfer = TRUE;
                 break;
             }
@@ -737,7 +761,10 @@ OGRErr OGRDataSource::ProcessSQLDropIndex( const char *pszSQLCommand )
             {
                 eErr = poLayer->GetIndex()->DropIndex( i );
                 if( eErr != OGRERR_NONE )
+                {
+                    CSLDestroy(papszTokens);
                     return eErr;
+                }
             }
         }
 
@@ -1515,6 +1542,8 @@ OGRLayer* OGRDataSource::BuildLayerFromSelectInfo(void* psSelectInfoIn,
         }
 
         nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
+        if( iTable == 0 )
+            nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
     }
     
 /* -------------------------------------------------------------------- */
@@ -1562,6 +1591,12 @@ OGRLayer* OGRDataSource::BuildLayerFromSelectInfo(void* psSelectInfoIn,
                 sFieldList.types[iOutField] = SWQ_FLOAT;
             else if( poFDefn->GetType() == OFTString )
                 sFieldList.types[iOutField] = SWQ_STRING;
+            else if( poFDefn->GetType() == OFTTime )
+                sFieldList.types[iOutField] = SWQ_TIME;
+            else if( poFDefn->GetType() == OFTDate )
+                sFieldList.types[iOutField] = SWQ_DATE;
+            else if( poFDefn->GetType() == OFTDateTime )
+                sFieldList.types[iOutField] = SWQ_TIMESTAMP;
             else
                 sFieldList.types[iOutField] = SWQ_OTHER;
 
@@ -1570,7 +1605,25 @@ OGRLayer* OGRDataSource::BuildLayerFromSelectInfo(void* psSelectInfoIn,
         }
 
         if( iTable == 0 )
-            nFIDIndex = poSrcLayer->GetLayerDefn()->GetFieldCount();
+        {
+            nFIDIndex = sFieldList.count;
+
+            for( iField = 0; 
+                 iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
+                 iField++ )
+            {
+                OGRGeomFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
+                int iOutField = sFieldList.count++;
+                sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
+                if( *sFieldList.names[iOutField] == '\0' )
+                    sFieldList.names[iOutField] = (char*) OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME;
+                sFieldList.types[iOutField] = SWQ_GEOMETRY;
+
+                sFieldList.table_ids[iOutField] = iTable;
+                sFieldList.ids[iOutField] =
+                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcLayer->GetLayerDefn(), iField);
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1872,3 +1925,14 @@ void OGR_DS_SetStyleTable( OGRDataSourceH hDS, OGRStyleTableH hStyleTable )
     
     ((OGRDataSource *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
 }
+
+/************************************************************************/
+/*                         IsGenericSQLDialect()                        */
+/************************************************************************/
+
+int OGRDataSource::IsGenericSQLDialect(const char* pszDialect)
+{
+    return ( pszDialect != NULL && (EQUAL(pszDialect,"OGRSQL") ||
+                                    EQUAL(pszDialect,"SQLITE")) );
+
+}
diff --git a/ogr/ogrsf_frmts/generic/ogrlayer.cpp b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
index ee41636..4284322 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayer.cpp 26015 2013-05-20 08:19:40Z warmerdam $
+ * $Id: ogrlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogr_attrind.h"
 #include "swq.h"
 
-CPL_CVSID("$Id: ogrlayer.cpp 26015 2013-05-20 08:19:40Z warmerdam $");
+CPL_CVSID("$Id: ogrlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                              OGRLayer()                              */
@@ -44,6 +45,7 @@ OGRLayer::OGRLayer()
 {
     m_poStyleTable = NULL;
     m_poAttrQuery = NULL;
+    m_pszAttrQueryString = NULL;
     m_poAttrIndex = NULL;
     m_nRefCount = 0;
 
@@ -52,6 +54,7 @@ OGRLayer::OGRLayer()
     m_poFilterGeom = NULL;
     m_bFilterIsEnvelope = FALSE;
     m_pPreparedFilterGeom = NULL;
+    m_iGeomFieldFilter = 0;
 }
 
 /************************************************************************/
@@ -79,6 +82,8 @@ OGRLayer::~OGRLayer()
         m_poAttrQuery = NULL;
     }
 
+    CPLFree( m_pszAttrQueryString );
+
     if( m_poFilterGeom )
     {
         delete m_poFilterGeom;
@@ -201,6 +206,21 @@ int OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
 OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 {
+    return GetExtentInternal(0, psExtent, bForce);
+}
+
+OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce )
+
+{
+    if( iGeomField == 0 )
+        return GetExtent(psExtent, bForce);
+    else
+        return GetExtentInternal(iGeomField, psExtent, bForce);
+}
+
+OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce )
+
+{
     OGRFeature  *poFeature;
     OGREnvelope oEnv;
     GBool       bExtentSet = FALSE;
@@ -214,8 +234,16 @@ OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 /*      If this layer has a none geometry type, then we can             */
 /*      reasonably assume there are not extents available.              */
 /* -------------------------------------------------------------------- */
-    if( GetLayerDefn()->GetGeomType() == wkbNone )
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
         return OGRERR_FAILURE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If not forced, we should avoid having to scan all the           */
@@ -231,7 +259,7 @@ OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     ResetReading();
     while( (poFeature = GetNextFeature()) != NULL )
     {
-        OGRGeometry *poGeom = poFeature->GetGeometryRef();
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
         if (poGeom == NULL || poGeom->IsEmpty())
         {
             /* Do nothing */
@@ -273,12 +301,28 @@ OGRErr OGR_L_GetExtent( OGRLayerH hLayer, OGREnvelope *psExtent, int bForce )
 }
 
 /************************************************************************/
+/*                         OGR_L_GetExtentEx()                          */
+/************************************************************************/
+
+OGRErr OGR_L_GetExtentEx( OGRLayerH hLayer, int iGeomField,
+                          OGREnvelope *psExtent, int bForce )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_GetExtentEx", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->GetExtent( iGeomField, psExtent, bForce );
+}
+
+/************************************************************************/
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
 OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Are we just clearing any existing query?                        */
 /* -------------------------------------------------------------------- */
@@ -379,16 +423,30 @@ OGRFeature *OGRLayer::GetFeature( long nFID )
 {
     OGRFeature *poFeature;
 
+    /* Save old attribute and spatial filters */
+    char* pszOldFilter = m_pszAttrQueryString ? CPLStrdup(m_pszAttrQueryString) : NULL;
+    OGRGeometry* poOldFilterGeom = ( m_poFilterGeom != NULL ) ? m_poFilterGeom->clone() : NULL;
+    int iOldGeomFieldFilter = m_iGeomFieldFilter;
+    /* Unset filters */
+    SetAttributeFilter(NULL);
+    SetSpatialFilter(0, NULL);
+
     ResetReading();
     while( (poFeature = GetNextFeature()) != NULL )
     {
         if( poFeature->GetFID() == nFID )
-            return poFeature;
+            break;
         else
             delete poFeature;
     }
     
-    return NULL;
+    /* Restore filters */
+    SetAttributeFilter(pszOldFilter);
+    CPLFree(pszOldFilter);
+    SetSpatialFilter(iOldGeomFieldFilter, poOldFilterGeom);
+    delete poOldFilterGeom;
+    
+    return poFeature;
 }
 
 /************************************************************************/
@@ -697,6 +755,37 @@ OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFie
 }
 
 /************************************************************************/
+/*                         CreateGeomField()                            */
+/************************************************************************/
+
+OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn * poField, int bApproxOK )
+
+{
+    (void) poField;
+    (void) bApproxOK;
+
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "CreateGeomField() not supported by this layer.\n" );
+              
+    return OGRERR_UNSUPPORTED_OPERATION;
+}
+
+/************************************************************************/
+/*                        OGR_L_CreateGeomField()                       */
+/************************************************************************/
+
+OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+                              int bApproxOK )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1( hField, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->CreateGeomField( (OGRGeomFieldDefn *) hField, 
+                                                   bApproxOK );
+}
+
+/************************************************************************/
 /*                          StartTransaction()                          */
 /************************************************************************/
 
@@ -775,6 +864,39 @@ OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
 }
 
 /************************************************************************/
+/*                         OGR_L_FindFieldIndex()                       */
+/************************************************************************/
+
+int OGR_L_FindFieldIndex( OGRLayerH hLayer, const char *pszFieldName, int bExactMatch )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_FindFieldIndex", -1 );
+
+    return ((OGRLayer *)hLayer)->FindFieldIndex( pszFieldName, bExactMatch );
+}
+
+/************************************************************************/
+/*                           FindFieldIndex()                           */
+/************************************************************************/
+
+int OGRLayer::FindFieldIndex( const char *pszFieldName, int bExactMatch )
+{
+    return GetLayerDefn()->GetFieldIndex( pszFieldName );
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRLayer::GetSpatialRef()
+{ 
+    if( GetLayerDefn()->GetGeomFieldCount() > 0 )
+        return GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
+    else
+        return NULL;
+}
+
+/************************************************************************/
 /*                        OGR_L_GetSpatialRef()                         */
 /************************************************************************/
 
@@ -828,10 +950,35 @@ OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer )
 void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 
 {
+    m_iGeomFieldFilter = 0;
     if( InstallFilter( poGeomIn ) )
         ResetReading();
 }
 
+
+void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+
+{
+    if( iGeomField == 0 )
+    {
+        m_iGeomFieldFilter = iGeomField;
+        SetSpatialFilter( poGeomIn );
+    }
+    else
+    {
+        if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+            return;
+        }
+
+        m_iGeomFieldFilter = iGeomField;
+        if( InstallFilter( poGeomIn ) )
+            ResetReading();
+    }
+}
+
 /************************************************************************/
 /*                       OGR_L_SetSpatialFilter()                       */
 /************************************************************************/
@@ -845,6 +992,18 @@ void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
 }
 
 /************************************************************************/
+/*                      OGR_L_SetSpatialFilterEx()                      */
+/************************************************************************/
+
+void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField, 
+                               OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterEx" );
+
+    ((OGRLayer *) hLayer)->SetSpatialFilter( iGeomField, (OGRGeometry *) hGeom );
+}
+/************************************************************************/
 /*                        SetSpatialFilterRect()                        */
 /************************************************************************/
 
@@ -852,6 +1011,15 @@ void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
                                      double dfMaxX, double dfMaxY )
 
 {
+    SetSpatialFilterRect( 0, dfMinX, dfMinY, dfMaxX, dfMaxY );
+}
+
+
+void OGRLayer::SetSpatialFilterRect( int iGeomField, 
+                                     double dfMinX, double dfMinY, 
+                                     double dfMaxX, double dfMaxY )
+
+{
     OGRLinearRing  oRing;
     OGRPolygon oPoly;
 
@@ -863,7 +1031,11 @@ void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
 
     oPoly.addRing( &oRing );
 
-    SetSpatialFilter( &oPoly );
+    if( iGeomField == 0 )
+        /* for drivers that only overload SetSpatialFilter(OGRGeometry*) */
+        SetSpatialFilter( &oPoly );
+    else
+        SetSpatialFilter( iGeomField, &oPoly );
 }
 
 /************************************************************************/
@@ -882,6 +1054,23 @@ void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
 }
 
 /************************************************************************/
+/*                    OGR_L_SetSpatialFilterRectEx()                    */
+/************************************************************************/
+
+void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
+                                   int iGeomField,
+                                   double dfMinX, double dfMinY, 
+                                   double dfMaxX, double dfMaxY )
+
+{
+    VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRectEx" );
+
+    ((OGRLayer *) hLayer)->SetSpatialFilterRect( iGeomField,
+                                                 dfMinX, dfMinY, 
+                                                 dfMaxX, dfMaxY );
+}
+
+/************************************************************************/
 /*                           InstallFilter()                            */
 /*                                                                      */
 /*      This method is only intended to be used from within             */
@@ -1226,7 +1415,10 @@ const char *OGR_L_GetFIDColumn( OGRLayerH hLayer )
 const char *OGRLayer::GetGeometryColumn()
 
 {
-    return "";
+    if( GetLayerDefn()->GetGeomFieldCount() > 0 )
+        return GetLayerDefn()->GetGeomFieldDefn(0)->GetNameRef();
+    else
+        return "";
 }
 
 /************************************************************************/
@@ -1387,7 +1579,16 @@ OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
             // check ordinary fields
             int iField = poDefn->GetFieldIndex(pszFieldName);
             if ( iField == -1 )
-                return OGRERR_FAILURE;
+            {
+                // check geometry field
+                iField = poDefn->GetGeomFieldIndex(pszFieldName);
+                if ( iField == -1 )
+                {
+                    return OGRERR_FAILURE;
+                }
+                else
+                    poDefn->GetGeomFieldDefn(iField)->SetIgnored( TRUE );
+            }
             else
                 poDefn->GetFieldDefn(iField)->SetIgnored( TRUE );
         }
@@ -1471,8 +1672,14 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
             if( pszInputPrefix != NULL )
                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix, oFieldDefn.GetNameRef()));
             ret = pLayerResult->CreateField(&oFieldDefn);
-            if (!bSkipFailures && ret != OGRERR_NONE) return ret;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) 
+                    return ret;
+                else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
             mapInput[iField] = iField;
         }
         if (!combined) return ret;
@@ -1482,8 +1689,14 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
             if( pszMethodPrefix != NULL )
                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix, oFieldDefn.GetNameRef()));
             ret = pLayerResult->CreateField(&oFieldDefn);
-            if (!bSkipFailures && ret != OGRERR_NONE) return ret;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) 
+                    return ret;
+                else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
             mapMethod[iField] = nFieldsInput+iField;
         }
     }
@@ -1678,8 +1891,15 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
                 delete y;
                 ret = pLayerResult->CreateFeature(z);
                 delete z;
-                if (!bSkipFailures && ret != OGRERR_NONE) {delete x; goto done;}
-                ret = OGRERR_NONE;
+                if (ret != OGRERR_NONE) {
+                    if (!bSkipFailures) {
+                        delete x; 
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                }
             }
         }
 
@@ -1923,8 +2143,17 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
                 delete y;
                 ret = pLayerResult->CreateFeature(z);
                 delete z;
-                if (!bSkipFailures && ret != OGRERR_NONE) {delete x; if (x_geom_diff) delete x_geom_diff; goto done;}
-                ret = OGRERR_NONE;
+                if (ret != OGRERR_NONE) {
+                    if (!bSkipFailures) {
+                        delete x;
+                        if (x_geom_diff)
+                            delete x_geom_diff;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                }
             }
         }
 
@@ -1943,8 +2172,14 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
             delete x;
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
 
@@ -1999,8 +2234,14 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
             delete x;
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
@@ -2244,8 +2485,14 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
         if (z) {
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
 
@@ -2300,8 +2547,14 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
         if (z) {
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
@@ -2542,8 +2795,16 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
                 delete y;
                 ret = pLayerResult->CreateFeature(z);
                 delete z;
-                if (!bSkipFailures && ret != OGRERR_NONE) {delete x; delete x_geom_diff; goto done;}
-                ret = OGRERR_NONE;
+                if (ret != OGRERR_NONE) {
+                    if (!bSkipFailures) {
+                        delete x;
+                        delete x_geom_diff;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                }
             }
         }
 
@@ -2562,8 +2823,14 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
             delete x;
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
@@ -2800,8 +3067,14 @@ OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
             delete x;
             ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
 
@@ -2831,8 +3104,14 @@ OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
         delete y;
         ret = pLayerResult->CreateFeature(z);
         delete z;
-        if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-        ret = OGRERR_NONE;
+        if (ret != OGRERR_NONE) {
+            if (!bSkipFailures) {
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
@@ -3068,8 +3347,14 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
                 ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
@@ -3299,8 +3584,14 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
                 ret = pLayerResult->CreateFeature(z);
             delete z;
-            if (!bSkipFailures && ret != OGRERR_NONE) goto done;
-            ret = OGRERR_NONE;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
         }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
index 12bdcf0..8d11f1e 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.cpp 24633 2012-07-01 14:37:25Z rouault $
+ * $Id: ogrlayerdecorator.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRLayerDecorator class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogrlayerdecorator.h"
 
-CPL_CVSID("$Id: ogrlayerdecorator.cpp 24633 2012-07-01 14:37:25Z rouault $");
+CPL_CVSID("$Id: ogrlayerdecorator.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 OGRLayerDecorator::OGRLayerDecorator(OGRLayer* poDecoratedLayer,
                                      int bTakeOwnership) :
@@ -56,12 +56,23 @@ void        OGRLayerDecorator::SetSpatialFilter( OGRGeometry * poGeom )
     m_poDecoratedLayer->SetSpatialFilter(poGeom);
 }
 
+void        OGRLayerDecorator::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
+{
+    m_poDecoratedLayer->SetSpatialFilter(iGeomField, poGeom);
+}
+
 void        OGRLayerDecorator::SetSpatialFilterRect( double dfMinX, double dfMinY,
                                   double dfMaxX, double dfMaxY )
 {
     m_poDecoratedLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
 }
 
+void        OGRLayerDecorator::SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                  double dfMaxX, double dfMaxY )
+{
+    m_poDecoratedLayer->SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
 OGRErr      OGRLayerDecorator::SetAttributeFilter( const char * poAttrFilter )
 {
     return m_poDecoratedLayer->SetAttributeFilter(poAttrFilter);
@@ -132,6 +143,11 @@ OGRErr      OGRLayerDecorator::GetExtent(OGREnvelope *psExtent, int bForce)
     return m_poDecoratedLayer->GetExtent(psExtent, bForce);
 }
 
+OGRErr      OGRLayerDecorator::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+{
+    return m_poDecoratedLayer->GetExtent(iGeomField, psExtent, bForce);
+}
+
 int         OGRLayerDecorator::TestCapability( const char * pszCapability )
 {
     return m_poDecoratedLayer->TestCapability(pszCapability);
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
index 291f1e6..182d85a 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.h 24633 2012-07-01 14:37:25Z rouault $
+ * $Id: ogrlayerdecorator.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerDecorator class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -48,6 +48,9 @@ class OGRLayerDecorator : public OGRLayer
     virtual void        SetSpatialFilter( OGRGeometry * );
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
                                               double dfMaxX, double dfMaxY );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -66,6 +69,7 @@ class OGRLayerDecorator : public OGRLayer
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
 
     virtual int         TestCapability( const char * );
@@ -94,6 +98,8 @@ class OGRLayerDecorator : public OGRLayer
     virtual const char *GetGeometryColumn();
 
     virtual OGRErr      SetIgnoredFields( const char **papszFields );
+
+    OGRLayer* GetBaseLayer()    { return m_poDecoratedLayer; }
 };
 
 #endif // _OGRLAYERDECORATOR_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
index 9933a20..905bb1a 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrlayerpool.cpp 24646 2012-07-02 07:21:55Z rouault $
+ * $Id: ogrlayerpool.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogrlayerpool.h"
 
-CPL_CVSID("$Id: ogrlayerpool.cpp 24646 2012-07-02 07:21:55Z rouault $");
+CPL_CVSID("$Id: ogrlayerpool.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      OGRAbstractProxiedLayer()                       */
@@ -227,7 +227,7 @@ OGRGeometry *OGRProxiedLayer::GetSpatialFilter()
 }
 
 /************************************************************************/
-/*                          GetSpatialFilter()                          */
+/*                          SetSpatialFilter()                          */
 /************************************************************************/
 
 void        OGRProxiedLayer::SetSpatialFilter( OGRGeometry * poGeom )
@@ -237,6 +237,15 @@ void        OGRProxiedLayer::SetSpatialFilter( OGRGeometry * poGeom )
 }
 
 /************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void        OGRProxiedLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
+{
+    if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return;
+    poUnderlyingLayer->SetSpatialFilter(iGeomField, poGeom);
+}
+/************************************************************************/
 /*                          SetAttributeFilter()                        */
 /************************************************************************/
 
@@ -391,6 +400,16 @@ int         OGRProxiedLayer::GetFeatureCount( int bForce )
 /*                             GetExtent()                              */
 /************************************************************************/
 
+OGRErr      OGRProxiedLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+{
+    if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return OGRERR_FAILURE;
+    return poUnderlyingLayer->GetExtent(iGeomField, psExtent, bForce);
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
 OGRErr      OGRProxiedLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 {
     if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return OGRERR_FAILURE;
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.h b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
index ef62c25..a0bc8bf 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrlayerpool.h 24642 2012-07-01 20:45:46Z rouault $
+ * $Id: ogrlayerpool.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -110,6 +110,7 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
 
     virtual OGRGeometry *GetSpatialFilter();
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -128,6 +129,7 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
 
     virtual int         TestCapability( const char * );
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
new file mode 100644
index 0000000..fa18b3f
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * $Id: ogrmutexeddatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRMutexedDataSource class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrmutexeddatasource.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: ogrmutexeddatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+OGRMutexedDataSource::OGRMutexedDataSource(OGRDataSource* poBaseDataSource,
+                                           int bTakeOwnership,
+                                           void* hMutexIn) :
+            m_poBaseDataSource(poBaseDataSource),
+            m_bHasOwnership(bTakeOwnership),
+            m_hGlobalMutex(hMutexIn)
+{
+}
+
+OGRMutexedDataSource::~OGRMutexedDataSource()
+{
+    if( m_bHasOwnership )
+        delete m_poBaseDataSource;
+}
+
+const char  *OGRMutexedDataSource::GetName()
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->GetName();
+}
+
+int         OGRMutexedDataSource::GetLayerCount()
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->GetLayerCount();
+}
+
+OGRLayer    *OGRMutexedDataSource::GetLayer(int iIndex)
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->GetLayer(iIndex);
+}
+
+OGRLayer    *OGRMutexedDataSource::GetLayerByName(const char *pszName)
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->GetLayerByName(pszName);
+}
+
+OGRErr      OGRMutexedDataSource::DeleteLayer(int iIndex)
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->DeleteLayer(iIndex);
+}
+
+int         OGRMutexedDataSource::TestCapability( const char * pszCap )
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->TestCapability(pszCap);
+}
+
+OGRLayer   *OGRMutexedDataSource::CreateLayer( const char *pszName, 
+                                     OGRSpatialReference *poSpatialRef,
+                                     OGRwkbGeometryType eGType,
+                                     char ** papszOptions)
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->CreateLayer(pszName, poSpatialRef, eGType, papszOptions);
+}
+
+OGRLayer   *OGRMutexedDataSource::CopyLayer( OGRLayer *poSrcLayer, 
+                                   const char *pszNewName, 
+                                   char **papszOptions )
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->CopyLayer(poSrcLayer, pszNewName, papszOptions );
+}
+
+OGRStyleTable *OGRMutexedDataSource::GetStyleTable()
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->GetStyleTable();
+}
+
+void        OGRMutexedDataSource::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    m_poBaseDataSource->SetStyleTableDirectly(poStyleTable);
+}
+
+void        OGRMutexedDataSource::SetStyleTable(OGRStyleTable *poStyleTable)
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    m_poBaseDataSource->SetStyleTable(poStyleTable);
+}
+
+OGRLayer *  OGRMutexedDataSource::ExecuteSQL( const char *pszStatement,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect )
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->ExecuteSQL(pszStatement, poSpatialFilter,
+                                          pszDialect);
+}
+
+void        OGRMutexedDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    m_poBaseDataSource->ReleaseResultSet(poResultsSet);
+}
+
+OGRErr      OGRMutexedDataSource::SyncToDisk()
+{
+    CPLMutexHolderOptionalLockD(m_hGlobalMutex);
+    return m_poBaseDataSource->SyncToDisk();
+}
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
new file mode 100644
index 0000000..9321dad
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * $Id: ogrmutexeddatasource.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Defines OGRLMutexedDataSource class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
+#define _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+/** OGRMutexedDataSource class protects all virtual methods of OGRDataSource
+ *  with a mutex.
+ *  If the passed mutex is NULL, then no locking will be done.
+ *
+ *  Note that the constructors and destructors are not explictely protected
+ *  by the mutex*
+ */
+class CPL_DLL OGRMutexedDataSource : public OGRDataSource
+{
+  protected:
+    OGRDataSource *m_poBaseDataSource;
+    int            m_bHasOwnership;
+    void          *m_hGlobalMutex;
+
+  public:
+
+    /* The construction of the object isn't protected by the mutex */
+                 OGRMutexedDataSource(OGRDataSource* poBaseDataSource,
+                                      int bTakeOwnership,
+                                      void* hMutexIn);
+
+    /* The destruction of the object isn't protected by the mutex */
+    virtual     ~OGRMutexedDataSource();
+
+    virtual const char  *GetName();
+
+    virtual int         GetLayerCount() ;
+    virtual OGRLayer    *GetLayer(int);
+    virtual OGRLayer    *GetLayerByName(const char *);
+    virtual OGRErr      DeleteLayer(int);
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRLayer   *CreateLayer( const char *pszName, 
+                                     OGRSpatialReference *poSpatialRef = NULL,
+                                     OGRwkbGeometryType eGType = wkbUnknown,
+                                     char ** papszOptions = NULL );
+    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer, 
+                                   const char *pszNewName, 
+                                   char **papszOptions = NULL );
+
+    virtual OGRStyleTable *GetStyleTable();
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+                            
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
+
+    virtual OGRErr      SyncToDisk();
+};
+
+#endif // _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
new file mode 100644
index 0000000..f24481f
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
@@ -0,0 +1,258 @@
+/******************************************************************************
+ * $Id: ogrmutexedlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRMutexedLayer class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrmutexedlayer.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: ogrmutexedlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+OGRMutexedLayer::OGRMutexedLayer(OGRLayer* poDecoratedLayer,
+                                 int bTakeOwnership,
+                                 void* hMutex) :
+        OGRLayerDecorator(poDecoratedLayer, bTakeOwnership), m_hMutex(hMutex)
+{
+}
+
+OGRMutexedLayer::~OGRMutexedLayer()
+{
+}
+
+
+OGRGeometry *OGRMutexedLayer::GetSpatialFilter()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetSpatialFilter();
+}
+
+void        OGRMutexedLayer::SetSpatialFilter( OGRGeometry * poGeom )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    OGRLayerDecorator::SetSpatialFilter(poGeom);
+}
+
+void        OGRMutexedLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                  double dfMaxX, double dfMaxY )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    OGRLayerDecorator::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+void        OGRMutexedLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    OGRLayerDecorator::SetSpatialFilter(iGeomField, poGeom);
+}
+
+void        OGRMutexedLayer::SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                  double dfMaxX, double dfMaxY )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    OGRLayerDecorator::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+OGRErr      OGRMutexedLayer::SetAttributeFilter( const char * poAttrFilter )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetAttributeFilter(poAttrFilter);
+}
+
+void        OGRMutexedLayer::ResetReading()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    OGRLayerDecorator::ResetReading();
+}
+
+OGRFeature *OGRMutexedLayer::GetNextFeature()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetNextFeature();
+}
+
+OGRErr      OGRMutexedLayer::SetNextByIndex( long nIndex )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetNextByIndex(nIndex);
+}
+
+OGRFeature *OGRMutexedLayer::GetFeature( long nFID )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetFeature(nFID);
+}
+
+OGRErr      OGRMutexedLayer::SetFeature( OGRFeature *poFeature )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetFeature(poFeature);
+}
+
+OGRErr      OGRMutexedLayer::CreateFeature( OGRFeature *poFeature )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::CreateFeature(poFeature);
+}
+
+OGRErr      OGRMutexedLayer::DeleteFeature( long nFID )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::DeleteFeature(nFID);
+}
+
+const char *OGRMutexedLayer::GetName()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetName();
+}
+
+OGRwkbGeometryType OGRMutexedLayer::GetGeomType()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetGeomType();
+}
+
+OGRFeatureDefn *OGRMutexedLayer::GetLayerDefn()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetLayerDefn();
+}
+
+OGRSpatialReference *OGRMutexedLayer::GetSpatialRef()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetSpatialRef();
+}
+
+int         OGRMutexedLayer::GetFeatureCount( int bForce )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetFeatureCount(bForce);
+}
+
+OGRErr      OGRMutexedLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetExtent(iGeomField, psExtent, bForce);
+}
+
+OGRErr      OGRMutexedLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetExtent(psExtent, bForce);
+}
+
+int         OGRMutexedLayer::TestCapability( const char * pszCapability )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::TestCapability(pszCapability);
+}
+
+OGRErr      OGRMutexedLayer::CreateField( OGRFieldDefn *poField,
+                                            int bApproxOK )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::CreateField(poField, bApproxOK);
+}
+
+OGRErr      OGRMutexedLayer::DeleteField( int iField )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::DeleteField(iField);
+}
+
+OGRErr      OGRMutexedLayer::ReorderFields( int* panMap )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::ReorderFields(panMap);
+}
+
+OGRErr      OGRMutexedLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+}
+
+OGRErr      OGRMutexedLayer::SyncToDisk()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SyncToDisk();
+}
+
+OGRStyleTable *OGRMutexedLayer::GetStyleTable()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetStyleTable();
+}
+
+void        OGRMutexedLayer::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetStyleTableDirectly(poStyleTable);
+}
+
+void        OGRMutexedLayer::SetStyleTable(OGRStyleTable *poStyleTable)
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetStyleTable(poStyleTable);
+}
+
+OGRErr      OGRMutexedLayer::StartTransaction()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::StartTransaction();
+}
+
+OGRErr      OGRMutexedLayer::CommitTransaction()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::CommitTransaction();
+}
+
+OGRErr      OGRMutexedLayer::RollbackTransaction()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::RollbackTransaction();
+}
+
+const char *OGRMutexedLayer::GetFIDColumn()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetFIDColumn();
+}
+
+const char *OGRMutexedLayer::GetGeometryColumn()
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::GetGeometryColumn();
+}
+
+OGRErr      OGRMutexedLayer::SetIgnoredFields( const char **papszFields )
+{
+    CPLMutexHolderOptionalLockD(m_hMutex);
+    return OGRLayerDecorator::SetIgnoredFields(papszFields);
+}
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
new file mode 100644
index 0000000..5d0ffe2
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ * $Id: ogrmutexedlayer.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Defines OGRLMutexedLayer class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGRMUTEXEDLAYER_H_INCLUDED
+#define _OGRMUTEXEDLAYER_H_INCLUDED
+
+#include "ogrlayerdecorator.h"
+
+/** OGRMutexedLayer class protects all virtual methods of OGRLayer with a mutex.
+ *
+ *  If the passed mutex is NULL, then no locking will be done.
+ *
+ *  Note that the constructors and destructors are not explictely protected
+ *  by the mutex.
+ */
+class CPL_DLL OGRMutexedLayer : public OGRLayerDecorator
+{
+  protected:
+        void          *m_hMutex;
+
+  public:
+
+    /* The construction of the object isn't protected by the mutex */
+                       OGRMutexedLayer(OGRLayer* poDecoratedLayer,
+                                       int bTakeOwnership,
+                                       void* hMutex);
+
+    /* The destruction of the object isn't protected by the mutex */
+    virtual           ~OGRMutexedLayer();
+
+    virtual OGRGeometry *GetSpatialFilter();
+    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRErr      SetNextByIndex( long nIndex );
+    virtual OGRFeature *GetFeature( long nFID );
+    virtual OGRErr      SetFeature( OGRFeature *poFeature );
+    virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( long nFID );
+
+    virtual const char *GetName();
+    virtual OGRwkbGeometryType GetGeomType();
+    virtual OGRFeatureDefn *GetLayerDefn();
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual int         GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+    virtual int         TestCapability( const char * );
+
+    /* Deprecated (and un-implemented method) --> we won't decorate it ! */
+    /* virtual const char *GetInfo( const char * ); */
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual OGRErr      DeleteField( int iField );
+    virtual OGRErr      ReorderFields( int* panMap );
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+
+    virtual OGRErr      SyncToDisk();
+
+    virtual OGRStyleTable *GetStyleTable();
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+
+    virtual OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+
+    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+};
+
+#endif // _OGRMUTEXEDLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
index fcb211d..30d1d1c 100644
--- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrregisterall.cpp 24669 2012-07-10 16:04:24Z rouault $
+ * $Id: ogrregisterall.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Function to register all known OGR drivers.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrregisterall.cpp 24669 2012-07-10 16:04:24Z rouault $");
+CPL_CVSID("$Id: ogrregisterall.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRRegisterAll()                           */
@@ -101,6 +102,7 @@ void OGRRegisterAll()
     RegisterOGRGMT();
 #endif
 #ifdef SQLITE_ENABLED
+    RegisterOGRGeoPackage();
     RegisterOGRSQLite();
 #endif
 #ifdef DODS_ENABLED
@@ -109,6 +111,9 @@ void OGRRegisterAll()
 #ifdef ODBC_ENABLED
     RegisterOGRODBC();
 #endif
+#ifdef WASP_ENABLED
+    RegisterOGRWAsP();
+#endif
 
 /* Register before PGeo and Geomedia drivers */
 /* that don't work well on Linux */
@@ -143,6 +148,10 @@ void OGRRegisterAll()
 #ifdef SDE_ENABLED
     RegisterOGRSDE();
 #endif
+/* Register OpenFileGDB before FGDB as it is more capable for read-only */
+#ifdef OPENFILEGDB_ENABLED
+    RegisterOGROpenFileGDB();
+#endif
 #ifdef FGDB_ENABLED
     RegisterOGRFileGDB();
 #endif
@@ -203,7 +212,7 @@ void OGRRegisterAll()
     RegisterOGRWFS();
 #endif
 #ifdef SOSI_ENABLED 
-	RegisterOGRSOSI(); 
+    RegisterOGRSOSI(); 
 #endif
 #ifdef HTF_ENABLED
     RegisterOGRHTF();
@@ -220,6 +229,9 @@ void OGRRegisterAll()
 #ifdef GFT_ENABLED
     RegisterOGRGFT();
 #endif
+#ifdef GME_ENABLED
+    RegisterOGRGME();
+#endif
 #ifdef SVG_ENABLED
     RegisterOGRSVG();
 #endif
@@ -253,4 +265,13 @@ void OGRRegisterAll()
 #ifdef PDF_ENABLED
     RegisterOGRPDF();
 #endif
+#ifdef WALK_ENABLED
+    RegisterOGRWalk();
+#endif
+#ifdef CARTODB_ENABLED
+    RegisterOGRCartoDB();
+#endif
+#ifdef SXF_ENABLED
+    RegisterOGRSXF();
+#endif
 } /* OGRRegisterAll */
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
index ebb43f8..611f9df 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriver.cpp 23413 2011-11-22 21:53:32Z rouault $
+ * $Id: ogrsfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFDriver class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsfdriver.cpp 23413 2011-11-22 21:53:32Z rouault $");
+CPL_CVSID("$Id: ogrsfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSFDriver()                            */
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
index 5b51ab6..df1f474 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriverregistrar.cpp 25329 2012-12-17 18:38:43Z mloskot $
+ * $Id: ogrsfdriverregistrar.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSFDriverRegistrar class implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 #include <unistd.h>
 #endif
 
-CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 25329 2012-12-17 18:38:43Z mloskot $");
+CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void *hDRMutex = NULL;
 static OGRSFDriverRegistrar * volatile poRegistrar = NULL;
@@ -147,7 +148,6 @@ void OGRCleanupAll()
         if( poRegistrar != NULL )
             delete poRegistrar;
         OSRCleanup();
-        swq_op_registrar::DeInitialize();
     }
 
     CPLDestroyMutex( hDRMutex );
@@ -761,6 +761,9 @@ OGRSFDriverH OGRGetDriverByName( const char *pszName )
  * There are a few rules for the driver path.  If the GDAL_DRIVER_PATH 
  * environment variable it set, it is taken to be a list of directories to 
  * search separated by colons on unix, or semi-colons on Windows.  
+ * 
+ * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
+ * config option to "disable".
  *
  * If that is not set the following defaults are used:
  *
@@ -788,6 +791,16 @@ void OGRSFDriverRegistrar::AutoLoadDrivers()
             CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
 
 /* -------------------------------------------------------------------- */
+/*      Allow applications to completely disable this search by         */
+/*      setting the driver path to the special string "disable".        */
+/* -------------------------------------------------------------------- */
+    if( pszGDAL_DRIVER_PATH != NULL && EQUAL(pszGDAL_DRIVER_PATH,"disable")) 
+    {
+        CPLDebug( "GDAL", "OGRSFDriverRegistrar::AutoLoadDrivers() disabled." );
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Where should we look for stuff?                                 */
 /* -------------------------------------------------------------------- */
     if( pszGDAL_DRIVER_PATH != NULL )
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
index 172547d..a633d2a 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrunionlayer.cpp 24640 2012-07-01 19:37:38Z rouault $
+ * $Id: ogrunionlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRUnionLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,50 @@
 #include "ogrwarpedlayer.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrunionlayer.cpp 24640 2012-07-01 19:37:38Z rouault $");
+CPL_CVSID("$Id: ogrunionlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+/************************************************************************/
+/*                      OGRUnionLayerGeomFieldDefn()                    */
+/************************************************************************/
+
+OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char* pszName,
+                                                       OGRwkbGeometryType eType) :
+        OGRGeomFieldDefn(pszName, eType), bGeomTypeSet(FALSE), bSRSSet(FALSE)
+{
+}
+
+/************************************************************************/
+/*                      OGRUnionLayerGeomFieldDefn()                    */
+/************************************************************************/
+
+OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
+                                    OGRGeomFieldDefn* poSrc) :
+    OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
+    bGeomTypeSet(FALSE), bSRSSet(FALSE)
+{
+    SetSpatialRef(poSrc->GetSpatialRef());
+}
+
+/************************************************************************/
+/*                      OGRUnionLayerGeomFieldDefn()                    */
+/************************************************************************/
+
+OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
+                                    OGRUnionLayerGeomFieldDefn* poSrc) :
+    OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
+    bGeomTypeSet(poSrc->bGeomTypeSet), bSRSSet(poSrc->bSRSSet)
+{
+    SetSpatialRef(poSrc->GetSpatialRef());
+    sStaticEnvelope = poSrc->sStaticEnvelope;
+}
+
+/************************************************************************/
+/*                     ~OGRUnionLayerGeomFieldDefn()                    */
+/************************************************************************/
+
+OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn()
+{
+}
 
 /************************************************************************/
 /*                          OGRUnionLayer()                             */
@@ -52,24 +95,21 @@ OGRUnionLayer::OGRUnionLayer( const char* pszName,
     poFeatureDefn = NULL;
     nFields = 0;
     papoFields = NULL;
+    nGeomFields = 0;
+    papoGeomFields = NULL;
     eFieldStrategy = FIELD_UNION_ALL_LAYERS;
 
-    eGeomType = wkbUnknown;
-    eGeometryTypeStrategy = GEOMTYPE_UNION_ALL_LAYERS;
-
     bPreserveSrcFID = FALSE;
 
     nFeatureCount = -1;
 
-    poSRS = NULL;
-    bSRSSet = FALSE;
-
     iCurLayer = -1;
     pszAttributeFilter = NULL;
     nNextFID = 0;
     panMap = NULL;
     papszIgnoredFields = NULL;
     bAttrFilterPassThroughValue = -1;
+    poGlobalSRS = NULL;
 
     pabModifiedLayers = (int*)CPLCalloc(sizeof(int), nSrcLayers);
     pabCheckIfAutoWrap = (int*)CPLCalloc(sizeof(int), nSrcLayers);
@@ -93,6 +133,9 @@ OGRUnionLayer::~OGRUnionLayer()
     for(i = 0; i < nFields; i++)
         delete papoFields[i];
     CPLFree(papoFields);
+    for(i = 0; i < nGeomFields; i++)
+        delete papoGeomFields[i];
+    CPLFree(papoGeomFields);
 
     CPLFree(pszAttributeFilter);
     CPLFree(panMap);
@@ -100,25 +143,10 @@ OGRUnionLayer::~OGRUnionLayer()
     CPLFree(pabModifiedLayers);
     CPLFree(pabCheckIfAutoWrap);
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     if( poFeatureDefn )
         poFeatureDefn->Release();
-}
-
-/************************************************************************/
-/*                               SetSRS()                               */
-/************************************************************************/
-
-void OGRUnionLayer::SetSRS(OGRSpatialReference *poSRSIn)
-{
-    CPLAssert(poFeatureDefn == NULL);
-
-    bSRSSet = TRUE;
-    if( poSRS )
-        poSRS->Release();
-    poSRS = (poSRSIn != NULL) ? poSRSIn->Clone() : NULL;
+    if( poGlobalSRS != NULL )
+        poGlobalSRS->Release();
 }
 
 /************************************************************************/
@@ -127,7 +155,9 @@ void OGRUnionLayer::SetSRS(OGRSpatialReference *poSRSIn)
 
 void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
                               int nFieldsIn,
-                              OGRFieldDefn** papoFieldsIn)
+                              OGRFieldDefn** papoFieldsIn,
+                              int nGeomFieldsIn,
+                              OGRUnionLayerGeomFieldDefn** papoGeomFieldsIn)
 {
     CPLAssert(nFields == 0);
     CPLAssert(poFeatureDefn == NULL);
@@ -140,20 +170,14 @@ void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
         for(int i=0;i<nFields;i++)
             papoFields[i] = new OGRFieldDefn(papoFieldsIn[i]);
     }
-}
-
-/************************************************************************/
-/*                          SetGeometryType()                           */
-/************************************************************************/
-
-void OGRUnionLayer::SetGeometryType(GeometryTypeUnionStrategy
-                                                    eGeometryTypeStrategyIn,
-                                    OGRwkbGeometryType eGeomTypeIn)
-{
-    CPLAssert(poFeatureDefn == NULL);
-
-    eGeometryTypeStrategy = eGeometryTypeStrategyIn;
-    eGeomType = eGeomTypeIn;
+    nGeomFields = nGeomFieldsIn;
+    if( nGeomFields > 0 )
+    {
+        papoGeomFields = (OGRUnionLayerGeomFieldDefn** )CPLMalloc(
+                            nGeomFields * sizeof(OGRUnionLayerGeomFieldDefn*));
+        for(int i=0;i<nGeomFields;i++)
+            papoGeomFields[i] = new OGRUnionLayerGeomFieldDefn(papoGeomFieldsIn[i]);
+    }
 }
 
 /************************************************************************/
@@ -192,21 +216,6 @@ void OGRUnionLayer::SetFeatureCount(int nFeatureCountIn)
 }
 
 /************************************************************************/
-/*                              SetExtent()                             */
-/************************************************************************/
-
-void OGRUnionLayer::SetExtent( double dfXMin, double dfYMin,
-                               double dfXMax, double dfYMax )
-{
-    CPLAssert(poFeatureDefn == NULL);
-
-    sStaticEnvelope.MinX = dfXMin;
-    sStaticEnvelope.MinY = dfYMin;
-    sStaticEnvelope.MaxX = dfXMax;
-    sStaticEnvelope.MaxY = dfYMax;
-}
-
-/************************************************************************/
 /*                         MergeFieldDefn()                             */
 /************************************************************************/
 
@@ -241,6 +250,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
 
     poFeatureDefn = new OGRFeatureDefn( osName );
     poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType(wkbNone);
 
     int iCompareFirstIndex = 0;
     if( osSourceLayerFieldName.size() )
@@ -252,24 +262,79 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
 
     if( eFieldStrategy == FIELD_SPECIFIED )
     {
-        for(int i = 0; i < nFields; i++)
+        int i;
+        for(i = 0; i < nFields; i++)
             poFeatureDefn->AddFieldDefn(papoFields[i]);
+        for(i = 0; i < nGeomFields; i++)
+        {
+            poFeatureDefn->AddGeomFieldDefn(new OGRUnionLayerGeomFieldDefn(papoGeomFields[i]), FALSE);
+            OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
+                (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(i);
+
+            if( poGeomFieldDefn->bGeomTypeSet == FALSE ||
+                poGeomFieldDefn->bSRSSet == FALSE )
+            {
+                for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
+                {
+                    OGRFeatureDefn* poSrcFeatureDefn =
+                                papoSrcLayers[iLayer]->GetLayerDefn();
+                    int nIndex =
+                        poSrcFeatureDefn->GetGeomFieldIndex(poGeomFieldDefn->GetNameRef());
+                    if( nIndex >= 0 )
+                    {
+                        OGRGeomFieldDefn* poSrcGeomFieldDefn =
+                            poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
+                        if( poGeomFieldDefn->bGeomTypeSet == FALSE )
+                        {
+                            poGeomFieldDefn->bGeomTypeSet = TRUE;
+                            poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType());
+                        }
+                        if( poGeomFieldDefn->bSRSSet == FALSE )
+                        {
+                            poGeomFieldDefn->bSRSSet = TRUE;
+                            poGeomFieldDefn->SetSpatialRef(poSrcGeomFieldDefn->GetSpatialRef());
+                            if( i == 0 && poGlobalSRS == NULL )
+                            {
+                                poGlobalSRS = poSrcGeomFieldDefn->GetSpatialRef();
+                                if( poGlobalSRS != NULL )
+                                    poGlobalSRS->Reference();
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
     }
     else if( eFieldStrategy == FIELD_FROM_FIRST_LAYER )
     {
         OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
-        for(int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
+        int i;
+        for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
+        for(i = 0;  nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+        {
+            OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
+            poFeatureDefn->AddGeomFieldDefn(
+                new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
+        }
     }
     else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS )
     {
+        if( nGeomFields == 1 )
+        {
+            poFeatureDefn->AddGeomFieldDefn(
+                        new OGRUnionLayerGeomFieldDefn(papoGeomFields[0]), FALSE);
+        }
+
         for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
         {
             OGRFeatureDefn* poSrcFeatureDefn =
                                 papoSrcLayers[iLayer]->GetLayerDefn();
 
             /* Add any field that is found in the source layers */
-            for(int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
+            int i;
+            for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
             {
                 OGRFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
                 int nIndex =
@@ -283,6 +348,45 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                     MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
                 }
             }
+
+            for(i = 0; nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+            {
+                OGRGeomFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
+                int nIndex =
+                    poFeatureDefn->GetGeomFieldIndex(poSrcFieldDefn->GetNameRef());
+                if( nIndex < 0 )
+                {
+                    poFeatureDefn->AddGeomFieldDefn(
+                        new OGRUnionLayerGeomFieldDefn(poSrcFieldDefn), FALSE);
+                    if( poFeatureDefn->GetGeomFieldCount() == 1 && nGeomFields == 0 &&
+                        GetSpatialRef() != NULL )
+                    {
+                        OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
+                            (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(0);
+                        poGeomFieldDefn->bSRSSet = TRUE;
+                        poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
+                    }
+                }
+                else
+                {
+                    if( nIndex == 0 && nGeomFields == 1 )
+                    {
+                        OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
+                            (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(0);
+                        if( poGeomFieldDefn->bGeomTypeSet == FALSE )
+                        {
+                            poGeomFieldDefn->bGeomTypeSet = TRUE;
+                            poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
+                        }
+                        if( poGeomFieldDefn->bSRSSet == FALSE )
+                        {
+                            poGeomFieldDefn->bSRSSet = TRUE;
+                            poGeomFieldDefn->SetSpatialRef(poSrcFieldDefn->GetSpatialRef());
+                        }
+                    }
+                    /* TODO: merge type, SRS, extent ? */
+                }
+            }
         }
     }
     else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS )
@@ -291,6 +395,12 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
         int i;
         for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
+        for(i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+        {
+            OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
+            poFeatureDefn->AddGeomFieldDefn(
+                new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
+        }
 
         /* Remove any field that is not found in the source layers */
         for(int iLayer = 1; iLayer < nSrcLayers; iLayer++)
@@ -315,11 +425,25 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                     i ++;
                 }
             }
+            for(i = 0; i < poFeatureDefn->GetGeomFieldCount();)
+            {
+                OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(i);
+                int nSrcIndex = poSrcFeatureDefn->GetGeomFieldIndex(
+                                                    poFieldDefn->GetNameRef());
+                if( nSrcIndex < 0 )
+                {
+                    poFeatureDefn->DeleteGeomFieldDefn(i);
+                }
+                else
+                {
+                    /* TODO: merge type, SRS, extent ? */
+
+                    i ++;
+                }
+            }
         }
     }
 
-    poFeatureDefn->SetGeomType(GetGeomType());
-
     return poFeatureDefn;
 }
 
@@ -329,26 +453,40 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
 
 OGRwkbGeometryType OGRUnionLayer::GetGeomType()
 {
-    if( eGeometryTypeStrategy == GEOMTYPE_SPECIFIED )
-        return eGeomType;
-
-    if( eGeometryTypeStrategy == GEOMTYPE_FROM_FIRST_LAYER )
+    if( nGeomFields < 0 )
+        return wkbNone;
+    if( nGeomFields >= 1 && papoGeomFields[0]->bGeomTypeSet )
     {
-        eGeomType = papoSrcLayers[0]->GetGeomType();
+        return papoGeomFields[0]->GetType();
     }
-    else if( eGeometryTypeStrategy == GEOMTYPE_UNION_ALL_LAYERS )
+
+    return OGRLayer::GetGeomType();
+}
+
+/************************************************************************/
+/*                    SetSpatialFilterToSourceLayer()                   */
+/************************************************************************/
+
+void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer* poSrcLayer)
+{
+    if( m_iGeomFieldFilter >= 0 &&
+        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
     {
-        eGeomType = papoSrcLayers[0]->GetGeomType();
-        for(int iLayer = 1; iLayer < nSrcLayers; iLayer++)
+        int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
+            GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
+        if( iSrcGeomField >= 0 )
         {
-            OGRwkbGeometryType eSrcGeomType =
-                                    papoSrcLayers[iLayer]->GetGeomType();
-            eGeomType = OGRMergeGeometryTypes(eGeomType, eSrcGeomType);
+            poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
+        }
+        else
+        {
+            poSrcLayer->SetSpatialFilter(NULL);
         }
     }
-    eGeometryTypeStrategy = GEOMTYPE_SPECIFIED;
-
-    return eGeomType;
+    else
+    {
+        poSrcLayer->SetSpatialFilter(NULL);
+    }
 }
 
 /************************************************************************/
@@ -359,7 +497,7 @@ void OGRUnionLayer::ConfigureActiveLayer()
 {
     AutoWarpLayerIfNecessary(iCurLayer);
     ApplyAttributeFilterToSrcLayer(iCurLayer);
-    papoSrcLayers[iCurLayer]->SetSpatialFilter(m_poFilterGeom);
+    SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
     papoSrcLayers[iCurLayer]->ResetReading();
 
     /* Establish map */
@@ -391,13 +529,15 @@ void OGRUnionLayer::ConfigureActiveLayer()
             const char* pszFieldName = *papszIter;
             if ( EQUAL(pszFieldName, "OGR_GEOMETRY") ||
                  EQUAL(pszFieldName, "OGR_STYLE") ||
-                 poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 )
+                 poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
+                 poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0 )
             {
                 papszFieldsSrc = CSLAddString(papszFieldsSrc, pszFieldName);
             }
             papszIter++;
         }
 
+        /* Attribute fields */
         int* panSrcFieldsUsed = (int*) CPLCalloc(sizeof(int),
                                           poSrcFeatureDefn->GetFieldCount());
         for(int iField = 0;
@@ -422,6 +562,31 @@ void OGRUnionLayer::ConfigureActiveLayer()
         }
         CPLFree(panSrcFieldsUsed);
 
+        /* geometry fields now */
+        panSrcFieldsUsed = (int*) CPLCalloc(sizeof(int),
+                                          poSrcFeatureDefn->GetGeomFieldCount());
+        for(int iField = 0;
+                iField < poFeatureDefn->GetGeomFieldCount(); iField++)
+        {
+            OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iField);
+            int iSrcField =
+                    poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+        }
+        for(int iSrcField = 0;
+                iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField ++)
+        {
+            if( !panSrcFieldsUsed[iSrcField] )
+            {
+                OGRGeomFieldDefn *poSrcDefn =
+                        poSrcFeatureDefn->GetGeomFieldDefn( iSrcField );
+                papszFieldsSrc =
+                        CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
+            }
+        }
+        CPLFree(panSrcFieldsUsed);
+
         papoSrcLayers[iCurLayer]->SetIgnoredFields((const char**)papszFieldsSrc);
 
         CSLDestroy(papszFieldsSrc);
@@ -449,36 +614,48 @@ void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
     {
         pabCheckIfAutoWrap[iLayer] = TRUE;
 
-        OGRSpatialReference* poSRS = GetSpatialRef();
-        if( poSRS != NULL )
-            poSRS->Reference();
+        for(int i=0; i<GetLayerDefn()->GetGeomFieldCount();i++)
+        {
+            OGRSpatialReference* poSRS = GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef();
+            if( poSRS != NULL )
+                poSRS->Reference();
+
+            OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[iLayer]->GetLayerDefn();
+            int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
+                    GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef());
+            if( iSrcGeomField >= 0 )
+            {
+                OGRSpatialReference* poSRS2 =
+                    poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
 
-        OGRSpatialReference* poSRS2 = papoSrcLayers[iLayer]->GetSpatialRef();
+                if( (poSRS == NULL && poSRS2 != NULL) ||
+                    (poSRS != NULL && poSRS2 == NULL) )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "SRS of geometry field '%s' layer %s not consistant with UnionLayer SRS",
+                            GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
+                            papoSrcLayers[iLayer]->GetName());
+                }
+                else if (poSRS != NULL && poSRS2 != NULL &&
+                        poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
+                {
+                    CPLDebug("VRT", "SRS of geometry field '%s' layer %s not consistant with UnionLayer SRS. "
+                            "Trying auto warping",
+                            GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
+                            papoSrcLayers[iLayer]->GetName());
+                    OGRCoordinateTransformation* poCT =
+                        OGRCreateCoordinateTransformation( poSRS2, poSRS );
+                    OGRCoordinateTransformation* poReversedCT = (poCT != NULL) ?
+                        OGRCreateCoordinateTransformation( poSRS, poSRS2 ) : NULL;
+                    if( poCT != NULL && poReversedCT != NULL )
+                        papoSrcLayers[iLayer] = new OGRWarpedLayer(
+                                    papoSrcLayers[iLayer], iSrcGeomField, TRUE, poCT, poReversedCT);
+                }
+            }
 
-        if( (poSRS == NULL && poSRS2 != NULL) ||
-            (poSRS != NULL && poSRS2 == NULL) )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "SRS of layer %s not consistant with layer SRS",
-                    papoSrcLayers[iLayer]->GetName());
-        }
-        else if (poSRS != NULL && poSRS2 != NULL &&
-                 poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
-        {
-            CPLDebug("VRT", "SRS of layer %s not consistant with layer SRS. "
-                     "Trying auto warping",
-                     papoSrcLayers[iLayer]->GetName());
-            OGRCoordinateTransformation* poCT =
-                OGRCreateCoordinateTransformation( poSRS2, poSRS );
-            OGRCoordinateTransformation* poReversedCT = (poCT != NULL) ?
-                OGRCreateCoordinateTransformation( poSRS, poSRS2 ) : NULL;
-            if( poCT != NULL && poReversedCT != NULL )
-                papoSrcLayers[iLayer] = new OGRWarpedLayer(
-                            papoSrcLayers[iLayer], TRUE, poCT, poReversedCT);
+            if( poSRS != NULL )
+                poSRS->Release();
         }
-
-        if( poSRS != NULL )
-            poSRS->Release();
     }
 }
 
@@ -514,7 +691,7 @@ OGRFeature *OGRUnionLayer::GetNextFeature()
         delete poSrcFeature;
 
         if( (m_poFilterGeom == NULL ||
-             FilterGeometry( poFeature->GetGeometryRef() ) ) &&
+             FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) ) &&
             (m_poAttrQuery == NULL ||
              m_poAttrQuery->Evaluate( poFeature )) )
         {
@@ -532,27 +709,41 @@ OGRFeature *OGRUnionLayer::GetNextFeature()
 
 OGRFeature *OGRUnionLayer::GetFeature( long nFeatureId )
 {
-    if( !bPreserveSrcFID )
-        return OGRLayer::GetFeature(nFeatureId);
+    OGRFeature* poFeature = NULL;
 
-    for(int i=0;i<nSrcLayers;i++)
+    if( !bPreserveSrcFID )
     {
-        iCurLayer = i;
-        ConfigureActiveLayer();
+        poFeature = OGRLayer::GetFeature(nFeatureId);
+    }
+    else
+    {
+        int iGeomFieldFilterSave = m_iGeomFieldFilter;
+        OGRGeometry* poGeomSave = m_poFilterGeom;
+        m_poFilterGeom = NULL;
+        SetSpatialFilter(NULL);
 
-        OGRFeature* poSrcFeature = papoSrcLayers[i]->GetFeature(nFeatureId);
-        if( poSrcFeature != NULL )
+        for(int i=0;i<nSrcLayers;i++)
         {
-            OGRFeature* poFeature = TranslateFromSrcLayer(poSrcFeature);
-            delete poSrcFeature;
+            iCurLayer = i;
+            ConfigureActiveLayer();
 
-            return poFeature;
+            OGRFeature* poSrcFeature = papoSrcLayers[i]->GetFeature(nFeatureId);
+            if( poSrcFeature != NULL )
+            {
+                poFeature = TranslateFromSrcLayer(poSrcFeature);
+                delete poSrcFeature;
+
+                break;
+            }
         }
-    }
 
-    ResetReading();
+        SetSpatialFilter(iGeomFieldFilterSave, poGeomSave);
+        delete poGeomSave;
 
-    return NULL;
+        ResetReading();
+    }
+
+    return poFeature;
 }
 
 /************************************************************************/
@@ -671,10 +862,19 @@ OGRErr OGRUnionLayer::SetFeature( OGRFeature* poFeature )
 
 OGRSpatialReference *OGRUnionLayer::GetSpatialRef()
 {
-    if( bSRSSet )
-        return poSRS;
-    else
-        return papoSrcLayers[0]->GetSpatialRef();
+    if( nGeomFields < 0 )
+        return NULL;
+    if( nGeomFields >= 1 &&
+        papoGeomFields[0]->bSRSSet )
+        return papoGeomFields[0]->GetSpatialRef();
+
+    if( poGlobalSRS == NULL )
+    {
+        poGlobalSRS = papoSrcLayers[0]->GetSpatialRef();
+        if( poGlobalSRS != NULL )
+            poGlobalSRS->Reference();
+    }
+    return poGlobalSRS;
 }
 
 /************************************************************************/
@@ -759,7 +959,7 @@ int OGRUnionLayer::GetFeatureCount( int bForce )
     {
         AutoWarpLayerIfNecessary(i);
         ApplyAttributeFilterToSrcLayer(i);
-        papoSrcLayers[i]->SetSpatialFilter(m_poFilterGeom);
+        SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
         nRet += papoSrcLayers[i]->GetFeatureCount(bForce);
     }
     ResetReading();
@@ -815,7 +1015,7 @@ int  OGRUnionLayer::TestCapability( const char * pszCap )
         {
             AutoWarpLayerIfNecessary(i);
             ApplyAttributeFilterToSrcLayer(i);
-            papoSrcLayers[i]->SetSpatialFilter(m_poFilterGeom);
+            SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
             if( !papoSrcLayers[i]->TestCapability(pszCap) )
                 return FALSE;
         }
@@ -824,7 +1024,8 @@ int  OGRUnionLayer::TestCapability( const char * pszCap )
 
     if( EQUAL(pszCap, OLCFastGetExtent ) )
     {
-        if( sStaticEnvelope.IsInit() )
+        if( nGeomFields >= 1 &&
+            papoGeomFields[0]->sStaticEnvelope.IsInit() )
             return TRUE;
 
         for(int i = 0; i < nSrcLayers; i++)
@@ -904,32 +1105,45 @@ int  OGRUnionLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                             GetExtent()                              */
+/*                              GetExtent()                             */
 /************************************************************************/
 
-OGRErr OGRUnionLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+OGRErr OGRUnionLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
 {
-    if( sStaticEnvelope.IsInit() )
+    if( iGeomField >= 0 && iGeomField < nGeomFields &&
+        papoGeomFields[iGeomField]->sStaticEnvelope.IsInit() )
     {
-        memcpy(psExtent, &sStaticEnvelope, sizeof(OGREnvelope));
+        memcpy(psExtent, &papoGeomFields[iGeomField]->sStaticEnvelope, sizeof(OGREnvelope));
         return OGRERR_NONE;
     }
+    
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        return OGRERR_FAILURE;
+    }
 
     int bInit = FALSE;
     for(int i = 0; i < nSrcLayers; i++)
     {
         AutoWarpLayerIfNecessary(i);
-        if( !bInit )
-        {
-            if( papoSrcLayers[i]->GetExtent(psExtent, bForce) == OGRERR_NONE )
-                bInit = TRUE;
-        }
-        else
+        int iSrcGeomField = papoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
+            GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
+        if( iSrcGeomField >= 0 )
         {
-            OGREnvelope sExtent;
-            if( papoSrcLayers[i]->GetExtent(&sExtent, bForce) == OGRERR_NONE )
+            if( !bInit )
             {
-                psExtent->Merge(sExtent);
+                if( papoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent, bForce) == OGRERR_NONE )
+                    bInit = TRUE;
+            }
+            else
+            {
+                OGREnvelope sExtent;
+                if( papoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent, bForce) == OGRERR_NONE )
+                {
+                    psExtent->Merge(sExtent);
+                }
             }
         }
     }
@@ -937,17 +1151,50 @@ OGRErr OGRUnionLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 }
 
 /************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRUnionLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+{
+    return GetExtent(0, psExtent, bForce);
+}
+
+/************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
 
 void OGRUnionLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 {
-    OGRLayer::SetSpatialFilter(poGeomIn);
+    SetSpatialFilter(0, poGeomIn);
+}
+
+/************************************************************************/
+/*                         SetSpatialFilter()                           */
+/************************************************************************/
+
+void OGRUnionLayer::SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+    {
+        if( poGeom != NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Invalid geometry field index : %d", iGeomField);
+            return;
+        }
+    }
+
+    m_iGeomFieldFilter = iGeomField;
+    if( InstallFilter( poGeom ) )
+        ResetReading();
 
     if( iCurLayer >= 0 && iCurLayer < nSrcLayers)
-        papoSrcLayers[iCurLayer]->SetSpatialFilter(poGeomIn);
+    {
+        SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
+    }
 }
 
+
 /************************************************************************/
 /*                        TranslateFromSrcLayer()                       */
 /************************************************************************/
@@ -966,13 +1213,19 @@ OGRFeature* OGRUnionLayer::TranslateFromSrcLayer(OGRFeature* poSrcFeature)
         poFeature->SetField(0, papoSrcLayers[iCurLayer]->GetName());
     }
 
-    if( poFeatureDefn->IsGeometryIgnored() )
-        poFeature->SetGeometryDirectly(NULL);
-    else
+    for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
     {
-        OGRGeometry* poGeom = poFeature->GetGeometryRef();
-        if( poGeom != NULL )
-            poGeom->assignSpatialReference(GetSpatialRef());
+        if( poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored() )
+            poFeature->SetGeomFieldDirectly(i, NULL);
+        else
+        {
+            OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+            if( poGeom != NULL )
+            {
+                poGeom->assignSpatialReference(
+                    poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
+            }
+        }
     }
 
     if( bPreserveSrcFID )
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.h b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
index 5b03dcd..5a93946 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrunionlayer.h 24640 2012-07-01 19:37:38Z rouault $
+ * $Id: ogrunionlayer.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRUnionLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,6 +33,24 @@
 #include "ogrsf_frmts.h"
 
 /************************************************************************/
+/*                      OGRUnionLayerGeomFieldDefn                      */
+/************************************************************************/
+
+class OGRUnionLayerGeomFieldDefn: public OGRGeomFieldDefn
+{
+    public:
+
+    int             bGeomTypeSet;
+    int             bSRSSet;
+    OGREnvelope     sStaticEnvelope;
+
+            OGRUnionLayerGeomFieldDefn(const char* pszName, OGRwkbGeometryType eType);
+            OGRUnionLayerGeomFieldDefn(OGRGeomFieldDefn* poSrc);
+            OGRUnionLayerGeomFieldDefn(OGRUnionLayerGeomFieldDefn* poSrc);
+           ~OGRUnionLayerGeomFieldDefn();
+};
+
+/************************************************************************/
 /*                         OGRUnionLayer                                */
 /************************************************************************/
 
@@ -44,13 +62,6 @@ typedef enum
     FIELD_SPECIFIED,
 } FieldUnionStrategy;
 
-typedef enum
-{
-    GEOMTYPE_FROM_FIRST_LAYER,
-    GEOMTYPE_UNION_ALL_LAYERS,
-    GEOMTYPE_SPECIFIED,
-} GeometryTypeUnionStrategy;
-
 class OGRUnionLayer : public OGRLayer
 {
   protected:
@@ -62,19 +73,14 @@ class OGRUnionLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
     int                 nFields;
     OGRFieldDefn      **papoFields;
+    int                 nGeomFields;
+    OGRUnionLayerGeomFieldDefn **papoGeomFields;
     FieldUnionStrategy eFieldStrategy;
     CPLString           osSourceLayerFieldName;
 
-    OGRwkbGeometryType  eGeomType;
-    GeometryTypeUnionStrategy eGeometryTypeStrategy;
-
     int                 bPreserveSrcFID;
 
-    OGRSpatialReference *poSRS;
-    int                  bSRSSet;
-
     int                 nFeatureCount;
-    OGREnvelope         sStaticEnvelope;
 
     int                 iCurLayer;
     char               *pszAttributeFilter;
@@ -84,12 +90,14 @@ class OGRUnionLayer : public OGRLayer
     int                 bAttrFilterPassThroughValue;
     int                *pabModifiedLayers;
     int                *pabCheckIfAutoWrap;
+    OGRSpatialReference *poGlobalSRS;
 
     void                AutoWarpLayerIfNecessary(int iSubLayer);
     OGRFeature         *TranslateFromSrcLayer(OGRFeature* poSrcFeature);
     void                ApplyAttributeFilterToSrcLayer(int iSubLayer);
     int                 GetAttrFilterPassThroughValue();
     void                ConfigureActiveLayer();
+    void                SetSpatialFilterToSourceLayer(OGRLayer* poSrcLayer);
 
   public:
                         OGRUnionLayer( const char* pszName,
@@ -101,17 +109,14 @@ class OGRUnionLayer : public OGRLayer
 
     /* All the following non virtual methods must be called just after the constructor */
     /* and before any virtual method */
-    void                SetSRS(OGRSpatialReference *poSRS);  /* duplicated by the method */
     void                SetFields(FieldUnionStrategy eFieldStrategy,
                                   int nFields,
-                                  OGRFieldDefn** papoFields); /* duplicated by the method */
-    void                SetGeometryType(GeometryTypeUnionStrategy eGeometryTypeStrategy,
-                                        OGRwkbGeometryType eGeomType);
+                                  OGRFieldDefn** papoFields,  /* duplicated by the method */
+                                  int nGeomFields, /* maybe -1 to explicitely disable geometry fields */
+                                  OGRUnionLayerGeomFieldDefn** papoGeomFields  /* duplicated by the method */);
     void                SetSourceLayerFieldName(const char* pszSourceLayerFieldName);
     void                SetPreserveSrcFID(int bPreserveSrcFID);
     void                SetFeatureCount(int nFeatureCount);
-    void                SetExtent(double dfXMin, double dfYMin, double dfXMax, double dfYMax);
-
     virtual const char  *GetName() { return osName.c_str(); }
     virtual OGRwkbGeometryType GetGeomType();
 
@@ -134,9 +139,11 @@ class OGRUnionLayer : public OGRLayer
 
     virtual int         TestCapability( const char * );
 
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
 
     virtual void        SetSpatialFilter( OGRGeometry * poGeomIn );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
 
     virtual OGRErr      SetIgnoredFields( const char **papszFields );
 
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
index d392d9a..408da69 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.cpp 24633 2012-07-01 14:37:25Z rouault $
+ * $Id: ogrwarpedlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWarpedLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,23 +29,27 @@
 
 #include "ogrwarpedlayer.h"
 
-CPL_CVSID("$Id: ogrwarpedlayer.cpp 24633 2012-07-01 14:37:25Z rouault $");
+CPL_CVSID("$Id: ogrwarpedlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRWarpedLayer()                            */
 /************************************************************************/
 
 OGRWarpedLayer::OGRWarpedLayer( OGRLayer* poDecoratedLayer,
+                                int iGeomField,
                                 int bTakeOwnership,
                                 OGRCoordinateTransformation* poCT,
                                 OGRCoordinateTransformation* poReversedCT ) :
                                       OGRLayerDecorator(poDecoratedLayer,
                                                         bTakeOwnership),
+                                      m_iGeomField(iGeomField),
                                       m_poCT(poCT),
                                       m_poReversedCT(poReversedCT)
 {
     CPLAssert(poCT != NULL);
 
+    m_poFeatureDefn = NULL;
+
     if( m_poCT->GetTargetCS() != NULL )
     {
         m_poSRS = m_poCT->GetTargetCS();
@@ -61,6 +65,8 @@ OGRWarpedLayer::OGRWarpedLayer( OGRLayer* poDecoratedLayer,
 
 OGRWarpedLayer::~OGRWarpedLayer()
 {
+    if( m_poFeatureDefn != NULL )
+        m_poFeatureDefn->Release();
     if( m_poSRS != NULL )
         m_poSRS->Release();
     delete m_poCT;
@@ -73,38 +79,139 @@ OGRWarpedLayer::~OGRWarpedLayer()
 
 void OGRWarpedLayer::SetSpatialFilter( OGRGeometry * poGeom )
 {
-    OGRLayer::SetSpatialFilter(poGeom);
+    SetSpatialFilter( 0, poGeom );
+}
+
+/************************************************************************/
+/*                          SetSpatialFilterRect()                      */
+/************************************************************************/
+
+void OGRWarpedLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                           double dfMaxX, double dfMaxY )
+{
+    OGRLayer::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+/************************************************************************/
+/*                         SetSpatialFilter()                           */
+/************************************************************************/
 
-    if( poGeom == NULL || m_poReversedCT == NULL )
+void OGRWarpedLayer::SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
     {
-        m_poDecoratedLayer->SetSpatialFilter(NULL);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Invalid geometry field index : %d", iGeomField);
+        return;
     }
-    else
+
+    m_iGeomFieldFilter = iGeomField;
+    if( InstallFilter( poGeom ) )
+        ResetReading();
+
+    if( m_iGeomFieldFilter == m_iGeomField )
     {
-        OGREnvelope sEnvelope;
-        poGeom->getEnvelope(&sEnvelope);
-        if( ReprojectEnvelope(&sEnvelope, m_poReversedCT) )
+        if( poGeom == NULL || m_poReversedCT == NULL )
         {
-            m_poDecoratedLayer->SetSpatialFilterRect(sEnvelope.MinX,
-                                                     sEnvelope.MinY,
-                                                     sEnvelope.MaxX,
-                                                     sEnvelope.MaxY);
+            m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
+                                                NULL);
         }
         else
         {
-            m_poDecoratedLayer->SetSpatialFilter(NULL);
+            OGREnvelope sEnvelope;
+            poGeom->getEnvelope(&sEnvelope);
+            if( CPLIsInf(sEnvelope.MinX) && CPLIsInf(sEnvelope.MinY) &&
+                CPLIsInf(sEnvelope.MaxX) && CPLIsInf(sEnvelope.MaxY) )
+            {
+                m_poDecoratedLayer->SetSpatialFilterRect(m_iGeomFieldFilter,
+                                                        sEnvelope.MinX,
+                                                        sEnvelope.MinY,
+                                                        sEnvelope.MaxX,
+                                                        sEnvelope.MaxY);
+            }
+            else if( ReprojectEnvelope(&sEnvelope, m_poReversedCT) )
+            {
+                m_poDecoratedLayer->SetSpatialFilterRect(m_iGeomFieldFilter,
+                                                        sEnvelope.MinX,
+                                                        sEnvelope.MinY,
+                                                        sEnvelope.MaxX,
+                                                        sEnvelope.MaxY);
+            }
+            else
+            {
+                m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
+                                                    NULL);
+            }
         }
     }
+    else
+    {
+        m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
+                                             poGeom);
+    }
 }
 
 /************************************************************************/
-/*                          SetSpatialFilterRect()                      */
+/*                        SetSpatialFilterRect()                        */
 /************************************************************************/
 
-void OGRWarpedLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
+void OGRWarpedLayer::SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
                                            double dfMaxX, double dfMaxY )
 {
-    OGRLayer::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+    OGRLayer::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+
+/************************************************************************/
+/*                     SrcFeatureToWarpedFeature()                      */
+/************************************************************************/
+
+OGRFeature *OGRWarpedLayer::SrcFeatureToWarpedFeature(OGRFeature* poSrcFeature)
+{
+    OGRFeature* poFeature = new OGRFeature(GetLayerDefn());
+    poFeature->SetFrom(poSrcFeature);
+    poFeature->SetFID(poSrcFeature->GetFID());
+
+    OGRGeometry* poGeom = poFeature->GetGeomFieldRef(m_iGeomField);
+    if( poGeom == NULL )
+        return poFeature;
+
+    if( poGeom->transform(m_poCT) != OGRERR_NONE )
+    {
+        delete poFeature->StealGeometry(m_iGeomField);
+    }
+
+    return poFeature;
+}
+
+
+/************************************************************************/
+/*                     WarpedFeatureToSrcFeature()                      */
+/************************************************************************/
+
+OGRFeature *OGRWarpedLayer::WarpedFeatureToSrcFeature(OGRFeature* poFeature)
+{
+    OGRFeature* poSrcFeature = new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
+    poSrcFeature->SetFrom(poFeature);
+    poSrcFeature->SetFID(poFeature->GetFID());
+
+    OGRGeometry* poGeom = poSrcFeature->GetGeomFieldRef(m_iGeomField);
+    if( poGeom != NULL )
+    {
+        if( m_poReversedCT == NULL )
+        {
+            delete poSrcFeature;
+            return NULL;
+        }
+
+        if( poGeom->transform(m_poReversedCT) != OGRERR_NONE )
+        {
+            delete poSrcFeature;
+            return NULL;
+        }
+    }
+
+    return poSrcFeature;
 }
 
 /************************************************************************/
@@ -119,23 +226,17 @@ OGRFeature *OGRWarpedLayer::GetNextFeature()
         if( poFeature == NULL )
             return NULL;
 
-        OGRGeometry* poGeom = poFeature->GetGeometryRef();
-        if( poGeom == NULL )
-            return poFeature;
+        OGRFeature* poFeatureNew = SrcFeatureToWarpedFeature(poFeature);
+        delete poFeature;
 
-        if( poGeom->transform(m_poCT) != OGRERR_NONE )
+        OGRGeometry* poGeom = poFeatureNew->GetGeomFieldRef(m_iGeomField);
+        if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
         {
-            delete poFeature->StealGeometry();
+            delete poFeatureNew;
+            continue;
         }
-        else
-        {
-            if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
-            {
-                delete poFeature;
-                continue;
-            }
-        }
-        return poFeature;
+
+        return poFeatureNew;
     }
 }
 
@@ -148,11 +249,9 @@ OGRFeature *OGRWarpedLayer::GetFeature( long nFID )
     OGRFeature* poFeature = m_poDecoratedLayer->GetFeature(nFID);
     if( poFeature != NULL )
     {
-        OGRGeometry* poGeom = poFeature->GetGeometryRef();
-        if( poGeom != NULL && poGeom->transform(m_poCT) != OGRERR_NONE )
-        {
-            delete poFeature->StealGeometry();
-        }
+        OGRFeature* poFeatureNew = SrcFeatureToWarpedFeature(poFeature);
+        delete poFeature;
+        poFeature = poFeatureNew;
     }
     return poFeature;
 }
@@ -163,31 +262,15 @@ OGRFeature *OGRWarpedLayer::GetFeature( long nFID )
 
 OGRErr      OGRWarpedLayer::SetFeature( OGRFeature *poFeature )
 {
-    OGRGeometry* poOrigGeom = poFeature->GetGeometryRef();
     OGRErr eErr;
 
-    if( poOrigGeom != NULL )
-    {
-        if( m_poReversedCT == NULL )
-            return OGRERR_FAILURE;
-
-        OGRGeometry* poTransformedGeom = poOrigGeom->clone();
-        if( poTransformedGeom->transform(m_poReversedCT) != OGRERR_NONE )
-        {
-            delete poTransformedGeom;
-            return OGRERR_FAILURE;
-        }
-        poFeature->StealGeometry();
-        poFeature->SetGeometryDirectly(poTransformedGeom);
+    OGRFeature* poFeatureNew = WarpedFeatureToSrcFeature(poFeature);
+    if( poFeatureNew == NULL )
+        return OGRERR_FAILURE;
 
-        eErr = m_poDecoratedLayer->SetFeature(poFeature);
+    eErr = m_poDecoratedLayer->SetFeature(poFeatureNew);
 
-        poFeature->StealGeometry();
-        poFeature->SetGeometryDirectly(poOrigGeom);
-        delete poTransformedGeom;
-    }
-    else
-        eErr = m_poDecoratedLayer->SetFeature(poFeature);
+    delete poFeatureNew;
 
     return eErr;
 }
@@ -198,33 +281,35 @@ OGRErr      OGRWarpedLayer::SetFeature( OGRFeature *poFeature )
 
 OGRErr      OGRWarpedLayer::CreateFeature( OGRFeature *poFeature )
 {
-    OGRGeometry* poOrigGeom = poFeature->GetGeometryRef();
     OGRErr eErr;
 
-    if( poOrigGeom != NULL )
-    {
-        if( m_poReversedCT == NULL )
-            return OGRERR_FAILURE;
+    OGRFeature* poFeatureNew = WarpedFeatureToSrcFeature(poFeature);
+    if( poFeatureNew == NULL )
+        return OGRERR_FAILURE;
+   
+    eErr = m_poDecoratedLayer->CreateFeature(poFeatureNew);
 
-        OGRGeometry* poTransformedGeom = poOrigGeom->clone();
-        if( poTransformedGeom->transform(m_poReversedCT) != OGRERR_NONE )
-        {
-            delete poTransformedGeom;
-            return OGRERR_FAILURE;
-        }
-        poFeature->StealGeometry();
-        poFeature->SetGeometryDirectly(poTransformedGeom);
+    delete poFeatureNew;
 
-        eErr = m_poDecoratedLayer->CreateFeature(poFeature);
+    return eErr;
+}
 
-        poFeature->StealGeometry();
-        poFeature->SetGeometryDirectly(poOrigGeom);
-        delete poTransformedGeom;
-    }
-    else
-        eErr = m_poDecoratedLayer->CreateFeature(poFeature);
 
-    return eErr;
+/************************************************************************/
+/*                            GetLayerDefn()                           */
+/************************************************************************/
+
+OGRFeatureDefn *OGRWarpedLayer::GetLayerDefn()
+{
+    if( m_poFeatureDefn != NULL )
+        return m_poFeatureDefn;
+
+    m_poFeatureDefn = m_poDecoratedLayer->GetLayerDefn()->Clone();
+    m_poFeatureDefn->Reference();
+    if( m_poFeatureDefn->GetGeomFieldCount() > 0 )
+        m_poFeatureDefn->GetGeomFieldDefn(m_iGeomField)->SetSpatialRef(m_poSRS);
+
+    return m_poFeatureDefn;
 }
 
 /************************************************************************/
@@ -233,8 +318,12 @@ OGRErr      OGRWarpedLayer::CreateFeature( OGRFeature *poFeature )
 
 OGRSpatialReference *OGRWarpedLayer::GetSpatialRef()
 {
-    return m_poSRS;
+    if( m_iGeomField == 0 )
+        return m_poSRS;
+    else
+        return OGRLayer::GetSpatialRef();
 }
+
 /************************************************************************/
 /*                           GetFeatureCount()                          */
 /************************************************************************/
@@ -251,26 +340,40 @@ int OGRWarpedLayer::GetFeatureCount( int bForce )
 /*                              GetExtent()                             */
 /************************************************************************/
 
-OGRErr      OGRWarpedLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+OGRErr OGRWarpedLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 {
-    if( sStaticEnvelope.IsInit() )
-    {
-        memcpy(psExtent, &sStaticEnvelope, sizeof(OGREnvelope));
-        return OGRERR_NONE;
-    }
+    return GetExtent(0, psExtent, bForce);
+}
 
-    OGREnvelope sExtent;
-    OGRErr eErr = m_poDecoratedLayer->GetExtent(&sExtent, bForce);
-    if( eErr != OGRERR_NONE )
-        return eErr;
+/************************************************************************/
+/*                              GetExtent()                             */
+/************************************************************************/
 
-    if( ReprojectEnvelope(&sExtent, m_poCT) )
+OGRErr      OGRWarpedLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+{
+    if( iGeomField == m_iGeomField )
     {
-        memcpy(psExtent, &sExtent, sizeof(OGREnvelope));
-        return OGRERR_NONE;
+        if( sStaticEnvelope.IsInit() )
+        {
+            memcpy(psExtent, &sStaticEnvelope, sizeof(OGREnvelope));
+            return OGRERR_NONE;
+        }
+
+        OGREnvelope sExtent;
+        OGRErr eErr = m_poDecoratedLayer->GetExtent(m_iGeomField, &sExtent, bForce);
+        if( eErr != OGRERR_NONE )
+            return eErr;
+
+        if( ReprojectEnvelope(&sExtent, m_poCT) )
+        {
+            memcpy(psExtent, &sExtent, sizeof(OGREnvelope));
+            return OGRERR_NONE;
+        }
+        else
+            return OGRERR_FAILURE;
     }
     else
-        return OGRERR_FAILURE;
+        return m_poDecoratedLayer->GetExtent(iGeomField, psExtent, bForce);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
index e7f1f70..755b694 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.h 24633 2012-07-01 14:37:25Z rouault $
+ * $Id: ogrwarpedlayer.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRWarpedLayer class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,6 +39,9 @@
 class OGRWarpedLayer : public OGRLayerDecorator
 {
   protected:
+      OGRFeatureDefn              *m_poFeatureDefn;
+      int                          m_iGeomField;
+
       OGRCoordinateTransformation *m_poCT;
       OGRCoordinateTransformation *m_poReversedCT; /* may be NULL */
       OGRSpatialReference         *m_poSRS;
@@ -48,9 +51,13 @@ class OGRWarpedLayer : public OGRLayerDecorator
       static int ReprojectEnvelope( OGREnvelope* psEnvelope,
                                     OGRCoordinateTransformation* poCT );
 
+      OGRFeature *                 SrcFeatureToWarpedFeature(OGRFeature* poFeature);
+      OGRFeature *                 WarpedFeatureToSrcFeature(OGRFeature* poFeature);
+
   public:
 
                        OGRWarpedLayer(OGRLayer* poDecoratedLayer,
+                                      int iGeomField,
                                       int bTakeOwnership,
                                       OGRCoordinateTransformation* poCT,  /* must NOT be NULL, ownership acquired by OGRWarpedLayer */
                                       OGRCoordinateTransformation* poReversedCT /* may be NULL, ownership acquired by OGRWarpedLayer */);
@@ -61,15 +68,21 @@ class OGRWarpedLayer : public OGRLayerDecorator
     virtual void        SetSpatialFilter( OGRGeometry * );
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
                                               double dfMaxX, double dfMaxY );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
 
     virtual OGRFeature *GetNextFeature();
     virtual OGRFeature *GetFeature( long nFID );
     virtual OGRErr      SetFeature( OGRFeature *poFeature );
     virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 
+    virtual OGRFeatureDefn *GetLayerDefn();
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
 
     virtual int         TestCapability( const char * );
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.c b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
index 63ecc4b..e28b2d1 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007,  Geoconcept and IGN
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.h b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
index 0e6d5e8..b76e0e1 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007,  Geoconcept and IGN
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
index 48da138..54f0894 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
@@ -9,6 +9,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007,  Geoconcept and IGN
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
index 5b2563b..bc4cd51 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
@@ -9,6 +9,7 @@
  *
  **********************************************************************
  * Copyright (c) 2007,  Geoconcept and IGN
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
index 657a312..69689f1 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Geoconcept and IGN
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
index 7211980..a3b987e 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007,  Geoconcept and IGN
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/geojson/GNUmakefile b/ogr/ogrsf_frmts/geojson/GNUmakefile
index a4e2542..f4e4a61 100644
--- a/ogr/ogrsf_frmts/geojson/GNUmakefile
+++ b/ogr/ogrsf_frmts/geojson/GNUmakefile
@@ -2,10 +2,12 @@
 #
 # Makefile to build OGR GeoJSON driver
 #
-SUBDIRS-yes	:= jsonc
-
 include ../../../GDALmake.opt
 
+ifeq ($(LIBJSONC_SETTING),internal)
+SUBDIRS-yes	:= libjson
+endif
+
 OBJ = \
 	ogrgeojsondriver.o \
 	ogrgeojsondatasource.o \
@@ -14,9 +16,10 @@ OBJ = \
 	ogrgeojsonutils.o \
 	ogrgeojsonreader.o \
 	ogrgeojsonwriter.o \
-	ogresrijsonreader.o
+	ogresrijsonreader.o \
+	ogrtopojsonreader.o
 
-CPPFLAGS	:= -I. -Ijsonc -I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:= $(JSON_INCLUDE) -I. -I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:        $(foreach d,$(SUBDIRS-yes),$(d)-target) $(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/geojson/drv_geojson.html b/ogr/ogrsf_frmts/geojson/drv_geojson.html
index 0607c38..6fd5630 100644
--- a/ogr/ogrsf_frmts/geojson/drv_geojson.html
+++ b/ogr/ogrsf_frmts/geojson/drv_geojson.html
@@ -24,6 +24,8 @@ The implementation is based on <a href="http://wiki.geojson.org/GeoJSON_draft_ve
 <a href="http://www.esri.com/industries/landing-pages/geoservices/geoservices.html">GeoServices REST Specification<a/>, like
 implemented by <a href="http://help.arcgis.com/en/arcgisserver/10.0/apis/rest/index.html">ArcGIS Server REST API</a></p>
 
+<p>Starting with OGR 1.11, the GeoJSON driver can read the <a href="https://github.com/mbostock/topojson/wiki/Specification">TopoJSON format</a></p>
+
 <h2>Datasource</h2>
 
 <p>The OGR GeoJSON driver accepts three types of sources of data:
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/AUTHORS b/ogr/ogrsf_frmts/geojson/jsonc/AUTHORS
deleted file mode 100644
index 38f2ce0..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/AUTHORS
+++ /dev/null
@@ -1,2 +0,0 @@
-Michael Clark <michael at metaparadigm.com>
-C. Watford (christopher.watford at gmail.com)
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/COPYING b/ogr/ogrsf_frmts/geojson/jsonc/COPYING
deleted file mode 100644
index f8ff2e1..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/COPYING
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2004, 2005 Metaparadigm Pte Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog b/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog
deleted file mode 100644
index 4cd28d3..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog
+++ /dev/null
@@ -1,107 +0,0 @@
-GDAL modified version:
-  * See svn log -r18532:HEAD http://svn.osgeo.org/gdal/trunk/gdal/ogr/ogrsf_frmts/geojson/jsonc
-
-
-0.9
-  * Add README.html README-WIN32.html config.h.win32 to Makefile.am
-    Michael Clark, <michael at metaparadigm.com>
-  * Add const qualifier to the json_tokener_parse functions
-    Eric Haszlakiewicz, EHASZLA at transunion dot com
-  * Rename min and max so we can never clash with C or C++ std library
-    Ian Atha, thatha at yahoo dash inc dot com
-  * Fix any noticeable spelling or grammar errors.
-  * Make sure every va_start has a va_end.
-  * Check all pointers for validity.
-    Erik Hovland, erik at hovland dot org
-  * Fix json_object_get_boolean to return false for empty string
-    Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com
-  * optimizations to json_tokener_parse_ex(), printbuf_memappend()
-    Brent Miller, bdmiller at yahoo dash inc dot com
-  * Disable REFCOUNT_DEBUG by default in json_object.c
-  * Don't use this as a variable, so we can compile with a C++ compiler
-  * Add casts from void* to type of assignment when using malloc 
-  * Add #ifdef __cplusplus guards to all of the headers
-  * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table
-    Michael Clark, <michael at metaparadigm.com>
-  * Null pointer dereference fix. Fix json_object_get_boolean strlen test
-    to not return TRUE for zero length string. Remove redundant includes.
-    Erik Hovland, erik at hovland dot org
-  * Fixed warning reported by adding -Wstrict-prototypes
-    -Wold-style-definition to the compilatin flags.
-    Dotan Barak, dotanba at gmail dot com
-  * Add const correctness to public interfaces
-    Gerard Krol, g dot c dot krol at student dot tudelft dot nl
-
-0.8
-  * Add va_end for every va_start
-    Dotan Barak, dotanba at gmail dot com
-  * Add macros to enable compiling out debug code
-    Geoffrey Young, geoff at modperlcookbook dot org
-  * Fix bug with use of capital E in numbers with exponents
-    Mateusz Loskot, mateusz at loskot dot net
-  * Add stddef.h include
-  * Patch allows for json-c compile with -Werror and not fail due to
-    -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
-    Geoffrey Young, geoff at modperlcookbook dot org
-
-0.7
-  * Add escaping of backslash to json output
-  * Add escaping of foward slash on tokenizing and output
-  * Changes to internal tokenizer from using recursion to
-    using a depth state structure to allow incremental parsing
-
-0.6
-  * Fix bug in escaping of control characters
-    Johan Bj�rklund, johbjo09 at kth dot se
-  * Remove include "config.h" from headers (should only
-    be included from .c files)
-    Michael Clark <michael at metaparadigm.com>
-
-0.5
-  * Make headers C++ compatible by change *this to *obj
-  * Add ifdef C++ extern "C" to headers
-  * Use simpler definition of min and max in bits.h
-    Larry Lansing, llansing at fuzzynerd dot com
-
-  * Remove automake 1.6 requirement
-  * Move autogen commands into autogen.sh. Update README
-  * Remove error pointer special case for Windows
-  * Change license from LGPL to MIT
-    Michael Clark <michael at metaparadigm.com>
-
-0.4
-  * Fix additional error case in object parsing
-  * Add back sign reversal in nested object parse as error pointer
-    value is negative, while error value is positive.
-    Michael Clark <michael at metaparadigm.com>
-
-0.3
-  * fix pointer arithmetic bug for error pointer check in is_error() macro
-  * fix type passed to printbuf_memappend in json_tokener
-  * update autotools bootstrap instructions in README
-    Michael Clark <michael at metaparadigm.com>
-
-0.2
-  * printbuf.c - C. Watford (christopher.watford at gmail.com)
-    Added a Win32/Win64 compliant implementation of vasprintf
-  * debug.c - C. Watford (christopher.watford at gmail.com)
-    Removed usage of vsyslog on Win32/Win64 systems, needs to be handled
-    by a configure script
-  * json_object.c - C. Watford (christopher.watford at gmail.com)
-    Added scope operator to wrap usage of json_object_object_foreach, this
-    needs to be rethought to be more ANSI C friendly
-  * json_object.h - C. Watford (christopher.watford at gmail.com)
-    Added Microsoft C friendly version of json_object_object_foreach
-  * json_tokener.c - C. Watford (christopher.watford at gmail.com)
-    Added a Win32/Win64 compliant implementation of strndup
-  * json_util.c - C. Watford (christopher.watford at gmail.com)
-    Added cast and mask to suffice size_t v. unsigned int conversion
-    correctness 
-  * json_tokener.c - sign reversal issue on error info for nested object parse
-    spotted by Johan Bj�rklund (johbjo09 at kth.se)
-  * json_object.c - escape " in json_escape_str
-  * Change to automake and libtool to build shared and static library
-    Michael Clark <michael at metaparadigm.com>
-	
-0.1
-  * initial release
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/GNUmakefile b/ogr/ogrsf_frmts/geojson/jsonc/GNUmakefile
deleted file mode 100644
index 4353799..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/GNUmakefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# $Id$
-#
-# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
-# 
-include ../../../../GDALmake.opt
-
-OBJ = \
-	arraylist.o \
-	debug.o \
-	json_object.o \
-	json_tokener.o \
-	json_util.o \
-	linkhash.o \
-	printbuf.o
-
-O_OBJ = $(foreach file,$(OBJ),../../o/$(file))
-
-CPPFLAGS := $(CPPFLAGS)
-
-default:	$(O_OBJ:.o=.$(OBJ_EXT))
-
-../../o/%.$(OBJ_EXT):	%.c
-	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
-
-clean:
-	rm -f *.o $(O_OBJ)
-	rm -f *~
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/README.html b/ogr/ogrsf_frmts/geojson/jsonc/README.html
deleted file mode 100644
index c5cba3a..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/README.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html 
-     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-	<head>
-		<title>JSON-C - A JSON implementation in C</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-	</head>
-	<body>
-		<h2>JSON-C - A JSON implementation in C</h2>
-		<p>Latest release: <a href="json-c-0.9.tar.gz">json-c-0.9.tar.gz</a></p>
-		<p>JSON-C implements a reference counting object model that allows you to easily 
-			construct JSON objects in C, output them as JSON formatted strings and parse 
-			JSON formatted strings back into the C representation of JSON objects.</p>
-		<p>Minimal documentation exists <a href="doc/html/json__object_8h.html">here</a>, 
-			Although you are probably better reading the example code in test1.c.</p>
-		<p>To setup JSON-C to build on your system please run <tt>configure</tt> before 
-			compiling. If you are on Win32 and are not using the VS project file, be sure 
-			to rename <tt>config.h.win32</tt> to <tt>config.h</tt> before building.</p>
-		<P>Win32 specific notes can be found <a href="README-WIN32.html">here</a>.</P>
-		<p>Please send bug reports to <a href="mailto:michael at metaparadigm.com">michael at metaparadigm.com</a></p>
-		<p>Please send Win32 bug reports to <a href="mailto:christopher.watford at gmail.com">christopher.watford at gmail.com</a></p>
-		<h3>Anonymous Subversion</h3>
-		<p><code># <b>svn co http://svn.metaparadigm.com/svn/json-c/trunk json-c</b></code></p>
-		<p>Copyright Metaparadigm Pte. Ltd. 2004, 2005. <a href="mailto:michael at metaparadigm.com">Michael 
-				Clark </a>
-		</p>
-		<p>This program is free software; you can redistribute it and/or modify it under 
-			the terms of the MIT License. See COPYING for details.</p>
-		<hr>
-	</body>
-</html>
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/arraylist.c b/ogr/ogrsf_frmts/geojson/jsonc/arraylist.c
deleted file mode 100644
index 62af419..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/arraylist.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#include "config.h"
-
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <string.h>
-#endif /* STDC_HEADERS */
-
-#if defined HAVE_STRINGS_H && !defined _STRING_H && !defined __USE_BSD
-# include <strings.h>
-#endif /* HAVE_STRINGS_H */
-
-#include "bits.h"
-#include "arraylist.h"
-
-struct array_list*
-array_list_new(array_list_free_fn *free_fn)
-{
-  struct array_list *arr;
-
-  arr = (struct array_list*)calloc(1, sizeof(struct array_list));
-  if(!arr) return NULL;
-  arr->size = ARRAY_LIST_DEFAULT_SIZE;
-  arr->length = 0;
-  arr->free_fn = free_fn;
-  if((arr->array = (void**)calloc(sizeof(void*), arr->size)) == NULL) {
-    free(arr);
-    return NULL;
-  }
-  return arr;
-}
-
-extern void
-array_list_free(struct array_list *arr)
-{
-  int i;
-  for(i = 0; i < arr->length; i++)
-    if(arr->array[i]) arr->free_fn(arr->array[i]);
-  free(arr->array);
-  free(arr);
-}
-
-void*
-array_list_get_idx(struct array_list *arr, int i)
-{
-  if(i >= arr->length) return NULL;
-  return arr->array[i];
-}
-
-static int array_list_expand_internal(struct array_list *arr, int max)
-{
-  void *t;
-  int new_size;
-
-  if(max < arr->size) return 0;
-  new_size = json_max(arr->size << 1, max);
-  if((t = realloc(arr->array, new_size*sizeof(void*))) == NULL) return -1;
-  arr->array = (void**)t;
-  (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
-  arr->size = new_size;
-  return 0;
-}
-
-int
-array_list_put_idx(struct array_list *arr, int idx, void *data)
-{
-  if(array_list_expand_internal(arr, idx)) return -1;
-  if(arr->array[idx]) arr->free_fn(arr->array[idx]);
-  arr->array[idx] = data;
-  if(arr->length <= idx) arr->length = idx + 1;
-  return 0;
-}
-
-int
-array_list_add(struct array_list *arr, void *data)
-{
-  return array_list_put_idx(arr, arr->length, data);
-}
-
-int
-array_list_length(struct array_list *arr)
-{
-  return arr->length;
-}
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/arraylist.h b/ogr/ogrsf_frmts/geojson/jsonc/arraylist.h
deleted file mode 100644
index bc85c80..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/arraylist.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _arraylist_h_
-#define _arraylist_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ARRAY_LIST_DEFAULT_SIZE 32
-
-typedef void (array_list_free_fn) (void *data);
-
-struct array_list
-{
-  void **array;
-  int length;
-  int size;
-  array_list_free_fn *free_fn;
-};
-
-extern struct array_list*
-array_list_new(array_list_free_fn *free_fn);
-
-extern void
-array_list_free(struct array_list *al);
-
-extern void*
-array_list_get_idx(struct array_list *al, int i);
-
-extern int
-array_list_put_idx(struct array_list *al, int i, void *data);
-
-extern int
-array_list_add(struct array_list *al, void *data);
-
-extern int
-array_list_length(struct array_list *al);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/bits.h b/ogr/ogrsf_frmts/geojson/jsonc/bits.h
deleted file mode 100644
index f308da3..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/bits.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _bits_h_
-#define _bits_h_
-
-#ifndef json_min
-#define json_min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef json_max
-#define json_max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
-#define error_ptr(error) ((void*)error)
-#define is_error(ptr) ((unsigned long)ptr > (unsigned long)-4000L)
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/config.h b/ogr/ogrsf_frmts/geojson/jsonc/config.h
deleted file mode 100644
index 6a94390..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/config.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * $Id: config.h.win32,v 1.2 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-/* config.h.win32  Generated by configure.  */
-
-#define PACKAGE_STRING "JSON C Library 0.2"
-#define PACKAGE_BUGREPORT "michael at metaparadigm.com"
-#define PACKAGE_NAME "JSON C Library"
-#define PACKAGE_TARNAME "json-c"
-#define PACKAGE_VERSION "0.2"
-
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-#ifndef __GNUC__
-#define __attribute__(x) /* DO NOTHING */
-#endif
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
-   to 0 otherwise. */
-#define HAVE_MALLOC 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `open' function. */
-#undef HAVE_OPEN
-
-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
-   and to 0 otherwise. */
-#define HAVE_REALLOC 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strdup' function. */
-#ifdef _GNU_SOURCE
-#define HAVE_STRNDUP 1
-#else
-#undef HAVE_STRNDUP
-#endif
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the `strerror' function. */
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <syslog.h> header file. */
-#undef HAVE_SYSLOG_H
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#ifdef _WIN32_WCE
-#undef HAVE_SYS_STAT_H
-#else
-#define HAVE_SYS_STAT_H 1
-#endif
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#ifdef _WIN32_WCE
-#undef HAVE_SYS_TYPES_H
-#else
-#define HAVE_SYS_TYPES_H 1
-#endif
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `vprintf' function. */
-#ifdef _MSC_VER
-#undef HAVE_VPRINTF
-#endif
-
-/* Define to 1 if you have the `vasprintf' function. */
-#define HAVE_VASPRINTF 1
-#ifdef _MSC_VER
-#undef HAVE_VASPRINTF
-#endif
-
-/* Define to 1 if you have the `vsyslog' function. */
-#undef HAVE_VSYSLOG
-
-/* Define to 1 if you have the `strncasecmp' function. */
-#ifndef HAVE_STRNCASECMP
-#define HAVE_STRNCASECMP 1
-#endif
-#if defined(_MSC_VER) && !defined(strncasecmp)
-   /* MSC has the version as _strnicmp */
-#define strncasecmp _strnicmp
-#endif
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-#include <cpl_config.h>
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/debug.h b/ogr/ogrsf_frmts/geojson/jsonc/debug.h
deleted file mode 100644
index 18e98c3..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/debug.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _DEBUG_H_
-#define _DEBUG_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void mc_set_debug(int debug);
-extern int mc_get_debug(void);
-
-extern void mc_set_syslog(int syslog);
-extern void mc_abort(const char *msg, ...);
-extern void mc_debug(const char *msg, ...);
-extern void mc_error(const char *msg, ...);
-extern void mc_info(const char *msg, ...);
-
-#ifdef MC_MAINTAINER_MODE
-#define MC_SET_DEBUG(x) mc_set_debug(x)
-#define MC_GET_DEBUG() mc_get_debug()
-#define MC_SET_SYSLOG(x) mc_set_syslog(x)
-#define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__)
-#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
-#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
-#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
-#else
-#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
-#define MC_GET_DEBUG() (0)
-#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
-#if defined(_MSC_VER) && _MSC_VER <= 1310
-/* VC++ 7.1 and earlier don't like macros with ... */
-#define MC_ABORT
-#define MC_DEBUG
-#define MC_ERROR
-#define MC_INFO
-#else
-#define MC_ABORT(x, ...) if (0) mc_abort(x, ##__VA_ARGS__)
-#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
-#define MC_ERROR(x, ...) if (0) mc_error(x, ##__VA_ARGS__)
-#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
-#endif
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json.h b/ogr/ogrsf_frmts/geojson/jsonc/json.h
deleted file mode 100644
index a5a3432..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _json_h_
-#define _json_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "bits.h"
-#include "debug.h"
-#include "linkhash.h"
-#include "arraylist.h"
-#include "json_util.h"
-#include "json_object.h"
-#include "json_tokener.h"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object.c b/ogr/ogrsf_frmts/geojson/jsonc/json_object.c
deleted file mode 100644
index 1c2a12e..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#include "cpl_conv.h"
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "debug.h"
-#include "printbuf.h"
-#include "linkhash.h"
-#include "arraylist.h"
-#include "json_object.h"
-#include "json_object_private.h"
-
-#if !HAVE_STRNDUP
-  char* strndup(const char* str, size_t n);
-#endif /* !HAVE_STRNDUP */
-
-/* #define REFCOUNT_DEBUG 1 */
-
-const char *json_number_chars = "0123456789.+-eE";
-const char *json_hex_chars = "0123456789abcdef";
-
-#ifdef REFCOUNT_DEBUG
-static const char* json_type_name[] = {
-  "null",
-  "boolean",
-  "double",
-  "int",
-  "object",
-  "array",
-  "string",
-};
-#endif /* REFCOUNT_DEBUG */
-
-static void json_object_generic_delete(struct json_object* jso);
-static struct json_object* json_object_new(enum json_type o_type);
-
-
-/* ref count debugging */
-
-#ifdef REFCOUNT_DEBUG
-
-static struct lh_table *json_object_table;
-
-static void json_object_init(void) __attribute__ ((constructor));
-static void json_object_init(void) {
-  MC_DEBUG("json_object_init: creating object table\n");
-  json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
-}
-
-static void json_object_fini(void) __attribute__ ((destructor));
-static void json_object_fini(void) {
-  struct lh_entry *ent;
-  if(MC_GET_DEBUG()) {
-    if (json_object_table->count) {
-      MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
-  	       json_object_table->count);
-      lh_foreach(json_object_table, ent) {
-        struct json_object* obj = (struct json_object*)ent->v;
-        MC_DEBUG("\t%s:%p\n", json_type_name[obj->o_type], obj);
-      }
-    }
-  }
-  MC_DEBUG("json_object_fini: freeing object table\n");
-  lh_table_free(json_object_table);
-}
-#endif /* REFCOUNT_DEBUG */
-
-
-/* string escaping */
-
-static int json_escape_str(struct printbuf *pb, char *str)
-{
-  int pos = 0, start_offset = 0;
-  unsigned char c;
-  do {
-    c = str[pos];
-    switch(c) {
-    case '\0':
-      break;
-    case '\b':
-    case '\n':
-    case '\r':
-    case '\t':
-    case '"':
-    case '\\':
-    case '/':
-      if(pos - start_offset > 0)
-	printbuf_memappend(pb, str + start_offset, pos - start_offset);
-      if(c == '\b') printbuf_memappend(pb, "\\b", 2);
-      else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
-      else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
-      else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
-      else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
-      else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
-      else if(c == '/') printbuf_memappend(pb, "\\/", 2);
-      start_offset = ++pos;
-      break;
-    default:
-      if(c < ' ') {
-	if(pos - start_offset > 0)
-	  printbuf_memappend(pb, str + start_offset, pos - start_offset);
-	sprintbuf(pb, "\\u00%c%c",
-		  json_hex_chars[c >> 4],
-		  json_hex_chars[c & 0xf]);
-	start_offset = ++pos;
-      } else pos++;
-    }
-  } while(c);
-  if(pos - start_offset > 0)
-    printbuf_memappend(pb, str + start_offset, pos - start_offset);
-  return 0;
-}
-
-
-/* reference counting */
-
-extern struct json_object* json_object_get(struct json_object *jso)
-{
-  if(jso) {
-    jso->_ref_count++;
-  }
-  return jso;
-}
-
-extern void json_object_put(struct json_object *jso)
-{
-  if(jso) {
-    jso->_ref_count--;
-    if(!jso->_ref_count) jso->_delete(jso);
-  }
-}
-
-
-/* generic object construction and destruction parts */
-
-static void json_object_generic_delete(struct json_object* jso)
-{
-#ifdef REFCOUNT_DEBUG
-  MC_DEBUG("json_object_delete_%s: %p\n",
-	   json_type_name[jso->o_type], jso);
-  lh_table_delete(json_object_table, jso);
-#endif /* REFCOUNT_DEBUG */
-  printbuf_free(jso->_pb);
-  free(jso);
-}
-
-static struct json_object* json_object_new(enum json_type o_type)
-{
-  struct json_object *jso;
-
-  jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
-  if(!jso) return NULL;
-  jso->o_type = o_type;
-  jso->_ref_count = 1;
-  jso->_delete = &json_object_generic_delete;
-#ifdef REFCOUNT_DEBUG
-  lh_table_insert(json_object_table, jso, jso);
-  MC_DEBUG("json_object_new_%s: %p\n", json_type_name[jso->o_type], jso);
-#endif /* REFCOUNT_DEBUG */
-  return jso;
-}
-
-
-/* type checking functions */
-
-int json_object_is_type(struct json_object *jso, enum json_type type)
-{
-  return (jso->o_type == type);
-}
-
-enum json_type json_object_get_type(struct json_object *jso)
-{
-  return jso->o_type;
-}
-
-
-/* json_object_to_json_string */
-
-const char* json_object_to_json_string(struct json_object *jso)
-{
-  if(!jso) return "null";
-  if(!jso->_pb) {
-    if((jso->_pb = printbuf_new()) == NULL) return NULL;
-  } else {
-    printbuf_reset(jso->_pb);
-  }
-  if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;
-  return jso->_pb->buf;
-}
-
-
-/* json_object_object */
-
-static int json_object_object_to_json_string(struct json_object* jso,
-					     struct printbuf *pb)
-{
-  int i=0;
-  struct json_object_iter iter;
-  iter.key = NULL;
-  sprintbuf(pb, "{");
-
-  /* CAW: scope operator to make ANSI correctness */
-  /* CAW: switched to json_object_object_foreachC which uses an iterator struct */
-	json_object_object_foreachC(jso, iter) {
-			if(i) sprintbuf(pb, ",");
-			sprintbuf(pb, " \"");
-			json_escape_str(pb, iter.key);
-			sprintbuf(pb, "\": ");
-			if(iter.val == NULL) sprintbuf(pb, "null");
-			else iter.val->_to_json_string(iter.val, pb);
-			i++;
-	}
-
-  return sprintbuf(pb, " }");
-}
-
-static void json_object_lh_entry_free(struct lh_entry *ent)
-{
-  free(ent->k);
-  json_object_put((struct json_object*)ent->v);
-}
-
-static void json_object_object_delete(struct json_object* jso)
-{
-  lh_table_free(jso->o.c_object);
-  json_object_generic_delete(jso);
-}
-
-struct json_object* json_object_new_object(void)
-{
-  struct json_object *jso = json_object_new(json_type_object);
-  if(!jso) return NULL;
-  jso->_delete = &json_object_object_delete;
-  jso->_to_json_string = &json_object_object_to_json_string;
-  jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
-					NULL, &json_object_lh_entry_free);
-  return jso;
-}
-
-struct lh_table* json_object_get_object(struct json_object *jso)
-{
-  if(!jso) return NULL;
-  switch(jso->o_type) {
-  case json_type_object:
-    return jso->o.c_object;
-  default:
-    return NULL;
-  }
-}
-
-void json_object_object_add(struct json_object* jso, const char *key,
-			    struct json_object *val)
-{
-  lh_table_delete(jso->o.c_object, key);
-  lh_table_insert(jso->o.c_object, strdup(key), val);
-}
-
-struct json_object* json_object_object_get(struct json_object* jso, const char *key)
-{
-  return (struct json_object*) lh_table_lookup(jso->o.c_object, key);
-}
-
-void json_object_object_del(struct json_object* jso, const char *key)
-{
-  lh_table_delete(jso->o.c_object, key);
-}
-
-
-/* json_object_boolean */
-
-static int json_object_boolean_to_json_string(struct json_object* jso,
-					      struct printbuf *pb)
-{
-  if(jso->o.c_boolean) return sprintbuf(pb, "true");
-  else return sprintbuf(pb, "false");
-}
-
-struct json_object* json_object_new_boolean(boolean b)
-{
-  struct json_object *jso = json_object_new(json_type_boolean);
-  if(!jso) return NULL;
-  jso->_to_json_string = &json_object_boolean_to_json_string;
-  jso->o.c_boolean = b;
-  return jso;
-}
-
-boolean json_object_get_boolean(struct json_object *jso)
-{
-  if(!jso) return FALSE;
-  switch(jso->o_type) {
-  case json_type_boolean:
-    return jso->o.c_boolean;
-  case json_type_int:
-    return (jso->o.c_int != 0);
-  case json_type_double:
-    return (jso->o.c_double != 0);
-  case json_type_string:
-    return (strlen(jso->o.c_string) != 0);
-  default:
-    return FALSE;
-  }
-}
-
-
-/* json_object_int */
-
-static int json_object_int_to_json_string(struct json_object* jso,
-					  struct printbuf *pb)
-{
-  return sprintbuf(pb, "%d", jso->o.c_int);
-}
-
-struct json_object* json_object_new_int(int i)
-{
-  struct json_object *jso = json_object_new(json_type_int);
-  if(!jso) return NULL;
-  jso->_to_json_string = &json_object_int_to_json_string;
-  jso->o.c_int = i;
-  return jso;
-}
-
-int json_object_get_int(struct json_object *jso)
-{
-  int cint;
-
-  if(!jso) return 0;
-  switch(jso->o_type) {
-  case json_type_int:
-    return jso->o.c_int;
-  case json_type_double:
-    return (int)jso->o.c_double;
-  case json_type_boolean:
-    return jso->o.c_boolean;
-  case json_type_string:
-    if(sscanf(jso->o.c_string, "%d", &cint) == 1) return cint;
-  default:
-    return 0;
-  }
-}
-
-
-/* json_object_double */
-
-/* Begin: GDAL addition */
-/************************************************************************/
-/*                        json_OGRFormatDouble()                        */
-/* Copied & slightly adapted from ogrutils.cpp                          */
-/************************************************************************/
-
-static int json_OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
-                                 char chDecimalSep, int nPrecision )
-{
-    int i;
-    int bHasTruncated = FALSE;
-    char szFormat[16];
-    int ret;
-    
-    sprintf(szFormat, "%%.%df", nPrecision);
-
-    ret = snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
-    /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
-    if (ret >= nBufferLen || ret == -1)
-        return -1;
-
-    while(TRUE)
-    {
-        int nCountBeforeDot = 0;
-        int iDotPos = -1;
-        i = 0;
-        while( pszBuffer[i] != '\0' )
-        {
-            if ((pszBuffer[i] == '.' || pszBuffer[i] == ',') && chDecimalSep != '\0')
-            {
-                iDotPos = i;
-                pszBuffer[i] = chDecimalSep;
-            }
-            else if (iDotPos < 0 && pszBuffer[i] != '-')
-                nCountBeforeDot ++;
-            i++;
-        }
-
-    /* -------------------------------------------------------------------- */
-    /*      Trim trailing 00000x's as they are likely roundoff error.       */
-    /* -------------------------------------------------------------------- */
-        if( i > 10 && iDotPos >=0 )
-        {
-            if (/* && pszBuffer[i-1] == '1' &&*/
-                pszBuffer[i-2] == '0'
-                && pszBuffer[i-3] == '0'
-                && pszBuffer[i-4] == '0'
-                && pszBuffer[i-5] == '0'
-                && pszBuffer[i-6] == '0' )
-            {
-                pszBuffer[--i] = '\0';
-            }
-            else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
-                  /* && pszBuffer[i-2] == '0' && */
-                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
-                    && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
-                    && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
-                    && pszBuffer[i-8] == '0'
-                    && pszBuffer[i-9] == '0')
-            {
-                i -= 8;
-                pszBuffer[i] = '\0';
-            }
-        }
-
-    /* -------------------------------------------------------------------- */
-    /*      Trim trailing zeros.                                            */
-    /* -------------------------------------------------------------------- */
-        while( i > 2 && pszBuffer[i-1] == '0' && pszBuffer[i-2] != '.' )
-        {
-            pszBuffer[--i] = '\0';
-        }
-
-    /* -------------------------------------------------------------------- */
-    /*      Detect trailing 99999X's as they are likely roundoff error.     */
-    /* -------------------------------------------------------------------- */
-        if( !bHasTruncated &&
-            i > 10 &&
-            iDotPos >= 0 &&
-            nPrecision >= 15)
-        {
-            if (/*pszBuffer[i-1] == '9' && */
-                 pszBuffer[i-2] == '9'
-                && pszBuffer[i-3] == '9'
-                && pszBuffer[i-4] == '9'
-                && pszBuffer[i-5] == '9'
-                && pszBuffer[i-6] == '9' )
-            {
-                snprintf(pszBuffer, nBufferLen, "%.9f", dfVal);
-                bHasTruncated = TRUE;
-                continue;
-            }
-            else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
-                     /*pszBuffer[i-2] == '9' && */
-                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9')
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
-                    && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
-                    && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
-                    && pszBuffer[i-8] == '9'
-                    && pszBuffer[i-9] == '9')
-            {
-                sprintf(szFormat, "%%.%df", MIN(5,12 - nCountBeforeDot));
-                snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
-                bHasTruncated = TRUE;
-                continue;
-            }
-        }
-
-        break;
-    }
-
-    return strlen(pszBuffer);
-}
-/* End: GDAL addition */
-
-static int json_object_double_to_json_string(struct json_object* jso,
-					     struct printbuf *pb)
-{
-   /* GDAL modified */
-  char szBuffer[75];
-  int ret = json_OGRFormatDouble( szBuffer, sizeof(szBuffer), jso->o.c_double, '.',
-                                  (jso->_precision < 0) ? 15 : jso->_precision );
-  if (ret < 0)
-    return ret;
-  return printbuf_memappend(pb, szBuffer, ret);
-}
-
-struct json_object* json_object_new_double(double d)
-{
-  struct json_object *jso = json_object_new(json_type_double);
-  if(!jso) return NULL;
-  jso->_to_json_string = &json_object_double_to_json_string;
-  jso->o.c_double = d;
-  jso->_precision = -1; /* GDAL addition */
-  return jso;
-}
-
-/* Begin: GDAL addition */
-struct json_object* json_object_new_double_with_precision(double d, int nPrecision)
-{
-  struct json_object *jso = json_object_new(json_type_double);
-  if(!jso) return NULL;
-  jso->_to_json_string = &json_object_double_to_json_string;
-  jso->o.c_double = d;
-  jso->_precision = (nPrecision < 32) ? nPrecision : 32;
-  return jso;
-}
-/* End: GDAL addition */
-
-double json_object_get_double(struct json_object *jso)
-{
-  if(!jso) return 0.0;
-  switch(jso->o_type) {
-  case json_type_double:
-    return jso->o.c_double;
-  case json_type_int:
-    return jso->o.c_int;
-  case json_type_boolean:
-    return jso->o.c_boolean;
-  case json_type_string:
-    return CPLAtof(jso->o.c_string);
-  default:
-    return 0.0;
-  }
-}
-
-
-/* json_object_string */
-
-static int json_object_string_to_json_string(struct json_object* jso,
-					     struct printbuf *pb)
-{
-  sprintbuf(pb, "\"");
-  json_escape_str(pb, jso->o.c_string);
-  sprintbuf(pb, "\"");
-  return 0;
-}
-
-static void json_object_string_delete(struct json_object* jso)
-{
-  free(jso->o.c_string);
-  json_object_generic_delete(jso);
-}
-
-struct json_object* json_object_new_string(const char *s)
-{
-  struct json_object *jso = json_object_new(json_type_string);
-  if(!jso) return NULL;
-  jso->_delete = &json_object_string_delete;
-  jso->_to_json_string = &json_object_string_to_json_string;
-  jso->o.c_string = strdup(s);
-  return jso;
-}
-
-struct json_object* json_object_new_string_len(const char *s, int len)
-{
-  struct json_object *jso = json_object_new(json_type_string);
-  if(!jso) return NULL;
-  jso->_delete = &json_object_string_delete;
-  jso->_to_json_string = &json_object_string_to_json_string;
-  jso->o.c_string = strndup(s, len);
-  return jso;
-}
-
-const char* json_object_get_string(struct json_object *jso)
-{
-  if(!jso) return NULL;
-  switch(jso->o_type) {
-  case json_type_string:
-    return jso->o.c_string;
-  default:
-    return json_object_to_json_string(jso);
-  }
-}
-
-
-/* json_object_array */
-
-static int json_object_array_to_json_string(struct json_object* jso,
-					    struct printbuf *pb)
-{
-  int i;
-  sprintbuf(pb, "[");
-  for(i=0; i < json_object_array_length(jso); i++) {
-	  struct json_object *val;
-	  if(i) { sprintbuf(pb, ", "); }
-	  else { sprintbuf(pb, " "); }
-
-      val = json_object_array_get_idx(jso, i);
-	  if(val == NULL) { sprintbuf(pb, "null"); }
-	  else { val->_to_json_string(val, pb); }
-  }
-  return sprintbuf(pb, " ]");
-}
-
-static void json_object_array_entry_free(void *data)
-{
-  json_object_put((struct json_object*)data);
-}
-
-static void json_object_array_delete(struct json_object* jso)
-{
-  array_list_free(jso->o.c_array);
-  json_object_generic_delete(jso);
-}
-
-struct json_object* json_object_new_array(void)
-{
-  struct json_object *jso = json_object_new(json_type_array);
-  if(!jso) return NULL;
-  jso->_delete = &json_object_array_delete;
-  jso->_to_json_string = &json_object_array_to_json_string;
-  jso->o.c_array = array_list_new(&json_object_array_entry_free);
-  return jso;
-}
-
-struct array_list* json_object_get_array(struct json_object *jso)
-{
-  if(!jso) return NULL;
-  switch(jso->o_type) {
-  case json_type_array:
-    return jso->o.c_array;
-  default:
-    return NULL;
-  }
-}
-
-int json_object_array_length(struct json_object *jso)
-{
-  return array_list_length(jso->o.c_array);
-}
-
-int json_object_array_add(struct json_object *jso,struct json_object *val)
-{
-  return array_list_add(jso->o.c_array, val);
-}
-
-int json_object_array_put_idx(struct json_object *jso, int idx,
-			      struct json_object *val)
-{
-  return array_list_put_idx(jso->o.c_array, idx, val);
-}
-
-struct json_object* json_object_array_get_idx(struct json_object *jso,
-					      int idx)
-{
-  return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
-}
-
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object.h b/ogr/ogrsf_frmts/geojson/jsonc/json_object.h
deleted file mode 100644
index a2bdcce..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _json_object_h_
-#define _json_object_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define JSON_OBJECT_DEF_HASH_ENTRIES 16
-
-#undef FALSE
-#define FALSE ((boolean)0)
-
-#undef TRUE
-#define TRUE ((boolean)1)
-
-extern const char *json_number_chars;
-extern const char *json_hex_chars;
-
-/* forward structure definitions */
-
-typedef int boolean;
-typedef struct printbuf printbuf;
-typedef struct lh_table lh_table;
-typedef struct array_list array_list;
-typedef struct json_object json_object;
-typedef struct json_object_iter json_object_iter;
-typedef struct json_tokener json_tokener;
-
-/* supported object types */
-
-typedef enum json_type {
-  json_type_null,
-  json_type_boolean,
-  json_type_double,
-  json_type_int,
-  json_type_object,
-  json_type_array,
-  json_type_string
-} json_type;
-
-/* reference counting functions */
-
-/**
- * Increment the reference count of json_object
- * @param obj the json_object instance
- */
-extern struct json_object* json_object_get(struct json_object *obj);
-
-/**
- * Decrement the reference count of json_object and free if it reaches zero
- * @param obj the json_object instance
- */
-extern void json_object_put(struct json_object *obj);
-
-
-/**
- * Check if the json_object is of a given type
- * @param obj the json_object instance
- * @param type one of:
-     json_type_boolean,
-     json_type_double,
-     json_type_int,
-     json_type_object,
-     json_type_array,
-     json_type_string,
- */
-extern int json_object_is_type(struct json_object *obj, enum json_type type);
-
-/**
- * Get the type of the json_object
- * @param obj the json_object instance
- * @returns type being one of:
-     json_type_boolean,
-     json_type_double,
-     json_type_int,
-     json_type_object,
-     json_type_array,
-     json_type_string,
- */
-extern enum json_type json_object_get_type(struct json_object *obj);
-
-
-/** Stringify object to json format
- * @param obj the json_object instance
- * @returns a string in JSON format
- */
-extern const char* json_object_to_json_string(struct json_object *obj);
-
-
-/* object type methods */
-
-/** Create a new empty object
- * @returns a json_object of type json_type_object
- */
-extern struct json_object* json_object_new_object(void);
-
-/** Get the hashtable of a json_object of type json_type_object
- * @param obj the json_object instance
- * @returns a linkhash
- */
-extern struct lh_table* json_object_get_object(struct json_object *obj);
-
-/** Add an object field to a json_object of type json_type_object
- *
- * The reference count will *not* be incremented. This is to make adding
- * fields to objects in code more compact. If you want to retain a reference
- * to an added object you must wrap the passed object with json_object_get
- *
- * @param obj the json_object instance
- * @param key the object field name (a private copy will be duplicated)
- * @param val a json_object or NULL member to associate with the given field
- */
-extern void json_object_object_add(struct json_object* obj, const char *key,
-				   struct json_object *val);
-
-/** Get the json_object associate with a given object field
- * @param obj the json_object instance
- * @param key the object field name
- * @returns the json_object associated with the given field name
- */
-extern struct json_object* json_object_object_get(struct json_object* obj,
-						  const char *key);
-
-/** Delete the given json_object field
- *
- * The reference count will be decremented for the deleted object
- *
- * @param obj the json_object instance
- * @param key the object field name
- */
-extern void json_object_object_del(struct json_object* obj, const char *key);
-
-/** Iterate through all keys and values of an object
- * @param obj the json_object instance
- * @param key the local name for the char* key variable defined in the body
- * @param val the local name for the json_object* object variable defined in the body
- */
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-
-# define json_object_object_foreach(obj,key,val) \
- char *key; struct json_object *val; \
- for(struct lh_entry *entry = json_object_get_object(obj)->head; ({ if(entry) { key = (char*)entry->k; val = (struct json_object*)entry->v; } ; entry; }); entry = entry->next )
-
-#else /* ANSI C or MSC */
-
-# define json_object_object_foreach(obj,key,val) \
- char *key; struct json_object *val; struct lh_entry *entry; \
- for(entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, val = (struct json_object*)entry->v, entry) : 0); entry = entry->next)
-
-#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
-
-/** Iterate through all keys and values of an object (ANSI C Safe)
- * @param obj the json_object instance
- * @param iter the object iterator
- */
-#define json_object_object_foreachC(obj,iter) \
- for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
-
-/* Array type methods */
-
-/** Create a new empty json_object of type json_type_array
- * @returns a json_object of type json_type_array
- */
-extern struct json_object* json_object_new_array(void);
-
-/** Get the arraylist of a json_object of type json_type_array
- * @param obj the json_object instance
- * @returns an arraylist
- */
-extern struct array_list* json_object_get_array(struct json_object *obj);
-
-/** Get the length of a json_object of type json_type_array
- * @param obj the json_object instance
- * @returns an int
- */
-extern int json_object_array_length(struct json_object *obj);
-
-/** Add an element to the end of a json_object of type json_type_array
- *
- * The reference count will *not* be incremented. This is to make adding
- * fields to objects in code more compact. If you want to retain a reference
- * to an added object you must wrap the passed object with json_object_get
- *
- * @param obj the json_object instance
- * @param val the json_object to be added
- */
-extern int json_object_array_add(struct json_object *obj,
-				 struct json_object *val);
-
-/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
- *
- * The reference count will *not* be incremented. This is to make adding
- * fields to objects in code more compact. If you want to retain a reference
- * to an added object you must wrap the passed object with json_object_get
- *
- * The reference count of a replaced object will be decremented.
- *
- * The array size will be automatically be expanded to the size of the
- * index if the index is larger than the current size.
- *
- * @param obj the json_object instance
- * @param idx the index to insert the element at
- * @param val the json_object to be added
- */
-extern int json_object_array_put_idx(struct json_object *obj, int idx,
-				     struct json_object *val);
-
-/** Get the element at specificed index of the array (a json_object of type json_type_array)
- * @param obj the json_object instance
- * @param idx the index to get the element at
- * @returns the json_object at the specified index (or NULL)
- */
-extern struct json_object* json_object_array_get_idx(struct json_object *obj,
-						     int idx);
-
-/* boolean type methods */
-
-/** Create a new empty json_object of type json_type_boolean
- * @param b a boolean TRUE or FALSE (0 or 1)
- * @returns a json_object of type json_type_boolean
- */
-extern struct json_object* json_object_new_boolean(boolean b);
-
-/** Get the boolean value of a json_object
- *
- * The type is coerced to a boolean if the passed object is not a boolean.
- * integer and double objects will return FALSE if there value is zero
- * or TRUE otherwise. If the passed object is a string it will return
- * TRUE if it has a non zero length. If any other object type is passed
- * TRUE will be returned if the object is not NULL.
- *
- * @param obj the json_object instance
- * @returns a boolean
- */
-extern boolean json_object_get_boolean(struct json_object *obj);
-
-
-/* int type methods */
-
-/** Create a new empty json_object of type json_type_int
- * @param i the integer
- * @returns a json_object of type json_type_int
- */
-extern struct json_object* json_object_new_int(int i);
-
-/** Get the int value of a json_object
- *
- * The type is coerced to a int if the passed object is not a int.
- * double objects will return their integer conversion. Strings will be
- * parsed as an integer. If no conversion exists then 0 is returned.
- *
- * @param obj the json_object instance
- * @returns an int
- */
-extern int json_object_get_int(struct json_object *obj);
-
-
-/* double type methods */
-
-/** Create a new empty json_object of type json_type_double
- * @param d the double
- * @returns a json_object of type json_type_double
- */
-extern struct json_object* json_object_new_double(double d);
-
-/* Begin: GDAL addition */
-/** Create a new empty json_object of type json_type_double
- * @param d the double
- * @param nPrecision number of significant figures to use when serializing to string
- * @returns a json_object of type json_type_double
- */
-extern struct json_object* json_object_new_double_with_precision(double d, int nPrecision);
-/* End: GDAL addition */
-
-/** Get the double value of a json_object
- *
- * The type is coerced to a double if the passed object is not a double.
- * integer objects will return their dboule conversion. Strings will be
- * parsed as a double. If no conversion exists then 0.0 is returned.
- *
- * @param obj the json_object instance
- * @returns an double
- */
-extern double json_object_get_double(struct json_object *obj);
-
-
-/* string type methods */
-
-/** Create a new empty json_object of type json_type_string
- *
- * A copy of the string is made and the memory is managed by the json_object
- *
- * @param s the string
- * @returns a json_object of type json_type_string
- */
-extern struct json_object* json_object_new_string(const char *s);
-
-extern struct json_object* json_object_new_string_len(const char *s, int len);
-
-/** Get the string value of a json_object
- *
- * If the passed object is not of type json_type_string then the JSON
- * representation of the object is returned.
- *
- * The returned string memory is managed by the json_object and will
- * be freed when the reference count of the json_object drops to zero.
- *
- * @param obj the json_object instance
- * @returns a string
- */
-extern const char* json_object_get_string(struct json_object *obj);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h b/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h
deleted file mode 100644
index 9265239..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _json_object_private_h_
-#define _json_object_private_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (json_object_delete_fn)(struct json_object *o);
-typedef int (json_object_to_json_string_fn)(struct json_object *o,
-					    struct printbuf *pb);
-
-struct json_object
-{
-  enum json_type o_type;
-  json_object_delete_fn *_delete;
-  json_object_to_json_string_fn *_to_json_string;
-  int _ref_count;
-  struct printbuf *_pb;
-  union data {
-    boolean c_boolean;
-    double c_double;
-    int c_int;
-    struct lh_table *c_object;
-    struct array_list *c_array;
-    char *c_string;
-  } o;
-  int _precision; /* GDAL addition */
-};
-
-/* CAW: added for ANSI C iteration correctness */
-struct json_object_iter
-{
-	char *key;
-	struct json_object *val;
-	struct lh_entry *entry;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.c b/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.c
deleted file mode 100644
index f13dcfe..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- *
- * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
- * The copyrights to the contents of this file are licensed under the MIT License
- * (http://www.opensource.org/licenses/mit-license.php)
- */
-
-#include "config.h"
-
-#include "cpl_conv.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "bits.h"
-#include "debug.h"
-#include "printbuf.h"
-#include "arraylist.h"
-#include "json_object.h"
-#include "json_tokener.h"
-
-#include <cpl_port.h> /* MIN and MAX macros */
-
-#if !HAVE_STRNCASECMP
-# if defined(_MSC_VER)
-   /* MSC has the version as _strnicmp */
-#  define strncasecmp _strnicmp
-# else
-#  error You do not have strncasecmp on your system.
-# endif
-#endif /* HAVE_STRNCASECMP */
-
-
-static const char* json_null_str = "null";
-static const char* json_true_str = "true";
-static const char* json_false_str = "false";
-
-const char* json_tokener_errors[] = {
-  "success",
-  "continue",
-  "nesting to deep",
-  "unexpected end of data",
-  "unexpected character",
-  "null expected",
-  "boolean expected",
-  "number expected",
-  "array value separator ',' expected",
-  "quoted object property name expected",
-  "object property name separator ':' expected",
-  "object value separator ',' expected",
-  "invalid string sequence",
-  "expected comment",
-};
-
-
-struct json_tokener* json_tokener_new(void)
-{
-  struct json_tokener *tok;
-
-  tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
-  if (!tok) return NULL;
-  tok->pb = printbuf_new();
-  json_tokener_reset(tok);
-  return tok;
-}
-
-void json_tokener_free(struct json_tokener *tok)
-{
-  json_tokener_reset(tok);
-  if(tok) printbuf_free(tok->pb);
-  free(tok);
-}
-
-static void json_tokener_reset_level(struct json_tokener *tok, int depth)
-{
-  tok->stack[depth].state = json_tokener_state_eatws;
-  tok->stack[depth].saved_state = json_tokener_state_start;
-  json_object_put(tok->stack[depth].current);
-  tok->stack[depth].current = NULL;
-  free(tok->stack[depth].obj_field_name);
-  tok->stack[depth].obj_field_name = NULL;
-}
-
-void json_tokener_reset(struct json_tokener *tok)
-{
-  int i;
-  if (!tok)
-    return;
-
-  for(i = tok->depth; i >= 0; i--)
-    json_tokener_reset_level(tok, i);
-  tok->depth = 0;
-  tok->err = json_tokener_success;
-}
-
-struct json_object* json_tokener_parse(const char *str)
-{
-  struct json_tokener* tok;
-  struct json_object* obj;
-
-  tok = json_tokener_new();
-  obj = json_tokener_parse_ex(tok, str, -1);
-  if(tok->err != json_tokener_success)
-    obj = (struct json_object*)error_ptr(-tok->err);
-  json_tokener_free(tok);
-  return obj;
-}
-
-
-#if !HAVE_STRNDUP
-/* CAW: compliant version of strndup() */
-char* strndup(const char* str, size_t n)
-{
-  if(str) {
-    size_t len = strlen(str);
-    size_t nn = json_min(len,n);
-    char* s = (char*)malloc(sizeof(char) * (nn + 1));
-
-    if(s) {
-      memcpy(s, str, nn);
-      s[nn] = '\0';
-    }
-
-    return s;
-  }
-
-  return NULL;
-}
-#endif
-
-
-#define state  tok->stack[tok->depth].state
-#define saved_state  tok->stack[tok->depth].saved_state
-#define current tok->stack[tok->depth].current
-#define obj_field_name tok->stack[tok->depth].obj_field_name
-
-/* Optimization:
- * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
- * iterating character-by character.  A large performance boost is
- * achieved by using tighter loops to locally handle units such as
- * comments and strings.  Loops that handle an entire token within 
- * their scope also gather entire strings and pass them to 
- * printbuf_memappend() in a single call, rather than calling
- * printbuf_memappend() one char at a time.
- *
- * POP_CHAR() and ADVANCE_CHAR() macros are used for code that is
- * common to both the main loop and the tighter loops.
- */
-
-/* POP_CHAR(dest, tok) macro:
- *   Not really a pop()...peeks at the current char and stores it in dest.
- *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
- *   Implicit inputs:  str, len vars
- */
-#define POP_CHAR(dest, tok)                                                  \
-  (((tok)->char_offset == len) ?                                          \
-   (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
-    (((tok)->err = json_tokener_success), 0)                              \
-    :                                                                   \
-    (((tok)->err = json_tokener_continue), 0)                             \
-    ) :                                                                 \
-   (((dest) = *str), 1)                                                 \
-   )
- 
-/* ADVANCE_CHAR() macro:
- *   Incrementes str & tok->char_offset.
- *   For convenience of existing conditionals, returns the old value of c (0 on eof)
- *   Implicit inputs:  c var
- */
-#define ADVANCE_CHAR(str, tok) \
-  ( ++(str), ((tok)->char_offset)++, c)
-
-/* End optimization macro defs */
-
-
-struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
-					  const char *str, int len)
-{
-  struct json_object *obj = NULL;
-  char c = '\1';
-
-  tok->char_offset = 0;
-  tok->err = json_tokener_success;
-
-  while (POP_CHAR(c, tok)) {
-
-  redo_char:
-    switch(state) {
-
-    case json_tokener_state_eatws:
-      /* Advance until we change state */
-      while (isspace(c)) {
-	if ((!ADVANCE_CHAR(str, tok)) || (!POP_CHAR(c, tok)))
-	  goto out;
-      }
-      if(c == '/') {
-	printbuf_reset(tok->pb);
-	printbuf_memappend_fast(tok->pb, &c, 1);
-	state = json_tokener_state_comment_start;
-      } else {
-	state = saved_state;
-	goto redo_char;
-      }
-      break;
-
-    case json_tokener_state_start:
-      switch(c) {
-      case '{':
-	state = json_tokener_state_eatws;
-	saved_state = json_tokener_state_object_field_start;
-	current = json_object_new_object();
-	break;
-      case '[':
-	state = json_tokener_state_eatws;
-	saved_state = json_tokener_state_array;
-	current = json_object_new_array();
-	break;
-      case 'N':
-      case 'n':
-	state = json_tokener_state_null;
-	printbuf_reset(tok->pb);
-	tok->st_pos = 0;
-	goto redo_char;
-      case '"':
-      case '\'':
-	state = json_tokener_state_string;
-	printbuf_reset(tok->pb);
-	tok->quote_char = c;
-	break;
-      case 'T':
-      case 't':
-      case 'F':
-      case 'f':
-	state = json_tokener_state_boolean;
-	printbuf_reset(tok->pb);
-	tok->st_pos = 0;
-	goto redo_char;
-#if defined(__GNUC__)
-	  case '0' ... '9':
-#else
-	  case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-#endif
-      case '-':
-	state = json_tokener_state_number;
-	printbuf_reset(tok->pb);
-	tok->is_double = 0;
-	goto redo_char;
-      default:
-	tok->err = json_tokener_error_parse_unexpected;
-	goto out;
-      }
-      break;
-
-    case json_tokener_state_finish:
-      if(tok->depth == 0) goto out;
-      obj = json_object_get(current);
-      json_tokener_reset_level(tok, tok->depth);
-      tok->depth--;
-      goto redo_char;
-
-    case json_tokener_state_null:
-      printbuf_memappend_fast(tok->pb, &c, 1);
-      if(strncasecmp(json_null_str, tok->pb->buf,
-		     json_min(tok->st_pos+1, strlen(json_null_str))) == 0) {
-	if(tok->st_pos == strlen(json_null_str)) {
-	  current = NULL;
-	  saved_state = json_tokener_state_finish;
-	  state = json_tokener_state_eatws;
-	  goto redo_char;
-	}
-      } else {
-	tok->err = json_tokener_error_parse_null;
-	goto out;
-      }
-      tok->st_pos++;
-      break;
-
-    case json_tokener_state_comment_start:
-      if(c == '*') {
-	state = json_tokener_state_comment;
-      } else if(c == '/') {
-	state = json_tokener_state_comment_eol;
-      } else {
-	tok->err = json_tokener_error_parse_comment;
-	goto out;
-      }
-      printbuf_memappend_fast(tok->pb, &c, 1);
-      break;
-
-    case json_tokener_state_comment:
-              {
-          /* Advance until we change state */
-          const char *case_start = str;
-          while(c != '*') {
-            if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) {
-              printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-              goto out;
-            } 
-          }
-          printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
-          state = json_tokener_state_comment_end;
-        }
-            break;
-
-    case json_tokener_state_comment_eol:
-      {
-	/* Advance until we change state */
-	const char *case_start = str;
-	while(c != '\n') {
-	  if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    goto out;
-	  }
-	}
-	printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
-	state = json_tokener_state_eatws;
-      }
-      break;
-
-    case json_tokener_state_comment_end:
-      printbuf_memappend_fast(tok->pb, &c, 1);
-      if(c == '/') {
-	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
-	state = json_tokener_state_eatws;
-      } else {
-	state = json_tokener_state_comment;
-      }
-      break;
-
-    case json_tokener_state_string:
-      {
-	/* Advance until we change state */
-	const char *case_start = str;
-	while(1) {
-	  if(c == tok->quote_char) {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    current = json_object_new_string(tok->pb->buf);
-	    saved_state = json_tokener_state_finish;
-	    state = json_tokener_state_eatws;
-	    break;
-	  } else if(c == '\\') {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    saved_state = json_tokener_state_string;
-	    state = json_tokener_state_string_escape;
-	    break;
-	  }
-	  if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    goto out;
-	  }
-	}
-      }
-      break;
-
-    case json_tokener_state_string_escape:
-      switch(c) {
-      case '"':
-      case '\\':
-      case '/':
-	printbuf_memappend_fast(tok->pb, &c, 1);
-	state = saved_state;
-	break;
-      case 'b':
-      case 'n':
-      case 'r':
-      case 't':
-	if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
-	else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
-	else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
-	else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
-	state = saved_state;
-	break;
-      case 'u':
-	tok->ucs_char = 0;
-	tok->st_pos = 0;
-	state = json_tokener_state_escape_unicode;
-	break;
-      default:
-	tok->err = json_tokener_error_parse_string;
-	goto out;
-      }
-      break;
-
-    case json_tokener_state_escape_unicode:
-            /* Note that the following code is inefficient for handling large
-       * chunks of extended chars, calling printbuf_memappend() once
-       * for each multi-byte character of input.
-       * This is a good area for future optimization.
-       */
-	{
-	  /* Advance until we change state */
-	  while(1) {
-	    if(strchr(json_hex_chars, c)) {
-	      tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
-	      if(tok->st_pos == 4) {
-		unsigned char utf_out[3];
-		if (tok->ucs_char < 0x80) {
-		  utf_out[0] = tok->ucs_char;
-		  printbuf_memappend_fast(tok->pb, (char*)utf_out, 1);
-		} else if (tok->ucs_char < 0x800) {
-		  utf_out[0] = 0xc0 | (tok->ucs_char >> 6);
-		  utf_out[1] = 0x80 | (tok->ucs_char & 0x3f);
-		  printbuf_memappend_fast(tok->pb, (char*)utf_out, 2);
-		} else {
-		  utf_out[0] = 0xe0 | (tok->ucs_char >> 12);
-		  utf_out[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
-		  utf_out[2] = 0x80 | (tok->ucs_char & 0x3f);
-		  printbuf_memappend_fast(tok->pb, (char*)utf_out, 3);
-		}
-		state = saved_state;
-		break;
-	      }
-	    } else {
-	      tok->err = json_tokener_error_parse_string;
-	      goto out;
-	      	  }
-	  if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok))
-	    goto out;
-	}
-      }
-      break;
-
-    case json_tokener_state_boolean:
-      printbuf_memappend_fast(tok->pb, &c, 1);
-      if(strncasecmp(json_true_str, tok->pb->buf,
-		     json_min(tok->st_pos+1, strlen(json_true_str))) == 0) {
-	if(tok->st_pos == strlen(json_true_str)) {
-	  current = json_object_new_boolean(1);
-	  saved_state = json_tokener_state_finish;
-	  state = json_tokener_state_eatws;
-	  goto redo_char;
-	}
-      } else if(strncasecmp(json_false_str, tok->pb->buf,
-			    json_min(tok->st_pos+1, strlen(json_false_str))) == 0) {
-	if(tok->st_pos == strlen(json_false_str)) {
-	  current = json_object_new_boolean(0);
-	  saved_state = json_tokener_state_finish;
-	  state = json_tokener_state_eatws;
-	  goto redo_char;
-	}
-      } else {
-	tok->err = json_tokener_error_parse_boolean;
-	goto out;
-      }
-      tok->st_pos++;
-      break;
-
-    case json_tokener_state_number:
-      {
-	/* Advance until we change state */
-	const char *case_start = str;
-	int case_len=0;
-	while(c && strchr(json_number_chars, c)) {
-	  ++case_len;
-	  if(c == '.' || c == 'e') tok->is_double = 1;
-	  if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) {
-	    printbuf_memappend_fast(tok->pb, case_start, case_len);
-	    goto out;
-	  }
-	}
-        if (case_len>0)
-          printbuf_memappend_fast(tok->pb, case_start, case_len);
-      }
-      {
-        int numi;
-        double numd;
-        if(!tok->is_double && sscanf(tok->pb->buf, "%d", &numi) == 1) {
-          current = json_object_new_int(numi);
-        } else if(tok->is_double) {
-          numd = CPLAtof(tok->pb->buf);
-          current = json_object_new_double(numd);
-        } else {
-          tok->err = json_tokener_error_parse_number;
-          goto out;
-        }
-        saved_state = json_tokener_state_finish;
-        state = json_tokener_state_eatws;
-        goto redo_char;
-      }
-      break;
-
-    case json_tokener_state_array:
-      if(c == ']') {
-	saved_state = json_tokener_state_finish;
-	state = json_tokener_state_eatws;
-      } else {
-	if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
-	  tok->err = json_tokener_error_depth;
-	  goto out;
-	}
-	state = json_tokener_state_array_add;
-	tok->depth++;
-	json_tokener_reset_level(tok, tok->depth);
-	goto redo_char;
-      }
-      break;
-
-    case json_tokener_state_array_add:
-      json_object_array_add(current, obj);
-      saved_state = json_tokener_state_array_sep;
-      state = json_tokener_state_eatws;
-      goto redo_char;
-
-    case json_tokener_state_array_sep:
-      if(c == ']') {
-	saved_state = json_tokener_state_finish;
-	state = json_tokener_state_eatws;
-      } else if(c == ',') {
-	saved_state = json_tokener_state_array;
-	state = json_tokener_state_eatws;
-      } else {
-	tok->err = json_tokener_error_parse_array;
-	goto out;
-      }
-      break;
-
-    case json_tokener_state_object_field_start:
-      if(c == '}') {
-	saved_state = json_tokener_state_finish;
-	state = json_tokener_state_eatws;
-      } else if (c == '"' || c == '\'') {
-	tok->quote_char = c;
-	printbuf_reset(tok->pb);
-	state = json_tokener_state_object_field;
-      } else {
-	tok->err = json_tokener_error_parse_object_key_name;
-	goto out;
-      }
-      break;
-
-    case json_tokener_state_object_field:
-      {
-	/* Advance until we change state */
-	const char *case_start = str;
-	while(1) {
-	  if(c == tok->quote_char) {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    obj_field_name = strdup(tok->pb->buf);
-	    saved_state = json_tokener_state_object_field_end;
-	    state = json_tokener_state_eatws;
-	    break;
-	  } else if(c == '\\') {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    saved_state = json_tokener_state_object_field;
-	    state = json_tokener_state_string_escape;
-	    break;
-	  }
-	  if (!ADVANCE_CHAR(str, tok) || !POP_CHAR(c, tok)) {
-	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
-	    goto out;
-	  }
-	}
-      }
-      break;
-
-    case json_tokener_state_object_field_end:
-      if(c == ':') {
-	saved_state = json_tokener_state_object_value;
-	state = json_tokener_state_eatws;
-      } else {
-	tok->err = json_tokener_error_parse_object_key_sep;
-	goto out;
-      }
-      break;
-
-    case json_tokener_state_object_value:
-      if(tok->depth >= JSON_TOKENER_MAX_DEPTH-1) {
-	tok->err = json_tokener_error_depth;
-	goto out;
-      }
-      state = json_tokener_state_object_value_add;
-      tok->depth++;
-      json_tokener_reset_level(tok, tok->depth);
-      goto redo_char;
-
-    case json_tokener_state_object_value_add:
-      json_object_object_add(current, obj_field_name, obj);
-      free(obj_field_name);
-      obj_field_name = NULL;
-      saved_state = json_tokener_state_object_sep;
-      state = json_tokener_state_eatws;
-      goto redo_char;
-
-    case json_tokener_state_object_sep:
-      if(c == '}') {
-	saved_state = json_tokener_state_finish;
-	state = json_tokener_state_eatws;
-      } else if(c == ',') {
-	saved_state = json_tokener_state_object_field_start;
-	state = json_tokener_state_eatws;
-      } else {
-	tok->err = json_tokener_error_parse_object_value_sep;
-	goto out;
-      }
-      break;
-
-    }
-    if (!ADVANCE_CHAR(str, tok))
-      goto out;
-  } /* while(POP_CHAR) */
-
- out:
-  if (!c) { /* We hit an eof char (0) */
-    if(state != json_tokener_state_finish &&
-       saved_state != json_tokener_state_finish)
-      tok->err = json_tokener_error_parse_eof;
-  }
-
-  if(tok->err == json_tokener_success) return json_object_get(current);
-  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
-	   json_tokener_errors[tok->err], tok->char_offset);
-  return NULL;
-}
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.h b/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.h
deleted file mode 100644
index 7d40b40..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_tokener.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _json_tokener_h_
-#define _json_tokener_h_
-
-#include <stddef.h>
-#include "json_object.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum json_tokener_error {
-  json_tokener_success,
-  json_tokener_continue,
-  json_tokener_error_depth,
-  json_tokener_error_parse_eof,
-  json_tokener_error_parse_unexpected,
-  json_tokener_error_parse_null,
-  json_tokener_error_parse_boolean,
-  json_tokener_error_parse_number,
-  json_tokener_error_parse_array,
-  json_tokener_error_parse_object_key_name,
-  json_tokener_error_parse_object_key_sep,
-  json_tokener_error_parse_object_value_sep,
-  json_tokener_error_parse_string,
-  json_tokener_error_parse_comment
-};
-
-enum json_tokener_state {
-  json_tokener_state_eatws,
-  json_tokener_state_start,
-  json_tokener_state_finish,
-  json_tokener_state_null,
-  json_tokener_state_comment_start,
-  json_tokener_state_comment,
-  json_tokener_state_comment_eol,
-  json_tokener_state_comment_end,
-  json_tokener_state_string,
-  json_tokener_state_string_escape,
-  json_tokener_state_escape_unicode,
-  json_tokener_state_boolean,
-  json_tokener_state_number,
-  json_tokener_state_array,
-  json_tokener_state_array_add,
-  json_tokener_state_array_sep,
-  json_tokener_state_object_field_start,
-  json_tokener_state_object_field,
-  json_tokener_state_object_field_end,
-  json_tokener_state_object_value,
-  json_tokener_state_object_value_add,
-  json_tokener_state_object_sep
-};
-
-struct json_tokener_srec
-{
-  enum json_tokener_state state, saved_state;
-  struct json_object *obj;
-  struct json_object *current;
-  char *obj_field_name;
-};
-
-#define JSON_TOKENER_MAX_DEPTH 32
-
-struct json_tokener
-{
-  char *str;
-  struct printbuf *pb;
-  int depth, is_double, st_pos, char_offset;
-  ptrdiff_t err;
-  unsigned int ucs_char;
-  char quote_char;
-  struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
-};
-
-extern const char* json_tokener_errors[];
-
-extern struct json_tokener* json_tokener_new(void);
-extern void json_tokener_free(struct json_tokener *tok);
-extern void json_tokener_reset(struct json_tokener *tok);
-extern struct json_object* json_tokener_parse(const char *str);
-extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
-						 const char *str, int len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_util.c b/ogr/ogrsf_frmts/geojson/jsonc/json_util.c
deleted file mode 100644
index af6f3d6..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_util.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif /* HAVE_SYS_TYPES_H */
-
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif /* HAVE_SYS_STAT_H */
-
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# include <io.h>
-#endif /* defined(WIN32) */
-
-#if !HAVE_OPEN && defined(WIN32)
-# define open _open
-#endif
-
-
-#include "bits.h"
-#include "debug.h"
-#include "printbuf.h"
-#include "json_object.h"
-#include "json_tokener.h"
-#include "json_util.h"
-
-struct json_object* json_object_from_file(char *filename)
-{
-  struct printbuf *pb;
-  struct json_object *obj;
-  char buf[JSON_FILE_BUF_SIZE];
-  int fd, ret;
-
-  if((fd = open(filename, O_RDONLY)) < 0) {
-    MC_ERROR("json_object_from_file: error reading file %s: %s\n",
-	     filename, strerror(errno));
-    return (struct json_object*)error_ptr(-1);
-  }
-  if(!(pb = printbuf_new())) {
-    MC_ERROR("json_object_from_file: printbuf_new failed\n");
-    return (struct json_object*)error_ptr(-1);
-  }
-  while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
-    printbuf_memappend(pb, buf, ret);
-  }
-  close(fd);
-  if(ret < 0) {
-    MC_ABORT("json_object_from_file: error reading file %s: %s\n",
-	     filename, strerror(errno));
-    printbuf_free(pb);
-    return (struct json_object*)error_ptr(-1);
-  }
-  obj = json_tokener_parse(pb->buf);
-  printbuf_free(pb);
-  return obj;
-}
-
-int json_object_to_file(char *filename, struct json_object *obj)
-{
-  const char *json_str;
-  int fd, ret;
-  unsigned int wpos, wsize;
-
-  if(!obj) {
-    MC_ERROR("json_object_to_file: object is null\n");
-    return -1;
-  }
-
-  if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
-    MC_ERROR("json_object_to_file: error opening file %s: %s\n",
-	     filename, strerror(errno));
-    return -1;
-  }
-
-  if(!(json_str = json_object_to_json_string(obj))) { return -1; }
-
-
-  wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
-  wpos = 0;
-  while(wpos < wsize) {
-    if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
-      close(fd);
-      MC_ERROR("json_object_to_file: error writing file %s: %s\n",
-	     filename, strerror(errno));
-      return -1;
-    }
-
-	/* because of the above check for ret < 0, we can safely cast and add */
-    wpos += (unsigned int)ret;
-  }
-
-  close(fd);
-  return 0;
-}
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_util.h b/ogr/ogrsf_frmts/geojson/jsonc/json_util.h
deleted file mode 100644
index 6ab0287..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#ifndef _json_util_h_
-#define _json_util_h_
-
-#include "json_object.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define JSON_FILE_BUF_SIZE 4096
-
-/* utility functions */
-extern struct json_object* json_object_from_file(char *filename);
-extern int json_object_to_file(char *filename, struct json_object *obj);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/linkhash.c b/ogr/ogrsf_frmts/geojson/jsonc/linkhash.c
deleted file mode 100644
index 998cf7d..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/linkhash.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <limits.h>
-
-#include "linkhash.h"
-
-void lh_abort(const char *msg, ...)
-{
-	va_list ap;
-	va_start(ap, msg);
-	vprintf(msg, ap);
-	va_end(ap);
-	exit(1);
-}
-
-unsigned long lh_ptr_hash(const void *k)
-{
-	/* CAW: refactored to be 64bit nice */
-	return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
-}
-
-int lh_ptr_equal(const void *k1, const void *k2)
-{
-	return (k1 == k2);
-}
-
-unsigned long lh_char_hash(const void *k)
-{
-	unsigned int h = 0;
-	const char* data = (const char*)k;
- 
-	while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
-
-	return h;
-}
-
-int lh_char_equal(const void *k1, const void *k2)
-{
-	return (strcmp((const char*)k1, (const char*)k2) == 0);
-}
-
-struct lh_table* lh_table_new(int size, const char *name,
-			      lh_entry_free_fn *free_fn,
-			      lh_hash_fn *hash_fn,
-			      lh_equal_fn *equal_fn)
-{
-	int i;
-	struct lh_table *t;
-
-	t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
-	if(!t) lh_abort("lh_table_new: calloc failed\n");
-	t->count = 0;
-	t->size = size;
-	t->name = name;
-	t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
-	if(!t->table) lh_abort("lh_table_new: calloc failed\n");
-	t->free_fn = free_fn;
-	t->hash_fn = hash_fn;
-	t->equal_fn = equal_fn;
-	for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
-	return t;
-}
-
-struct lh_table* lh_kchar_table_new(int size, const char *name,
-				    lh_entry_free_fn *free_fn)
-{
-	return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
-}
-
-struct lh_table* lh_kptr_table_new(int size, const char *name,
-				   lh_entry_free_fn *free_fn)
-{
-	return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
-}
-
-void lh_table_resize(struct lh_table *t, int new_size)
-{
-	struct lh_table *new_t;
-	struct lh_entry *ent;
-
-	new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
-	ent = t->head;
-	while(ent) {
-		lh_table_insert(new_t, ent->k, ent->v);
-		ent = ent->next;
-	}
-	free(t->table);
-	t->table = new_t->table;
-	t->size = new_size;
-	t->head = new_t->head;
-	t->tail = new_t->tail;
-	t->resizes++;
-	free(new_t);
-}
-
-void lh_table_free(struct lh_table *t)
-{
-	struct lh_entry *c;
-	for(c = t->head; c != NULL; c = c->next) {
-		if(t->free_fn) {
-			t->free_fn(c);
-		}
-	}
-	free(t->table);
-	free(t);
-}
-
-
-int lh_table_insert(struct lh_table *t, void *k, const void *v)
-{
-	unsigned long h, n;
-
-	t->inserts++;
-	if(t->count > t->size * 0.66) lh_table_resize(t, t->size * 2);
-
-	h = t->hash_fn(k);
-	n = h % t->size;
-
-	while( 1 ) {
-		if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
-		t->collisions++;
-		if(++n == t->size) n = 0;
-	}
-
-	t->table[n].k = k;
-	t->table[n].v = v;
-	t->count++;
-
-	if(t->head == NULL) {
-		t->head = t->tail = &t->table[n];
-		t->table[n].next = t->table[n].prev = NULL;
-	} else {
-		t->tail->next = &t->table[n];
-		t->table[n].prev = t->tail;
-		t->table[n].next = NULL;
-		t->tail = &t->table[n];
-	}
-
-	return 0;
-}
-
-
-struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
-{
-	unsigned long h = t->hash_fn(k);
-	unsigned long n = h % t->size;
-
-	t->lookups++;
-	while( 1 ) {
-		if(t->table[n].k == LH_EMPTY) return NULL;
-		if(t->table[n].k != LH_FREED &&
-		   t->equal_fn(t->table[n].k, k)) return &t->table[n];
-		if(++n == t->size) n = 0;
-	}
-	return NULL;
-}
-
-
-const void* lh_table_lookup(struct lh_table *t, const void *k)
-{
-	struct lh_entry *e = lh_table_lookup_entry(t, k);
-	if(e) return e->v;
-	return NULL;
-}
-
-
-int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
-{
-	ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
-
-	/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
-	if(n < 0) { return -2; }
-
-	if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
-	t->count--;
-	if(t->free_fn) t->free_fn(e);
-	t->table[n].v = NULL;
-	t->table[n].k = LH_FREED;
-	if(t->tail == &t->table[n] && t->head == &t->table[n]) {
-		t->head = t->tail = NULL;
-	} else if (t->head == &t->table[n]) {
-		t->head->next->prev = NULL;
-		t->head = t->head->next;
-	} else if (t->tail == &t->table[n]) {
-		t->tail->prev->next = NULL;
-		t->tail = t->tail->prev;
-	} else {
-		t->table[n].prev->next = t->table[n].next;
-		t->table[n].next->prev = t->table[n].prev;
-	}
-	t->table[n].next = t->table[n].prev = NULL;
-	return 0;
-}
-
-
-int lh_table_delete(struct lh_table *t, const void *k)
-{
-	struct lh_entry *e = lh_table_lookup_entry(t, k);
-	if(!e) return -1;
-	return lh_table_delete_entry(t, e);
-}
-
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/linkhash.h b/ogr/ogrsf_frmts/geojson/jsonc/linkhash.h
deleted file mode 100644
index 90f219d..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/linkhash.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- */
- 
-#ifndef _linkhash_h_
-#define _linkhash_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * golden prime used in hash functions
- */
-#define LH_PRIME 0x9e370001UL
-
-/**
- * sentinel pointer value for empty slots
- */
-#define LH_EMPTY (void*)-1
-
-/**
- * sentinel pointer value for freed slots
- */
-#define LH_FREED (void*)-2
-
-struct lh_entry;
-
-/**
- * callback function prototypes
- */
-typedef void (lh_entry_free_fn) (struct lh_entry *e);
-/**
- * callback function prototypes
- */
-typedef unsigned long (lh_hash_fn) (const void *k);
-/**
- * callback function prototypes
- */
-typedef int (lh_equal_fn) (const void *k1, const void *k2);
-
-/**
- * An entry in the hash table
- */
-struct lh_entry {
-	/**
-	 * The key.
-	 */
-	void *k;
-	/**
-	 * The value.
-	 */
-	const void *v;
-	/**
-	 * The next entry
-	 */
-	struct lh_entry *next;
-	/**
-	 * The previous entry.
-	 */
-	struct lh_entry *prev;
-};
-
-
-/**
- * The hash table structure.
- */
-struct lh_table {
-	/**
-	 * Size of our hash.
-	 */
-	int size;
-	/**
-	 * Numbers of entries.
-	 */
-	int count;
-
-	/**
-	 * Number of collisions.
-	 */
-	int collisions;
-
-	/**
-	 * Number of resizes.
-	 */
-	int resizes;
-
-	/**
-	 * Number of lookups.
-	 */
-	int lookups;
-
-	/**
-	 * Number of inserts.
-	 */
-	int inserts;
-
-	/**
-	 * Number of deletes.
-	 */
-	int deletes;
-
-	/**
-	 * Name of the hash table.
-	 */
-	const char *name;
-
-	/**
-	 * The first entry.
-	 */
-	struct lh_entry *head;
-
-	/**
-	 * The last entry.
-	 */
-	struct lh_entry *tail;
-
-	struct lh_entry *table;
-
-	/**
-	 * A pointer onto the function responsible for freeing an entry.
-	 */
-	lh_entry_free_fn *free_fn;
-	lh_hash_fn *hash_fn;
-	lh_equal_fn *equal_fn;
-};
-
-
-/**
- * Pre-defined hash and equality functions
- */
-extern unsigned long lh_ptr_hash(const void *k);
-extern int lh_ptr_equal(const void *k1, const void *k2);
-
-extern unsigned long lh_char_hash(const void *k);
-extern int lh_char_equal(const void *k1, const void *k2);
-
-
-/**
- * Convenience list iterator.
- */
-#define lh_foreach(table, entry) \
-for(entry = table->head; entry; entry = entry->next)
-
-/**
- * lh_foreach_safe allows calling of deletion routine while iterating.
- */
-#define lh_foreach_safe(table, entry, tmp) \
-for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
-
-
-
-/**
- * Create a new linkhash table.
- * @param size initial table size. The table is automatically resized
- * although this incurs a performance penalty.
- * @param name the table name.
- * @param free_fn callback function used to free memory for entries
- * when lh_table_free or lh_table_delete is called.
- * If NULL is provided, then memory for keys and values
- * must be freed by the caller.
- * @param hash_fn  function used to hash keys. 2 standard ones are defined:
- * lh_ptr_hash and lh_char_hash for hashing pointer values
- * and C strings respectively.
- * @param equal_fn comparison function to compare keys. 2 standard ones defined:
- * lh_ptr_hash and lh_char_hash for comparing pointer values
- * and C strings respectively.
- * @return a pointer onto the linkhash table.
- */
-extern struct lh_table* lh_table_new(int size, const char *name,
-				     lh_entry_free_fn *free_fn,
-				     lh_hash_fn *hash_fn,
-				     lh_equal_fn *equal_fn);
-
-/**
- * Convenience function to create a new linkhash
- * table with char keys.
- * @param size initial table size.
- * @param name table name.
- * @param free_fn callback function used to free memory for entries.
- * @return a pointer onto the linkhash table.
- */
-extern struct lh_table* lh_kchar_table_new(int size, const char *name,
-					   lh_entry_free_fn *free_fn);
-
-
-/**
- * Convenience function to create a new linkhash
- * table with ptr keys.
- * @param size initial table size.
- * @param name table name.
- * @param free_fn callback function used to free memory for entries.
- * @return a pointer onto the linkhash table.
- */
-extern struct lh_table* lh_kptr_table_new(int size, const char *name,
-					  lh_entry_free_fn *free_fn);
-
-
-/**
- * Free a linkhash table.
- * If a callback free function is provided then it is called for all
- * entries in the table.
- * @param t table to free.
- */
-extern void lh_table_free(struct lh_table *t);
-
-
-/**
- * Insert a record into the table.
- * @param t the table to insert into.
- * @param k a pointer to the key to insert.
- * @param v a pointer to the value to insert.
- */
-extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
-
-
-/**
- * Lookup a record into the table.
- * @param t the table to lookup
- * @param k a pointer to the key to lookup
- * @return a pointer to the record structure of the value or NULL if it does not exist.
- */
-extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
-
-/**
- * Lookup a record into the table
- * @param t the table to lookup
- * @param k a pointer to the key to lookup
- * @return a pointer to the found value or NULL if it does not exist.
- */
-extern const void* lh_table_lookup(struct lh_table *t, const void *k);
-
-
-/**
- * Delete a record from the table.
- * If a callback free function is provided then it is called for the
- * for the item being deleted.
- * @param t the table to delete from.
- * @param e a pointer to the entry to delete.
- * @return 0 if the item was deleted.
- * @return -1 if it was not found.
- */
-extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
-
-
-/**
- * Delete a record from the table.
- * If a callback free function is provided then it is called for the
- * for the item being deleted.
- * @param t the table to delete from.
- * @param k a pointer to the key to delete.
- * @return 0 if the item was deleted.
- * @return -1 if it was not found.
- */
-extern int lh_table_delete(struct lh_table *t, const void *k);
-
-
-void lh_abort(const char *msg, ...);
-void lh_table_resize(struct lh_table *t, int new_size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc b/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc
deleted file mode 100644
index 6cbe3ff..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc
+++ /dev/null
@@ -1,25 +0,0 @@
-# $Id$
-#
-# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
-# 
-
-OBJ = \
-	arraylist.obj \
-	debug.obj \
-	json_object.obj \
-	json_tokener.obj \
-	json_util.obj \
-	linkhash.obj \
-	printbuf.obj
-
-GDAL_ROOT	=	..\..\..\..
-
-!INCLUDE $(GDAL_ROOT)\nmake.opt
-
-EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(SOFTWARNFLAGS)
-
-default:	$(OBJ)
-
-clean:
-	-del *.lib
-	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c b/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c
deleted file mode 100644
index d5760f2..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- *
- * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
- * The copyrights to the contents of this file are licensed under the MIT License
- * (http://www.opensource.org/licenses/mit-license.php)
- */
-
-#include "config.h"
-
-#if defined(__GNUC__) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE 1 /* seems to be required to bring in vasprintf */
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cpl_string.h" 
-
-#if HAVE_STDARG_H
-# include <stdarg.h>
-#else /* !HAVE_STDARG_H */
-# error Not enough var arg support!
-#endif /* HAVE_STDARG_H */
-
-#include "bits.h"
-#include "debug.h"
-#include "printbuf.h"
-
-struct printbuf* printbuf_new(void)
-{
-  struct printbuf *p;
-
-  p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
-  if(!p) return NULL;
-  p->size = 32;
-  p->bpos = 0;
-  if((p->buf = (char*)malloc(p->size)) == NULL) {
-    free(p);
-    return NULL;
-  }
-  return p;
-}
-
-
-int printbuf_memappend(struct printbuf *p, const char *buf, int size)
-{
-  char *t;
-  if(p->size - p->bpos <= size) {
-    int new_size = json_max(p->size * 2, p->bpos + size + 8);
-#ifdef PRINTBUF_DEBUG
-    MC_DEBUG("printbuf_memappend: realloc "
-	     "bpos=%d wrsize=%d old_size=%d new_size=%d\n",
-	     p->bpos, size, p->size, new_size);
-#endif /* PRINTBUF_DEBUG */
-    if((t = (char*)realloc(p->buf, new_size)) == NULL) return -1;
-    p->size = new_size;
-    p->buf = t;
-  }
-  memcpy(p->buf + p->bpos, buf, size);
-  p->bpos += size;
-  p->buf[p->bpos]= '\0';
-  return size;
-}
-
-/* Use CPLVASPrintf for portability issues */
-int sprintbuf(struct printbuf *p, const char *msg, ...)
-{
-  va_list ap;
-  char *t;
-  int size, ret; 
-
-  /* user stack buffer first */
-  va_start(ap, msg);
-  if((size = CPLVASPrintf(&t, msg, ap)) == -1) return -1; 
-  va_end(ap);
-  
-  if (strcmp(msg, "%f") == 0)
-  {
-      char* pszComma = strchr(t, ',');
-      if (pszComma)
-          *pszComma = '.';
-  }
-  
-  ret = printbuf_memappend(p, t, size);
-  CPLFree(t);
-  return ret;
-}
-
-void printbuf_reset(struct printbuf *p)
-{
-  p->buf[0] = '\0';
-  p->bpos = 0;
-}
-
-void printbuf_free(struct printbuf *p)
-{
-  if(p) {
-    free(p->buf);
-    free(p);
-  }
-}
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.h b/ogr/ogrsf_frmts/geojson/jsonc/printbuf.h
deleted file mode 100644
index 53fa921..0000000
--- a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
- *
- * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
- * Michael Clark <michael at metaparadigm.com>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the MIT license. See COPYING for details.
- *
- *
- * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
- * The copyrights to the contents of this file are licensed under the MIT License
- * (http://www.opensource.org/licenses/mit-license.php)
- */
-
-#ifndef _printbuf_h_
-#define _printbuf_h_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#undef PRINTBUF_DEBUG
-
-struct printbuf {
-  char *buf;
-  int bpos;
-  int size;
-};
-
-extern struct printbuf*
-printbuf_new(void);
-
-/* As an optimization, printbuf_memappend is defined as a macro that
- * handles copying data if the buffer is large enough; otherwise it
- * invokes printbuf_memappend_real() which performs the heavy lifting
- * of realloc()ing the buffer and copying data.
- */
-extern int
-printbuf_memappend(struct printbuf *p, const char *buf, int size);
-
-#define printbuf_memappend_fast(p, bufptr, bufsize)          \
-do {                                                         \
-  if ((p->size - p->bpos) > bufsize) {                       \
-    memcpy(p->buf + p->bpos, (bufptr), bufsize);             \
-    p->bpos += bufsize;                                      \
-    p->buf[p->bpos]= '\0';                                   \
-  } else {  printbuf_memappend(p, (bufptr), bufsize); }      \
-} while (0)
-
-extern int
-sprintbuf(struct printbuf *p, const char *msg, ...);
-
-extern void
-printbuf_reset(struct printbuf *p);
-
-extern void
-printbuf_free(struct printbuf *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/AUTHORS b/ogr/ogrsf_frmts/geojson/libjson/AUTHORS
new file mode 100644
index 0000000..b389989
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/AUTHORS
@@ -0,0 +1,5 @@
+Michael Clark <michael at metaparadigm.com>
+Jehiah Czebotar <jehiah at gmail.com>
+Eric Haszlakiewicz <hawicz+json-c at gmail.com>
+C. Watford (christopher.watford at gmail.com)
+
diff --git a/ogr/ogrsf_frmts/geojson/libjson/COPYING b/ogr/ogrsf_frmts/geojson/libjson/COPYING
new file mode 100644
index 0000000..740d125
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/COPYING
@@ -0,0 +1,42 @@
+
+Copyright (c) 2009-2012 Eric Haszlakiewicz
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+----------------------------------------------------------------
+
+Copyright (c) 2004, 2005 Metaparadigm Pte Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/ogr/ogrsf_frmts/geojson/libjson/ChangeLog b/ogr/ogrsf_frmts/geojson/libjson/ChangeLog
new file mode 100644
index 0000000..4e74c90
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/ChangeLog
@@ -0,0 +1,175 @@
+
+0.11
+
+  * IMPORTANT: the name of the library has changed to libjson-c.so and
+     the header files are now in include/json-c.
+     The pkgconfig name has also changed from json to json-c.
+     You should change your build to use appropriate -I and -l options.
+     A compatibility shim is in place so builds using the old name will
+     continue to work, but that will be removed in the next release.
+  * Maximum recursion depth is now a runtime option.
+     json_tokener_new() is provided for compatibility.
+     json_tokener_new_ex(depth)
+  * Include json_object_iterator.h in the installed headers.
+  * Add support for building on Android.
+  * Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid.
+  * Make it safe to delete keys while iterating with the json_object_object_foreach macro.
+  * Add a json_set_serializer() function to allow the string output of a json_object to be customized.
+  * Make float parsing locale independent.
+  * Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag.
+  * Enable -Werror when building.
+  * speed improvements to parsing 64-bit integers on systems with working sscanf
+  * Add a json_object_object_length function.
+  * Fix a bug (buffer overrun) when expanding arrays to more than 64 entries.
+
+0.10
+
+  * Add a json_object_to_json_string_ext() function to allow output to be
+     formatted in a more human readable form.
+  * Add json_object_object_get_ex(), a NULL-safe get object method, to be able
+     to distinguish between a key not present and the value being NULL.
+  * Add an alternative iterator implementation, see json_object_iterator.h
+  * Make json_object_iter public to enable external use of the
+     json_object_object_foreachC macro.
+  * Add a printbuf_memset() function to provide an effecient way to set and
+     append things like whitespace indentation.
+  * Adjust json_object_is_type and json_object_get_type so they return
+      json_type_null for NULL objects and handle NULL passed to
+      json_objct_object_get().
+  * Rename boolean type to json_bool.
+  * Fix various compile issues for Visual Studio and MinGW.
+  * Allow json_tokener_parse_ex() to be re-used to parse multiple object.
+     Also, fix some parsing issues with capitalized hexadecimal numbers and
+     number in E notation.
+  * Add json_tokener_get_error() and json_tokener_error_desc() to better 
+     encapsulate the process of retrieving errors while parsing.
+  * Various improvements to the documentation of many functions.
+  * Add new json_object_array_sort() function.
+  * Fix a bug in json_object_get_int(), which would incorrectly return 0
+    when called on a string type object.
+    Eric Haszlakiewicz
+  * Add a json_type_to_name() function.
+    Eric Haszlakiewicz
+  * Add a json_tokener_parse_verbose() function.
+    Jehiah Czebotar
+  * Improve support for null bytes within JSON strings.
+    Jehiah Czebotar
+  * Fix file descriptor leak if memory allocation fails in json_util
+    Zachary Blair, zack_blair at hotmail dot com
+  * Add int64 support. Two new functions json_object_net_int64 and
+    json_object_get_int64. Binary compatibility preserved.
+    Eric Haszlakiewicz, EHASZLA at transunion com
+    Rui Miguel Silva Seabra, rms at 1407 dot org
+  * Fix subtle bug in linkhash where lookup could hang after all slots
+    were filled then successively freed.
+    Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com
+  * Make json_object_from_file take const char *filename
+    Spotted by Vikram Raj V, vsagar at attinteractive dot com
+  * Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am)
+    Brent Miller, bdmiller at yahoo dash inc dot com
+  * Correction to comment describing printbuf_memappend in printbuf.h
+    Brent Miller, bdmiller at yahoo dash inc dot com
+
+0.9
+  * Add README.html README-WIN32.html config.h.win32 to Makefile.am
+    Michael Clark, <michael at metaparadigm.com>
+  * Add const qualifier to the json_tokener_parse functions
+    Eric Haszlakiewicz, EHASZLA at transunion dot com
+  * Rename min and max so we can never clash with C or C++ std library
+    Ian Atha, thatha at yahoo dash inc dot com
+  * Fix any noticeable spelling or grammar errors.
+  * Make sure every va_start has a va_end.
+  * Check all pointers for validity.
+    Erik Hovland, erik at hovland dot org
+  * Fix json_object_get_boolean to return false for empty string
+    Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com
+  * optimizations to json_tokener_parse_ex(), printbuf_memappend()
+    Brent Miller, bdmiller at yahoo dash inc dot com
+  * Disable REFCOUNT_DEBUG by default in json_object.c
+  * Don't use this as a variable, so we can compile with a C++ compiler
+  * Add casts from void* to type of assignment when using malloc 
+  * Add #ifdef __cplusplus guards to all of the headers
+  * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table
+    Michael Clark, <michael at metaparadigm.com>
+  * Null pointer dereference fix. Fix json_object_get_boolean strlen test
+    to not return TRUE for zero length string. Remove redundant includes.
+    Erik Hovland, erik at hovland dot org
+  * Fixed warning reported by adding -Wstrict-prototypes
+    -Wold-style-definition to the compilatin flags.
+    Dotan Barak, dotanba at gmail dot com
+  * Add const correctness to public interfaces
+    Gerard Krol, g dot c dot krol at student dot tudelft dot nl
+
+0.8
+  * Add va_end for every va_start
+    Dotan Barak, dotanba at gmail dot com
+  * Add macros to enable compiling out debug code
+    Geoffrey Young, geoff at modperlcookbook dot org
+  * Fix bug with use of capital E in numbers with exponents
+    Mateusz Loskot, mateusz at loskot dot net
+  * Add stddef.h include
+  * Patch allows for json-c compile with -Werror and not fail due to
+    -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
+    Geoffrey Young, geoff at modperlcookbook dot org
+
+0.7
+  * Add escaping of backslash to json output
+  * Add escaping of foward slash on tokenizing and output
+  * Changes to internal tokenizer from using recursion to
+    using a depth state structure to allow incremental parsing
+
+0.6
+  * Fix bug in escaping of control characters
+    Johan Bj�rklund, johbjo09 at kth dot se
+  * Remove include "config.h" from headers (should only
+    be included from .c files)
+    Michael Clark <michael at metaparadigm.com>
+
+0.5
+  * Make headers C++ compatible by change *this to *obj
+  * Add ifdef C++ extern "C" to headers
+  * Use simpler definition of min and max in bits.h
+    Larry Lansing, llansing at fuzzynerd dot com
+
+  * Remove automake 1.6 requirement
+  * Move autogen commands into autogen.sh. Update README
+  * Remove error pointer special case for Windows
+  * Change license from LGPL to MIT
+    Michael Clark <michael at metaparadigm.com>
+
+0.4
+  * Fix additional error case in object parsing
+  * Add back sign reversal in nested object parse as error pointer
+    value is negative, while error value is positive.
+    Michael Clark <michael at metaparadigm.com>
+
+0.3
+  * fix pointer arithmetic bug for error pointer check in is_error() macro
+  * fix type passed to printbuf_memappend in json_tokener
+  * update autotools bootstrap instructions in README
+    Michael Clark <michael at metaparadigm.com>
+
+0.2
+  * printbuf.c - C. Watford (christopher.watford at gmail.com)
+    Added a Win32/Win64 compliant implementation of vasprintf
+  * debug.c - C. Watford (christopher.watford at gmail.com)
+    Removed usage of vsyslog on Win32/Win64 systems, needs to be handled
+    by a configure script
+  * json_object.c - C. Watford (christopher.watford at gmail.com)
+    Added scope operator to wrap usage of json_object_object_foreach, this
+    needs to be rethought to be more ANSI C friendly
+  * json_object.h - C. Watford (christopher.watford at gmail.com)
+    Added Microsoft C friendly version of json_object_object_foreach
+  * json_tokener.c - C. Watford (christopher.watford at gmail.com)
+    Added a Win32/Win64 compliant implementation of strndup
+  * json_util.c - C. Watford (christopher.watford at gmail.com)
+    Added cast and mask to suffice size_t v. unsigned int conversion
+    correctness 
+  * json_tokener.c - sign reversal issue on error info for nested object parse
+    spotted by Johan Bj�rklund (johbjo09 at kth.se)
+  * json_object.c - escape " in json_escape_str
+  * Change to automake and libtool to build shared and static library
+    Michael Clark <michael at metaparadigm.com>
+	
+0.1
+  * initial release
diff --git a/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile b/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile
new file mode 100644
index 0000000..8106b61
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile
@@ -0,0 +1,29 @@
+# $Id$
+#
+# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
+# 
+include ../../../../GDALmake.opt
+
+OBJ = \
+	arraylist.o \
+	debug.o \
+	json_object.o \
+	json_tokener.o \
+	json_util.o \
+	linkhash.o \
+	printbuf.o \
+	json_object_iterator.o \
+	json_c_version.o
+
+O_OBJ = $(foreach file,$(OBJ),../../o/$(file))
+
+CPPFLAGS := $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+../../o/%.$(OBJ_EXT):	%.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+clean:
+	rm -f *.o $(O_OBJ)
+	rm -f *~
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/README b/ogr/ogrsf_frmts/geojson/libjson/README
similarity index 100%
rename from ogr/ogrsf_frmts/geojson/jsonc/README
rename to ogr/ogrsf_frmts/geojson/libjson/README
diff --git a/ogr/ogrsf_frmts/geojson/libjson/README.html b/ogr/ogrsf_frmts/geojson/libjson/README.html
new file mode 100644
index 0000000..7c2f9f4
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/README.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+	<head>
+		<title>JSON-C - A JSON implementation in C</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	</head>
+	<body>
+		<h2>JSON-C - A JSON implementation in C</h2>
+
+		<h3>Overview</h3>
+		<p>JSON-C implements a reference counting object model that allows you to easily 
+		construct JSON objects in C, output them as JSON formatted strings and parse 
+		JSON formatted strings back into the C representation of JSON objects.</p>
+
+		<h3>Building</h3>
+		<p>To setup JSON-C to build on your system please run <tt>configure</tt> and <tt>make</tt>.</p>
+		<p>If you are on Win32 and are not using the VS project file, be sure 
+		to rename <tt>config.h.win32</tt> to <tt>config.h</tt> before building.</p>
+
+		<h3>Documentation</h3>
+		<P>Doxygen generated documentation exists <a href="doc/html/json__object_8h.html">here</a>
+		and Win32 specific notes can be found <a href="README-WIN32.html">here</a>.</P>
+
+		<h3><a href="https://github.com/json-c/json-c">GIT Reposository</a></h3>
+		<p><strong><code>git clone https://github.com/json-c/json-c.git</code></strong></p>
+
+		<h3><a href="http://groups.google.com/group/json-c">Mailing List</a></h3>
+                <pi>Send email to <strong><code>json-c <i><at></i> googlegroups <i><dot></i> com</code></strong></p>
+
+		<h3><a href="COPYING">License</a></h3>
+		<p>This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..</p>
+		<hr/>
+	</body>
+</html>
diff --git a/ogr/ogrsf_frmts/geojson/libjson/arraylist.c b/ogr/ogrsf_frmts/geojson/libjson/arraylist.c
new file mode 100644
index 0000000..81b6fa2
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/arraylist.c
@@ -0,0 +1,101 @@
+/*
+ * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#endif /* STDC_HEADERS */
+
+#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+
+#include "bits.h"
+#include "arraylist.h"
+
+struct array_list*
+array_list_new(array_list_free_fn *free_fn)
+{
+  struct array_list *arr;
+
+  arr = (struct array_list*)calloc(1, sizeof(struct array_list));
+  if(!arr) return NULL;
+  arr->size = ARRAY_LIST_DEFAULT_SIZE;
+  arr->length = 0;
+  arr->free_fn = free_fn;
+  if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
+    free(arr);
+    return NULL;
+  }
+  return arr;
+}
+
+extern void
+array_list_free(struct array_list *arr)
+{
+  int i;
+  for(i = 0; i < arr->length; i++)
+    if(arr->array[i]) arr->free_fn(arr->array[i]);
+  free(arr->array);
+  free(arr);
+}
+
+void*
+array_list_get_idx(struct array_list *arr, int i)
+{
+  if(i >= arr->length) return NULL;
+  return arr->array[i];
+}
+
+static int array_list_expand_internal(struct array_list *arr, int max)
+{
+  void *t;
+  int new_size;
+
+  if(max < arr->size) return 0;
+  new_size = json_max(arr->size << 1, max);
+  if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
+  arr->array = (void**)t;
+  (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
+  arr->size = new_size;
+  return 0;
+}
+
+int
+array_list_put_idx(struct array_list *arr, int idx, void *data)
+{
+  if(array_list_expand_internal(arr, idx+1)) return -1;
+  if(arr->array[idx]) arr->free_fn(arr->array[idx]);
+  arr->array[idx] = data;
+  if(arr->length <= idx) arr->length = idx + 1;
+  return 0;
+}
+
+int
+array_list_add(struct array_list *arr, void *data)
+{
+  return array_list_put_idx(arr, arr->length, data);
+}
+
+void
+array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *))
+{
+  qsort(arr->array, arr->length, sizeof(arr->array[0]),
+	(int (*)(const void *, const void *))sort_fn);
+}
+
+int
+array_list_length(struct array_list *arr)
+{
+  return arr->length;
+}
diff --git a/ogr/ogrsf_frmts/geojson/libjson/arraylist.h b/ogr/ogrsf_frmts/geojson/libjson/arraylist.h
new file mode 100644
index 0000000..4f3113c
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/arraylist.h
@@ -0,0 +1,56 @@
+/*
+ * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _arraylist_h_
+#define _arraylist_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ARRAY_LIST_DEFAULT_SIZE 32
+
+typedef void (array_list_free_fn) (void *data);
+
+struct array_list
+{
+  void **array;
+  int length;
+  int size;
+  array_list_free_fn *free_fn;
+};
+
+extern struct array_list*
+array_list_new(array_list_free_fn *free_fn);
+
+extern void
+array_list_free(struct array_list *al);
+
+extern void*
+array_list_get_idx(struct array_list *al, int i);
+
+extern int
+array_list_put_idx(struct array_list *al, int i, void *data);
+
+extern int
+array_list_add(struct array_list *al, void *data);
+
+extern int
+array_list_length(struct array_list *al);
+
+extern void
+array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/bits.h b/ogr/ogrsf_frmts/geojson/libjson/bits.h
new file mode 100644
index 0000000..c8cbbc8
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/bits.h
@@ -0,0 +1,28 @@
+/*
+ * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _bits_h_
+#define _bits_h_
+
+#ifndef json_min
+#define json_min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef json_max
+#define json_max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+#define error_ptr(error) ((void*)error)
+#define error_description(error)  (json_tokener_errors[error])
+#define is_error(ptr) (ptr == NULL)
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/config.h b/ogr/ogrsf_frmts/geojson/libjson/config.h
new file mode 100644
index 0000000..190931b
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/config.h
@@ -0,0 +1,126 @@
+/*
+ * $Id: config.h.win32,v 1.2 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+/* config.h.win32  Generated by configure.  */
+
+#define PACKAGE_STRING "JSON C Library 0.2"
+#define PACKAGE_BUGREPORT "michael at metaparadigm.com"
+#define PACKAGE_NAME "JSON C Library"
+#define PACKAGE_TARNAME "json-c"
+#define PACKAGE_VERSION "0.2"
+
+#include "symbol_renames.h"
+
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+#ifndef __GNUC__
+#define __attribute__(x) /* DO NOTHING */
+#endif
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `open' function. */
+#undef HAVE_OPEN
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#define HAVE_REALLOC 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR 1
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifdef _WIN32_WCE
+#undef HAVE_SYS_STAT_H
+#else
+#define HAVE_SYS_STAT_H 1
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifdef _WIN32_WCE
+#undef HAVE_SYS_TYPES_H
+#else
+#define HAVE_SYS_TYPES_H 1
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#ifdef _MSC_VER
+#undef HAVE_VPRINTF
+#endif
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+#ifdef _MSC_VER
+#undef HAVE_VASPRINTF
+#endif
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#ifndef HAVE_STRNCASECMP
+#define HAVE_STRNCASECMP 1
+#endif
+#if defined(_MSC_VER) && !defined(strncasecmp)
+   /* MSC has the version as _strnicmp */
+#define strncasecmp _strnicmp
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+#include <cpl_config.h>
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/debug.c b/ogr/ogrsf_frmts/geojson/libjson/debug.c
similarity index 100%
rename from ogr/ogrsf_frmts/geojson/jsonc/debug.c
rename to ogr/ogrsf_frmts/geojson/libjson/debug.c
diff --git a/ogr/ogrsf_frmts/geojson/libjson/debug.h b/ogr/ogrsf_frmts/geojson/libjson/debug.h
new file mode 100644
index 0000000..9a59574
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/debug.h
@@ -0,0 +1,84 @@
+/*
+ * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "symbol_renames.h"
+
+extern void mc_set_debug(int debug);
+extern int mc_get_debug(void);
+
+extern void mc_set_syslog(int syslog);
+extern void mc_abort(const char *msg, ...);
+extern void mc_debug(const char *msg, ...);
+extern void mc_error(const char *msg, ...);
+extern void mc_info(const char *msg, ...);
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#ifndef PARSER_BROKEN_FIXED
+
+#define JASSERT(cond) do {} while(0)
+
+#else
+
+#define JASSERT(cond) do { \
+		if (!(cond)) { \
+			mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
+			*(int *)0 = 1;\
+			abort(); \
+		}\
+	} while(0)
+
+#endif
+
+#ifdef MC_MAINTAINER_MODE
+#define MC_SET_DEBUG(x) mc_set_debug(x)
+#define MC_GET_DEBUG() mc_get_debug()
+#define MC_SET_SYSLOG(x) mc_set_syslog(x)
+#define MC_ABORT(x, ...) mc_abort(x, ##__VA_ARGS__)
+#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
+#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
+#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
+#else
+#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
+#define MC_GET_DEBUG() (0)
+#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
+#if defined(_MSC_VER) && _MSC_VER <= 1310
+/* VC++ 7.1 and earlier don't like macros with ... */
+#define MC_ABORT
+#define MC_DEBUG
+#define MC_ERROR
+#define MC_INFO
+#else
+#define MC_ABORT(x, ...) if (0) mc_abort(x, ##__VA_ARGS__)
+#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
+#define MC_ERROR(x, ...) if (0) mc_error(x, ##__VA_ARGS__)
+#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/dump_symbols.sh b/ogr/ogrsf_frmts/geojson/libjson/dump_symbols.sh
new file mode 100755
index 0000000..a39a0d4
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/dump_symbols.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+symbol_list=""
+for filename in arraylist.o debug.o json_c_version.o json_object.o json_tokener.o json_object_iterator.o json_util.o linkhash.o printbuf.o ; do
+symbol_list="$symbol_list $(objdump -t ../../o/$filename | grep text | awk '{print $6}' | grep -v .text)"
+symbol_list="$symbol_list $(objdump -t ../../o/$filename | grep .data.rel.local | awk '{print $6}' | grep -v .data.rel.local)"
+done
+
+echo "/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */"
+echo "#ifndef symbol_renames"
+echo "#define symbol_renames"
+echo ""
+for symbol in $symbol_list
+do
+    echo "#define $symbol gdal_$symbol"
+done
+echo ""
+echo "#endif /*  symbol_renames */"
+
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json.h b/ogr/ogrsf_frmts/geojson/libjson/json.h
new file mode 100644
index 0000000..4339b20
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json.h
@@ -0,0 +1,34 @@
+/*
+ * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_h_
+#define _json_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bits.h"
+#include "debug.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_util.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_object_iterator.h"
+#include "json_c_version.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_c_version.c b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.c
new file mode 100644
index 0000000..13eb188
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+#include "config.h"
+
+#include "json_c_version.h"
+
+const char *json_c_version(void)
+{
+	return JSON_C_VERSION;
+}
+
+int json_c_version_num(void)
+{
+	return JSON_C_VERSION_NUM;
+}
+
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h
new file mode 100644
index 0000000..ff20f95
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+#ifndef _json_c_version_h_
+#define _json_c_version_h_
+
+#define JSON_C_MAJOR_VERSION 0
+#define JSON_C_MINOR_VERSION 11
+#define JSON_C_MICRO_VERSION 0
+#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
+                            (JSON_C_MINOR_VERSION << 8) | \
+                            JSON_C_MICRO_VERSION)
+#define JSON_C_VERSION "0.11"
+
+const char *json_c_version(void); /* Returns JSON_C_VERSION */
+int json_c_version_num(void);     /* Returns JSON_C_VERSION_NUM */
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_config.h b/ogr/ogrsf_frmts/geojson/libjson/json_config.h
new file mode 100644
index 0000000..965ff1c
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_config.h
@@ -0,0 +1,4 @@
+/* json_config.h.  Generated from json_config.h.in by configure.  */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define JSON_C_HAVE_INTTYPES_H 1
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h b/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h
new file mode 100644
index 0000000..9de8d24
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h
@@ -0,0 +1,28 @@
+
+#ifndef _json_inttypes_h_
+#define _json_inttypes_h_
+
+#include "json_config.h"
+
+#if defined(_MSC_VER) && _MSC_VER <= 1700
+
+/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */
+typedef __int32 int32_t;
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    ((int32_t)_I32_MAX)
+typedef __int64 int64_t;
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    ((int64_t)_I64_MAX)
+#define PRId64 "I64d"
+#define SCNd64 "I64d"
+
+#else
+
+#ifdef JSON_C_HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+/* inttypes.h includes stdint.h */
+
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.c b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
new file mode 100644
index 0000000..6158d05
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
@@ -0,0 +1,778 @@
+/*
+ * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "cpl_conv.h"
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "debug.h"
+#include "printbuf.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_object_private.h"
+#include "json_util.h"
+
+#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
+  /* MSC has the version as _strdup */
+# define strdup _strdup
+#elif !defined(HAVE_STRDUP)
+# error You do not have strdup on your system.
+#endif /* HAVE_STRDUP */
+
+// Don't define this.  It's not thread-safe.
+/* #define REFCOUNT_DEBUG 1 */
+
+const char *json_number_chars = "0123456789.+-eE";
+const char *json_hex_chars = "0123456789abcdefABCDEF";
+
+static void json_object_generic_delete(struct json_object* jso);
+static struct json_object* json_object_new(enum json_type o_type);
+
+static json_object_to_json_string_fn json_object_object_to_json_string;
+static json_object_to_json_string_fn json_object_boolean_to_json_string;
+static json_object_to_json_string_fn json_object_int_to_json_string;
+static json_object_to_json_string_fn json_object_double_to_json_string;
+static json_object_to_json_string_fn json_object_string_to_json_string;
+static json_object_to_json_string_fn json_object_array_to_json_string;
+
+
+/* ref count debugging */
+
+#ifdef REFCOUNT_DEBUG
+
+static struct lh_table *json_object_table;
+
+static void json_object_init(void) __attribute__ ((constructor));
+static void json_object_init(void) {
+  MC_DEBUG("json_object_init: creating object table\n");
+  json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
+}
+
+static void json_object_fini(void) __attribute__ ((destructor));
+static void json_object_fini(void) {
+  struct lh_entry *ent;
+  if(MC_GET_DEBUG()) {
+    if (json_object_table->count) {
+      MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
+  	       json_object_table->count);
+      lh_foreach(json_object_table, ent) {
+        struct json_object* obj = (struct json_object*)ent->v;
+        MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj);
+      }
+    }
+  }
+  MC_DEBUG("json_object_fini: freeing object table\n");
+  lh_table_free(json_object_table);
+}
+#endif /* REFCOUNT_DEBUG */
+
+
+/* string escaping */
+
+static int json_escape_str(struct printbuf *pb, char *str, int len)
+{
+  int pos = 0, start_offset = 0;
+  unsigned char c;
+  while (len--) {
+    c = str[pos];
+    switch(c) {
+    case '\b':
+    case '\n':
+    case '\r':
+    case '\t':
+    case '\f':
+    case '"':
+    case '\\':
+    case '/':
+      if(pos - start_offset > 0)
+	printbuf_memappend(pb, str + start_offset, pos - start_offset);
+      if(c == '\b') printbuf_memappend(pb, "\\b", 2);
+      else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
+      else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
+      else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
+      else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
+      else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
+      else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
+      else if(c == '/') printbuf_memappend(pb, "\\/", 2);
+      start_offset = ++pos;
+      break;
+    default:
+      if(c < ' ') {
+	if(pos - start_offset > 0)
+	  printbuf_memappend(pb, str + start_offset, pos - start_offset);
+	sprintbuf(pb, "\\u00%c%c",
+		  json_hex_chars[c >> 4],
+		  json_hex_chars[c & 0xf]);
+	start_offset = ++pos;
+      } else pos++;
+    }
+  }
+  if(pos - start_offset > 0)
+    printbuf_memappend(pb, str + start_offset, pos - start_offset);
+  return 0;
+}
+
+
+/* reference counting */
+
+extern struct json_object* json_object_get(struct json_object *jso)
+{
+  if(jso) {
+    jso->_ref_count++;
+  }
+  return jso;
+}
+
+int json_object_put(struct json_object *jso)
+{
+	if(jso)
+	{
+		jso->_ref_count--;
+		if(!jso->_ref_count)
+		{
+			if (jso->_user_delete)
+				jso->_user_delete(jso, jso->_userdata);
+			jso->_delete(jso);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+/* generic object construction and destruction parts */
+
+static void json_object_generic_delete(struct json_object* jso)
+{
+#ifdef REFCOUNT_DEBUG
+  MC_DEBUG("json_object_delete_%s: %p\n",
+	   json_type_to_name(jso->o_type), jso);
+  lh_table_delete(json_object_table, jso);
+#endif /* REFCOUNT_DEBUG */
+  printbuf_free(jso->_pb);
+  free(jso);
+}
+
+static struct json_object* json_object_new(enum json_type o_type)
+{
+  struct json_object *jso;
+
+  jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
+  if(!jso) return NULL;
+  jso->o_type = o_type;
+  jso->_ref_count = 1;
+  jso->_delete = &json_object_generic_delete;
+#ifdef REFCOUNT_DEBUG
+  lh_table_insert(json_object_table, jso, jso);
+  MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
+#endif /* REFCOUNT_DEBUG */
+  return jso;
+}
+
+
+/* type checking functions */
+
+int json_object_is_type(struct json_object *jso, enum json_type type)
+{
+  if (!jso)
+    return (type == json_type_null);
+  return (jso->o_type == type);
+}
+
+enum json_type json_object_get_type(struct json_object *jso)
+{
+  if (!jso)
+    return json_type_null;
+  return jso->o_type;
+}
+
+/* set a custom conversion to string */
+
+void json_object_set_serializer(json_object *jso,
+	json_object_to_json_string_fn to_string_func,
+	void *userdata,
+	json_object_delete_fn *user_delete)
+{
+	// First, clean up any previously existing user info
+	if (jso->_user_delete)
+	{
+		jso->_user_delete(jso, jso->_userdata);
+	}
+	jso->_userdata = NULL;
+	jso->_user_delete = NULL;
+
+	if (to_string_func == NULL)
+	{
+		// Reset to the standard serialization function
+		switch(jso->o_type)
+		{
+		case json_type_null:
+			jso->_to_json_string = NULL;
+			break;
+		case json_type_boolean:
+			jso->_to_json_string = &json_object_boolean_to_json_string;
+			break;
+		case json_type_double:
+			jso->_to_json_string = &json_object_double_to_json_string;
+			break;
+		case json_type_int:
+			jso->_to_json_string = &json_object_int_to_json_string;
+			break;
+		case json_type_object:
+			jso->_to_json_string = &json_object_object_to_json_string;
+			break;
+		case json_type_array:
+			jso->_to_json_string = &json_object_array_to_json_string;
+			break;
+		case json_type_string:
+			jso->_to_json_string = &json_object_string_to_json_string;
+			break;
+		}
+		return;
+	}
+
+	jso->_to_json_string = to_string_func;
+	jso->_userdata = userdata;
+	jso->_user_delete = user_delete;
+}
+
+
+/* extended conversion to string */
+
+const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
+{
+	if (!jso)
+		return "null";
+
+	if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
+		return NULL;
+
+	printbuf_reset(jso->_pb);
+
+	if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
+		return NULL;
+
+	return jso->_pb->buf;
+}
+
+/* backwards-compatible conversion to string */
+
+const char* json_object_to_json_string(struct json_object *jso)
+{
+	return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
+}
+
+static void indent(struct printbuf *pb, int level, int flags)
+{
+	if (flags & JSON_C_TO_STRING_PRETTY)
+	{
+		printbuf_memset(pb, -1, ' ', level * 2);
+	}
+}
+
+/* json_object_object */
+
+static int json_object_object_to_json_string(struct json_object* jso,
+					     struct printbuf *pb,
+					     int level,
+						 int flags)
+{
+	int had_children = 0;
+	struct json_object_iter iter;
+
+	sprintbuf(pb, "{" /*}*/);
+	if (flags & JSON_C_TO_STRING_PRETTY)
+		sprintbuf(pb, "\n");
+	json_object_object_foreachC(jso, iter)
+	{
+		if (had_children)
+		{
+			sprintbuf(pb, ",");
+			if (flags & JSON_C_TO_STRING_PRETTY)
+				sprintbuf(pb, "\n");
+		}
+		had_children = 1;
+		if (flags & JSON_C_TO_STRING_SPACED)
+			sprintbuf(pb, " ");
+		indent(pb, level+1, flags);
+		sprintbuf(pb, "\"");
+		json_escape_str(pb, iter.key, strlen(iter.key));
+		if (flags & JSON_C_TO_STRING_SPACED)
+			sprintbuf(pb, "\": ");
+		else
+			sprintbuf(pb, "\":");
+		if(iter.val == NULL)
+			sprintbuf(pb, "null");
+		else
+			iter.val->_to_json_string(iter.val, pb, level+1,flags);
+	}
+	if (flags & JSON_C_TO_STRING_PRETTY)
+	{
+		if (had_children)
+			sprintbuf(pb, "\n");
+		indent(pb,level,flags);
+	}
+	if (flags & JSON_C_TO_STRING_SPACED)
+		return sprintbuf(pb, /*{*/ " }");
+	else
+		return sprintbuf(pb, /*{*/ "}");
+}
+
+
+static void json_object_lh_entry_free(struct lh_entry *ent)
+{
+  free(ent->k);
+  json_object_put((struct json_object*)ent->v);
+}
+
+static void json_object_object_delete(struct json_object* jso)
+{
+  lh_table_free(jso->o.c_object);
+  json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_object(void)
+{
+  struct json_object *jso = json_object_new(json_type_object);
+  if(!jso) return NULL;
+  jso->_delete = &json_object_object_delete;
+  jso->_to_json_string = &json_object_object_to_json_string;
+  jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
+					NULL, &json_object_lh_entry_free);
+  return jso;
+}
+
+struct lh_table* json_object_get_object(struct json_object *jso)
+{
+  if(!jso) return NULL;
+  switch(jso->o_type) {
+  case json_type_object:
+    return jso->o.c_object;
+  default:
+    return NULL;
+  }
+}
+
+void json_object_object_add(struct json_object* jso, const char *key,
+			    struct json_object *val)
+{
+	// We lookup the entry and replace the value, rather than just deleting
+	// and re-adding it, so the existing key remains valid.
+	json_object *existing_value = NULL;
+	struct lh_entry *existing_entry;
+	existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
+	if (!existing_entry)
+	{
+		lh_table_insert(jso->o.c_object, strdup(key), val);
+		return;
+	}
+	existing_value = (void *)existing_entry->v;
+	if (existing_value)
+		json_object_put(existing_value);
+	existing_entry->v = val;
+}
+
+int json_object_object_length(struct json_object *jso)
+{
+	return lh_table_length(jso->o.c_object);
+}
+
+struct json_object* json_object_object_get(struct json_object* jso, const char *key)
+{
+	struct json_object *result = NULL;
+	json_object_object_get_ex(jso, key, &result);
+	return result;
+}
+
+json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
+{
+	if (value != NULL)
+		*value = NULL;
+
+	if (NULL == jso)
+		return FALSE;
+
+	switch(jso->o_type)
+	{
+	case json_type_object:
+		return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
+	default:
+		if (value != NULL)
+			*value = NULL;
+		return FALSE;
+	}
+}
+
+void json_object_object_del(struct json_object* jso, const char *key)
+{
+	lh_table_delete(jso->o.c_object, key);
+}
+
+
+/* json_object_boolean */
+
+static int json_object_boolean_to_json_string(struct json_object* jso,
+					      struct printbuf *pb,
+					      int level,
+						  int flags)
+{
+  if(jso->o.c_boolean) return sprintbuf(pb, "true");
+  else return sprintbuf(pb, "false");
+}
+
+struct json_object* json_object_new_boolean(json_bool b)
+{
+  struct json_object *jso = json_object_new(json_type_boolean);
+  if(!jso) return NULL;
+  jso->_to_json_string = &json_object_boolean_to_json_string;
+  jso->o.c_boolean = b;
+  return jso;
+}
+
+json_bool json_object_get_boolean(struct json_object *jso)
+{
+  if(!jso) return FALSE;
+  switch(jso->o_type) {
+  case json_type_boolean:
+    return jso->o.c_boolean;
+  case json_type_int:
+    return (jso->o.c_int64 != 0);
+  case json_type_double:
+    return (jso->o.c_double != 0);
+  case json_type_string:
+    return (jso->o.c_string.len != 0);
+  default:
+    return FALSE;
+  }
+}
+
+
+/* json_object_int */
+
+static int json_object_int_to_json_string(struct json_object* jso,
+					  struct printbuf *pb,
+					  int level,
+					  int flags)
+{
+  return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
+}
+
+struct json_object* json_object_new_int(int32_t i)
+{
+  struct json_object *jso = json_object_new(json_type_int);
+  if(!jso) return NULL;
+  jso->_to_json_string = &json_object_int_to_json_string;
+  jso->o.c_int64 = i;
+  return jso;
+}
+
+int32_t json_object_get_int(struct json_object *jso)
+{
+  int64_t cint64;
+  enum json_type o_type;
+
+  if(!jso) return 0;
+
+  o_type = jso->o_type;
+  cint64 = jso->o.c_int64;
+
+  if (o_type == json_type_string)
+  {
+	/*
+	 * Parse strings into 64-bit numbers, then use the
+	 * 64-to-32-bit number handling below.
+	 */
+	if (json_parse_int64(jso->o.c_string.str, &cint64) != 0)
+		return 0; /* whoops, it didn't work. */
+	o_type = json_type_int;
+  }
+
+  switch(o_type) {
+  case json_type_int:
+	/* Make sure we return the correct values for out of range numbers. */
+	if (cint64 <= INT32_MIN)
+		return INT32_MIN;
+	else if (cint64 >= INT32_MAX)
+		return INT32_MAX;
+	else
+		return (int32_t)cint64;
+  case json_type_double:
+    return (int32_t)jso->o.c_double;
+  case json_type_boolean:
+    return jso->o.c_boolean;
+  default:
+    return 0;
+  }
+}
+
+struct json_object* json_object_new_int64(int64_t i)
+{
+  struct json_object *jso = json_object_new(json_type_int);
+  if(!jso) return NULL;
+  jso->_to_json_string = &json_object_int_to_json_string;
+  jso->o.c_int64 = i;
+  return jso;
+}
+
+int64_t json_object_get_int64(struct json_object *jso)
+{
+   int64_t cint;
+
+  if(!jso) return 0;
+  switch(jso->o_type) {
+  case json_type_int:
+    return jso->o.c_int64;
+  case json_type_double:
+    return (int64_t)jso->o.c_double;
+  case json_type_boolean:
+    return jso->o.c_boolean;
+  case json_type_string:
+	if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint;
+  default:
+    return 0;
+  }
+}
+
+
+/* json_object_double */
+
+static int json_object_double_to_json_string(struct json_object* jso,
+					     struct printbuf *pb,
+					     int level,
+						 int flags)
+{
+  char buf[128], *p, *q;
+  int size;
+
+  size = snprintf(buf, 128, "%f", jso->o.c_double);
+  p = strchr(buf, ',');
+  if (p) {
+    *p = '.';
+  } else {
+    p = strchr(buf, '.');
+  }
+  if (p && (flags & JSON_C_TO_STRING_NOZERO)) {
+    /* last useful digit, always keep 1 zero */
+    p++;
+    for (q=p ; *q ; q++) {
+      if (*q!='0') p=q;
+    }
+    /* drop trailing zeroes */
+    *(++p) = 0;
+    size = p-buf;
+  }
+  printbuf_memappend(pb, buf, size);
+  return size;
+}
+
+struct json_object* json_object_new_double(double d)
+{
+  struct json_object *jso = json_object_new(json_type_double);
+  if(!jso) return NULL;
+  jso->_to_json_string = &json_object_double_to_json_string;
+  jso->o.c_double = d;
+  return jso;
+}
+
+double json_object_get_double(struct json_object *jso)
+{
+  if(!jso) return 0.0;
+  switch(jso->o_type) {
+  case json_type_double:
+    return jso->o.c_double;
+  case json_type_int:
+    return jso->o.c_int64;
+  case json_type_boolean:
+    return jso->o.c_boolean;
+  case json_type_string:
+    return CPLAtof(jso->o.c_string.str);
+  default:
+    return 0.0;
+  }
+}
+
+
+/* json_object_string */
+
+static int json_object_string_to_json_string(struct json_object* jso,
+					     struct printbuf *pb,
+					     int level,
+						 int flags)
+{
+  sprintbuf(pb, "\"");
+  json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
+  sprintbuf(pb, "\"");
+  return 0;
+}
+
+static void json_object_string_delete(struct json_object* jso)
+{
+  free(jso->o.c_string.str);
+  json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_string(const char *s)
+{
+  struct json_object *jso = json_object_new(json_type_string);
+  if(!jso) return NULL;
+  jso->_delete = &json_object_string_delete;
+  jso->_to_json_string = &json_object_string_to_json_string;
+  jso->o.c_string.str = strdup(s);
+  jso->o.c_string.len = strlen(s);
+  return jso;
+}
+
+struct json_object* json_object_new_string_len(const char *s, int len)
+{
+  struct json_object *jso = json_object_new(json_type_string);
+  if(!jso) return NULL;
+  jso->_delete = &json_object_string_delete;
+  jso->_to_json_string = &json_object_string_to_json_string;
+  jso->o.c_string.str = (char*)malloc(len + 1);
+  memcpy(jso->o.c_string.str, (void *)s, len);
+  jso->o.c_string.str[len] = '\0';
+  jso->o.c_string.len = len;
+  return jso;
+}
+
+const char* json_object_get_string(struct json_object *jso)
+{
+  if(!jso) return NULL;
+  switch(jso->o_type) {
+  case json_type_string:
+    return jso->o.c_string.str;
+  default:
+    return json_object_to_json_string(jso);
+  }
+}
+
+int json_object_get_string_len(struct json_object *jso)  {
+  if(!jso) return 0;
+  switch(jso->o_type) {
+  case json_type_string:
+    return jso->o.c_string.len;
+  default:
+    return 0;
+  }
+}
+
+
+/* json_object_array */
+
+static int json_object_array_to_json_string(struct json_object* jso,
+                                            struct printbuf *pb,
+                                            int level,
+                                            int flags)
+{
+	int had_children = 0;
+	int ii;
+	sprintbuf(pb, "[");
+	if (flags & JSON_C_TO_STRING_PRETTY)
+		sprintbuf(pb, "\n");
+	for(ii=0; ii < json_object_array_length(jso); ii++)
+	{
+		struct json_object *val;
+		if (had_children)
+		{
+			sprintbuf(pb, ",");
+			if (flags & JSON_C_TO_STRING_PRETTY)
+				sprintbuf(pb, "\n");
+		}
+		had_children = 1;
+		if (flags & JSON_C_TO_STRING_SPACED)
+			sprintbuf(pb, " ");
+		indent(pb, level + 1, flags);
+		val = json_object_array_get_idx(jso, ii);
+		if(val == NULL)
+			sprintbuf(pb, "null");
+		else
+			val->_to_json_string(val, pb, level+1, flags);
+	}
+	if (flags & JSON_C_TO_STRING_PRETTY)
+	{
+		if (had_children)
+			sprintbuf(pb, "\n");
+		indent(pb,level,flags);
+	}
+
+	if (flags & JSON_C_TO_STRING_SPACED)
+		return sprintbuf(pb, " ]");
+	else
+		return sprintbuf(pb, "]");
+}
+
+static void json_object_array_entry_free(void *data)
+{
+  json_object_put((struct json_object*)data);
+}
+
+static void json_object_array_delete(struct json_object* jso)
+{
+  array_list_free(jso->o.c_array);
+  json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_array(void)
+{
+  struct json_object *jso = json_object_new(json_type_array);
+  if(!jso) return NULL;
+  jso->_delete = &json_object_array_delete;
+  jso->_to_json_string = &json_object_array_to_json_string;
+  jso->o.c_array = array_list_new(&json_object_array_entry_free);
+  return jso;
+}
+
+struct array_list* json_object_get_array(struct json_object *jso)
+{
+  if(!jso) return NULL;
+  switch(jso->o_type) {
+  case json_type_array:
+    return jso->o.c_array;
+  default:
+    return NULL;
+  }
+}
+
+void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *))
+{
+  array_list_sort(jso->o.c_array, sort_fn);
+}
+
+int json_object_array_length(struct json_object *jso)
+{
+  return array_list_length(jso->o.c_array);
+}
+
+int json_object_array_add(struct json_object *jso,struct json_object *val)
+{
+  return array_list_add(jso->o.c_array, val);
+}
+
+int json_object_array_put_idx(struct json_object *jso, int idx,
+			      struct json_object *val)
+{
+  return array_list_put_idx(jso->o.c_array, idx, val);
+}
+
+struct json_object* json_object_array_get_idx(struct json_object *jso,
+					      int idx)
+{
+  return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
+}
+
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.h b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
new file mode 100644
index 0000000..05b73b9
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
@@ -0,0 +1,563 @@
+/*
+ * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_h_
+#define _json_object_h_
+
+#include "symbol_renames.h"
+
+#include "json_inttypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JSON_OBJECT_DEF_HASH_ENTRIES 16
+
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output
+ * to have no extra whitespace or formatting applied.
+ */
+#define JSON_C_TO_STRING_PLAIN      0
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output to have
+ * minimal whitespace inserted to make things slightly more readable.
+ */
+#define JSON_C_TO_STRING_SPACED     (1<<0)
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes
+ * the output to be formatted.
+ *
+ * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
+ * for an example of the format.
+ */
+#define JSON_C_TO_STRING_PRETTY     (1<<1)
+/**
+ * A flag to drop trailing zero for float values
+ */
+#define JSON_C_TO_STRING_NOZERO     (1<<2)
+
+#undef FALSE
+#define FALSE ((json_bool)0)
+
+#undef TRUE
+#define TRUE ((json_bool)1)
+
+extern const char *json_number_chars;
+extern const char *json_hex_chars;
+
+/* CAW: added for ANSI C iteration correctness */
+struct json_object_iter
+{
+	char *key;
+	struct json_object *val;
+	struct lh_entry *entry;
+};
+
+/* forward structure definitions */
+
+typedef int json_bool;
+typedef struct printbuf printbuf;
+typedef struct lh_table lh_table;
+typedef struct array_list array_list;
+typedef struct json_object json_object;
+typedef struct json_object_iter json_object_iter;
+typedef struct json_tokener json_tokener;
+
+/**
+ * Type of custom user delete functions.  See json_object_set_serializer.
+ */
+typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata);
+
+/**
+ * Type of a custom serialization function.  See json_object_set_serializer.
+ */
+typedef int (json_object_to_json_string_fn)(struct json_object *jso,
+						struct printbuf *pb,
+						int level,
+						int flags);
+
+/* supported object types */
+
+typedef enum json_type {
+  /* If you change this, be sure to update json_type_to_name() too */
+  json_type_null,
+  json_type_boolean,
+  json_type_double,
+  json_type_int,
+  json_type_object,
+  json_type_array,
+  json_type_string,
+} json_type;
+
+/* reference counting functions */
+
+/**
+ * Increment the reference count of json_object, thereby grabbing shared 
+ * ownership of obj.
+ *
+ * @param obj the json_object instance
+ */
+extern struct json_object* json_object_get(struct json_object *obj);
+
+/**
+ * Decrement the reference count of json_object and free if it reaches zero.
+ * You must have ownership of obj prior to doing this or you will cause an
+ * imbalance in the reference count.
+ *
+ * @param obj the json_object instance
+ * @returns 1 if the object was freed.
+ */
+int json_object_put(struct json_object *obj);
+
+/**
+ * Check if the json_object is of a given type
+ * @param obj the json_object instance
+ * @param type one of:
+     json_type_null (i.e. obj == NULL),
+     json_type_boolean,
+     json_type_double,
+     json_type_int,
+     json_type_object,
+     json_type_array,
+     json_type_string,
+ */
+extern int json_object_is_type(struct json_object *obj, enum json_type type);
+
+/**
+ * Get the type of the json_object.  See also json_type_to_name() to turn this
+ * into a string suitable, for instance, for logging.
+ *
+ * @param obj the json_object instance
+ * @returns type being one of:
+     json_type_null (i.e. obj == NULL),
+     json_type_boolean,
+     json_type_double,
+     json_type_int,
+     json_type_object,
+     json_type_array,
+     json_type_string,
+ */
+extern enum json_type json_object_get_type(struct json_object *obj);
+
+
+/** Stringify object to json format.
+ * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
+ * @param obj the json_object instance
+ * @returns a string in JSON format
+ */
+extern const char* json_object_to_json_string(struct json_object *obj);
+
+/** Stringify object to json format
+ * @param obj the json_object instance
+ * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
+ * @returns a string in JSON format
+ */
+extern const char* json_object_to_json_string_ext(struct json_object *obj, int
+flags);
+
+/**
+ * Set a custom serialization function to be used when this particular object
+ * is converted to a string by json_object_to_json_string.
+ *
+ * If a custom serializer is already set on this object, any existing 
+ * user_delete function is called before the new one is set.
+ *
+ * If to_string_func is NULL, the other parameters are ignored
+ * and the default behaviour is reset.
+ *
+ * The userdata parameter is optional and may be passed as NULL.  If provided,
+ * it is passed to to_string_func as-is.  This parameter may be NULL even
+ * if user_delete is non-NULL.
+ *
+ * The user_delete parameter is optional and may be passed as NULL, even if
+ * the userdata parameter is non-NULL.  It will be called just before the
+ * json_object is deleted, after it's reference count goes to zero
+ * (see json_object_put()).
+ * If this is not provided, it is up to the caller to free the userdata at
+ * an appropriate time. (i.e. after the json_object is deleted)
+ *
+ * @param jso the object to customize
+ * @param to_string_func the custom serialization function
+ * @param userdata an optional opaque cookie
+ * @param user_delete an optional function from freeing userdata
+ */
+/* GDAL added */ extern void json_object_set_serializer(json_object *jso,
+	json_object_to_json_string_fn to_string_func,
+	void *userdata,
+	json_object_delete_fn *user_delete);
+
+
+
+/* object type methods */
+
+/** Create a new empty object with a reference count of 1.  The caller of
+ * this object initially has sole ownership.  Remember, when using
+ * json_object_object_add or json_object_array_put_idx, ownership will
+ * transfer to the object/array.  Call json_object_get if you want to maintain
+ * shared ownership or also add this object as a child of multiple objects or
+ * arrays.  Any ownerships you acquired but did not transfer must be released
+ * through json_object_put.
+ *
+ * @returns a json_object of type json_type_object
+ */
+extern struct json_object* json_object_new_object(void);
+
+/** Get the hashtable of a json_object of type json_type_object
+ * @param obj the json_object instance
+ * @returns a linkhash
+ */
+extern struct lh_table* json_object_get_object(struct json_object *obj);
+
+/** Get the size of an object in terms of the number of fields it has.
+ * @param obj the json_object whose length to return
+ */
+extern int json_object_object_length(struct json_object* obj);
+
+/** Add an object field to a json_object of type json_type_object
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object, independent of the lifetime of obj, you must wrap the
+ * passed object with json_object_get.
+ *
+ * Upon calling this, the ownership of val transfers to obj.  Thus you must
+ * make sure that you do in fact have ownership over this object.  For instance,
+ * json_object_new_object will give you ownership until you transfer it,
+ * whereas json_object_object_get does not.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name (a private copy will be duplicated)
+ * @param val a json_object or NULL member to associate with the given field
+ */
+extern void json_object_object_add(struct json_object* obj, const char *key,
+				   struct json_object *val);
+
+/** Get the json_object associate with a given object field
+ *
+ * *No* reference counts will be changed.  There is no need to manually adjust
+ * reference counts through the json_object_put/json_object_get methods unless
+ * you need to have the child (value) reference maintain a different lifetime
+ * than the owning parent (obj). Ownership of the returned value is retained
+ * by obj (do not do json_object_put unless you have done a json_object_get).
+ * If you delete the value from obj (json_object_object_del) and wish to access
+ * the returned reference afterwards, make sure you have first gotten shared
+ * ownership through json_object_get (& don't forget to do a json_object_put
+ * or transfer ownership to prevent a memory leak).
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ * @returns the json_object associated with the given field name
+ */
+extern struct json_object* json_object_object_get(struct json_object* obj,
+						  const char *key);
+
+/** Get the json_object associated with a given object field.  
+ *
+ * This returns true if the key is found, false in all other cases (including 
+ * if obj isn't a json_type_object).
+ *
+ * *No* reference counts will be changed.  There is no need to manually adjust
+ * reference counts through the json_object_put/json_object_get methods unless
+ * you need to have the child (value) reference maintain a different lifetime
+ * than the owning parent (obj).  Ownership of value is retained by obj.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ * @param value a pointer where to store a reference to the json_object 
+ *              associated with the given field name.
+ *
+ *              It is safe to pass a NULL value.
+ * @returns whether or not the key exists
+ */
+extern json_bool json_object_object_get_ex(struct json_object* obj,
+						  const char *key,
+                                                  struct json_object **value);
+
+/** Delete the given json_object field
+ *
+ * The reference count will be decremented for the deleted object.  If there
+ * are no more owners of the value represented by this key, then the value is
+ * freed.  Otherwise, the reference to the value will remain in memory.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ */
+extern void json_object_object_del(struct json_object* obj, const char *key);
+
+/**
+ * Iterate through all keys and values of an object.
+ *
+ * Adding keys to the object while iterating is NOT allowed.
+ *
+ * Deleting an existing key, or replacing an existing key with a
+ * new value IS allowed.
+ *
+ * @param obj the json_object instance
+ * @param key the local name for the char* key variable defined in the body
+ * @param val the local name for the json_object* object variable defined in
+ *            the body
+ */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L
+
+# define json_object_object_foreach(obj,key,val) \
+	char *key; \
+	struct json_object *val __attribute__((__unused__)); \
+	for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \
+		({ if(entry ## key) { \
+			key = (char*)entry ## key->k; \
+			val = (struct json_object*)entry ## key->v; \
+			entry_next ## key = entry ## key->next; \
+		} ; entry ## key; }); \
+		entry ## key = entry_next ## key )
+
+#else /* ANSI C or MSC */
+
+# define json_object_object_foreach(obj,key,val) \
+	char *key;\
+	struct json_object *val; \
+	struct lh_entry *entry ## key; \
+	struct lh_entry *entry_next ## key = NULL; \
+	for(entry ## key = json_object_get_object(obj)->head; \
+		(entry ## key ? ( \
+			key = (char*)entry ## key->k, \
+			val = (struct json_object*)entry ## key->v, \
+			entry_next ## key = entry ## key->next, \
+			entry ## key) : 0); \
+		entry ## key = entry_next ## key)
+
+#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */
+
+/** Iterate through all keys and values of an object (ANSI C Safe)
+ * @param obj the json_object instance
+ * @param iter the object iterator
+ */
+#define json_object_object_foreachC(obj,iter) \
+ for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
+
+/* Array type methods */
+
+/** Create a new empty json_object of type json_type_array
+ * @returns a json_object of type json_type_array
+ */
+extern struct json_object* json_object_new_array(void);
+
+/** Get the arraylist of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @returns an arraylist
+ */
+extern struct array_list* json_object_get_array(struct json_object *obj);
+
+/** Get the length of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @returns an int
+ */
+extern int json_object_array_length(struct json_object *obj);
+
+/** Sorts the elements of jso of type json_type_array
+*
+* Pointers to the json_object pointers will be passed as the two arguments
+* to @sort_fn
+*
+* @param obj the json_object instance
+* @param sort_fn a sorting function
+*/
+extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *));
+
+/** Add an element to the end of a json_object of type json_type_array
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * @param obj the json_object instance
+ * @param val the json_object to be added
+ */
+extern int json_object_array_add(struct json_object *obj,
+				 struct json_object *val);
+
+/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * The reference count of a replaced object will be decremented.
+ *
+ * The array size will be automatically be expanded to the size of the
+ * index if the index is larger than the current size.
+ *
+ * @param obj the json_object instance
+ * @param idx the index to insert the element at
+ * @param val the json_object to be added
+ */
+extern int json_object_array_put_idx(struct json_object *obj, int idx,
+				     struct json_object *val);
+
+/** Get the element at specificed index of the array (a json_object of type json_type_array)
+ * @param obj the json_object instance
+ * @param idx the index to get the element at
+ * @returns the json_object at the specified index (or NULL)
+ */
+extern struct json_object* json_object_array_get_idx(struct json_object *obj,
+						     int idx);
+
+/* json_bool type methods */
+
+/** Create a new empty json_object of type json_type_boolean
+ * @param b a json_bool TRUE or FALSE (0 or 1)
+ * @returns a json_object of type json_type_boolean
+ */
+extern struct json_object* json_object_new_boolean(json_bool b);
+
+/** Get the json_bool value of a json_object
+ *
+ * The type is coerced to a json_bool if the passed object is not a json_bool.
+ * integer and double objects will return FALSE if there value is zero
+ * or TRUE otherwise. If the passed object is a string it will return
+ * TRUE if it has a non zero length. If any other object type is passed
+ * TRUE will be returned if the object is not NULL.
+ *
+ * @param obj the json_object instance
+ * @returns a json_bool
+ */
+extern json_bool json_object_get_boolean(struct json_object *obj);
+
+
+/* int type methods */
+
+/** Create a new empty json_object of type json_type_int
+ * Note that values are stored as 64-bit values internally.
+ * To ensure the full range is maintained, use json_object_new_int64 instead.
+ * @param i the integer
+ * @returns a json_object of type json_type_int
+ */
+extern struct json_object* json_object_new_int(int32_t i);
+
+
+/** Create a new empty json_object of type json_type_int
+ * @param i the integer
+ * @returns a json_object of type json_type_int
+ */
+extern struct json_object* json_object_new_int64(int64_t i);
+
+
+/** Get the int value of a json_object
+ *
+ * The type is coerced to a int if the passed object is not a int.
+ * double objects will return their integer conversion. Strings will be
+ * parsed as an integer. If no conversion exists then 0 is returned
+ * and errno is set to EINVAL. null is equivalent to 0 (no error values set)
+ *
+ * Note that integers are stored internally as 64-bit values.
+ * If the value of too big or too small to fit into 32-bit, INT32_MAX or
+ * INT32_MIN are returned, respectively.
+ *
+ * @param obj the json_object instance
+ * @returns an int
+ */
+extern int32_t json_object_get_int(struct json_object *obj);
+
+/** Get the int value of a json_object
+ *
+ * The type is coerced to a int64 if the passed object is not a int64.
+ * double objects will return their int64 conversion. Strings will be
+ * parsed as an int64. If no conversion exists then 0 is returned.
+ *
+ * NOTE: Set errno to 0 directly before a call to this function to determine
+ * whether or not conversion was successful (it does not clear the value for
+ * you).
+ *
+ * @param obj the json_object instance
+ * @returns an int64
+ */
+extern int64_t json_object_get_int64(struct json_object *obj);
+
+
+/* double type methods */
+
+/** Create a new empty json_object of type json_type_double
+ * @param d the double
+ * @returns a json_object of type json_type_double
+ */
+extern struct json_object* json_object_new_double(double d);
+
+/** Get the double floating point value of a json_object
+ *
+ * The type is coerced to a double if the passed object is not a double.
+ * integer objects will return their double conversion. Strings will be
+ * parsed as a double. If no conversion exists then 0.0 is returned and
+ * errno is set to EINVAL. null is equivalent to 0 (no error values set)
+ *
+ * If the value is too big to fit in a double, then the value is set to
+ * the closest infinity with errno set to ERANGE. If strings cannot be
+ * converted to their double value, then EINVAL is set & NaN is returned.
+ *
+ * Arrays of length 0 are interpreted as 0 (with no error flags set).
+ * Arrays of length 1 are effectively cast to the equivalent object and
+ * converted using the above rules.  All other arrays set the error to
+ * EINVAL & return NaN.
+ *
+ * NOTE: Set errno to 0 directly before a call to this function to
+ * determine whether or not conversion was successful (it does not clear
+ * the value for you).
+ *
+ * @param obj the json_object instance
+ * @returns a double floating point number
+ */
+extern double json_object_get_double(struct json_object *obj);
+
+
+/* string type methods */
+
+/** Create a new empty json_object of type json_type_string
+ *
+ * A copy of the string is made and the memory is managed by the json_object
+ *
+ * @param s the string
+ * @returns a json_object of type json_type_string
+ */
+extern struct json_object* json_object_new_string(const char *s);
+
+extern struct json_object* json_object_new_string_len(const char *s, int len);
+
+/** Get the string value of a json_object
+ *
+ * If the passed object is not of type json_type_string then the JSON
+ * representation of the object is returned.
+ *
+ * The returned string memory is managed by the json_object and will
+ * be freed when the reference count of the json_object drops to zero.
+ *
+ * @param obj the json_object instance
+ * @returns a string
+ */
+extern const char* json_object_get_string(struct json_object *obj);
+
+/** Get the string length of a json_object
+ *
+ * If the passed object is not of type json_type_string then zero
+ * will be returned.
+ *
+ * @param obj the json_object instance
+ * @returns int
+ */
+extern int json_object_get_string_len(struct json_object *obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.c b/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.c
new file mode 100644
index 0000000..7066649
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.c
@@ -0,0 +1,168 @@
+/**
+*******************************************************************************
+* @file json_object_iterator.c
+*
+* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the MIT license. See COPYING for details.
+*
+* @brief  json-c forces clients to use its private data
+*         structures for JSON Object iteration.  This API
+*         implementation corrects that by abstracting the
+*         private json-c details.
+*
+*******************************************************************************
+*/
+
+#include <stddef.h>
+
+#include "json.h"
+#include "json_object_private.h"
+
+#include "json_object_iterator.h"
+
+/**
+ * How It Works
+ *
+ * For each JSON Object, json-c maintains a linked list of zero
+ * or more lh_entry (link-hash entry) structures inside the
+ * Object's link-hash table (lh_table).
+ *
+ * Each lh_entry structure on the JSON Object's linked list
+ * represents a single name/value pair.  The "next" field of the
+ * last lh_entry in the list is set to NULL, which terminates
+ * the list.
+ *
+ * We represent a valid iterator that refers to an actual
+ * name/value pair via a pointer to the pair's lh_entry
+ * structure set as the iterator's opaque_ field.
+ *
+ * We follow json-c's current pair list representation by
+ * representing a valid "end" iterator (one that refers past the
+ * last pair) with a NULL value in the iterator's opaque_ field.
+ *
+ * A JSON Object without any pairs in it will have the "head"
+ * field of its lh_table structure set to NULL.  For such an
+ * object, json_object_iter_begin will return an iterator with
+ * the opaque_ field set to NULL, which is equivalent to the
+ * "end" iterator.
+ *
+ * When iterating, we simply update the iterator's opaque_ field
+ * to point to the next lh_entry structure in the linked list.
+ * opaque_ will become NULL once we iterate past the last pair
+ * in the list, which makes the iterator equivalent to the "end"
+ * iterator.
+ */
+
+/// Our current representation of the "end" iterator;
+///
+/// @note May not always be NULL
+static const void* kObjectEndIterValue = NULL;
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_begin(struct json_object* obj)
+{
+    struct json_object_iterator iter;
+    struct lh_table* pTable;
+
+    /// @note json_object_get_object will return NULL if passed NULL
+    ///       or a non-json_type_object instance
+    pTable = json_object_get_object(obj);
+    JASSERT(NULL != pTable);
+
+    /// @note For a pair-less Object, head is NULL, which matches our
+    ///       definition of the "end" iterator
+    iter.opaque_ = pTable->head;
+    return iter;
+}
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_end(const struct json_object* obj)
+{
+    struct json_object_iterator iter;
+
+    JASSERT(NULL != obj);
+    JASSERT(json_object_is_type(obj, json_type_object));
+
+    iter.opaque_ = kObjectEndIterValue;
+
+    return iter;
+}
+
+/**
+ * ****************************************************************************
+ */
+void
+json_object_iter_next(struct json_object_iterator* iter)
+{
+    JASSERT(NULL != iter);
+    JASSERT(kObjectEndIterValue != iter->opaque_);
+
+    iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
+}
+
+
+/**
+ * ****************************************************************************
+ */
+const char*
+json_object_iter_peek_name(const struct json_object_iterator* iter)
+{
+    JASSERT(NULL != iter);
+    JASSERT(kObjectEndIterValue != iter->opaque_);
+
+    return (const char*)(((struct lh_entry *)iter->opaque_)->k);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+struct json_object*
+json_object_iter_peek_value(const struct json_object_iterator* iter)
+{
+    JASSERT(NULL != iter);
+    JASSERT(kObjectEndIterValue != iter->opaque_);
+
+    return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+json_bool
+json_object_iter_equal(const struct json_object_iterator* iter1,
+                       const struct json_object_iterator* iter2)
+{
+    JASSERT(NULL != iter1);
+    JASSERT(NULL != iter2);
+
+    return (iter1->opaque_ == iter2->opaque_);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_init_default(void)
+{
+    struct json_object_iterator iter;
+
+    /**
+     * @note Make this a negative, invalid value, such that
+     *       accidental access to it would likely be trapped by the
+     *       hardware as an invalid address.
+     */
+    iter.opaque_ = NULL;
+
+    return iter;
+}
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.h b/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.h
new file mode 100644
index 0000000..f6e7ca6
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object_iterator.h
@@ -0,0 +1,239 @@
+/**
+*******************************************************************************
+* @file json_object_iterator.h
+*
+* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the MIT license. See COPYING for details.
+*
+* @brief  json-c forces clients to use its private data
+*         structures for JSON Object iteration.  This API
+*         corrects that by abstracting the private json-c
+*         details.
+*
+* API attributes: <br>
+*   * Thread-safe: NO<br>
+*   * Reentrant: NO
+*
+*******************************************************************************
+*/
+
+
+#ifndef JSON_OBJECT_ITERATOR_H
+#define JSON_OBJECT_ITERATOR_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Forward declaration for the opaque iterator information.
+ */
+struct json_object_iter_info_;
+
+/**
+ * The opaque iterator that references a name/value pair within
+ * a JSON Object instance or the "end" iterator value.
+ */
+struct json_object_iterator {
+    const void* opaque_;
+};
+
+
+/**
+ * forward declaration of json-c's JSON value instance structure
+ */
+struct json_object;
+
+
+/**
+ * Initializes an iterator structure to a "default" value that
+ * is convenient for initializing an iterator variable to a
+ * default state (e.g., initialization list in a class'
+ * constructor).
+ *
+ * @code
+ * struct json_object_iterator iter = json_object_iter_init_default();
+ * MyClass() : iter_(json_object_iter_init_default())
+ * @endcode
+ *
+ * @note The initialized value doesn't reference any specific
+ *       pair, is considered an invalid iterator, and MUST NOT
+ *       be passed to any json-c API that expects a valid
+ *       iterator.
+ *
+ * @note User and internal code MUST NOT make any assumptions
+ *       about and dependencies on the value of the "default"
+ *       iterator value.
+ *
+ * @return json_object_iterator
+ */
+struct json_object_iterator
+json_object_iter_init_default(void);
+
+/** Retrieves an iterator to the first pair of the JSON Object.
+ *
+ * @warning 	Any modification of the underlying pair invalidates all
+ * 		iterators to that pair.
+ *
+ * @param obj	JSON Object instance (MUST be of type json_object)
+ *
+ * @return json_object_iterator If the JSON Object has at
+ *              least one pair, on return, the iterator refers
+ *              to the first pair. If the JSON Object doesn't
+ *              have any pairs, the returned iterator is
+ *              equivalent to the "end" iterator for the same
+ *              JSON Object instance.
+ *
+ * @code
+ * struct json_object_iterator it;
+ * struct json_object_iterator itEnd;
+ * struct json_object* obj;
+ *
+ * obj = json_tokener_parse("{'first':'george', 'age':100}");
+ * it = json_object_iter_begin(obj);
+ * itEnd = json_object_iter_end(obj);
+ *
+ * while (!json_object_iter_equal(&it, &itEnd)) {
+ *     printf("%s\n",
+ *            json_object_iter_peek_name(&it));
+ *     json_object_iter_next(&it);
+ * }
+ *
+ * @endcode
+ */
+struct json_object_iterator
+json_object_iter_begin(struct json_object* obj);
+
+/** Retrieves the iterator that represents the position beyond the
+ *  last pair of the given JSON Object instance.
+ *
+ *  @warning Do NOT write code that assumes that the "end"
+ *        iterator value is NULL, even if it is so in a
+ *        particular instance of the implementation.
+ *
+ *  @note The reason we do not (and MUST NOT) provide
+ *        "json_object_iter_is_end(json_object_iterator* iter)"
+ *        type of API is because it would limit the underlying
+ *        representation of name/value containment (or force us
+ *        to add additional, otherwise unnecessary, fields to
+ *        the iterator structure). The "end" iterator and the
+ *        equality test method, on the other hand, permit us to
+ *        cleanly abstract pretty much any reasonable underlying
+ *        representation without burdening the iterator
+ *        structure with unnecessary data.
+ *
+ *  @note For performance reasons, memorize the "end" iterator prior
+ *        to any loop.
+ *
+ * @param obj JSON Object instance (MUST be of type json_object)
+ *
+ * @return json_object_iterator On return, the iterator refers
+ *              to the "end" of the Object instance's pairs
+ *              (i.e., NOT the last pair, but "beyond the last
+ *              pair" value)
+ */
+struct json_object_iterator
+json_object_iter_end(const struct json_object* obj);
+
+/** Returns an iterator to the next pair, if any
+ *
+ * @warning	Any modification of the underlying pair
+ *       	invalidates all iterators to that pair.
+ *
+ * @param iter [IN/OUT] Pointer to iterator that references a
+ *         name/value pair; MUST be a valid, non-end iterator.
+ *         WARNING: bad things will happen if invalid or "end"
+ *         iterator is passed. Upon return will contain the
+ *         reference to the next pair if there is one; if there
+ *         are no more pairs, will contain the "end" iterator
+ *         value, which may be compared against the return value
+ *         of json_object_iter_end() for the same JSON Object
+ *         instance.
+ */
+void
+json_object_iter_next(struct json_object_iterator* iter);
+
+
+/** Returns a const pointer to the name of the pair referenced
+ *  by the given iterator.
+ *
+ * @param iter pointer to iterator that references a name/value
+ *             pair; MUST be a valid, non-end iterator.
+ *
+ * @warning	bad things will happen if an invalid or
+ *             	"end" iterator is passed.
+ *
+ * @return const char* Pointer to the name of the referenced
+ *         name/value pair.  The name memory belongs to the
+ *         name/value pair, will be freed when the pair is
+ *         deleted or modified, and MUST NOT be modified or
+ *         freed by the user.
+ */
+const char*
+json_object_iter_peek_name(const struct json_object_iterator* iter);
+
+
+/** Returns a pointer to the json-c instance representing the
+ *  value of the referenced name/value pair, without altering
+ *  the instance's reference count.
+ *
+ * @param iter 	pointer to iterator that references a name/value
+ *             	pair; MUST be a valid, non-end iterator.
+ *
+ * @warning	bad things will happen if invalid or
+ *             "end" iterator is passed.
+ *
+ * @return struct json_object* Pointer to the json-c value
+ *         instance of the referenced name/value pair;  the
+ *         value's reference count is not changed by this
+ *         function: if you plan to hold on to this json-c node,
+ *         take a look at json_object_get() and
+ *         json_object_put(). IMPORTANT: json-c API represents
+ *         the JSON Null value as a NULL json_object instance
+ *         pointer.
+ */
+struct json_object*
+json_object_iter_peek_value(const struct json_object_iterator* iter);
+
+
+/** Tests two iterators for equality.  Typically used to test
+ *  for end of iteration by comparing an iterator to the
+ *  corresponding "end" iterator (that was derived from the same
+ *  JSON Object instance).
+ *
+ *  @note The reason we do not (and MUST NOT) provide
+ *        "json_object_iter_is_end(json_object_iterator* iter)"
+ *        type of API is because it would limit the underlying
+ *        representation of name/value containment (or force us
+ *        to add additional, otherwise unnecessary, fields to
+ *        the iterator structure). The equality test method, on
+ *        the other hand, permits us to cleanly abstract pretty
+ *        much any reasonable underlying representation.
+ *
+ * @param iter1 Pointer to first valid, non-NULL iterator
+ * @param iter2 POinter to second valid, non-NULL iterator
+ *
+ * @warning	if a NULL iterator pointer or an uninitialized
+ *       	or invalid iterator, or iterators derived from
+ *       	different JSON Object instances are passed, bad things
+ *       	will happen!
+ *
+ * @return json_bool non-zero if iterators are equal (i.e., both
+ *         reference the same name/value pair or are both at
+ *         "end"); zero if they are not equal.
+ */
+json_bool
+json_object_iter_equal(const struct json_object_iterator* iter1,
+                       const struct json_object_iterator* iter2);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // JSON_OBJECT_ITERATOR_H
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h b/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h
new file mode 100644
index 0000000..5ed791b
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h
@@ -0,0 +1,47 @@
+/*
+ * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_private_h_
+#define _json_object_private_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (json_object_private_delete_fn)(struct json_object *o);
+
+struct json_object
+{
+  enum json_type o_type;
+  json_object_private_delete_fn *_delete;
+  json_object_to_json_string_fn *_to_json_string;
+  int _ref_count;
+  struct printbuf *_pb;
+  union data {
+    json_bool c_boolean;
+    double c_double;
+    int64_t c_int64;
+    struct lh_table *c_object;
+    struct array_list *c_array;
+    struct {
+        char *str;
+        int len;
+    } c_string;
+  } o;
+  json_object_delete_fn *_user_delete;
+  void *_userdata;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c
new file mode 100644
index 0000000..1e28257
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c
@@ -0,0 +1,771 @@
+/*
+ * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#include "config.h"
+
+#include "cpl_conv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+#include "arraylist.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif /* HAVE_LOCALE_H */
+
+#if !HAVE_STRDUP && defined(_MSC_VER)
+  /* MSC has the version as _strdup */
+# define strdup _strdup
+#elif !HAVE_STRDUP
+# error You do not have strdup on your system.
+#endif /* HAVE_STRDUP */
+
+#if !HAVE_STRNCASECMP && defined(_MSC_VER)
+  /* MSC has the version as _strnicmp */
+# define strncasecmp _strnicmp
+#elif !HAVE_STRNCASECMP
+# error You do not have strncasecmp on your system.
+#endif /* HAVE_STRNCASECMP */
+
+static const char* json_null_str = "null";
+static const char* json_true_str = "true";
+static const char* json_false_str = "false";
+
+// XXX after v0.10 this array will become static:
+const char* json_tokener_errors[] = {
+  "success",
+  "continue",
+  "nesting too deep",
+  "unexpected end of data",
+  "unexpected character",
+  "null expected",
+  "boolean expected",
+  "number expected",
+  "array value separator ',' expected",
+  "quoted object property name expected",
+  "object property name separator ':' expected",
+  "object value separator ',' expected",
+  "invalid string sequence",
+  "expected comment",
+};
+
+const char *json_tokener_error_desc(enum json_tokener_error jerr)
+{
+	int jerr_int = (int)jerr;
+	if (jerr_int < 0 || jerr_int > (int)sizeof(json_tokener_errors))
+		return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
+	return json_tokener_errors[jerr];
+}
+
+enum json_tokener_error json_tokener_get_error(json_tokener *tok)
+{
+	return tok->err;
+}
+
+/* Stuff for decoding unicode sequences */
+#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
+#define IS_LOW_SURROGATE(uc)  (((uc) & 0xFC00) == 0xDC00)
+#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
+static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
+
+struct json_tokener* json_tokener_new_ex(int depth)
+{
+  struct json_tokener *tok;
+
+  tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
+  if (!tok) return NULL;
+  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
+  if (!tok->stack) {
+    free(tok);
+    return NULL;
+  }
+  tok->pb = printbuf_new();
+  tok->max_depth = depth;
+  json_tokener_reset(tok);
+  return tok;
+}
+
+struct json_tokener* json_tokener_new(void)
+{
+  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
+}
+
+void json_tokener_free(struct json_tokener *tok)
+{
+  json_tokener_reset(tok);
+  if (tok->pb) printbuf_free(tok->pb);
+  if (tok->stack) free(tok->stack);
+  free(tok);
+}
+
+static void json_tokener_reset_level(struct json_tokener *tok, int depth)
+{
+  tok->stack[depth].state = json_tokener_state_eatws;
+  tok->stack[depth].saved_state = json_tokener_state_start;
+  json_object_put(tok->stack[depth].current);
+  tok->stack[depth].current = NULL;
+  free(tok->stack[depth].obj_field_name);
+  tok->stack[depth].obj_field_name = NULL;
+}
+
+void json_tokener_reset(struct json_tokener *tok)
+{
+  int i;
+  if (!tok)
+    return;
+
+  for(i = tok->depth; i >= 0; i--)
+    json_tokener_reset_level(tok, i);
+  tok->depth = 0;
+  tok->err = json_tokener_success;
+}
+
+struct json_object* json_tokener_parse(const char *str)
+{
+    enum json_tokener_error jerr_ignored;
+    struct json_object* obj;
+    obj = json_tokener_parse_verbose(str, &jerr_ignored);
+    return obj;
+}
+
+struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
+{
+    struct json_tokener* tok;
+    struct json_object* obj;
+
+    tok = json_tokener_new();
+    if (!tok)
+      return NULL;
+    obj = json_tokener_parse_ex(tok, str, -1);
+    *error = tok->err;
+    if(tok->err != json_tokener_success) {
+		if (obj != NULL)
+			json_object_put(obj);
+        obj = NULL;
+    }
+
+    json_tokener_free(tok);
+    return obj;
+}
+
+#define state  tok->stack[tok->depth].state
+#define saved_state  tok->stack[tok->depth].saved_state
+#define current tok->stack[tok->depth].current
+#define obj_field_name tok->stack[tok->depth].obj_field_name
+
+/* Optimization:
+ * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
+ * iterating character-by character.  A large performance boost is
+ * achieved by using tighter loops to locally handle units such as
+ * comments and strings.  Loops that handle an entire token within
+ * their scope also gather entire strings and pass them to
+ * printbuf_memappend() in a single call, rather than calling
+ * printbuf_memappend() one char at a time.
+ *
+ * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
+ * common to both the main loop and the tighter loops.
+ */
+
+/* PEEK_CHAR(dest, tok) macro:
+ *   Peeks at the current char and stores it in dest.
+ *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
+ *   Implicit inputs:  str, len vars
+ */
+#define PEEK_CHAR(dest, tok)                                                  \
+  (((tok)->char_offset == len) ?                                          \
+   (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
+    (((tok)->err = json_tokener_success), 0)                              \
+    :                                                                   \
+    (((tok)->err = json_tokener_continue), 0)                             \
+    ) :                                                                 \
+   (((dest) = *str), 1)                                                 \
+   )
+
+/* ADVANCE_CHAR() macro:
+ *   Incrementes str & tok->char_offset.
+ *   For convenience of existing conditionals, returns the old value of c (0 on eof)
+ *   Implicit inputs:  c var
+ */
+#define ADVANCE_CHAR(str, tok) \
+  ( ++(str), ((tok)->char_offset)++, c)
+
+
+/* End optimization macro defs */
+
+
+struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+					  const char *str, int len)
+{
+  struct json_object *obj = NULL;
+  char c = '\1';
+#ifdef HAVE_SETLOCALE
+  char *oldlocale=NULL, *tmplocale;
+
+  tmplocale = setlocale(LC_NUMERIC, NULL);
+  if (tmplocale) oldlocale = strdup(tmplocale);
+  setlocale(LC_NUMERIC, "C");
+#endif
+
+  tok->char_offset = 0;
+  tok->err = json_tokener_success;
+
+  while (PEEK_CHAR(c, tok)) {
+
+  redo_char:
+    switch(state) {
+
+    case json_tokener_state_eatws:
+      /* Advance until we change state */
+      while (isspace((int)c)) {
+	if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
+	  goto out;
+      }
+      if(c == '/') {
+	printbuf_reset(tok->pb);
+	printbuf_memappend_fast(tok->pb, &c, 1);
+	state = json_tokener_state_comment_start;
+      } else {
+	state = saved_state;
+	goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_start:
+      switch(c) {
+      case '{':
+	state = json_tokener_state_eatws;
+	saved_state = json_tokener_state_object_field_start;
+	current = json_object_new_object();
+	break;
+      case '[':
+	state = json_tokener_state_eatws;
+	saved_state = json_tokener_state_array;
+	current = json_object_new_array();
+	break;
+      case 'N':
+      case 'n':
+	state = json_tokener_state_null;
+	printbuf_reset(tok->pb);
+	tok->st_pos = 0;
+	goto redo_char;
+      case '"':
+      case '\'':
+	state = json_tokener_state_string;
+	printbuf_reset(tok->pb);
+	tok->quote_char = c;
+	break;
+      case 'T':
+      case 't':
+      case 'F':
+      case 'f':
+	state = json_tokener_state_boolean;
+	printbuf_reset(tok->pb);
+	tok->st_pos = 0;
+	goto redo_char;
+#if defined(__GNUC__)
+	  case '0' ... '9':
+#else
+	  case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+#endif
+      case '-':
+	state = json_tokener_state_number;
+	printbuf_reset(tok->pb);
+	tok->is_double = 0;
+	goto redo_char;
+      default:
+	tok->err = json_tokener_error_parse_unexpected;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_finish:
+      if(tok->depth == 0) goto out;
+      obj = json_object_get(current);
+      json_tokener_reset_level(tok, tok->depth);
+      tok->depth--;
+      goto redo_char;
+
+    case json_tokener_state_null:
+      printbuf_memappend_fast(tok->pb, &c, 1);
+      if(strncasecmp(json_null_str, tok->pb->buf,
+		     json_min(tok->st_pos+1, (int)strlen(json_null_str))) == 0) {
+	if(tok->st_pos == (int)strlen(json_null_str)) {
+	  current = NULL;
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else {
+	tok->err = json_tokener_error_parse_null;
+	goto out;
+      }
+      tok->st_pos++;
+      break;
+
+    case json_tokener_state_comment_start:
+      if(c == '*') {
+	state = json_tokener_state_comment;
+      } else if(c == '/') {
+	state = json_tokener_state_comment_eol;
+      } else {
+	tok->err = json_tokener_error_parse_comment;
+	goto out;
+      }
+      printbuf_memappend_fast(tok->pb, &c, 1);
+      break;
+
+    case json_tokener_state_comment:
+              {
+          /* Advance until we change state */
+          const char *case_start = str;
+          while(c != '*') {
+            if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+              printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+              goto out;
+            }
+          }
+          printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
+          state = json_tokener_state_comment_end;
+        }
+            break;
+
+    case json_tokener_state_comment_eol:
+      {
+	/* Advance until we change state */
+	const char *case_start = str;
+	while(c != '\n') {
+	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    goto out;
+	  }
+	}
+	printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
+	state = json_tokener_state_eatws;
+      }
+      break;
+
+    case json_tokener_state_comment_end:
+      printbuf_memappend_fast(tok->pb, &c, 1);
+      if(c == '/') {
+	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
+	state = json_tokener_state_eatws;
+      } else {
+	state = json_tokener_state_comment;
+      }
+      break;
+
+    case json_tokener_state_string:
+      {
+	/* Advance until we change state */
+	const char *case_start = str;
+	while(1) {
+	  if(c == tok->quote_char) {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
+	    saved_state = json_tokener_state_finish;
+	    state = json_tokener_state_eatws;
+	    break;
+	  } else if(c == '\\') {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    saved_state = json_tokener_state_string;
+	    state = json_tokener_state_string_escape;
+	    break;
+	  }
+	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    goto out;
+	  }
+	}
+      }
+      break;
+
+    case json_tokener_state_string_escape:
+      switch(c) {
+      case '"':
+      case '\\':
+      case '/':
+	printbuf_memappend_fast(tok->pb, &c, 1);
+	state = saved_state;
+	break;
+      case 'b':
+      case 'n':
+      case 'r':
+      case 't':
+      case 'f':
+	if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
+	else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
+	else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
+	else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
+	else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
+	state = saved_state;
+	break;
+      case 'u':
+	tok->ucs_char = 0;
+	tok->st_pos = 0;
+	state = json_tokener_state_escape_unicode;
+	break;
+      default:
+	tok->err = json_tokener_error_parse_string;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_escape_unicode:
+	{
+          unsigned int got_hi_surrogate = 0;
+
+	  /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
+	  while(1) {
+	    if(strchr(json_hex_chars, c)) {
+	      tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
+	      if(tok->st_pos == 4) {
+		unsigned char unescaped_utf[4];
+
+                if (got_hi_surrogate) {
+		  if (IS_LOW_SURROGATE(tok->ucs_char)) {
+                    /* Recalculate the ucs_char, then fall thru to process normally */
+                    tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
+                  } else {
+                    /* Hi surrogate was not followed by a low surrogate */
+                    /* Replace the hi and process the rest normally */
+		    printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+                  }
+                  got_hi_surrogate = 0;
+                }
+
+		if (tok->ucs_char < 0x80) {
+		  unescaped_utf[0] = tok->ucs_char;
+		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
+		} else if (tok->ucs_char < 0x800) {
+		  unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
+		  unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
+		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
+		} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
+                  /* Got a high surrogate.  Remember it and look for the
+                   * the beginning of another sequence, which should be the
+                   * low surrogate.
+                   */
+                  got_hi_surrogate = tok->ucs_char;
+                  /* Not at end, and the next two chars should be "\u" */
+                  if ((tok->char_offset+1 != len) &&
+                      (tok->char_offset+2 != len) &&
+                      (str[1] == '\\') &&
+                      (str[2] == 'u'))
+                  {
+                /* Advance through the 16 bit surrogate, and move on to the
+                 * next sequence. The next step is to process the following
+                 * characters.
+                 */
+	            if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
+                    printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+                }
+                    /* Advance to the first char of the next sequence and
+                     * continue processing with the next sequence.
+                     */
+	            if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+	              printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+	              goto out;
+                    }
+	            tok->ucs_char = 0;
+                    tok->st_pos = 0;
+                    continue; /* other json_tokener_state_escape_unicode */
+                  } else {
+                    /* Got a high surrogate without another sequence following
+                     * it.  Put a replacement char in for the hi surrogate
+                     * and pretend we finished.
+                     */
+		    printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+                  }
+		} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
+                  /* Got a low surrogate not preceded by a high */
+		  printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+                } else if (tok->ucs_char < 0x10000) {
+		  unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
+		  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+		  unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
+		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
+		} else if (tok->ucs_char < 0x110000) {
+		  unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
+		  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
+		  unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+		  unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
+		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
+		} else {
+                  /* Don't know what we got--insert the replacement char */
+		  printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+                }
+		state = saved_state;
+		break;
+	      }
+	    } else {
+	      tok->err = json_tokener_error_parse_string;
+	      goto out;
+	    }
+	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+            if (got_hi_surrogate) /* Clean up any pending chars */
+	      printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+	    goto out;
+	  }
+	}
+      }
+      break;
+
+    case json_tokener_state_boolean:
+      printbuf_memappend_fast(tok->pb, &c, 1);
+      if(strncasecmp(json_true_str, tok->pb->buf,
+		     json_min(tok->st_pos+1, (int)strlen(json_true_str))) == 0) {
+	if(tok->st_pos == (int)strlen(json_true_str)) {
+	  current = json_object_new_boolean(1);
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else if(strncasecmp(json_false_str, tok->pb->buf,
+			    json_min(tok->st_pos+1, (int)strlen(json_false_str))) == 0) {
+	if(tok->st_pos == (int)strlen(json_false_str)) {
+	  current = json_object_new_boolean(0);
+	  saved_state = json_tokener_state_finish;
+	  state = json_tokener_state_eatws;
+	  goto redo_char;
+	}
+      } else {
+	tok->err = json_tokener_error_parse_boolean;
+	goto out;
+      }
+      tok->st_pos++;
+      break;
+
+    case json_tokener_state_number:
+      {
+	/* Advance until we change state */
+	const char *case_start = str;
+	int case_len=0;
+	while(c && strchr(json_number_chars, c)) {
+	  ++case_len;
+	  if(c == '.' || c == 'e' || c == 'E')
+	    tok->is_double = 1;
+	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+	    printbuf_memappend_fast(tok->pb, case_start, case_len);
+	    goto out;
+	  }
+	}
+        if (case_len>0)
+          printbuf_memappend_fast(tok->pb, case_start, case_len);
+      }
+      {
+	int64_t num64;
+	double  numd;
+	if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
+		current = json_object_new_int64(num64);
+	} else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) {
+          current = json_object_new_double(numd);
+        } else {
+          tok->err = json_tokener_error_parse_number;
+          goto out;
+        }
+        saved_state = json_tokener_state_finish;
+        state = json_tokener_state_eatws;
+        goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_array_after_sep:
+    case json_tokener_state_array:
+      if(c == ']') {
+		if (state == json_tokener_state_array_after_sep &&
+			(tok->flags & JSON_TOKENER_STRICT))
+		{
+			tok->err = json_tokener_error_parse_unexpected;
+			goto out;
+		}
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else {
+	if(tok->depth >= tok->max_depth-1) {
+	  tok->err = json_tokener_error_depth;
+	  goto out;
+	}
+	state = json_tokener_state_array_add;
+	tok->depth++;
+	json_tokener_reset_level(tok, tok->depth);
+	goto redo_char;
+      }
+      break;
+
+    case json_tokener_state_array_add:
+      json_object_array_add(current, obj);
+      saved_state = json_tokener_state_array_sep;
+      state = json_tokener_state_eatws;
+      goto redo_char;
+
+    case json_tokener_state_array_sep:
+      if(c == ']') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if(c == ',') {
+	saved_state = json_tokener_state_array_after_sep;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_array;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_field_start:
+    case json_tokener_state_object_field_start_after_sep:
+      if(c == '}') {
+		if (state == json_tokener_state_object_field_start_after_sep &&
+		    (tok->flags & JSON_TOKENER_STRICT))
+		{
+			tok->err = json_tokener_error_parse_unexpected;
+			goto out;
+		}
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if (c == '"' || c == '\'') {
+	tok->quote_char = c;
+	printbuf_reset(tok->pb);
+	state = json_tokener_state_object_field;
+      } else {
+	tok->err = json_tokener_error_parse_object_key_name;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_field:
+      {
+	/* Advance until we change state */
+	const char *case_start = str;
+	while(1) {
+	  if(c == tok->quote_char) {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    obj_field_name = strdup(tok->pb->buf);
+	    saved_state = json_tokener_state_object_field_end;
+	    state = json_tokener_state_eatws;
+	    break;
+	  } else if(c == '\\') {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    saved_state = json_tokener_state_object_field;
+	    state = json_tokener_state_string_escape;
+	    break;
+	  }
+	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+	    goto out;
+	  }
+	}
+      }
+      break;
+
+    case json_tokener_state_object_field_end:
+      if(c == ':') {
+	saved_state = json_tokener_state_object_value;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_object_key_sep;
+	goto out;
+      }
+      break;
+
+    case json_tokener_state_object_value:
+      if(tok->depth >= tok->max_depth-1) {
+	tok->err = json_tokener_error_depth;
+	goto out;
+      }
+      state = json_tokener_state_object_value_add;
+      tok->depth++;
+      json_tokener_reset_level(tok, tok->depth);
+      goto redo_char;
+
+    case json_tokener_state_object_value_add:
+      json_object_object_add(current, obj_field_name, obj);
+      free(obj_field_name);
+      obj_field_name = NULL;
+      saved_state = json_tokener_state_object_sep;
+      state = json_tokener_state_eatws;
+      goto redo_char;
+
+    case json_tokener_state_object_sep:
+      if(c == '}') {
+	saved_state = json_tokener_state_finish;
+	state = json_tokener_state_eatws;
+      } else if(c == ',') {
+	saved_state = json_tokener_state_object_field_start_after_sep;
+	state = json_tokener_state_eatws;
+      } else {
+	tok->err = json_tokener_error_parse_object_value_sep;
+	goto out;
+      }
+      break;
+
+    }
+    if (!ADVANCE_CHAR(str, tok))
+      goto out;
+  } /* while(POP_CHAR) */
+
+ out:
+  if (!c) { /* We hit an eof char (0) */
+    if(state != json_tokener_state_finish &&
+       saved_state != json_tokener_state_finish)
+      tok->err = json_tokener_error_parse_eof;
+  }
+
+#ifdef HAVE_SETLOCALE
+  setlocale(LC_NUMERIC, oldlocale);
+  if (oldlocale) free(oldlocale);
+#endif
+
+  if (tok->err == json_tokener_success)
+  {
+    json_object *ret = json_object_get(current);
+	int ii;
+
+	/* Partially reset, so we parse additional objects on subsequent calls. */
+    for(ii = tok->depth; ii >= 0; ii--)
+      json_tokener_reset_level(tok, ii);
+    return ret;
+  }
+
+  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
+	   json_tokener_errors[tok->err], tok->char_offset);
+  return NULL;
+}
+
+void json_tokener_set_flags(struct json_tokener *tok, int flags)
+{
+	tok->flags = flags;
+}
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h
new file mode 100644
index 0000000..08e5ff7
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h
@@ -0,0 +1,209 @@
+/*
+ * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_tokener_h_
+#define _json_tokener_h_
+
+#include <stddef.h>
+#include "json_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum json_tokener_error {
+  json_tokener_success,
+  json_tokener_continue,
+  json_tokener_error_depth,
+  json_tokener_error_parse_eof,
+  json_tokener_error_parse_unexpected,
+  json_tokener_error_parse_null,
+  json_tokener_error_parse_boolean,
+  json_tokener_error_parse_number,
+  json_tokener_error_parse_array,
+  json_tokener_error_parse_object_key_name,
+  json_tokener_error_parse_object_key_sep,
+  json_tokener_error_parse_object_value_sep,
+  json_tokener_error_parse_string,
+  json_tokener_error_parse_comment
+};
+
+enum json_tokener_state {
+  json_tokener_state_eatws,
+  json_tokener_state_start,
+  json_tokener_state_finish,
+  json_tokener_state_null,
+  json_tokener_state_comment_start,
+  json_tokener_state_comment,
+  json_tokener_state_comment_eol,
+  json_tokener_state_comment_end,
+  json_tokener_state_string,
+  json_tokener_state_string_escape,
+  json_tokener_state_escape_unicode,
+  json_tokener_state_boolean,
+  json_tokener_state_number,
+  json_tokener_state_array,
+  json_tokener_state_array_add,
+  json_tokener_state_array_sep,
+  json_tokener_state_object_field_start,
+  json_tokener_state_object_field,
+  json_tokener_state_object_field_end,
+  json_tokener_state_object_value,
+  json_tokener_state_object_value_add,
+  json_tokener_state_object_sep,
+  json_tokener_state_array_after_sep,
+  json_tokener_state_object_field_start_after_sep
+};
+
+struct json_tokener_srec
+{
+  enum json_tokener_state state, saved_state;
+  struct json_object *obj;
+  struct json_object *current;
+  char *obj_field_name;
+};
+
+#define JSON_TOKENER_DEFAULT_DEPTH 32
+
+struct json_tokener
+{
+  char *str;
+  struct printbuf *pb;
+  int max_depth, depth, is_double, st_pos, char_offset;
+  enum json_tokener_error err;
+  unsigned int ucs_char;
+  char quote_char;
+  struct json_tokener_srec *stack;
+  int flags;
+};
+
+/**
+ * Be strict when parsing JSON input.  Use caution with
+ * this flag as what is considered valid may become more
+ * restrictive from one release to the next, causing your
+ * code to fail on previously working input.
+ *
+ * This flag is not set by default.
+ *
+ * @see json_tokener_set_flags()
+ */
+#define JSON_TOKENER_STRICT  0x01
+
+/**
+ * Given an error previously returned by json_tokener_get_error(),
+ * return a human readable description of the error.
+ *
+ * @return a generic error message is returned if an invalid error value is provided.
+ */
+const char *json_tokener_error_desc(enum json_tokener_error jerr);
+
+/** 
+ * @b XXX do not use json_tokener_errors directly.  
+ * After v0.10 this will be removed.
+ *
+ * See json_tokener_error_desc() instead.
+ */
+extern const char* json_tokener_errors[];
+
+/**
+ * Retrieve the error caused by the last call to json_tokener_parse_ex(),
+ * or json_tokener_success if there is no error.
+ *
+ * When parsing a JSON string in pieces, if the tokener is in the middle
+ * of parsing this will return json_tokener_continue.
+ *
+ * See also json_tokener_error_desc().
+ */
+enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
+
+extern struct json_tokener* json_tokener_new(void);
+extern struct json_tokener* json_tokener_new_ex(int depth);
+extern void json_tokener_free(struct json_tokener *tok);
+extern void json_tokener_reset(struct json_tokener *tok);
+extern struct json_object* json_tokener_parse(const char *str);
+extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
+
+/**
+ * Set flags that control how parsing will be done.
+ */
+extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
+
+/** 
+ * Parse a string and return a non-NULL json_object if a valid JSON value
+ * is found.  The string does not need to be a JSON object or array;
+ * it can also be a string, number or boolean value.
+ *
+ * A partial JSON string can be parsed.  If the parsing is incomplete,
+ * NULL will be returned and json_tokener_get_error() will be return 
+ * json_tokener_continue.
+ * json_tokener_parse_ex() can then be called with additional bytes in str
+ * to continue the parsing.  
+ *
+ * If json_tokener_parse_ex() returns NULL and the error anything other than
+ * json_tokener_continue, a fatal error has occurred and parsing must be
+ * halted.  Then tok object must not be re-used until json_tokener_reset() is
+ * called.
+ *
+ * When a valid JSON value is parsed, a non-NULL json_object will be
+ * returned.  Also, json_tokener_get_error() will return json_tokener_success.
+ * Be sure to check the type with json_object_is_type() or
+ * json_object_get_type() before using the object.
+ *
+ * @b XXX this shouldn't use internal fields:
+ * Trailing characters after the parsed value do not automatically cause an 
+ * error.  It is up to the caller to decide whether to treat this as an
+ * error or to handle the additional characters, perhaps by parsing another
+ * json value starting from that point.
+ *
+ * Extra characters can be detected by comparing the tok->char_offset against
+ * the length of the last len parameter passed in.
+ *
+ * The tokener does \b not maintain an internal buffer so the caller is
+ * responsible for calling json_tokener_parse_ex with an appropriate str
+ * parameter starting with the extra characters.
+ *
+ * Example:
+ * @code
+json_object *jobj = NULL;
+const char *mystring = NULL;
+int stringlen = 0;
+enum json_tokener_error jerr;
+do {
+	mystring = ...  // get JSON string, e.g. read from file, etc...
+	stringlen = strlen(mystring);
+	jobj = json_tokener_parse_ex(tok, mystring, stringlen);
+} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
+if (jerr != json_tokener_success)
+{
+	fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
+	// Handle errors, as appropriate for your application.
+}
+if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
+{
+	// Handle extra characters after parsed object as desired.
+	// e.g. issue an error, parse another object from that point, etc...
+}
+// Success, use jobj here.
+
+ at endcode
+ *
+ * @param tok a json_tokener previously allocated with json_tokener_new()
+ * @param str an string with any valid JSON expression, or portion of.  This does not need to be null terminated.
+ * @param len the length of str
+ */
+extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+						 const char *str, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_util.c b/ogr/ogrsf_frmts/geojson/libjson/json_util.c
new file mode 100644
index 0000000..fef9422
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_util.c
@@ -0,0 +1,303 @@
+/*
+ * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+#undef realloc
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <io.h>
+#endif /* defined(WIN32) */
+
+#if !defined(HAVE_OPEN) && defined(WIN32)
+# define open _open
+#endif
+
+#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
+  /* MSC has the version as _snprintf */
+# define snprintf _snprintf
+#elif !defined(HAVE_SNPRINTF)
+# error You do not have snprintf on your system.
+#endif /* HAVE_SNPRINTF */
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+static int sscanf_is_broken = 0;
+static int sscanf_is_broken_testdone = 0;
+static void sscanf_is_broken_test(void);
+
+struct json_object* json_object_from_file(const char *filename)
+{
+  struct printbuf *pb;
+  struct json_object *obj;
+  char buf[JSON_FILE_BUF_SIZE];
+  int fd, ret;
+
+  if((fd = open(filename, O_RDONLY)) < 0) {
+    MC_ERROR("json_object_from_file: error reading file %s: %s\n",
+	     filename, strerror(errno));
+    return NULL;
+  }
+  if(!(pb = printbuf_new())) {
+    close(fd);
+    MC_ERROR("json_object_from_file: printbuf_new failed\n");
+    return NULL;
+  }
+  while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
+    printbuf_memappend(pb, buf, ret);
+  }
+  close(fd);
+  if(ret < 0) {
+    MC_ABORT("json_object_from_file: error reading file %s: %s\n",
+	     filename, strerror(errno));
+    printbuf_free(pb);
+    return NULL;
+  }
+  obj = json_tokener_parse(pb->buf);
+  printbuf_free(pb);
+  return obj;
+}
+
+/* extended "format and write to file" function */
+
+int json_object_to_file_ext(char *filename, struct json_object *obj, int flags)
+{
+  const char *json_str;
+  int fd, ret;
+  unsigned int wpos, wsize;
+
+  if(!obj) {
+    MC_ERROR("json_object_to_file: object is null\n");
+    return -1;
+  }
+
+  if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
+    MC_ERROR("json_object_to_file: error opening file %s: %s\n",
+	     filename, strerror(errno));
+    return -1;
+  }
+
+  if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
+    close(fd);
+    return -1;
+  }
+
+  wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
+  wpos = 0;
+  while(wpos < wsize) {
+    if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
+      close(fd);
+      MC_ERROR("json_object_to_file: error writing file %s: %s\n",
+	     filename, strerror(errno));
+      return -1;
+    }
+
+	/* because of the above check for ret < 0, we can safely cast and add */
+    wpos += (unsigned int)ret;
+  }
+
+  close(fd);
+  return 0;
+}
+
+// backwards compatible "format and write to file" function
+
+int json_object_to_file(char *filename, struct json_object *obj)
+{
+  return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
+}
+
+int json_parse_double(const char *buf, double *retval)
+{
+  return (sscanf(buf, "%lf", retval)==1 ? 0 : 1);
+}
+
+/*
+ * Not all implementations of sscanf actually work properly.
+ * Check whether the one we're currently using does, and if
+ * it's broken, enable the workaround code.
+ */
+static void sscanf_is_broken_test()
+{
+	int64_t num64;
+    int ret_errno;
+    int is_int64_min;
+    int ret_errno2;
+    int is_int64_max;
+
+	(void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64);
+	ret_errno = errno;
+	is_int64_min = (num64 == INT64_MIN);
+
+	(void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64);
+	ret_errno2 = errno;
+	is_int64_max = (num64 == INT64_MAX);
+
+	if (ret_errno != ERANGE || !is_int64_min ||
+	    ret_errno2 != ERANGE || !is_int64_max)
+	{
+		MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n");
+		sscanf_is_broken = 1;
+	}
+}
+
+int json_parse_int64(const char *buf, int64_t *retval)
+{
+	int64_t num64;
+	const char *buf_sig_digits;
+	int orig_has_neg;
+	int saved_errno;
+
+	if (!sscanf_is_broken_testdone)
+	{
+		sscanf_is_broken_test();
+		sscanf_is_broken_testdone = 1;
+	}
+
+	// Skip leading spaces
+	while (isspace((int)*buf) && *buf)
+		buf++;
+
+	errno = 0; // sscanf won't always set errno, so initialize
+	if (sscanf(buf, "%" SCNd64, &num64) != 1)
+	{
+		MC_DEBUG("Failed to parse, sscanf != 1\n");
+		return 1;
+	}
+
+	saved_errno = errno;
+	buf_sig_digits = buf;
+	orig_has_neg = 0;
+	if (*buf_sig_digits == '-')
+	{
+		buf_sig_digits++;
+		orig_has_neg = 1;
+	}
+
+	// Not all sscanf implementations actually work
+	if (sscanf_is_broken && saved_errno != ERANGE)
+	{
+		char buf_cmp[100];
+		char *buf_cmp_start = buf_cmp;
+		int recheck_has_neg = 0;
+		int buf_cmp_len;
+
+		// Skip leading zeros, but keep at least one digit
+		while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
+			buf_sig_digits++;
+		if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
+			orig_has_neg = 0; // "-0" is the same as just plain "0"
+
+		snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
+		if (*buf_cmp_start == '-')
+		{
+			recheck_has_neg = 1;
+			buf_cmp_start++;
+		}
+		// No need to skip leading spaces or zeros here.
+
+		buf_cmp_len = strlen(buf_cmp_start);
+		/**
+		 * If the sign is different, or
+		 * some of the digits are different, or
+		 * there is another digit present in the original string
+		 * then we have NOT successfully parsed the value.
+		 */
+		if (orig_has_neg != recheck_has_neg ||
+		    strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
+			((int)strlen(buf_sig_digits) != buf_cmp_len &&
+			 isdigit((int)buf_sig_digits[buf_cmp_len])
+		    )
+		   )
+		{
+			saved_errno = ERANGE;
+		}
+	}
+
+	// Not all sscanf impl's set the value properly when out of range.
+	// Always do this, even for properly functioning implementations,
+	// since it shouldn't slow things down much.
+	if (saved_errno == ERANGE)
+	{
+		if (orig_has_neg)
+			num64 = INT64_MIN;
+		else
+			num64 = INT64_MAX;
+	}
+	*retval = num64;
+	return 0;
+}
+
+#ifndef HAVE_REALLOC
+void* rpl_realloc(void* p, size_t n)
+{
+	if (n == 0)
+		n = 1;
+	if (p == 0)
+		return malloc(n);
+	return realloc(p, n);
+}
+#endif
+
+#define NELEM(a)        (sizeof(a) / sizeof(a[0]))
+static const char* json_type_name[] = {
+  /* If you change this, be sure to update the enum json_type definition too */
+  "null",
+  "boolean",
+  "double",
+  "int",
+  "object",
+  "array",
+  "string",
+};
+
+const char *json_type_to_name(enum json_type o_type)
+{
+	int o_type_int = (int)o_type;
+	if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
+	{
+		MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
+		return NULL;
+	}
+	return json_type_name[o_type];
+}
+
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_util.h b/ogr/ogrsf_frmts/geojson/libjson/json_util.h
new file mode 100644
index 0000000..b9a69c8
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_util.h
@@ -0,0 +1,41 @@
+/*
+ * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_util_h_
+#define _json_util_h_
+
+#include "json_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JSON_FILE_BUF_SIZE 4096
+
+/* utility functions */
+extern struct json_object* json_object_from_file(const char *filename);
+extern int json_object_to_file(char *filename, struct json_object *obj);
+extern int json_object_to_file_ext(char *filename, struct json_object *obj, int flags);
+extern int json_parse_int64(const char *buf, int64_t *retval);
+extern int json_parse_double(const char *buf, double *retval);
+
+
+/**
+ * Return a string describing the type of the object.
+ * e.g. "int", or "object", etc...
+ */
+extern const char *json_type_to_name(enum json_type o_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/linkhash.c b/ogr/ogrsf_frmts/geojson/libjson/linkhash.c
new file mode 100644
index 0000000..5043148
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/linkhash.c
@@ -0,0 +1,233 @@
+/*
+ * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <limits.h>
+
+#include "linkhash.h"
+
+void lh_abort(const char *msg, ...)
+{
+	va_list ap;
+	va_start(ap, msg);
+	vprintf(msg, ap);
+	va_end(ap);
+	exit(1);
+}
+
+unsigned long lh_ptr_hash(const void *k)
+{
+	/* CAW: refactored to be 64bit nice */
+	return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
+}
+
+int lh_ptr_equal(const void *k1, const void *k2)
+{
+	return (k1 == k2);
+}
+
+unsigned long lh_char_hash(const void *k)
+{
+	unsigned int h = 0;
+	const char* data = (const char*)k;
+ 
+	while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
+
+	return h;
+}
+
+int lh_char_equal(const void *k1, const void *k2)
+{
+	return (strcmp((const char*)k1, (const char*)k2) == 0);
+}
+
+struct lh_table* lh_table_new(int size, const char *name,
+			      lh_entry_free_fn *free_fn,
+			      lh_hash_fn *hash_fn,
+			      lh_equal_fn *equal_fn)
+{
+	int i;
+	struct lh_table *t;
+
+	t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
+	if(!t) lh_abort("lh_table_new: calloc failed\n");
+	t->count = 0;
+	t->size = size;
+	t->name = name;
+	t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
+	if(!t->table) lh_abort("lh_table_new: calloc failed\n");
+	t->free_fn = free_fn;
+	t->hash_fn = hash_fn;
+	t->equal_fn = equal_fn;
+	for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
+	return t;
+}
+
+struct lh_table* lh_kchar_table_new(int size, const char *name,
+				    lh_entry_free_fn *free_fn)
+{
+	return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
+}
+
+struct lh_table* lh_kptr_table_new(int size, const char *name,
+				   lh_entry_free_fn *free_fn)
+{
+	return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
+}
+
+void lh_table_resize(struct lh_table *t, int new_size)
+{
+	struct lh_table *new_t;
+	struct lh_entry *ent;
+
+	new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
+	ent = t->head;
+	while(ent) {
+		lh_table_insert(new_t, ent->k, ent->v);
+		ent = ent->next;
+	}
+	free(t->table);
+	t->table = new_t->table;
+	t->size = new_size;
+	t->head = new_t->head;
+	t->tail = new_t->tail;
+	t->resizes++;
+	free(new_t);
+}
+
+void lh_table_free(struct lh_table *t)
+{
+	struct lh_entry *c;
+	for(c = t->head; c != NULL; c = c->next) {
+		if(t->free_fn) {
+			t->free_fn(c);
+		}
+	}
+	free(t->table);
+	free(t);
+}
+
+
+int lh_table_insert(struct lh_table *t, void *k, const void *v)
+{
+	unsigned long h, n;
+
+	t->inserts++;
+	if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2);
+
+	h = t->hash_fn(k);
+	n = h % t->size;
+
+	while( 1 ) {
+		if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
+		t->collisions++;
+		if ((int)++n == t->size) n = 0;
+	}
+
+	t->table[n].k = k;
+	t->table[n].v = v;
+	t->count++;
+
+	if(t->head == NULL) {
+		t->head = t->tail = &t->table[n];
+		t->table[n].next = t->table[n].prev = NULL;
+	} else {
+		t->tail->next = &t->table[n];
+		t->table[n].prev = t->tail;
+		t->table[n].next = NULL;
+		t->tail = &t->table[n];
+	}
+
+	return 0;
+}
+
+
+struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
+{
+	unsigned long h = t->hash_fn(k);
+	unsigned long n = h % t->size;
+	int count = 0;
+
+	t->lookups++;
+	while( count < t->size ) {
+		if(t->table[n].k == LH_EMPTY) return NULL;
+		if(t->table[n].k != LH_FREED &&
+		   t->equal_fn(t->table[n].k, k)) return &t->table[n];
+		if ((int)++n == t->size) n = 0;
+		count++;
+	}
+	return NULL;
+}
+
+
+const void* lh_table_lookup(struct lh_table *t, const void *k)
+{
+	void *result;
+	lh_table_lookup_ex(t, k, &result);
+	return result;
+}
+
+json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
+{
+	struct lh_entry *e = lh_table_lookup_entry(t, k);
+	if (e != NULL) {
+		if (v != NULL) *v = (void *)e->v;
+		return TRUE; /* key found */
+	}
+	if (v != NULL) *v = NULL;
+	return FALSE; /* key not found */
+}
+
+int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
+{
+	ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
+
+	/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
+	if(n < 0) { return -2; }
+
+	if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
+	t->count--;
+	if(t->free_fn) t->free_fn(e);
+	t->table[n].v = NULL;
+	t->table[n].k = LH_FREED;
+	if(t->tail == &t->table[n] && t->head == &t->table[n]) {
+		t->head = t->tail = NULL;
+	} else if (t->head == &t->table[n]) {
+		t->head->next->prev = NULL;
+		t->head = t->head->next;
+	} else if (t->tail == &t->table[n]) {
+		t->tail->prev->next = NULL;
+		t->tail = t->tail->prev;
+	} else {
+		t->table[n].prev->next = t->table[n].next;
+		t->table[n].next->prev = t->table[n].prev;
+	}
+	t->table[n].next = t->table[n].prev = NULL;
+	return 0;
+}
+
+
+int lh_table_delete(struct lh_table *t, const void *k)
+{
+	struct lh_entry *e = lh_table_lookup_entry(t, k);
+	if(!e) return -1;
+	return lh_table_delete_entry(t, e);
+}
+
+int lh_table_length(struct lh_table *t)
+{
+	return t->count;
+}
diff --git a/ogr/ogrsf_frmts/geojson/libjson/linkhash.h b/ogr/ogrsf_frmts/geojson/libjson/linkhash.h
new file mode 100644
index 0000000..378de0b
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/linkhash.h
@@ -0,0 +1,292 @@
+/*
+ * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+ 
+#ifndef _linkhash_h_
+#define _linkhash_h_
+
+#include "json_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * golden prime used in hash functions
+ */
+#define LH_PRIME 0x9e370001UL
+
+/**
+ * The fraction of filled hash buckets until an insert will cause the table
+ * to be resized.  
+ * This can range from just above 0 up to 1.0.
+ */
+#define LH_LOAD_FACTOR 0.66
+
+/**
+ * sentinel pointer value for empty slots
+ */
+#define LH_EMPTY (void*)-1
+
+/**
+ * sentinel pointer value for freed slots
+ */
+#define LH_FREED (void*)-2
+
+struct lh_entry;
+
+/**
+ * callback function prototypes
+ */
+typedef void (lh_entry_free_fn) (struct lh_entry *e);
+/**
+ * callback function prototypes
+ */
+typedef unsigned long (lh_hash_fn) (const void *k);
+/**
+ * callback function prototypes
+ */
+typedef int (lh_equal_fn) (const void *k1, const void *k2);
+
+/**
+ * An entry in the hash table
+ */
+struct lh_entry {
+	/**
+	 * The key.
+	 */
+	void *k;
+	/**
+	 * The value.
+	 */
+	const void *v;
+	/**
+	 * The next entry
+	 */
+	struct lh_entry *next;
+	/**
+	 * The previous entry.
+	 */
+	struct lh_entry *prev;
+};
+
+
+/**
+ * The hash table structure.
+ */
+struct lh_table {
+	/**
+	 * Size of our hash.
+	 */
+	int size;
+	/**
+	 * Numbers of entries.
+	 */
+	int count;
+
+	/**
+	 * Number of collisions.
+	 */
+	int collisions;
+
+	/**
+	 * Number of resizes.
+	 */
+	int resizes;
+
+	/**
+	 * Number of lookups.
+	 */
+	int lookups;
+
+	/**
+	 * Number of inserts.
+	 */
+	int inserts;
+
+	/**
+	 * Number of deletes.
+	 */
+	int deletes;
+
+	/**
+	 * Name of the hash table.
+	 */
+	const char *name;
+
+	/**
+	 * The first entry.
+	 */
+	struct lh_entry *head;
+
+	/**
+	 * The last entry.
+	 */
+	struct lh_entry *tail;
+
+	struct lh_entry *table;
+
+	/**
+	 * A pointer onto the function responsible for freeing an entry.
+	 */
+	lh_entry_free_fn *free_fn;
+	lh_hash_fn *hash_fn;
+	lh_equal_fn *equal_fn;
+};
+
+
+/**
+ * Pre-defined hash and equality functions
+ */
+extern unsigned long lh_ptr_hash(const void *k);
+extern int lh_ptr_equal(const void *k1, const void *k2);
+
+extern unsigned long lh_char_hash(const void *k);
+extern int lh_char_equal(const void *k1, const void *k2);
+
+
+/**
+ * Convenience list iterator.
+ */
+#define lh_foreach(table, entry) \
+for(entry = table->head; entry; entry = entry->next)
+
+/**
+ * lh_foreach_safe allows calling of deletion routine while iterating.
+ */
+#define lh_foreach_safe(table, entry, tmp) \
+for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
+
+
+
+/**
+ * Create a new linkhash table.
+ * @param size initial table size. The table is automatically resized
+ * although this incurs a performance penalty.
+ * @param name the table name.
+ * @param free_fn callback function used to free memory for entries
+ * when lh_table_free or lh_table_delete is called.
+ * If NULL is provided, then memory for keys and values
+ * must be freed by the caller.
+ * @param hash_fn  function used to hash keys. 2 standard ones are defined:
+ * lh_ptr_hash and lh_char_hash for hashing pointer values
+ * and C strings respectively.
+ * @param equal_fn comparison function to compare keys. 2 standard ones defined:
+ * lh_ptr_hash and lh_char_hash for comparing pointer values
+ * and C strings respectively.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_table_new(int size, const char *name,
+				     lh_entry_free_fn *free_fn,
+				     lh_hash_fn *hash_fn,
+				     lh_equal_fn *equal_fn);
+
+/**
+ * Convenience function to create a new linkhash
+ * table with char keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kchar_table_new(int size, const char *name,
+					   lh_entry_free_fn *free_fn);
+
+
+/**
+ * Convenience function to create a new linkhash
+ * table with ptr keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kptr_table_new(int size, const char *name,
+					  lh_entry_free_fn *free_fn);
+
+
+/**
+ * Free a linkhash table.
+ * If a callback free function is provided then it is called for all
+ * entries in the table.
+ * @param t table to free.
+ */
+extern void lh_table_free(struct lh_table *t);
+
+
+/**
+ * Insert a record into the table.
+ * @param t the table to insert into.
+ * @param k a pointer to the key to insert.
+ * @param v a pointer to the value to insert.
+ */
+extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
+
+
+/**
+ * Lookup a record into the table.
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the record structure of the value or NULL if it does not exist.
+ */
+extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
+
+/**
+ * Lookup a record into the table
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the found value or NULL if it does not exist.
+ * @deprecated Use lh_table_lookup_ex instead.
+ */
+extern const void* lh_table_lookup(struct lh_table *t, const void *k);
+
+/**
+ * Lookup a record in the table
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
+ * @return whether or not the key was found
+ */
+extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param e a pointer to the entry to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
+
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param k a pointer to the key to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete(struct lh_table *t, const void *k);
+
+extern int lh_table_length(struct lh_table *t);
+
+void lh_abort(const char *msg, ...);
+void lh_table_resize(struct lh_table *t, int new_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/makefile.vc b/ogr/ogrsf_frmts/geojson/libjson/makefile.vc
new file mode 100644
index 0000000..17ae024
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/makefile.vc
@@ -0,0 +1,27 @@
+# $Id$
+#
+# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
+# 
+
+OBJ = \
+	arraylist.obj \
+	debug.obj \
+	json_object.obj \
+	json_tokener.obj \
+	json_util.obj \
+	linkhash.obj \
+	printbuf.obj \
+	json_object_iterator.obj \
+	json_c_version.obj
+
+GDAL_ROOT	=	..\..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(SOFTWARNFLAGS)
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/geojson/libjson/printbuf.c b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
new file mode 100644
index 0000000..6ec9533
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
@@ -0,0 +1,148 @@
+/*
+ * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpl_string.h" 
+
+#if HAVE_STDARG_H
+# include <stdarg.h>
+#else /* !HAVE_STDARG_H */
+# error Not enough var arg support!
+#endif /* HAVE_STDARG_H */
+
+#include "bits.h"
+#include "debug.h"
+#include "printbuf.h"
+
+static int printbuf_extend(struct printbuf *p, int min_size);
+
+struct printbuf* printbuf_new(void)
+{
+  struct printbuf *p;
+
+  p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
+  if(!p) return NULL;
+  p->size = 32;
+  p->bpos = 0;
+  if(!(p->buf = (char*)malloc(p->size))) {
+    free(p);
+    return NULL;
+  }
+  return p;
+}
+
+
+/**
+ * Extend the buffer p so it has a size of at least min_size.
+ *
+ * If the current size is large enough, nothing is changed.
+ *
+ * Note: this does not check the available space!  The caller
+ *  is responsible for performing those calculations.
+ */
+static int printbuf_extend(struct printbuf *p, int min_size)
+{
+	char *t;
+	int new_size;
+
+	if (p->size >= min_size)
+		return 0;
+
+	new_size = json_max(p->size * 2, min_size + 8);
+#ifdef PRINTBUF_DEBUG
+	MC_DEBUG("printbuf_memappend: realloc "
+	  "bpos=%d min_size=%d old_size=%d new_size=%d\n",
+	  p->bpos, min_size, p->size, new_size);
+#endif /* PRINTBUF_DEBUG */
+	if(!(t = (char*)realloc(p->buf, new_size)))
+		return -1;
+	p->size = new_size;
+	p->buf = t;
+	return 0;
+}
+
+int printbuf_memappend(struct printbuf *p, const char *buf, int size)
+{
+  if (p->size <= p->bpos + size + 1) {
+    if (printbuf_extend(p, p->bpos + size + 1) < 0)
+      return -1;
+  }
+  memcpy(p->buf + p->bpos, buf, size);
+  p->bpos += size;
+  p->buf[p->bpos]= '\0';
+  return size;
+}
+
+int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
+{
+	int size_needed;
+
+	if (offset == -1)
+		offset = pb->bpos;
+	size_needed = offset + len;
+	if (pb->size < size_needed)
+	{
+		if (printbuf_extend(pb, size_needed) < 0)
+			return -1;
+	}
+
+	memset(pb->buf + offset, charvalue, len);
+	if (pb->bpos < size_needed)
+		pb->bpos = size_needed;
+
+	return 0;
+}
+/* Use CPLVASPrintf for portability issues */
+int sprintbuf(struct printbuf *p, const char *msg, ...)
+{
+  va_list ap;
+  char *t;
+  int size, ret; 
+
+  /* user stack buffer first */
+  va_start(ap, msg);
+  if((size = CPLVASPrintf(&t, msg, ap)) == -1) return -1; 
+  va_end(ap);
+  
+  if (strcmp(msg, "%f") == 0)
+  {
+      char* pszComma = strchr(t, ',');
+      if (pszComma)
+          *pszComma = '.';
+  }
+  
+  ret = printbuf_memappend(p, t, size);
+  CPLFree(t);
+  return ret;
+}
+
+void printbuf_reset(struct printbuf *p)
+{
+  p->buf[0] = '\0';
+  p->bpos = 0;
+}
+
+void printbuf_free(struct printbuf *p)
+{
+  if(p) {
+    free(p->buf);
+    free(p);
+  }
+}
diff --git a/ogr/ogrsf_frmts/geojson/libjson/printbuf.h b/ogr/ogrsf_frmts/geojson/libjson/printbuf.h
new file mode 100644
index 0000000..b1bde7f
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/printbuf.h
@@ -0,0 +1,77 @@
+/*
+ * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark <michael at metaparadigm.com>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#ifndef _printbuf_h_
+#define _printbuf_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct printbuf {
+  char *buf;
+  int bpos;
+  int size;
+};
+
+extern struct printbuf*
+printbuf_new(void);
+
+/* As an optimization, printbuf_memappend_fast is defined as a macro
+ * that handles copying data if the buffer is large enough; otherwise
+ * it invokes printbuf_memappend_real() which performs the heavy
+ * lifting of realloc()ing the buffer and copying data.
+ * Your code should not use printbuf_memappend directly--use
+ * printbuf_memappend_fast instead.
+ */
+extern int
+printbuf_memappend(struct printbuf *p, const char *buf, int size);
+
+#define printbuf_memappend_fast(p, bufptr, bufsize)          \
+do {                                                         \
+  if ((p->size - p->bpos) > bufsize) {                       \
+    memcpy(p->buf + p->bpos, (bufptr), bufsize);             \
+    p->bpos += bufsize;                                      \
+    p->buf[p->bpos]= '\0';                                   \
+  } else {  printbuf_memappend(p, (bufptr), bufsize); }      \
+} while (0)
+
+#define printbuf_length(p) ((p)->bpos)
+
+/**
+ * Set len bytes of the buffer to charvalue, starting at offset offset.
+ * Similar to calling memset(x, charvalue, len);
+ *
+ * The memory allocated for the buffer is extended as necessary.
+ *
+ * If offset is -1, this starts at the end of the current data in the buffer.
+ */
+extern int
+printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
+
+extern int
+sprintbuf(struct printbuf *p, const char *msg, ...);
+
+extern void
+printbuf_reset(struct printbuf *p);
+
+extern void
+printbuf_free(struct printbuf *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/symbol_renames.h b/ogr/ogrsf_frmts/geojson/libjson/symbol_renames.h
new file mode 100644
index 0000000..28d209a
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/libjson/symbol_renames.h
@@ -0,0 +1,127 @@
+/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */
+#ifndef symbol_renames
+#define symbol_renames
+
+#define array_list_expand_internal gdal_array_list_expand_internal
+#define array_list_add gdal_array_list_add
+#define array_list_free gdal_array_list_free
+#define array_list_get_idx gdal_array_list_get_idx
+#define array_list_length gdal_array_list_length
+#define array_list_new gdal_array_list_new
+#define array_list_put_idx gdal_array_list_put_idx
+#define array_list_sort gdal_array_list_sort
+#define mc_abort gdal_mc_abort
+#define mc_debug gdal_mc_debug
+#define mc_error gdal_mc_error
+#define mc_get_debug gdal_mc_get_debug
+#define mc_info gdal_mc_info
+#define mc_set_debug gdal_mc_set_debug
+#define mc_set_syslog gdal_mc_set_syslog
+#define json_c_version gdal_json_c_version
+#define json_c_version_num gdal_json_c_version_num
+#define indent gdal_indent
+#define json_escape_str gdal_json_escape_str
+#define json_object_array_delete gdal_json_object_array_delete
+#define json_object_array_entry_free gdal_json_object_array_entry_free
+#define json_object_array_to_json_string gdal_json_object_array_to_json_string
+#define json_object_boolean_to_json_string gdal_json_object_boolean_to_json_string
+#define json_object_double_to_json_string gdal_json_object_double_to_json_string
+#define json_object_generic_delete gdal_json_object_generic_delete
+#define json_object_int_to_json_string gdal_json_object_int_to_json_string
+#define json_object_lh_entry_free gdal_json_object_lh_entry_free
+#define json_object_new gdal_json_object_new
+#define json_object_object_delete gdal_json_object_object_delete
+#define json_object_object_to_json_string gdal_json_object_object_to_json_string
+#define json_object_string_delete gdal_json_object_string_delete
+#define json_object_string_to_json_string gdal_json_object_string_to_json_string
+#define json_object_array_add gdal_json_object_array_add
+#define json_object_array_get_idx gdal_json_object_array_get_idx
+#define json_object_array_length gdal_json_object_array_length
+#define json_object_array_put_idx gdal_json_object_array_put_idx
+#define json_object_array_sort gdal_json_object_array_sort
+#define json_object_get gdal_json_object_get
+#define json_object_get_array gdal_json_object_get_array
+#define json_object_get_boolean gdal_json_object_get_boolean
+#define json_object_get_double gdal_json_object_get_double
+#define json_object_get_int gdal_json_object_get_int
+#define json_object_get_int64 gdal_json_object_get_int64
+#define json_object_get_object gdal_json_object_get_object
+#define json_object_get_string gdal_json_object_get_string
+#define json_object_get_string_len gdal_json_object_get_string_len
+#define json_object_get_type gdal_json_object_get_type
+#define json_object_is_type gdal_json_object_is_type
+#define json_object_new_array gdal_json_object_new_array
+#define json_object_new_boolean gdal_json_object_new_boolean
+#define json_object_new_double gdal_json_object_new_double
+#define json_object_new_int gdal_json_object_new_int
+#define json_object_new_int64 gdal_json_object_new_int64
+#define json_object_new_object gdal_json_object_new_object
+#define json_object_new_string gdal_json_object_new_string
+#define json_object_new_string_len gdal_json_object_new_string_len
+#define json_object_object_add gdal_json_object_object_add
+#define json_object_object_del gdal_json_object_object_del
+#define json_object_object_get gdal_json_object_object_get
+#define json_object_object_get_ex gdal_json_object_object_get_ex
+#define json_object_object_length gdal_json_object_object_length
+#define json_object_put gdal_json_object_put
+#define json_object_set_serializer gdal_json_object_set_serializer
+#define json_object_to_json_string gdal_json_object_to_json_string
+#define json_object_to_json_string_ext gdal_json_object_to_json_string_ext
+#define json_hex_chars gdal_json_hex_chars
+#define json_number_chars gdal_json_number_chars
+#define json_tokener_reset_level gdal_json_tokener_reset_level
+#define json_tokener_error_desc gdal_json_tokener_error_desc
+#define json_tokener_free gdal_json_tokener_free
+#define json_tokener_get_error gdal_json_tokener_get_error
+#define json_tokener_new gdal_json_tokener_new
+#define json_tokener_new_ex gdal_json_tokener_new_ex
+#define json_tokener_parse gdal_json_tokener_parse
+#define json_tokener_parse_ex gdal_json_tokener_parse_ex
+#define json_tokener_parse_verbose gdal_json_tokener_parse_verbose
+#define json_tokener_reset gdal_json_tokener_reset
+#define json_tokener_set_flags gdal_json_tokener_set_flags
+#define json_false_str gdal_json_false_str
+#define json_null_str gdal_json_null_str
+#define json_true_str gdal_json_true_str
+#define json_tokener_errors gdal_json_tokener_errors
+#define json_object_iter_begin gdal_json_object_iter_begin
+#define json_object_iter_end gdal_json_object_iter_end
+#define json_object_iter_equal gdal_json_object_iter_equal
+#define json_object_iter_init_default gdal_json_object_iter_init_default
+#define json_object_iter_next gdal_json_object_iter_next
+#define json_object_iter_peek_name gdal_json_object_iter_peek_name
+#define json_object_iter_peek_value gdal_json_object_iter_peek_value
+#define sscanf_is_broken_test gdal_sscanf_is_broken_test
+#define json_object_from_file gdal_json_object_from_file
+#define json_object_to_file gdal_json_object_to_file
+#define json_object_to_file_ext gdal_json_object_to_file_ext
+#define json_parse_double gdal_json_parse_double
+#define json_parse_int64 gdal_json_parse_int64
+#define json_type_to_name gdal_json_type_to_name
+#define json_type_name gdal_json_type_name
+#define lh_abort gdal_lh_abort
+#define lh_char_equal gdal_lh_char_equal
+#define lh_char_hash gdal_lh_char_hash
+#define lh_kchar_table_new gdal_lh_kchar_table_new
+#define lh_kptr_table_new gdal_lh_kptr_table_new
+#define lh_ptr_equal gdal_lh_ptr_equal
+#define lh_ptr_hash gdal_lh_ptr_hash
+#define lh_table_delete gdal_lh_table_delete
+#define lh_table_delete_entry gdal_lh_table_delete_entry
+#define lh_table_free gdal_lh_table_free
+#define lh_table_insert gdal_lh_table_insert
+#define lh_table_length gdal_lh_table_length
+#define lh_table_lookup gdal_lh_table_lookup
+#define lh_table_lookup_entry gdal_lh_table_lookup_entry
+#define lh_table_lookup_ex gdal_lh_table_lookup_ex
+#define lh_table_new gdal_lh_table_new
+#define lh_table_resize gdal_lh_table_resize
+#define printbuf_extend gdal_printbuf_extend
+#define printbuf_free gdal_printbuf_free
+#define printbuf_memappend gdal_printbuf_memappend
+#define printbuf_memset gdal_printbuf_memset
+#define printbuf_new gdal_printbuf_new
+#define printbuf_reset gdal_printbuf_reset
+#define sprintbuf gdal_sprintbuf
+
+#endif /*  symbol_renames */
diff --git a/ogr/ogrsf_frmts/geojson/makefile.vc b/ogr/ogrsf_frmts/geojson/makefile.vc
index 8878556..09c999d 100644
--- a/ogr/ogrsf_frmts/geojson/makefile.vc
+++ b/ogr/ogrsf_frmts/geojson/makefile.vc
@@ -12,9 +12,10 @@ GEOJSON_OBJ = \
 	ogrgeojsonutils.obj \
 	ogrgeojsonreader.obj \
 	ogrgeojsonwriter.obj \
-	ogresrijsonreader.obj
+	ogresrijsonreader.obj \
+	ogrtopojsonreader.obj
 
-EXTRAFLAGS = -I. -I.. -I..\..
+EXTRAFLAGS = -I. -I.. -I..\.. -Ilibjson
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
@@ -24,12 +25,12 @@ EXTRAFLAGS = -I. -I.. -I..\..
 OBJ	=	$(GEOJSON_OBJ)
 
 default:	$(OBJ)
-	cd jsonc
+	cd libjson
 	$(MAKE) /f makefile.vc
 	cd ..
 	
 clean:
-	cd jsonc
+	cd libjson
 	$(MAKE) /f makefile.vc clean
 	cd ..
 	-del *.lib
diff --git a/ogr/ogrsf_frmts/geojson/ogr_geojson.h b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
index aa4aee3..4a33748 100644
--- a/ogr/ogrsf_frmts/geojson/ogr_geojson.h
+++ b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geojson.h 23662 2011-12-30 11:16:59Z rouault $
+ * $Id: ogr_geojson.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions of OGR OGRGeoJSON driver types.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -59,7 +60,6 @@ public:
     // OGRLayer Interface
     //
     OGRFeatureDefn* GetLayerDefn();
-    OGRSpatialReference* GetSpatialRef();
     
     int GetFeatureCount( int bForce = TRUE );
     void ResetReading();
@@ -72,7 +72,6 @@ public:
     // OGRGeoJSONLayer Interface
     //
     void AddFeature( OGRFeature* poFeature );
-    void SetSpatialRef( OGRSpatialReference* poSRS );
     void DetectGeometryType();
 
 private:
@@ -83,7 +82,6 @@ private:
 
     OGRGeoJSONDataSource* poDS_;
     OGRFeatureDefn* poFeatureDefn_;
-    OGRSpatialReference* poSRS_;
     CPLString sFIDColumn_;
 };
 
@@ -148,6 +146,8 @@ public:
                            OGRwkbGeometryType eGType = wkbUnknown,
                            char** papszOptions = NULL );
     int TestCapability( const char* pszCap );
+    
+    void AddLayer( OGRGeoJSONLayer* poLayer );
 
     //
     // OGRGeoJSONDataSource Interface
@@ -198,9 +198,9 @@ private:
     // Priavte utility functions
     //
     void Clear();
-    int ReadFromFile( const char* pszSource );
+    int ReadFromFile( const char* pszSource, VSILFILE* fpIn );
     int ReadFromService( const char* pszSource );
-    OGRGeoJSONLayer* LoadLayer();
+    void LoadLayers();
 };
 
 
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index 8a2c525..f33058f 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogresrijsonreader.cpp 24923 2012-09-16 09:46:59Z rouault $
+ * $Id: ogresrijsonreader.cpp 27050 2014-03-18 00:09:03Z kyle $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
@@ -7,8 +7,9 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2013, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,8 +33,7 @@
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
-#include <jsonc/json.h> // JSON-C
-#include <jsonc/json_object_private.h> // json_object_iter, complete type required
+#include <json.h> // JSON-C
 #include <ogr_api.h>
 
 /************************************************************************/
@@ -95,11 +95,10 @@ OGRErr OGRESRIJSONReader::Parse( const char* pszText )
 }
 
 /************************************************************************/
-/*                           ReadLayer()                                */
+/*                           ReadLayers()                               */
 /************************************************************************/
 
-OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
-                                                OGRGeoJSONDataSource* poDS )
+void OGRESRIJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
 {
     CPLAssert( NULL == poLayer_ );
 
@@ -107,12 +106,17 @@ OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
     {
         CPLDebug( "ESRIJSON",
                   "Missing parset ESRIJSON data. Forgot to call Parse()?" );
-        return NULL;
+        return;
     }
-        
-    poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
+
+    OGRSpatialReference* poSRS = NULL;
+    poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
+
+    poLayer_ = new OGRGeoJSONLayer( OGRGeoJSONLayer::DefaultName, poSRS,
                                     OGRESRIJSONGetGeometryType(poGJObject_),
                                     poDS );
+    if( poSRS != NULL )
+        poSRS->Release();
 
     if( !GenerateLayerDefn() )
     {
@@ -120,7 +124,7 @@ OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
             "Layer schema generation failed." );
 
         delete poLayer_;
-        return NULL;
+        return;
     }
 
     OGRGeoJSONLayer* poThisLayer = NULL;
@@ -128,18 +132,12 @@ OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
     if (poThisLayer == NULL)
     {
         delete poLayer_;
-        return NULL;
+        return;
     }
 
-    OGRSpatialReference* poSRS = NULL;
-    poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
-    if (poSRS != NULL )
-    {
-        poLayer_->SetSpatialRef( poSRS );
-        delete poSRS;
-    }
+    CPLErrorReset();
 
-    return poLayer_;
+    poDS->AddLayer(poLayer_);
 }
 
 /************************************************************************/
@@ -501,16 +499,198 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
     }
 
     double dfX, dfY;
-    if (iTypeX == json_type_double)
-        dfX = json_object_get_double( poObjX );
+    dfX = json_object_get_double( poObjX );
+    dfY = json_object_get_double( poObjY );
+
+    bool is3d = false;
+    double dfZ = 0.0;
+
+    json_object* poObjZ = OGRGeoJSONFindMemberByName( poObj, "z" );
+    if( NULL != poObjZ )
+    {
+        int iTypeZ = json_object_get_type(poObjZ);
+        if ( (json_type_double != iTypeZ) && (json_type_int != iTypeZ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
+                    json_object_to_json_string(poObjZ) );
+            return NULL;
+        }
+        is3d = true;
+        dfZ = json_object_get_double( poObjZ );
+    }
+
+    if(is3d)
+    {
+        return new OGRPoint(dfX, dfY, dfZ);
+    }
     else
-        dfX = json_object_get_int( poObjX );
-    if (iTypeY == json_type_double)
-        dfY = json_object_get_double( poObjY );
+    {
+       return new OGRPoint(dfX, dfY);
+    }
+}
+
+/************************************************************************/
+/*                     OGRESRIJSONReaderParseZM()                  */
+/************************************************************************/
+
+static int OGRESRIJSONReaderParseZM( json_object* poObj, int *bHasZ,
+                                     int *bHasM )
+{
+    CPLAssert( NULL != poObj );
+    /*
+    ** The esri geojson spec states that geometries other than point can
+    ** have the attributes hasZ and hasM.  A geometry that has a z value
+    ** implies the 3rd number in the tuple is z.  if hasM is true, but hasZ
+    ** is not, it is the M value, and is not supported in OGR.
+    */
+    int bZ, bM;
+    json_object* poObjHasZ = OGRGeoJSONFindMemberByName( poObj, "hasZ" );
+    if( poObjHasZ == NULL )
+    {
+        bZ = FALSE;
+    }
     else
-        dfY = json_object_get_int( poObjY );
+    {
+        if( json_object_get_type( poObjHasZ ) != json_type_boolean )
+        {
+            bZ = FALSE;
+        }
+        else
+        {
+            bZ = json_object_get_boolean( poObjHasZ );
+        }
+    }
 
-    return new OGRPoint(dfX, dfY);
+    json_object* poObjHasM = OGRGeoJSONFindMemberByName( poObj, "hasM" );
+    if( poObjHasM == NULL )
+    {
+        bM = FALSE;
+    }
+    else
+    {
+        if( json_object_get_type( poObjHasM ) != json_type_boolean )
+        {
+            bM = FALSE;
+        }
+        else
+        {
+            bM = json_object_get_boolean( poObjHasM );
+        }
+    }
+    if( bHasZ != NULL )
+        *bHasZ = bZ;
+    if( bHasM != NULL )
+        *bHasM = bM;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                     OGRESRIJSONReaderParseXYZMArray()                  */
+/************************************************************************/
+
+static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
+                                          double* pdfX, double* pdfY,
+                                          double* pdfZ, int* pnNumCoords)
+{
+    if (poObjCoords == NULL)
+    {
+        CPLDebug( "ESRIJSON",
+                "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        return FALSE;
+    }
+
+    if( json_type_array != json_object_get_type( poObjCoords ))
+    {
+        CPLDebug( "ESRIJSON",
+                "OGRESRIJSONReaderParseXYZMArray: got non-array object." );
+        return FALSE;
+    }
+
+    int coordDimension = json_object_array_length( poObjCoords );
+    /*
+    ** We allow 4 coordinates if M is present, but it is eventually ignored.
+    */
+    if(coordDimension < 2 || coordDimension > 4)
+    {
+        CPLDebug( "ESRIJSON",
+                "OGRESRIJSONReaderParseXYZMArray: got an unexpected array object." );
+        return FALSE;
+    }
+
+    json_object* poObjCoord;
+    int iType;
+    double dfX, dfY, dfZ = 0.0;
+
+    // Read X coordinate
+    poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
+    if (poObjCoord == NULL)
+    {
+        CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        return FALSE;
+    }
+
+    iType = json_object_get_type(poObjCoord);
+    if ( (json_type_double != iType) && (json_type_int != iType) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Invalid X coordinate. Type is not double or integer for \'%s\'.",
+                json_object_to_json_string(poObjCoord) );
+        return FALSE;
+    }
+
+    dfX = json_object_get_double( poObjCoord );
+
+    // Read Y coordinate
+    poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
+    if (poObjCoord == NULL)
+    {
+        CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        return FALSE;
+    }
+
+    iType = json_object_get_type(poObjCoord);
+    if ( (json_type_double != iType) && (json_type_int != iType) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
+                json_object_to_json_string(poObjCoord) );
+        return FALSE;
+    }
+
+    dfY = json_object_get_double( poObjCoord );
+
+    // Read Z coordinate
+    if(coordDimension > 2)
+    {
+        poObjCoord = json_object_array_get_idx( poObjCoords, 2 );
+        if (poObjCoord == NULL)
+        {
+            CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
+            return FALSE;
+        }
+
+        iType = json_object_get_type(poObjCoord);
+        if ( (json_type_double != iType) && (json_type_int != iType) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
+                    json_object_to_json_string(poObjCoord) );
+            return FALSE;
+        }
+        dfZ = json_object_get_double( poObjCoord );
+    }
+
+    if( pnNumCoords != NULL )
+        *pnNumCoords = coordDimension;
+    if( pdfX != NULL )
+        *pdfX = dfX;
+    if( pdfY != NULL )
+        *pdfY = dfY;
+    if( pdfZ != NULL )
+        *pdfZ = dfZ;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -521,6 +701,15 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
+
+    if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Failed to parse hasZ and/or hasM from geometry" );
+    }
+
     OGRLineString* poLine = NULL;
     
     json_object* poObjPaths = OGRGeoJSONFindMemberByName( poObj, "paths" );
@@ -557,78 +746,25 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
         const int nPoints = json_object_array_length( poObjPath );
         for(int i = 0; i < nPoints; i++)
         {
+            double dfX, dfY, dfZ;
+            int nNumCoords = 2;
             json_object* poObjCoords = NULL;
 
             poObjCoords = json_object_array_get_idx( poObjPath, i );
-            if (poObjCoords == NULL)
+            if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
                 delete poLine;
-                CPLDebug( "ESRIJSON",
-                        "LineString: got null object." );
                 return NULL;
             }
-            if( json_type_array != json_object_get_type( poObjCoords ) ||
-                json_object_array_length( poObjCoords ) != 2 )
-            {
-                delete poLine;
-                CPLDebug( "ESRIJSON",
-                        "LineString: got non-array object." );
-                return NULL;
-            }
-
-            json_object* poObjCoord;
-            int iType;
-            double dfX, dfY;
 
-            // Read X coordinate
-            poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
-            if (poObjCoord == NULL)
+            if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
             {
-                CPLDebug( "ESRIJSON", "LineString: got null object." );
-                delete poLine;
-                return NULL;
+                poLine->addPoint( dfX, dfY, dfZ);
             }
-
-            iType = json_object_get_type(poObjCoord);
-            if ( (json_type_double != iType) && (json_type_int != iType) )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Invalid X coordinate. Type is not double or integer for \'%s\'.",
-                        json_object_to_json_string(poObjCoord) );
-                delete poLine;
-                return NULL;
-            }
-
-            if (iType == json_type_double)
-                dfX = json_object_get_double( poObjCoord );
             else
-                dfX = json_object_get_int( poObjCoord );
-
-            // Read Y coordinate
-            poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
-            if (poObjCoord == NULL)
             {
-                CPLDebug( "ESRIJSON", "LineString: got null object." );
-                delete poLine;
-                return NULL;
-            }
-
-            iType = json_object_get_type(poObjCoord);
-            if ( (json_type_double != iType) && (json_type_int != iType) )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
-                        json_object_to_json_string(poObjCoord) );
-                delete poLine;
-                return NULL;
+                poLine->addPoint( dfX, dfY );
             }
-
-            if (iType == json_type_double)
-                dfY = json_object_get_double( poObjCoord );
-            else
-                dfY = json_object_get_int( poObjCoord );
-
-            poLine->addPoint( dfX, dfY );
         }
     }
 
@@ -643,6 +779,16 @@ OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
+
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
+
+    if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Failed to parse hasZ and/or hasM from geometry" );
+    }
+
     OGRPolygon* poPoly = NULL;
 
     json_object* poObjRings = OGRGeoJSONFindMemberByName( poObj, "rings" );
@@ -683,78 +829,25 @@ OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj)
         const int nPoints = json_object_array_length( poObjRing );
         for(int i = 0; i < nPoints; i++)
         {
+            int nNumCoords = 2;
+            double dfX, dfY, dfZ;
             json_object* poObjCoords = NULL;
 
             poObjCoords = json_object_array_get_idx( poObjRing, i );
-            if (poObjCoords == NULL)
-            {
-                delete poPoly;
-                CPLDebug( "ESRIJSON",
-                        "Polygon: got null object." );
-                return NULL;
-            }
-            if( json_type_array != json_object_get_type( poObjCoords ) ||
-                json_object_array_length( poObjCoords ) != 2 )
+            if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
                 delete poPoly;
-                CPLDebug( "ESRIJSON",
-                        "Polygon: got non-array object." );
                 return NULL;
             }
 
-            json_object* poObjCoord;
-            int iType;
-            double dfX, dfY;
-
-            // Read X coordinate
-            poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
-            if (poObjCoord == NULL)
-            {
-                CPLDebug( "ESRIJSON", "Polygon: got null object." );
-                delete poPoly;
-                return NULL;
-            }
-
-            iType = json_object_get_type(poObjCoord);
-            if ( (json_type_double != iType) && (json_type_int != iType) )
+            if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Invalid X coordinate. Type is not double or integer for \'%s\'.",
-                        json_object_to_json_string(poObjCoord) );
-                delete poPoly;
-                return NULL;
+                poLine->addPoint( dfX, dfY, dfZ);
             }
-
-            if (iType == json_type_double)
-                dfX = json_object_get_double( poObjCoord );
             else
-                dfX = json_object_get_int( poObjCoord );
-
-            // Read Y coordinate
-            poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
-            if (poObjCoord == NULL)
-            {
-                CPLDebug( "ESRIJSON", "Polygon: got null object." );
-                delete poPoly;
-                return NULL;
-            }
-
-            iType = json_object_get_type(poObjCoord);
-            if ( (json_type_double != iType) && (json_type_int != iType) )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
-                        json_object_to_json_string(poObjCoord) );
-                delete poPoly;
-                return NULL;
+                poLine->addPoint( dfX, dfY );
             }
-
-            if (iType == json_type_double)
-                dfY = json_object_get_double( poObjCoord );
-            else
-                dfY = json_object_get_int( poObjCoord );
-
-            poLine->addPoint( dfX, dfY );
         }
     }
 
@@ -769,13 +862,22 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
+
+    if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Failed to parse hasZ and/or hasM from geometry" );
+    }
+
     OGRMultiPoint* poMulti = NULL;
 
     json_object* poObjPoints = OGRGeoJSONFindMemberByName( poObj, "points" );
     if( NULL == poObjPoints )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid LineString object. "
+            "Invalid MultiPoint object. "
             "Missing \'points\' member." );
         return NULL;
     }
@@ -783,7 +885,7 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
     if( json_type_array != json_object_get_type( poObjPoints ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid LineString object. "
+            "Invalid MultiPoint object. "
             "Invalid \'points\' member." );
         return NULL;
     }
@@ -793,78 +895,25 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
     const int nPoints = json_object_array_length( poObjPoints );
     for(int i = 0; i < nPoints; i++)
     {
+        double dfX, dfY, dfZ;
+        int nNumCoords = 2;
         json_object* poObjCoords = NULL;
 
         poObjCoords = json_object_array_get_idx( poObjPoints, i );
-        if (poObjCoords == NULL)
-        {
-            delete poMulti;
-            CPLDebug( "ESRIJSON",
-                    "MultiPoint: got null object." );
-            return NULL;
-        }
-        if( json_type_array != json_object_get_type( poObjCoords ) ||
-            json_object_array_length( poObjCoords ) != 2 )
-        {
-            delete poMulti;
-            CPLDebug( "ESRIJSON",
-                    "MultiPoint: got non-array object." );
-            return NULL;
-        }
-
-        json_object* poObjCoord;
-        int iType;
-        double dfX, dfY;
-
-        // Read X coordinate
-        poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
-        if (poObjCoord == NULL)
+        if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
         {
-            CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
             delete poMulti;
             return NULL;
         }
 
-        iType = json_object_get_type(poObjCoord);
-        if ( (json_type_double != iType) && (json_type_int != iType) )
+        if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid X coordinate. Type is not double or integer for \'%s\'.",
-                    json_object_to_json_string(poObjCoord) );
-            delete poMulti;
-            return NULL;
+            poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY, dfZ) );
         }
-
-        if (iType == json_type_double)
-            dfX = json_object_get_double( poObjCoord );
         else
-            dfX = json_object_get_int( poObjCoord );
-
-        // Read Y coordinate
-        poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
-        if (poObjCoord == NULL)
         {
-            CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
-            delete poMulti;
-            return NULL;
+            poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY) );
         }
-
-        iType = json_object_get_type(poObjCoord);
-        if ( (json_type_double != iType) && (json_type_int != iType) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
-                    json_object_to_json_string(poObjCoord) );
-            delete poMulti;
-            return NULL;
-        }
-
-        if (iType == json_type_double)
-            dfY = json_object_get_double( poObjCoord );
-        else
-            dfY = json_object_get_int( poObjCoord );
-
-        poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY) );
     }
 
     return poMulti;
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
index 3845f23..46b2b4d 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsondatasource.cpp 25665 2013-02-22 16:09:22Z rouault $
+ * $Id: ogrgeojsondatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDataSource class (OGR GeoJSON Driver).
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogrgeojsonutils.h"
 #include "ogrgeojsonreader.h"
 #include <cpl_http.h>
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 #include <cstddef>
 #include <cstdlib>
 using namespace std;
@@ -88,7 +89,9 @@ int OGRGeoJSONDataSource::Open( const char* pszName )
 /* -------------------------------------------------------------------- */
     GeoJSONSourceType nSrcType;
     
-    nSrcType = GeoJSONGetSourceType( pszName );
+    VSILFILE* fp = NULL;
+
+    nSrcType = GeoJSONGetSourceType( pszName, &fp );
     if( eGeoJSONSourceService == nSrcType )
     {
         if( (strstr(pszName, "SERVICE=WFS") || strstr(pszName, "service=WFS") ||
@@ -104,7 +107,7 @@ int OGRGeoJSONDataSource::Open( const char* pszName )
     }
     else if( eGeoJSONSourceFile == nSrcType )
     {
-        if( !ReadFromFile( pszName ) )
+        if( !ReadFromFile( pszName, fp ) )
             return FALSE;
     }
     else
@@ -127,8 +130,8 @@ int OGRGeoJSONDataSource::Open( const char* pszName )
         return FALSE;
     }
 
-    OGRGeoJSONLayer* poLayer = LoadLayer();
-    if( NULL == poLayer )
+    LoadLayers();
+    if( nLayers_ == 0 )
     {
         Clear();
         
@@ -137,22 +140,6 @@ int OGRGeoJSONDataSource::Open( const char* pszName )
         return FALSE;
     }
 
-    poLayer->DetectGeometryType();
-
-    /* Return layer in readable state. */
-    poLayer->ResetReading();
-/* -------------------------------------------------------------------- */
-/*      NOTE: Currently, the driver generates only one layer per        */
-/*      single GeoJSON file, input or service request.                  */
-/* -------------------------------------------------------------------- */
-    const int nLayerIndex = 0;
-    nLayers_ = 1;
-    
-    papoLayers_ = (OGRLayer**)CPLMalloc( sizeof(OGRLayer*) * nLayers_ );
-    papoLayers_[nLayerIndex] = poLayer; 
-
-    CPLAssert( NULL != papoLayers_ );
-    CPLAssert( nLayers_ > 0 );
     return TRUE;
 }
 
@@ -180,7 +167,7 @@ int OGRGeoJSONDataSource::GetLayerCount()
 
 OGRLayer* OGRGeoJSONDataSource::GetLayer( int nLayer )
 {
-    if( 0 <= nLayer || nLayer < nLayers_ )
+    if( 0 <= nLayer && nLayer < nLayers_ )
     {
         return papoLayers_[nLayer];
     }
@@ -382,55 +369,18 @@ void OGRGeoJSONDataSource::Clear()
 /*                           ReadFromFile()                             */
 /************************************************************************/
 
-int OGRGeoJSONDataSource::ReadFromFile( const char* pszSource )
+int OGRGeoJSONDataSource::ReadFromFile( const char* pszSource, VSILFILE* fpIn )
 {
-    CPLAssert( NULL == pszGeoData_ );
-
-    if( NULL == pszSource )
-    {
-        CPLDebug( "GeoJSON", "Input file path is null" );
-        return FALSE;
-    }
-
-    VSILFILE* fp = NULL;
-    fp = VSIFOpenL( pszSource, "rb" );
-    if( NULL == fp )
+    GByte* pabyOut = NULL;
+    if( !VSIIngestFile( fpIn, pszSource, &pabyOut, NULL, -1) )
     {
-        CPLDebug( "GeoJSON", "Failed to open input file '%s'", pszSource );
-        return FALSE;
-    }
-
-    vsi_l_offset nDataLen = 0;
-
-    VSIFSeekL( fp, 0, SEEK_END );
-    nDataLen = VSIFTellL( fp );
-
-    // With "large" VSI I/O API we can read data chunks larger than VSIMalloc
-    // could allocate. Catch it here.
-    if ( nDataLen > (vsi_l_offset)(size_t)nDataLen )
-    {
-        CPLDebug( "GeoJSON", "Input file too large to be opened" );
-        VSIFCloseL( fp );
-        return FALSE;
-    }
-
-    VSIFSeekL( fp, 0, SEEK_SET );
-
-    pszGeoData_ = (char*)VSIMalloc((size_t)(nDataLen + 1));
-    if( NULL == pszGeoData_ )
-    {
-        VSIFCloseL(fp);
-        return FALSE;
-    }
-
-    pszGeoData_[nDataLen] = '\0';
-    if( ( nDataLen != VSIFReadL( pszGeoData_, 1, (size_t)nDataLen, fp ) ) )
-    {
-        Clear();
-        VSIFCloseL( fp );
+        if( fpIn != NULL )
+            VSIFCloseL(fpIn);
         return FALSE;
     }
-    VSIFCloseL( fp );
+    if( fpIn != NULL )
+        VSIFCloseL(fpIn);
+    pszGeoData_ = (char*) pabyOut;
 
     pszName_ = CPLStrdup( pszSource );
 
@@ -513,44 +463,75 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 }
 
 /************************************************************************/
-/*                           LoadLayer()                                */
+/*                           LoadLayers()                               */
 /************************************************************************/
 
-OGRGeoJSONLayer* OGRGeoJSONDataSource::LoadLayer()
+void OGRGeoJSONDataSource::LoadLayers()
 {
     if( NULL == pszGeoData_ )
     {
         CPLError( CE_Failure, CPLE_ObjectNull,
                   "GeoJSON data buffer empty" );
-        return NULL;
+        return;
     }
+    
+    const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" };
+    for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
+    {
+        if( strncmp(pszGeoData_, apszPrefix[iP], strlen(apszPrefix[iP])) == 0 )
+        {
+            size_t nDataLen = strlen(pszGeoData_);
+            memmove( pszGeoData_, pszGeoData_ + strlen(apszPrefix[iP]),
+                    nDataLen - strlen(apszPrefix[iP]) );
+            size_t i = nDataLen - strlen(apszPrefix[iP]);
+            pszGeoData_[i] = '\0';
+            while( i > 0 && pszGeoData_[i] != ')' )
+            {
+                i --;
+            }
+            pszGeoData_[i] = '\0';
+        }
+    }
+
 
     if ( !GeoJSONIsObject( pszGeoData_) )
     {
         CPLDebug( "GeoJSON", "No valid GeoJSON data found in source '%s'", pszName_ );
-        return NULL;
+        return;
     }
 
     OGRErr err = OGRERR_NONE;
-    OGRGeoJSONLayer* poLayer = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Is it ESRI Feature Service data ?                               */
 /* -------------------------------------------------------------------- */
     if ( strstr(pszGeoData_, "esriGeometry") ||
-         strstr(pszGeoData_, "esriFieldTypeOID") )
+         strstr(pszGeoData_, "esriFieldType") )
     {
         OGRESRIJSONReader reader;
         err = reader.Parse( pszGeoData_ );
         if( OGRERR_NONE == err )
         {
-            // TODO: Think about better name selection
-            poLayer = reader.ReadLayer( OGRGeoJSONLayer::DefaultName, this );
+            reader.ReadLayers( this );
         }
+        return;
+    }
 
-        return poLayer;
+/* -------------------------------------------------------------------- */
+/*      Is it TopoJSON data ?                                           */
+/* -------------------------------------------------------------------- */
+    if ( strstr(pszGeoData_, "\"type\"") &&
+         strstr(pszGeoData_, "\"Topology\"")  )
+    {
+        OGRTopoJSONReader reader;
+        err = reader.Parse( pszGeoData_ );
+        if( OGRERR_NONE == err )
+        {
+            reader.ReadLayers( this );
+        }
+        return;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Configure GeoJSON format translator.                            */
 /* -------------------------------------------------------------------- */
@@ -574,9 +555,25 @@ OGRGeoJSONLayer* OGRGeoJSONDataSource::LoadLayer()
     err = reader.Parse( pszGeoData_ );
     if( OGRERR_NONE == err )
     {
-        // TODO: Think about better name selection
-        poLayer = reader.ReadLayer( OGRGeoJSONLayer::DefaultName, this );
+        reader.ReadLayers( this );
     }
 
-    return poLayer;
+    return;
+}
+
+/************************************************************************/
+/*                            AddLayer()                                */
+/************************************************************************/
+
+void OGRGeoJSONDataSource::AddLayer( OGRGeoJSONLayer* poLayer )
+{
+
+    poLayer->DetectGeometryType();
+
+    /* Return layer in readable state. */
+    poLayer->ResetReading();
+
+    papoLayers_ = (OGRLayer**)CPLRealloc( papoLayers_, sizeof(OGRLayer*) * (nLayers_ + 1));
+    papoLayers_[nLayers_] = poLayer; 
+    nLayers_ ++;
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
index f832fbd..ad2b13b 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonlayer.cpp 23866 2012-02-01 23:51:11Z warmerdam $
+ * $Id: ogrgeojsonlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,7 +28,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 #include <algorithm> // for_each, find_if
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 #include "ogr_geojson.h"
 
 /* Remove annoying warnings Microsoft Visual C++ */
@@ -51,18 +52,15 @@ OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
                                   OGRSpatialReference* poSRSIn,
                                   OGRwkbGeometryType eGType,
                                   OGRGeoJSONDataSource* poDS )
-    : iterCurrent_( seqFeatures_.end() ), poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), poSRS_( NULL )
+    : iterCurrent_( seqFeatures_.end() ), poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) )
 {
     CPLAssert( NULL != poDS_ );
     CPLAssert( NULL != poFeatureDefn_ );
     
     poFeatureDefn_->Reference();
     poFeatureDefn_->SetGeomType( eGType );
-
-    if( NULL != poSRSIn )
-    {
-        SetSpatialRef( poSRSIn );
-    }
+    if( poFeatureDefn_->GetGeomFieldCount() != 0 )
+        poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRSIn);
 }
 
 /************************************************************************/
@@ -78,11 +76,6 @@ OGRGeoJSONLayer::~OGRGeoJSONLayer()
     {
         poFeatureDefn_->Release();
     }
-
-    if( NULL != poSRS_ )
-    {
-        poSRS_->Release();   
-    }
 }
 
 /************************************************************************/
@@ -95,37 +88,6 @@ OGRFeatureDefn* OGRGeoJSONLayer::GetLayerDefn()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef                              */
-/************************************************************************/
-
-OGRSpatialReference* OGRGeoJSONLayer::GetSpatialRef()
-{
-    return poSRS_;
-}
-
-/************************************************************************/
-/*                           SetSpatialRef                              */
-/************************************************************************/
-
-void OGRGeoJSONLayer::SetSpatialRef( OGRSpatialReference* poSRSIn )
-{
-    if( NULL == poSRSIn )
-    {
-        poSRS_ = NULL;
-        // poSRS_ = new OGRSpatialReference();
-        // if( OGRERR_NONE != poSRS_->importFromEPSG( 4326 ) )
-        // {
-        //     delete poSRS_;
-        //     poSRS_ = NULL;
-        // }
-    }
-    else
-    {
-        poSRS_ = poSRSIn->Clone(); 
-    }
-}
-
-/************************************************************************/
 /*                           GetFeatureCount                            */
 /************************************************************************/
 
@@ -166,9 +128,9 @@ OGRFeature* OGRGeoJSONLayer::GetNextFeature()
             OGRFeature* poFeatureCopy = poFeature->Clone();
             CPLAssert( NULL != poFeatureCopy );
 
-            if (poFeatureCopy->GetGeometryRef() != NULL && poSRS_ != NULL)
+            if (poFeatureCopy->GetGeometryRef() != NULL && GetSpatialRef() != NULL)
             {
-                poFeatureCopy->GetGeometryRef()->assignSpatialReference( poSRS_ );
+                poFeatureCopy->GetGeometryRef()->assignSpatialReference( GetSpatialRef() );
             }
 
             return poFeatureCopy;
@@ -232,7 +194,7 @@ void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
 
         // TODO - mlokot: We need to redesign creation of FID column
         int nField = poNewFeature->GetFieldIndex( DefaultFIDColumn );
-        if( -1 != nField )
+        if( -1 != nField && GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTInteger )
         {
             poNewFeature->SetField( nField, nFID );
         }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
index 57e306e..bd21b03 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.cpp 25870 2013-04-06 20:35:40Z warmerdam $
+ * $Id: ogrgeojsonreader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,8 +30,7 @@
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
-#include <jsonc/json.h> // JSON-C
-#include <jsonc/json_object_private.h> // json_object_iter, complete type required
+#include <json.h> // JSON-C
 #include <ogr_api.h>
 
 /************************************************************************/
@@ -38,7 +38,7 @@
 /************************************************************************/
 
 OGRGeoJSONReader::OGRGeoJSONReader()
-    : poGJObject_( NULL ), poLayer_( NULL ),
+    : poGJObject_( NULL ),
         bGeometryPreserve_( true ),
         bAttributesSkip_( false ),
         bFlattenGeocouchSpatiallistFormat (-1), bFoundId (false), bFoundRev(false), bFoundTypeFeature(false), bIsGeocouchSpatiallistFormat(false)
@@ -58,7 +58,6 @@ OGRGeoJSONReader::~OGRGeoJSONReader()
     }
 
     poGJObject_ = NULL;
-    poLayer_ = NULL;
 }
 
 /************************************************************************/
@@ -95,38 +94,85 @@ OGRErr OGRGeoJSONReader::Parse( const char* pszText )
 }
 
 /************************************************************************/
-/*                           ReadLayer                                  */
+/*                           ReadLayers                                 */
 /************************************************************************/
 
-OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
-                                              OGRGeoJSONDataSource* poDS )
+void OGRGeoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
 {
-    CPLAssert( NULL == poLayer_ );
-
     if( NULL == poGJObject_ )
     {
         CPLDebug( "GeoJSON",
                   "Missing parset GeoJSON data. Forgot to call Parse()?" );
-        return NULL;
+        return;
     }
-        
-    poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
+
+    ReadLayer(poDS, OGRGeoJSONLayer::DefaultName, poGJObject_);
+}
+
+/************************************************************************/
+/*                           ReadLayer                                  */
+/************************************************************************/
+
+void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
+                                  const char* pszName,
+                                  json_object* poObj )
+{
+    GeoJSONObject::Type objType = OGRGeoJSONGetType( poObj );
+    if( objType == GeoJSONObject::eUnknown )
+    {
+        /* Check if the object contains key:value pairs where value */
+        /* is a standard GeoJSON object. In which case, use key as the layer */
+        /* name */
+        if( json_type_object == json_object_get_type( poObj ) )
+        {
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            json_object_object_foreachC( poObj, it )
+            {
+                objType = OGRGeoJSONGetType( it.val );
+                if( objType != GeoJSONObject::eUnknown )
+                    ReadLayer(poDS, it.key, it.val);
+            }
+        }
+
+        /*CPLError( CE_Failure, CPLE_AppDefined,
+            "Unrecognized GeoJSON structure." );*/
+
+        return;
+    }
+
+    OGRSpatialReference* poSRS = NULL;
+    poSRS = OGRGeoJSONReadSpatialReference( poObj );
+    if (poSRS == NULL ) {
+        // If there is none defined, we use 4326
+        poSRS = new OGRSpatialReference();
+        if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+    OGRGeoJSONLayer* poLayer = new OGRGeoJSONLayer( pszName, poSRS,
                                     OGRGeoJSONLayer::DefaultGeometryType,
                                     poDS );
+    if( poSRS != NULL )
+        poSRS->Release();
 
-    if( !GenerateLayerDefn() )
+    if( !GenerateLayerDefn(poLayer, poObj) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
             "Layer schema generation failed." );
 
-        delete poLayer_;
-        return NULL;
+        delete poLayer;
+        return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Translate single geometry-only Feature object.                  */
 /* -------------------------------------------------------------------- */
-    GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
 
     if( GeoJSONObject::ePoint == objType
         || GeoJSONObject::eMultiPoint == objType
@@ -137,13 +183,13 @@ OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
         || GeoJSONObject::eGeometryCollection == objType )
     {
         OGRGeometry* poGeometry = NULL;
-        poGeometry = ReadGeometry( poGJObject_ );
-        if( !AddFeature( poGeometry ) )
+        poGeometry = ReadGeometry( poObj );
+        if( !AddFeature( poLayer, poGeometry ) )
         {
             CPLDebug( "GeoJSON",
                       "Translation of single geometry failed." );
-            delete poLayer_;
-            return NULL;
+            delete poLayer;
+            return;
         }
     }
 /* -------------------------------------------------------------------- */
@@ -152,14 +198,14 @@ OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
     else if( GeoJSONObject::eFeature == objType )
     {
         OGRFeature* poFeature = NULL;
-        poFeature = ReadFeature( poGJObject_ );
-        if( !AddFeature( poFeature ) )
+        poFeature = ReadFeature( poLayer, poObj );
+        if( !AddFeature( poLayer, poFeature ) )
         {
             CPLDebug( "GeoJSON",
                       "Translation of single feature failed." );
 
-            delete poLayer_;
-            return NULL;
+            delete poLayer;
+            return;
         }
     }
 /* -------------------------------------------------------------------- */
@@ -167,42 +213,18 @@ OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
 /* -------------------------------------------------------------------- */
     else if( GeoJSONObject::eFeatureCollection == objType )
     {
-        OGRGeoJSONLayer* poThisLayer = NULL;
-        poThisLayer = ReadFeatureCollection( poGJObject_ );
-        CPLAssert( poLayer_ == poThisLayer );
+        ReadFeatureCollection( poLayer, poObj );
     }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Unrecognized GeoJSON structure." );
 
-        delete poLayer_;
-        return NULL;
-    }
+    CPLErrorReset();
 
-    OGRSpatialReference* poSRS = NULL;
-    poSRS = OGRGeoJSONReadSpatialReference( poGJObject_ );
-    if (poSRS == NULL ) {
-        // If there is none defined, we use 4326
-        poSRS = new OGRSpatialReference();
-        if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
-        {
-            delete poSRS;
-            poSRS = NULL;
-        }
-        poLayer_->SetSpatialRef( poSRS );
-        delete poSRS;
-    }
-    else {
-        poLayer_->SetSpatialRef( poSRS );
-        delete poSRS;
-    }
-
-    // TODO: FeatureCollection
-
-    return poLayer_;
+    poDS->AddLayer(poLayer);
 }
 
+/************************************************************************/
+/*                    OGRGeoJSONReadSpatialReference                    */
+/************************************************************************/
+
 OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
     
 /* -------------------------------------------------------------------- */
@@ -339,11 +361,11 @@ void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
 /*                         GenerateLayerDefn()                          */
 /************************************************************************/
 
-bool OGRGeoJSONReader::GenerateLayerDefn()
+bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object* poGJObject )
 {
-    CPLAssert( NULL != poGJObject_ );
-    CPLAssert( NULL != poLayer_->GetLayerDefn() );
-    CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
+    CPLAssert( NULL != poGJObject );
+    CPLAssert( NULL != poLayer->GetLayerDefn() );
+    CPLAssert( 0 == poLayer->GetLayerDefn()->GetFieldCount() );
 
     bool bSuccess = true;
 
@@ -353,15 +375,15 @@ bool OGRGeoJSONReader::GenerateLayerDefn()
 /* -------------------------------------------------------------------- */
 /*      Scan all features and generate layer definition.                */
 /* -------------------------------------------------------------------- */
-    GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
+    GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject );
     if( GeoJSONObject::eFeature == objType )
     {
-        bSuccess = GenerateFeatureDefn( poGJObject_ );
+        bSuccess = GenerateFeatureDefn( poLayer, poGJObject );
     }
     else if( GeoJSONObject::eFeatureCollection == objType )
     {
         json_object* poObjFeatures = NULL;
-        poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "features" );
+        poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject, "features" );
         if( NULL != poObjFeatures
             && json_type_array == json_object_get_type( poObjFeatures ) )
         {
@@ -370,7 +392,7 @@ bool OGRGeoJSONReader::GenerateLayerDefn()
             for( int i = 0; i < nFeatures; ++i )
             {
                 poObjFeature = json_object_array_get_idx( poObjFeatures, i );
-                if( !GenerateFeatureDefn( poObjFeature ) )
+                if( !GenerateFeatureDefn( poLayer, poObjFeature ) )
                 {
                     CPLDebug( "GeoJSON", "Create feature schema failure." );
                     bSuccess = false;
@@ -389,7 +411,7 @@ bool OGRGeoJSONReader::GenerateLayerDefn()
 /* -------------------------------------------------------------------- */
 /*      Validate and add FID column if necessary.                       */
 /* -------------------------------------------------------------------- */
-    OGRFeatureDefn* poLayerDefn = poLayer_->GetLayerDefn();
+    OGRFeatureDefn* poLayerDefn = poLayer->GetLayerDefn();
     CPLAssert( NULL != poLayerDefn );
 
     bool bHasFID = false;
@@ -400,7 +422,7 @@ bool OGRGeoJSONReader::GenerateLayerDefn()
         if( EQUAL( poDefn->GetNameRef(), OGRGeoJSONLayer::DefaultFIDColumn )
             && OFTInteger == poDefn->GetType() )
         {
-            poLayer_->SetFIDColumn( poDefn->GetNameRef() );
+            poLayer->SetFIDColumn( poDefn->GetNameRef() );
             bHasFID = true;
             break;
         }
@@ -424,9 +446,9 @@ bool OGRGeoJSONReader::GenerateLayerDefn()
 /************************************************************************/
 /*                        GenerateFeatureDefn()                         */
 /************************************************************************/
-bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
+bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_object* poObj )
 {
-    OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
+    OGRFeatureDefn* poDefn = poLayer->GetLayerDefn();
     CPLAssert( NULL != poDefn );
 
     bool bSuccess = false;
@@ -478,7 +500,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
                     {
                         poDefn->DeleteFieldDefn(poDefn->GetFieldIndex("type"));
                         bIsGeocouchSpatiallistFormat = true;
-                        return GenerateFeatureDefn(poObj);
+                        return GenerateFeatureDefn(poLayer, poObj);
                     }
                 }
 
@@ -493,7 +515,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
                 if( eType == OFTInteger )
                 {
                     OGRFieldType eNewType = GeoJSONPropertyToFieldType( it.val );
-                    if( eNewType == OFTReal )
+                    if( eNewType == OFTReal || eNewType == OFTString )
                         poFDefn->SetType(eNewType);
                 }
             }
@@ -503,9 +525,31 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poObj, it )
+        {
+            if( strcmp(it.key, "type") != 0 &&
+                strcmp(it.key, "geometry") != 0 &&
+                strcmp(it.key, "centroid") != 0 &&
+                strcmp(it.key, "bbox") != 0 &&
+                strcmp(it.key, "center") != 0 )
+            {
+                int nFldIndex = poDefn->GetFieldIndex( it.key );
+                if( -1 == nFldIndex )
+                {
+                    OGRFieldDefn fldDefn( it.key, OFTString );
+                    poDefn->AddFieldDefn( &fldDefn );
+                }
+            }
+        }
+
+        bSuccess = true; // SUCCESS
+        /*CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid Feature object. "
-                  "Missing \'properties\' member." );
+                  "Missing \'properties\' member." );*/
     }
 
     return bSuccess;
@@ -515,7 +559,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
 /*                           AddFeature                                 */
 /************************************************************************/
 
-bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
+bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeometry )
 {
     bool bAdded = false;
 
@@ -525,10 +569,10 @@ bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
     if( NULL != poGeometry )
     {
         OGRFeature* poFeature = NULL;
-        poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
+        poFeature = new OGRFeature( poLayer->GetLayerDefn() );
         poFeature->SetGeometryDirectly( poGeometry );
 
-        bAdded = AddFeature( poFeature );
+        bAdded = AddFeature( poLayer, poFeature );
     }
     
     return bAdded;
@@ -538,13 +582,13 @@ bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
 /*                           AddFeature                                 */
 /************************************************************************/
 
-bool OGRGeoJSONReader::AddFeature( OGRFeature* poFeature )
+bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature )
 {
     bool bAdded = false;
   
     if( NULL != poFeature )
     {
-        poLayer_->AddFeature( poFeature );
+        poLayer->AddFeature( poFeature );
         bAdded = true;
         delete poFeature;
     }
@@ -588,13 +632,12 @@ OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
 /*                           ReadFeature()                              */
 /************************************************************************/
 
-OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
+OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object* poObj )
 {
     CPLAssert( NULL != poObj );
-    CPLAssert( NULL != poLayer_ );
 
     OGRFeature* poFeature = NULL;
-    poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
+    poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
 /* -------------------------------------------------------------------- */
 /*      Translate GeoJSON "properties" object to feature attributes.    */
@@ -646,7 +689,7 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
                 poFeature->SetField( nField, json_object_get_int(it.val) );
 				
                 /* Check if FID available and set correct value. */
-                if( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
+                if( EQUAL( it.key, poLayer->GetFIDColumn() ) )
                     poFeature->SetFID( json_object_get_int(it.val) );
             }
             else if( OFTReal == eType )
@@ -710,6 +753,22 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
         }
     }
 
+    if( !bAttributesSkip_ && NULL == poObjProps )
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poObj, it )
+        {
+            int nFldIndex = poFeature->GetFieldIndex(it.key);
+            if( nFldIndex >= 0 )
+            {
+                poFeature->SetField(nFldIndex, json_object_get_string(it.val) );
+            }
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      If FID not set, try to use feature-level ID if available        */
 /*      and of integral type. Otherwise, leave unset (-1) then index    */
@@ -720,11 +779,11 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
         json_object* poObjId = NULL;
         poObjId = OGRGeoJSONFindMemberByName( poObj, OGRGeoJSONLayer::DefaultFIDColumn );
         if( NULL != poObjId
-            && EQUAL( OGRGeoJSONLayer::DefaultFIDColumn, poLayer_->GetFIDColumn() )
+            && EQUAL( OGRGeoJSONLayer::DefaultFIDColumn, poLayer->GetFIDColumn() )
             && OFTInteger == GeoJSONPropertyToFieldType( poObjId ) )
         {
             poFeature->SetFID( json_object_get_int( poObjId ) );
-            int nField = poFeature->GetFieldIndex( poLayer_->GetFIDColumn() );
+            int nField = poFeature->GetFieldIndex( poLayer->GetFIDColumn() );
             if( -1 != nField )
                 poFeature->SetField( nField, (int) poFeature->GetFID() );
         }
@@ -786,11 +845,9 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
 /*                           ReadFeatureCollection()                    */
 /************************************************************************/
 
-OGRGeoJSONLayer*
-OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
+void
+OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object* poObj )
 {
-    CPLAssert( NULL != poLayer_ );
-
     json_object* poObjFeatures = NULL;
     poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
     if( NULL == poObjFeatures )
@@ -798,7 +855,7 @@ OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid FeatureCollection object. "
                   "Missing \'features\' member." );
-        return NULL;
+        return;
     }
 
     if( json_type_array == json_object_get_type( poObjFeatures ) )
@@ -811,17 +868,12 @@ OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
         for( int i = 0; i < nFeatures; ++i )
         {
             poObjFeature = json_object_array_get_idx( poObjFeatures, i );
-            poFeature = OGRGeoJSONReader::ReadFeature( poObjFeature );
-            bAdded = AddFeature( poFeature );
+            poFeature = ReadFeature( poLayer, poObjFeature );
+            bAdded = AddFeature( poLayer, poFeature );
             //CPLAssert( bAdded );
         }
         //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     }
-
-    // We're returning class member to follow the same pattern of
-    // Read* functions call convention.
-    CPLAssert( NULL != poLayer_ );
-    return poLayer_;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
index 7ea8af2..7c2c26b 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.h 23325 2011-11-05 17:19:38Z rouault $
+ * $Id: ogrgeojsonreader.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #define OGR_GEOJSONREADER_H_INCLUDED
 
 #include <ogr_core.h>
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 
 /************************************************************************/
 /*                         FORWARD DECLARATIONS                         */
@@ -94,12 +95,15 @@ public:
     void SetSkipAttributes( bool bSkip );
 
     OGRErr Parse( const char* pszText );
-    OGRGeoJSONLayer* ReadLayer( const char* pszName, OGRGeoJSONDataSource* poDS );
+    void ReadLayers( OGRGeoJSONDataSource* poDS );
+    void ReadLayer( OGRGeoJSONDataSource* poDS,
+                    const char* pszName,
+                    json_object* poObj );
 
 private:
 
     json_object* poGJObject_;
-    OGRGeoJSONLayer* poLayer_;
+
     bool bGeometryPreserve_;
     bool bAttributesSkip_;
 
@@ -115,14 +119,14 @@ private:
     //
     // Translation utilities.
     //
-    bool GenerateLayerDefn();
-    bool GenerateFeatureDefn( json_object* poObj );
-    bool AddFeature( OGRGeometry* poGeometry );
-    bool AddFeature( OGRFeature* poFeature );
+    bool GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object* poGJObject );
+    bool GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_object* poObj );
+    bool AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeometry );
+    bool AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature );
 
     OGRGeometry* ReadGeometry( json_object* poObj );
-    OGRFeature* ReadFeature( json_object* poObj );
-    OGRGeoJSONLayer* ReadFeatureCollection( json_object* poObj );
+    OGRFeature* ReadFeature( OGRGeoJSONLayer* poLayer, json_object* poObj );
+    void ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object* poObj );
 };
 
 /************************************************************************/
@@ -162,7 +166,7 @@ public:
     ~OGRESRIJSONReader();
 
     OGRErr Parse( const char* pszText );
-    OGRGeoJSONLayer* ReadLayer( const char* pszName, OGRGeoJSONDataSource* poDS );
+    void ReadLayers( OGRGeoJSONDataSource* poDS );
 
 private:
 
@@ -194,4 +198,29 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj);
 OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj);
 OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj);
 
+/************************************************************************/
+/*                          OGRTopoJSONReader                           */
+/************************************************************************/
+
+class OGRTopoJSONReader
+{
+public:
+
+    OGRTopoJSONReader();
+    ~OGRTopoJSONReader();
+
+    OGRErr Parse( const char* pszText );
+    void ReadLayers( OGRGeoJSONDataSource* poDS );
+
+private:
+
+    json_object* poGJObject_;
+
+    //
+    // Copy operations not supported.
+    //
+    OGRTopoJSONReader( OGRTopoJSONReader const& );
+    OGRTopoJSONReader& operator=( OGRTopoJSONReader const& );
+};
+
 #endif /* OGR_GEOJSONUTILS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
index 2520eea..a86e36c 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.cpp 23293 2011-10-30 11:11:39Z rouault $
+ * $Id: ogrgeojsonutils.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of private utilities used within OGR GeoJSON Driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include <cpl_port.h>
 #include <cpl_conv.h>
 #include <ogr_geometry.h>
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 
 /************************************************************************/
 /*                           GeoJSONIsObject()                          */
@@ -47,17 +48,32 @@ int GeoJSONIsObject( const char* pszText )
     while( *pszText != '\0' && isspace( (unsigned char)*pszText ) )
         pszText++;
 
-    if( EQUALN( pszText, "{", 1) )
-        return TRUE;
+    const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" };
+    for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
+    {
+        if( strncmp(pszText, apszPrefix[iP], strlen(apszPrefix[iP])) == 0 )
+        {
+            pszText += strlen(apszPrefix[iP]);
+            break;
+        }
+    }
 
-    return FALSE;
+    if( *pszText != '{' )
+        return FALSE;
+
+    return ((strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"coordinates\"") != NULL)
+        || (strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"Topology\"") != NULL) 
+        || strstr(pszText, "\"FeatureCollection\"") != NULL
+        || strstr(pszText, "\"Feature\"") != NULL
+        || (strstr(pszText, "\"geometryType\"") != NULL && strstr(pszText, "\"esriGeometry") != NULL));
 }
 
 /************************************************************************/
 /*                           GeoJSONFileIsObject()                      */
 /************************************************************************/
 
-int GeoJSONFileIsObject( const char* pszSource ) 
+static
+int GeoJSONFileIsObject( const char* pszSource, VSILFILE** pfp ) 
 { 
     CPLAssert( NULL != pszSource ); 
  
@@ -88,38 +104,32 @@ int GeoJSONFileIsObject( const char* pszSource )
         VSIFCloseL( fp ); 
         CPLFree( pszGeoData ); 
         return FALSE; 
-    } 
-    VSIFCloseL( fp ); 
-    
-    char* pszIter = pszGeoData;
-    while( *pszIter != '\0' && isspace( (unsigned char)*pszIter ) )
-        pszIter++;
+    }
 
-    if( *pszIter != '{' )
+    if( !GeoJSONIsObject(pszGeoData) )
     {
         CPLFree( pszGeoData ); 
+        VSIFCloseL( fp ); 
         return FALSE;
     }
 
-    int bRet = FALSE; 
+    *pfp = fp;
 
-    if ((strstr(pszGeoData, "\"type\"") != NULL && strstr(pszGeoData, "\"coordinates\"") != NULL) 
-        || strstr(pszGeoData, "\"FeatureCollection\"") != NULL
-        || (strstr(pszGeoData, "\"geometryType\"") != NULL && strstr(pszGeoData, "\"esriGeometry") != NULL)) 
-        bRet = TRUE; 
-     
     CPLFree( pszGeoData ); 
-    return bRet; 
+
+    return TRUE; 
 } 
 
 /************************************************************************/
 /*                           GeoJSONGetSourceType()                     */
 /************************************************************************/
 
-GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource )
+GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource, VSILFILE** pfp )
 {
     GeoJSONSourceType srcType = eGeoJSONSourceUnknown;
 
+    *pfp = NULL;
+
     // NOTE: Sometimes URL ends with .geojson token, for example
     //       http://example/path/2232.geojson
     //       It's important to test beginning of source first.
@@ -129,6 +139,7 @@ GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource )
     }
     else if( EQUAL( CPLGetExtension( pszSource ), "geojson" )
              || EQUAL( CPLGetExtension( pszSource ), "json" )
+             || EQUAL( CPLGetExtension( pszSource ), "topojson" )
              || ((EQUALN( pszSource, "/vsigzip/", 9) || EQUALN( pszSource, "/vsizip/", 8)) &&
                  (strstr( pszSource, ".json") || strstr( pszSource, ".JSON") ||
                   strstr( pszSource, ".geojson") || strstr( pszSource, ".GEOJSON")) ))
@@ -139,7 +150,7 @@ GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource )
     {
         srcType = eGeoJSONSourceText;
     }
-    else if( GeoJSONFileIsObject( pszSource ) )
+    else if( GeoJSONFileIsObject( pszSource, pfp ) )
     {
         srcType = eGeoJSONSourceFile;
     }
@@ -169,6 +180,9 @@ GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource )
 /*                           GeoJSONPropertyToFieldType()               */
 /************************************************************************/
 
+#define MY_INT64_MAX ((((GIntBig)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
+#define MY_INT64_MIN ((((GIntBig)0x80000000) << 32))
+
 OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject )
 {
     if (poObject == NULL) { return OFTString; }
@@ -180,7 +194,38 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject )
     else if( json_type_double == type )
         return OFTReal;
     else if( json_type_int == type )
-        return OFTInteger;
+    {
+        GIntBig nVal = json_object_get_int64(poObject);
+        if( nVal == MY_INT64_MIN || nVal == MY_INT64_MAX )
+        {
+            static int bWarned = FALSE;
+            if( !bWarned )
+            {
+                bWarned = TRUE;
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Integer values ranging out of 64bit integer range "
+                         "have been found. Will be clamped to INT64_MIN/INT64_MAX");
+            }
+            return OFTString;
+        }
+        // FIXME when we have 64bit integer
+        if( nVal != (int) nVal )
+        {
+            static int bWarned = FALSE;
+            if( !bWarned )
+            {
+                bWarned = TRUE;
+                CPLDebug("GeoJSON",
+                         "64b-bit integer have been found. Will be reported as "
+                         "strings");
+            }
+            return OFTString;
+        }
+        else
+        {
+            return OFTInteger;
+        }
+    }
     else if( json_type_string == type )
         return OFTString;
     else if( json_type_array == type )
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
index fa03769..7cd1707 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.h 19489 2010-04-21 21:39:05Z rouault $
+ * $Id: ogrgeojsonutils.h 26296 2013-08-11 09:30:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities within OGR OGRGeoJSON Driver.
@@ -30,25 +30,12 @@
 #define OGR_GEOJSONUTILS_H_INCLUDED
 
 #include <ogr_core.h>
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
+#include "cpl_vsi.h"
 
 class OGRGeometry;
 
 /************************************************************************/
-/*                           mloskot_deleter functor                    */
-/************************************************************************/
-
-template <typename T>
-struct mloskot_deleter
-{
-    void operator()(T*& ptr)
-    {
-        delete ptr;
-        ptr = 0;
-    }
-};
-
-/************************************************************************/
 /*                           GeoJSONSourceType                          */
 /************************************************************************/
 
@@ -60,7 +47,7 @@ enum GeoJSONSourceType
     eGeoJSONSourceService
 };
 
-GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource );
+GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource, VSILFILE** pfp );
 
 /************************************************************************/
 /*                           GeoJSONProtocolType                        */
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
index 52c91b4..2575d30 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeojsonwritelayer.cpp 23663 2011-12-30 11:17:23Z rouault $
+ * $Id: ogrgeojsonwritelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONWriteLayer class (OGR GeoJSON Driver).
  * Author:   Mateusz Loskot, mateusz at loskot.net
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2007, Mateusz Loskot
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
index 4b1525d..2e661cd 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.cpp 22490 2011-06-03 10:26:47Z rouault $
+ * $Id: ogrgeojsonwriter.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of GeoJSON writer utilities (OGR GeoJSON Driver).
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,8 +30,11 @@
 #include "ogrgeojsonwriter.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
+#include <json_object_private.h>
+#include <printbuf.h>
 #include <ogr_api.h>
+#include <ogr_p.h>
 
 /************************************************************************/
 /*                           OGRGeoJSONWriteFeature                     */
@@ -311,6 +315,11 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision
     
     json_object* poObjRing = NULL;
     poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
+    if( poObjRing == NULL )
+    {
+        json_object_put(poObj);
+        return NULL;
+    }
     json_object_array_add( poObj, poObjRing );
 
     /* Interior rings. */
@@ -322,6 +331,11 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision
             continue;
 
         poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
+        if( poObjRing == NULL )
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
 
         json_object_array_add( poObj, poObjRing );
     }
@@ -349,6 +363,11 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPre
 
         json_object* poObjPoint = NULL;
         poObjPoint = OGRGeoJSONWritePoint( poPoint, nCoordPrecision );
+        if( poObjPoint == NULL )
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
 
         json_object_array_add( poObj, poObjPoint );
     }
@@ -376,6 +395,11 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int
 
         json_object* poObjLine = NULL;
         poObjLine = OGRGeoJSONWriteLineString( poLine, nCoordPrecision );
+        if( poObjLine == NULL )
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
         
         json_object_array_add( poObj, poObjLine );
     }
@@ -403,6 +427,11 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoor
 
         json_object* poObjPoly = NULL;
         poObjPoly = OGRGeoJSONWritePolygon( poPoly, nCoordPrecision );
+        if( poObjPoly == NULL )
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
         
         json_object_array_add( poObj, poObjPoly );
     }
@@ -429,6 +458,11 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
         
         json_object* poObjGeom = NULL;
         poObjGeom = OGRGeoJSONWriteGeometry( poGeom, nCoordPrecision );
+        if( poGeom == NULL )
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
         
         json_object_array_add( poObj, poObjGeom );
     }
@@ -442,6 +476,12 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
 json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision )
 {
     json_object* poObjCoords = NULL;
+    if( CPLIsInf(fX) || CPLIsInf(fY) ||
+        CPLIsNan(fX) || CPLIsNan(fY) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "Infinite or NaN coordinate encountered");
+        return NULL;
+    }
     poObjCoords = json_object_new_array();
     json_object_array_add( poObjCoords, json_object_new_double_with_precision( fX, nCoordPrecision ) );
     json_object_array_add( poObjCoords, json_object_new_double_with_precision( fY, nCoordPrecision ) );
@@ -452,6 +492,12 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoo
 json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision )
 {
     json_object* poObjCoords = NULL;
+    if( CPLIsInf(fX) || CPLIsInf(fY) || CPLIsInf(fZ) ||
+        CPLIsNan(fX) || CPLIsNan(fY) || CPLIsNan(fZ) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "Infinite or NaN coordinate encountered");
+        return NULL;
+    }
     poObjCoords = json_object_new_array();
     json_object_array_add( poObjCoords, json_object_new_double_with_precision( fX, nCoordPrecision ) );
     json_object_array_add( poObjCoords, json_object_new_double_with_precision( fY, nCoordPrecision ) );
@@ -476,6 +522,11 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecisi
             poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), nCoordPrecision );
         else
             poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), poLine->getZ(i), nCoordPrecision );
+        if( poObjPoint == NULL )
+        {
+            json_object_put(poObjCoords);
+            return NULL;
+        }
         json_object_array_add( poObjCoords, poObjPoint );
     }
     
@@ -545,3 +596,36 @@ char* OGR_G_ExportToJsonEx( OGRGeometryH hGeometry, char** papszOptions )
     /* Translation failed */
     return NULL;
 }
+
+/************************************************************************/
+/*               OGR_json_double_with_precision_to_string()             */
+/************************************************************************/
+
+static int OGR_json_double_with_precision_to_string(struct json_object *jso,
+                                                    struct printbuf *pb,
+                                                    int level,
+                                                    int flags)
+{
+    char szBuffer[75]; 
+    int nPrecision = (int) (size_t) jso->_userdata;
+    OGRFormatDouble( szBuffer, sizeof(szBuffer), jso->o.c_double, '.', 
+                     (nPrecision < 0) ? 15 : nPrecision ); 
+    if( szBuffer[0] == 't' /*oobig */ )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.18g", jso->o.c_double);
+    }
+    return printbuf_memappend(pb, szBuffer, strlen(szBuffer)); 
+}
+
+/************************************************************************/
+/*                   json_object_new_double_with_precision()            */
+/************************************************************************/
+
+json_object* json_object_new_double_with_precision(double dfVal,
+                                                   int nCoordPrecision)
+{
+    json_object* jso = json_object_new_double(dfVal);
+    json_object_set_serializer(jso, OGR_json_double_with_precision_to_string,
+                               (void*)(size_t)nCoordPrecision, NULL );
+    return jso;
+}
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
index e6f39b6..090d611 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.h 22490 2011-06-03 10:26:47Z rouault $
+ * $Id: ogrgeojsonwriter.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Mateusz Loskot
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #define OGR_GEOJSONWRITER_H_INCLUDED
 
 #include <ogr_core.h>
-#include <jsonc/json.h> // JSON-C
+#include <json.h> // JSON-C
 
 /************************************************************************/
 /*                         FORWARD DECLARATIONS                         */
@@ -47,6 +48,8 @@ class OGRPolygon;
 class OGRMultiPolygon;
 class OGRGeometryCollection;
 
+json_object* json_object_new_double_with_precision(double dfVal, int nCoordPrecision);
+
 /************************************************************************/
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
new file mode 100644
index 0000000..0871c65
--- /dev/null
+++ b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
@@ -0,0 +1,558 @@
+/******************************************************************************
+ * $Id: ogrtopojsonreader.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implementation of OGRTopoJSONReader class
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrgeojsonreader.h"
+#include "ogrgeojsonutils.h"
+#include "ogr_geojson.h"
+#include <json.h> // JSON-C
+#include <ogr_api.h>
+
+/************************************************************************/
+/*                          OGRTopoJSONReader()                         */
+/************************************************************************/
+
+OGRTopoJSONReader::OGRTopoJSONReader()
+    : poGJObject_( NULL )
+{
+    // Take a deep breath and get to work.
+}
+
+/************************************************************************/
+/*                         ~OGRTopoJSONReader()                         */
+/************************************************************************/
+
+OGRTopoJSONReader::~OGRTopoJSONReader()
+{
+    if( NULL != poGJObject_ )
+    {
+        json_object_put(poGJObject_);
+    }
+
+    poGJObject_ = NULL;
+}
+
+/************************************************************************/
+/*                           Parse()                                    */
+/************************************************************************/
+
+OGRErr OGRTopoJSONReader::Parse( const char* pszText )
+{
+    if( NULL != pszText )
+    {
+        json_tokener* jstok = NULL;
+        json_object* jsobj = NULL;
+
+        jstok = json_tokener_new();
+        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
+        if( jstok->err != json_tokener_success)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "TopoJSON parsing error: %s (at offset %d)",
+            	      json_tokener_errors[jstok->err], jstok->char_offset);
+            
+            json_tokener_free(jstok);
+            return OGRERR_CORRUPT_DATA;
+        }
+        json_tokener_free(jstok);
+
+        /* JSON tree is shared for while lifetime of the reader object
+         * and will be released in the destructor.
+         */
+        poGJObject_ = jsobj;
+    }
+
+    return OGRERR_NONE;
+}
+
+typedef struct
+{
+    double dfScale0, dfScale1;
+    double dfTranslate0, dfTranslate1;
+} ScalingParams;
+
+/************************************************************************/
+/*                            ParsePoint()                              */
+/************************************************************************/
+
+static int ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
+{
+    if( poPoint != NULL && json_type_array == json_object_get_type(poPoint) &&
+        json_object_array_length(poPoint) == 2 )
+    {
+        json_object* poX = json_object_array_get_idx(poPoint, 0);
+        json_object* poY = json_object_array_get_idx(poPoint, 1);
+        if( poX != NULL &&
+            (json_type_int == json_object_get_type(poX) ||
+                json_type_double == json_object_get_type(poX)) &&
+            poY != NULL &&
+            (json_type_int == json_object_get_type(poY) ||
+                json_type_double == json_object_get_type(poY)) )
+        {
+            *pdfX = json_object_get_double(poX);
+            *pdfY = json_object_get_double(poY);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                             ParseArc()                               */
+/************************************************************************/
+
+static void ParseArc(OGRLineString* poLS, json_object* poArcsDB, int nArcID,
+                     int bReverse, ScalingParams* psParams)
+{
+    json_object* poArcDB = json_object_array_get_idx(poArcsDB, nArcID);
+    if( poArcDB == NULL || json_type_array != json_object_get_type(poArcDB) )
+        return;
+    int nPoints = json_object_array_length(poArcDB);
+    double dfAccX = 0, dfAccY = 0;
+    int nBaseIndice = poLS->getNumPoints();
+    for(int i=0; i<nPoints; i++)
+    {
+        json_object* poPoint = json_object_array_get_idx(poArcDB, i);
+        double dfX = 0.0, dfY = 0.0;
+        if( ParsePoint( poPoint, &dfX, &dfY ) )
+        {
+            dfAccX += dfX;
+            dfAccY += dfY;
+            double dfX = dfAccX * psParams->dfScale0 + psParams->dfTranslate0;
+            double dfY = dfAccY * psParams->dfScale1 + psParams->dfTranslate1;
+            if( i == 0 )
+            {
+                if( !bReverse && poLS->getNumPoints() > 0 )
+                {
+                    poLS->setNumPoints( nBaseIndice + nPoints - 1 );
+                    nBaseIndice --;
+                    continue;
+                }
+                else if( bReverse && poLS->getNumPoints() > 0 )
+                {
+                    poLS->setNumPoints( nBaseIndice + nPoints - 1 );
+                    nPoints --;
+                    if( nPoints == 0 )
+                        break;
+                }
+                else
+                    poLS->setNumPoints( nBaseIndice + nPoints );
+            }
+
+            if( !bReverse )
+                poLS->setPoint(nBaseIndice + i, dfX, dfY);
+            else
+                poLS->setPoint(nBaseIndice + nPoints - 1 - i, dfX, dfY);
+        }
+    }
+}
+
+/************************************************************************/
+/*                        ParseLineString()                             */
+/************************************************************************/
+
+static void ParseLineString(OGRLineString* poLS, json_object* poRing,
+                            json_object* poArcsDB, ScalingParams* psParams)
+{
+    int nArcsDB = json_object_array_length(poArcsDB);
+
+    int nArcsRing = json_object_array_length(poRing);
+    for(int j=0; j<nArcsRing; j++)
+    {
+        json_object* poArcId = json_object_array_get_idx(poRing, j);
+        if( poArcId != NULL && json_type_int == json_object_get_type(poArcId) )
+        {
+            int nArcId = json_object_get_int(poArcId);
+            int bReverse = FALSE;
+            if( nArcId < 0 )
+            {
+                nArcId = - nArcId - 1;
+                bReverse = TRUE;
+            }
+            if( nArcId < nArcsDB )
+            {
+                ParseArc(poLS, poArcsDB, nArcId, bReverse, psParams);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                          ParsePolygon()                              */
+/************************************************************************/
+
+static void ParsePolygon(OGRPolygon* poPoly, json_object* poArcsObj,
+                         json_object* poArcsDB, ScalingParams* psParams)
+{
+    int nRings = json_object_array_length(poArcsObj);
+    for(int i=0; i<nRings; i++)
+    {
+        OGRLinearRing* poLR = new OGRLinearRing();
+        poPoly->addRingDirectly(poLR);
+
+        json_object* poRing = json_object_array_get_idx(poArcsObj, i);
+        if( poRing != NULL && json_type_array == json_object_get_type(poRing) )
+        {
+            ParseLineString(poLR, poRing, poArcsDB, psParams);
+        }
+    }
+}
+
+/************************************************************************/
+/*                       ParseMultiLineString()                         */
+/************************************************************************/
+
+static void ParseMultiLineString(OGRMultiLineString* poMLS, json_object* poArcsObj,
+                                 json_object* poArcsDB, ScalingParams* psParams)
+{
+    int nRings = json_object_array_length(poArcsObj);
+    for(int i=0; i<nRings; i++)
+    {
+        OGRLineString* poLS = new OGRLineString();
+        poMLS->addGeometryDirectly(poLS);
+
+        json_object* poRing = json_object_array_get_idx(poArcsObj, i);
+        if( poRing != NULL && json_type_array == json_object_get_type(poRing) )
+        {
+            ParseLineString(poLS, poRing, poArcsDB, psParams);
+        }
+    }
+}
+
+/************************************************************************/
+/*                       ParseMultiPolygon()                            */
+/************************************************************************/
+
+static void ParseMultiPolygon(OGRMultiPolygon* poMultiPoly, json_object* poArcsObj,
+                         json_object* poArcsDB, ScalingParams* psParams)
+{
+    int nPolys = json_object_array_length(poArcsObj);
+    for(int i=0; i<nPolys; i++)
+    {
+        OGRPolygon* poPoly = new OGRPolygon();
+        poMultiPoly->addGeometryDirectly(poPoly);
+
+        json_object* poPolyArcs = json_object_array_get_idx(poArcsObj, i);
+        if( poPolyArcs != NULL && json_type_array == json_object_get_type(poPolyArcs) )
+        {
+            ParsePolygon(poPoly, poPolyArcs, poArcsDB, psParams);
+        }
+    }
+}
+
+/************************************************************************/
+/*                          ParseObject()                               */
+/************************************************************************/
+
+static void ParseObject(const char* pszId,
+                        json_object* poObj, OGRGeoJSONLayer* poLayer,
+                        json_object* poArcsDB, ScalingParams* psParams)
+{
+    json_object* poType = OGRGeoJSONFindMemberByName(poObj, "type");
+    const char* pszType = json_object_get_string(poType);
+
+    json_object* poArcsObj = OGRGeoJSONFindMemberByName(poObj, "arcs");
+    json_object* poCoordinatesObj = OGRGeoJSONFindMemberByName(poObj, "coordinates");
+    if( strcmp(pszType, "Point") == 0 || strcmp(pszType, "MultiPoint") == 0 )
+    {
+        if( poCoordinatesObj == NULL || json_type_array != json_object_get_type(poCoordinatesObj) )
+            return;
+    }
+    else
+    {
+        if( poArcsObj == NULL || json_type_array != json_object_get_type(poArcsObj) )
+            return;
+    }
+
+    if( pszId == NULL )
+    {
+        json_object* poId = OGRGeoJSONFindMemberByName(poObj, "id");
+        if( poId != NULL &&
+            (json_type_string == json_object_get_type(poId) ||
+             json_type_int == json_object_get_type(poId)) )
+        {
+            pszId = json_object_get_string(poId);
+        }
+    }
+
+    OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn());
+    if( pszId != NULL )
+        poFeature->SetField("id", pszId);
+
+    json_object* poProperties = OGRGeoJSONFindMemberByName(poObj, "properties");
+    if( poProperties != NULL && json_type_object == json_object_get_type(poProperties) )
+    {
+        json_object* poName = OGRGeoJSONFindMemberByName(poProperties, "name");
+        if( poName != NULL && json_type_string == json_object_get_type(poName) )
+        {
+            const char* pszName = json_object_get_string(poName);
+            poFeature->SetField("name", pszName);
+        }
+    }
+
+    OGRGeometry* poGeom = NULL;
+    if( strcmp(pszType, "Point") == 0 )
+    {
+        double dfX = 0.0, dfY = 0.0;
+        if( ParsePoint( poCoordinatesObj, &dfX, &dfY ) )
+        {
+            dfX = dfX * psParams->dfScale0 + psParams->dfTranslate0;
+            dfY = dfY * psParams->dfScale1 + psParams->dfTranslate1;
+            poGeom = new OGRPoint(dfX, dfY);
+        }
+        else
+            poGeom = new OGRPoint();
+    }
+    else if( strcmp(pszType, "MultiPoint") == 0 )
+    {
+        OGRMultiPoint* poMP = new OGRMultiPoint();
+        poGeom = poMP;
+        int nTuples = json_object_array_length(poCoordinatesObj);
+        for(int i=0; i<nTuples; i++)
+        {
+            json_object* poPair = json_object_array_get_idx(poCoordinatesObj, i);
+            double dfX = 0.0, dfY = 0.0;
+            if( ParsePoint( poPair, &dfX, &dfY ) )
+            {
+                dfX = dfX * psParams->dfScale0 + psParams->dfTranslate0;
+                dfY = dfY * psParams->dfScale1 + psParams->dfTranslate1;
+                poMP->addGeometryDirectly(new OGRPoint(dfX, dfY));
+            }
+        }
+    }
+    else if( strcmp(pszType, "LineString") == 0 )
+    {
+        OGRLineString* poLS = new OGRLineString();
+        poGeom = poLS;
+        ParseLineString(poLS, poArcsObj, poArcsDB, psParams);
+    }
+    else if( strcmp(pszType, "MultiLineString") == 0 )
+    {
+        OGRMultiLineString* poMLS = new OGRMultiLineString();
+        poGeom = poMLS;
+        ParseMultiLineString(poMLS, poArcsObj, poArcsDB, psParams);
+    }
+    else if( strcmp(pszType, "Polygon") == 0 )
+    {
+        OGRPolygon* poPoly = new OGRPolygon();
+        poGeom = poPoly;
+        ParsePolygon(poPoly, poArcsObj, poArcsDB, psParams);
+    }
+    else if( strcmp(pszType, "MultiPolygon") == 0 )
+    {
+        OGRMultiPolygon* poMultiPoly = new OGRMultiPolygon();
+        poGeom = poMultiPoly;
+        ParseMultiPolygon(poMultiPoly, poArcsObj, poArcsDB, psParams);
+    }
+    
+    if( poGeom != NULL )
+        poFeature->SetGeometryDirectly(poGeom);
+    poLayer->AddFeature(poFeature);
+    delete poFeature;
+}
+
+/************************************************************************/
+/*                        ParseObjectMain()                             */
+/************************************************************************/
+
+static void ParseObjectMain(const char* pszId, json_object* poObj,
+                            OGRGeoJSONDataSource* poDS,
+                            OGRGeoJSONLayer **ppoMainLayer,
+                            json_object* poArcs,
+                            ScalingParams* psParams)
+{
+    if( poObj != NULL && json_type_object == json_object_get_type( poObj ) )
+    {
+        json_object* poType = OGRGeoJSONFindMemberByName(poObj, "type");
+        if( poType != NULL && json_type_string == json_object_get_type( poType ) )
+        {
+            const char* pszType = json_object_get_string(poType);
+            if( strcmp(pszType, "GeometryCollection") == 0 )
+            {
+                json_object* poGeometries = OGRGeoJSONFindMemberByName(poObj, "geometries");
+                if( poGeometries != NULL &&
+                    json_type_array == json_object_get_type( poGeometries ) )
+                {
+                    if( pszId == NULL )
+                    {
+                        json_object* poId = OGRGeoJSONFindMemberByName(poObj, "id");
+                        if( poId != NULL &&
+                            (json_type_string == json_object_get_type(poId) ||
+                            json_type_int == json_object_get_type(poId)) )
+                        {
+                            pszId = json_object_get_string(poId);
+                        }
+                    }
+
+                    OGRGeoJSONLayer* poLayer = new OGRGeoJSONLayer(
+                            pszId ? pszId : "TopoJSON", NULL,
+                            wkbUnknown, poDS );
+                    {
+                        OGRFieldDefn fldDefn( "id", OFTString );
+                        poLayer->GetLayerDefn()->AddFieldDefn( &fldDefn );
+                    }
+                    {
+                        OGRFieldDefn fldDefn( "name", OFTString );
+                        poLayer->GetLayerDefn()->AddFieldDefn( &fldDefn );
+                    }
+
+                    int nGeometries = json_object_array_length(poGeometries);
+                    for(int i=0; i<nGeometries; i++)
+                    {
+                        json_object* poGeom =
+                            json_object_array_get_idx(poGeometries, i);
+                        if( poGeom != NULL &&
+                            json_type_object == json_object_get_type( poGeom ) )
+                        {
+                            ParseObject(NULL, poGeom, poLayer, poArcs, psParams);
+                        }
+                    }
+
+                    poDS->AddLayer(poLayer);
+                }
+            }
+            else if( strcmp(pszType, "Point") == 0 ||
+                     strcmp(pszType, "MultiPoint") == 0 ||
+                     strcmp(pszType, "LineString") == 0 ||
+                     strcmp(pszType, "MultiLineString") == 0 ||
+                     strcmp(pszType, "Polygon") == 0 ||
+                     strcmp(pszType, "MultiPolygon") == 0 )
+            {
+                if( *ppoMainLayer == NULL )
+                {
+                    *ppoMainLayer = new OGRGeoJSONLayer(
+                        "TopoJSON", NULL, wkbUnknown, poDS );
+                    {
+                        OGRFieldDefn fldDefn( "id", OFTString );
+                        (*ppoMainLayer)->GetLayerDefn()->AddFieldDefn( &fldDefn );
+                    }
+                    {
+                        OGRFieldDefn fldDefn( "name", OFTString );
+                        (*ppoMainLayer)->GetLayerDefn()->AddFieldDefn( &fldDefn );
+                    }
+                }
+                ParseObject(pszId, poObj, *ppoMainLayer, poArcs, psParams);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           ReadLayers()                               */
+/************************************************************************/
+
+void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
+{
+    if( NULL == poGJObject_ )
+    {
+        CPLDebug( "TopoJSON",
+                  "Missing parset TopoJSON data. Forgot to call Parse()?" );
+        return;
+    }
+
+    ScalingParams sParams;
+    sParams.dfScale0 = 1.0;
+    sParams.dfScale1 = 1.0;
+    sParams.dfTranslate0 = 0.0;
+    sParams.dfTranslate1 = 0.0;
+    json_object* poObjTransform = OGRGeoJSONFindMemberByName( poGJObject_, "transform" );
+    if( NULL != poObjTransform && json_type_object == json_object_get_type( poObjTransform ) )
+    {
+        json_object* poObjScale = OGRGeoJSONFindMemberByName( poObjTransform, "scale" );
+        if( NULL != poObjScale && json_type_array == json_object_get_type( poObjScale ) &&
+            json_object_array_length( poObjScale ) == 2 )
+        {
+            json_object* poScale0 = json_object_array_get_idx(poObjScale, 0);
+            json_object* poScale1 = json_object_array_get_idx(poObjScale, 1);
+            if( poScale0 != NULL &&
+                (json_object_get_type(poScale0) == json_type_double ||
+                 json_object_get_type(poScale0) == json_type_int) &&
+                poScale1 != NULL &&
+                (json_object_get_type(poScale1) == json_type_double ||
+                 json_object_get_type(poScale1) == json_type_int) )
+            {
+                sParams.dfScale0 = json_object_get_double(poScale0);
+                sParams.dfScale1 = json_object_get_double(poScale1);
+            }
+        }
+
+        json_object* poObjTranslate = OGRGeoJSONFindMemberByName( poObjTransform, "translate" );
+        if( NULL != poObjTranslate && json_type_array == json_object_get_type( poObjTranslate ) &&
+            json_object_array_length( poObjTranslate ) == 2 )
+        {
+            json_object* poTranslate0 = json_object_array_get_idx(poObjTranslate, 0);
+            json_object* poTranslate1 = json_object_array_get_idx(poObjTranslate, 1);
+            if( poTranslate0 != NULL &&
+                (json_object_get_type(poTranslate0) == json_type_double ||
+                 json_object_get_type(poTranslate0) == json_type_int) &&
+                poTranslate1 != NULL &&
+                (json_object_get_type(poTranslate1) == json_type_double ||
+                 json_object_get_type(poTranslate1) == json_type_int) )
+            {
+                sParams.dfTranslate0 = json_object_get_double(poTranslate0);
+                sParams.dfTranslate1 = json_object_get_double(poTranslate1);
+            }
+        }
+    }
+
+    json_object* poArcs = OGRGeoJSONFindMemberByName( poGJObject_, "arcs" );
+    if( poArcs == NULL || json_type_array != json_object_get_type( poArcs ) )
+        return;
+
+    OGRGeoJSONLayer* poMainLayer = NULL;
+
+    json_object* poObjects = OGRGeoJSONFindMemberByName( poGJObject_, "objects" );
+    if( poObjects == NULL )
+        return;
+
+    if( json_type_object == json_object_get_type( poObjects ) )
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poObjects, it )
+        {
+            json_object* poObj = it.val;
+            ParseObjectMain(it.key, poObj, poDS, &poMainLayer, poArcs, &sParams);
+        }
+    }
+    else if( json_type_array == json_object_get_type( poObjects ) )
+    {
+        int nObjects = json_object_array_length(poObjects);
+        for(int i=0; i<nObjects; i++)
+        {
+            json_object* poObj = json_object_array_get_idx(poObjects, i);
+            ParseObjectMain(NULL, poObj, poDS, &poMainLayer, poArcs, &sParams);
+        }
+    }
+
+    if( poMainLayer != NULL )
+        poDS->AddLayer(poMainLayer);
+
+}
diff --git a/ogr/ogrsf_frmts/geomedia/GNUmakefile b/ogr/ogrsf_frmts/geomedia/GNUmakefile
index 1b12e2a..7a99793 100644
--- a/ogr/ogrsf_frmts/geomedia/GNUmakefile
+++ b/ogr/ogrsf_frmts/geomedia/GNUmakefile
@@ -5,7 +5,7 @@ include ../../../GDALmake.opt
 OBJ	=	ogrgeomediadatasource.o ogrgeomedialayer.o ogrgeomediadriver.o \
 		ogrgeomediatablelayer.o ogrgeomediaselectlayer.o
 
-CPPFLAGS	:=	$(GDAL_INCLUDE) -I.. -I../.. $(CPPFLAGS)
+CPPFLAGS	:=	$(GDAL_INCLUDE) -I.. -I../.. -I../pgeo $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/geomedia/makefile.vc b/ogr/ogrsf_frmts/geomedia/makefile.vc
index 01d79d4..fe0522a 100644
--- a/ogr/ogrsf_frmts/geomedia/makefile.vc
+++ b/ogr/ogrsf_frmts/geomedia/makefile.vc
@@ -6,7 +6,7 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = -I.. -I..\..
+EXTRAFLAGS = -I.. -I..\.. -I..\pgeo
 
 default:	$(OBJ)
 
diff --git a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
index 8996df0..41f145b 100644
--- a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
+++ b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_geomedia.h 21561 2011-01-23 12:22:58Z rouault $
+ * $Id: ogr_geomedia.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Geomedia MDB driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -34,6 +34,7 @@
 #include "ogrsf_frmts.h"
 #include "cpl_odbc.h"
 #include "cpl_error.h"
+#include "ogr_pgeo.h"
 
 /************************************************************************/
 /*                          OGRGeomediaLayer                            */
@@ -79,9 +80,7 @@ class OGRGeomediaLayer : public OGRLayer
     virtual OGRFeature *GetFeature( long nFeatureId );
     
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-
-    virtual OGRSpatialReference *GetSpatialRef();
-
+    
     virtual int         TestCapability( const char * );
 
     virtual const char *GetFIDColumn();
@@ -196,15 +195,8 @@ class OGRGeomediaDataSource : public OGRDataSource
 /*                          OGRGeomediaDriver                           */
 /************************************************************************/
 
-class OGRGeomediaDriver : public OGRSFDriver
+class OGRGeomediaDriver : public OGRODBCMDBDriver
 {
-    CPLString   osDriverFile;
-
-    bool        InstallMdbDriver();
-    bool        LibraryExists( const char* pszLibPath );
-    bool        FindDriverLib();
-    CPLString   FindDefaultLib(const char* pszLibName);
-
   public:
                 ~OGRGeomediaDriver();
                 
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
index 7d713e3..68f36d9 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeomediadatasource.cpp 21561 2011-01-23 12:22:58Z rouault $
+ * $Id: ogrgeomediadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrgeomediadatasource.cpp 21561 2011-01-23 12:22:58Z rouault $");
+CPL_CVSID("$Id: ogrgeomediadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       OGRGeomediaDataSource()                        */
@@ -391,9 +391,9 @@ OGRLayer * OGRGeomediaDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic imlplementation for OGRSQL dialect.                 */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
index 54d0b0b..afac77a 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeomediadriver.cpp 23931 2012-02-09 13:41:13Z rouault $
+ * $Id: ogrgeomediadriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -31,7 +31,7 @@
 #include "ogr_geomedia.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeomediadriver.cpp 23931 2012-02-09 13:41:13Z rouault $");
+CPL_CVSID("$Id: ogrgeomediadriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          ~OGRODBCDriver()                            */
@@ -62,6 +62,12 @@ OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
 {
     OGRGeomediaDataSource     *poDS;
 
+    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+        return NULL;
+
     if( !EQUALN(pszFilename,"GEOMEDIA:",9) 
         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
@@ -141,144 +147,6 @@ int OGRGeomediaDriver::TestCapability( const char * pszCap )
     return FALSE;
 }
 
-
-/*
- * START OF UNIX-only features.
- */
-#ifndef WIN32
-
-/************************************************************************/
-/*                           InstallMdbDriver()                         */
-/************************************************************************/
-
-bool OGRGeomediaDriver::InstallMdbDriver()
-{
-    if ( !FindDriverLib() )
-    {
-        return false;
-    }
-    else
-    {
-        CPLAssert( !osDriverFile.empty() );
-        CPLDebug( "Geomedia", "MDB Tools driver: %s", osDriverFile.c_str() );
-
-        CPLString driverName("Microsoft Access Driver (*.mdb)");
-        CPLString driver(driverName);
-        driver += '\0';
-        driver += "Driver=";
-        driver += osDriverFile; // Found by FindDriverLib()
-        driver += '\0';
-        driver += "FileUsage=1";
-        driver += '\0';
-        driver += '\0';
-
-        // Create installer and register driver
-        CPLODBCDriverInstaller dri;
-
-        if ( !dri.InstallDriver(driver.c_str(), 0, ODBC_INSTALL_COMPLETE) )
-        {
-            // Report ODBC error
-            CPLError( CE_Failure, CPLE_AppDefined, "ODBC: %s", dri.GetLastError() );
-            return false;
-        }
-    }
-
-    return true;
-}
-
-/************************************************************************/
-/*                           FindDriverLib()                            */
-/************************************************************************/
-
-bool OGRGeomediaDriver::FindDriverLib()
-{
-    // Default name and path of driver library
-    const char* aszDefaultLibName[] = {
-        "libmdbodbc.so",
-        "libmdbodbc.so.0" /* for Ubuntu 8.04 support */
-    };
-    const int nLibNames = sizeof(aszDefaultLibName) / sizeof(aszDefaultLibName[0]);
-    const char* libPath[] = { 
-        "/usr/lib",
-        "/usr/local/lib"
-    };
-    const int nLibPaths = sizeof(libPath) / sizeof(libPath[0]);
-
-    CPLString strLibPath("");
-
-    const char* pszDrvCfg = CPLGetConfigOption("MDBDRIVER_PATH", NULL);
-    if ( NULL != pszDrvCfg )
-    {
-        // Directory or file path
-        strLibPath = pszDrvCfg;
-
-        VSIStatBuf sStatBuf = { 0 };
-        if ( VSIStat( pszDrvCfg, &sStatBuf ) == 0
-             && VSI_ISDIR( sStatBuf.st_mode ) ) 
-        {
-            // Find default library in custom directory
-            const char* pszDriverFile = CPLFormFilename( pszDrvCfg, aszDefaultLibName[0], NULL );
-            CPLAssert( 0 != pszDriverFile );
-        
-            strLibPath = pszDriverFile;
-        }
-
-        if ( LibraryExists( strLibPath.c_str() ) )
-        {
-            // Save custom driver path
-            osDriverFile = strLibPath;
-            return true;
-        }
-    }
-
-    // Try to find library in default path
-    for ( int i = 0; i < nLibPaths; i++ )
-    {
-        for ( int j = 0; j < nLibNames; j++ )
-        {
-            const char* pszDriverFile = CPLFormFilename( libPath[i], aszDefaultLibName[j], NULL );
-            CPLAssert( 0 != pszDriverFile );
-
-            if ( LibraryExists( pszDriverFile ) )
-            {
-                // Save default driver path
-                osDriverFile = pszDriverFile;
-                return true;
-            }
-        }
-    }
-
-    CPLError(CE_Failure, CPLE_AppDefined, "Geomedia: MDB Tools driver not found!\n");
-    // Driver not found!
-    return false;
-}
-
-/************************************************************************/
-/*                           LibraryExists()                            */
-/************************************************************************/
-
-bool OGRGeomediaDriver::LibraryExists(const char* pszLibPath)
-{
-    CPLAssert( 0 != pszLibPath );
-
-    VSIStatBuf stb = { 0 } ;
-
-    if ( 0 == VSIStat( pszLibPath, &stb ) )
-    {
-        if (VSI_ISREG( stb.st_mode ) || VSI_ISLNK(stb.st_mode))
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-#endif /* ndef WIN32 */
-/*
- * END OF UNIX-only features
- */
-
 /************************************************************************/
 /*                           RegisterOGRODBC()                          */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
index 2db02f2..3e1d1c1 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomedialayer.cpp 21547 2011-01-22 14:47:01Z rouault $
+ * $Id: ogrgeomedialayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaLayer class, code shared between
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrgeomedialayer.cpp 21547 2011-01-22 14:47:01Z rouault $");
+CPL_CVSID("$Id: ogrgeomedialayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRGeomediaLayer()                          */
@@ -108,6 +108,7 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
     int    nRawColumns = poStmt->GetColCount();
 
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
@@ -324,16 +325,6 @@ int OGRGeomediaLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRGeomediaLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
index bc994d8..b306ece 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediaselectlayer.cpp 21545 2011-01-22 14:26:31Z rouault $
+ * $Id: ogrgeomediaselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaSelectLayer class, layer access to the results
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_geomedia.h"
 
-CPL_CVSID("$Id: ogrgeomediaselectlayer.cpp 21545 2011-01-22 14:26:31Z rouault $");
+CPL_CVSID("$Id: ogrgeomediaselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRGeomediaSelectLayer()                      */
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
index af604d7..3e09095 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeomediatablelayer.cpp 21561 2011-01-23 12:22:58Z rouault $
+ * $Id: ogrgeomediatablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaTableLayer class, access to an existing table.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_geomedia.h"
 
-CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 21561 2011-01-23 12:22:58Z rouault $");
+CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRGeomediaTableLayer()                     */
diff --git a/ogr/ogrsf_frmts/georss/ogr_georss.h b/ogr/ogrsf_frmts/georss/ogr_georss.h
index 36ef8b5..5088fd3 100644
--- a/ogr/ogrsf_frmts/georss/ogr_georss.h
+++ b/ogr/ogrsf_frmts/georss/ogr_georss.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -134,8 +134,6 @@ class OGRGeoRSSLayer : public OGRLayer
     
     int                 TestCapability( const char * );
     
-    OGRSpatialReference *GetSpatialRef();
-    
     int                 GetFeatureCount( int bForce );
 
     void                LoadSchema();
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
index df7e9d3..6a3bb04 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeorssdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
+ * $Id: ogrgeorssdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgeorssdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
+CPL_CVSID("$Id: ogrgeorssdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRGeoRSSDataSource()                          */
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
index e7dcaa8..9cd29c1 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeorssdriver.cpp 15919 2008-12-08 21:02:58Z rouault $
+ * $Id: ogrgeorssdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_georss.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeorssdriver.cpp 15919 2008-12-08 21:02:58Z rouault $");
+CPL_CVSID("$Id: ogrgeorssdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRGeoRSSDriver()                            */
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
index 3a93f71..19f573a 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgeorsslayer.cpp 25445 2013-01-04 18:46:53Z rouault $
+ * $Id: ogrgeorsslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSLayer class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeorsslayer.cpp 25445 2013-01-04 18:46:53Z rouault $");
+CPL_CVSID("$Id: ogrgeorsslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const char* apszAllowedATOMFieldNamesWithSubElements[] = { "author", "contributor", NULL };
 
@@ -98,7 +98,10 @@ OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
 
     poSRS = poSRSIn;
     if (poSRS)
+    {
         poSRS->Reference();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+    }
 
     nTotalFeatureCount = 0;
 
@@ -938,19 +941,6 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRGeoRSSLayer::GetSpatialRef()
-
-{
-    if (!bWriteMode && !bHasReadSchema)
-        LoadSchema();
-
-    return poSRS;
-}
-
-/************************************************************************/
 /*              OGRGeoRSSLayerIsStandardFieldInternal()                 */
 /************************************************************************/
 
@@ -1791,6 +1781,8 @@ void OGRGeoRSSLayer::LoadSchema()
 
     if (eGeomType != wkbUnknown)
         poFeatureDefn->SetGeomType(eGeomType);
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     if (setOfFoundFields)
         CPLHashSetDestroy(setOfFoundFields);
@@ -2224,6 +2216,8 @@ int OGRGeoRSSLayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCSequentialWrite) )
         return bWriteMode;
+    else if( EQUAL(pszCap,OLCCreateField) )
+        return bWriteMode;
     else 
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/gft/drv_gft.html b/ogr/ogrsf_frmts/gft/drv_gft.html
index b0cb046..7c78090 100644
--- a/ogr/ogrsf_frmts/gft/drv_gft.html
+++ b/ogr/ogrsf_frmts/gft/drv_gft.html
@@ -39,8 +39,8 @@ Most operations, in particular write operations, require a valid Google
 account to provide authentication information to the driver. The only 
 exception is read-only access to public tables.<p>
 
-In order to creating an authorization key, it is necessary to 
-<a href="http://www.google.com/url?q=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fauth%3Fscope%3Dhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Ffusiontables%26state%3D%252Fprofile%26redirect_uri%3Durn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%26response_type%3Dcode%26client_id%3D265656308688.apps.googleusercontent.com">
+In order to create an authorization key, it is necessary to 
+<a href="https://www.google.com/url?q=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fauth%3Fscope%3Dhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Ffusiontables%26state%3D%252Fprofile%26redirect_uri%3Durn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%26response_type%3Dcode%26client_id%3D265656308688.apps.googleusercontent.com">
 login and authorize</a> access to fusion tables for a google (ie. gmail) 
 account.  The resulting authorization key can be turned into a refresh 
 token for use OGR using the gdal/swig/python/scripts/gdal_auth.py script 
diff --git a/ogr/ogrsf_frmts/gft/ogr_gft.h b/ogr/ogrsf_frmts/gft/ogr_gft.h
index 84c9e27..0572140 100644
--- a/ogr/ogrsf_frmts/gft/ogr_gft.h
+++ b/ogr/ogrsf_frmts/gft/ogr_gft.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_gft.h 25483 2013-01-10 17:06:59Z warmerdam $
+ * $Id: ogr_gft.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Definition of classes for OGR Google Fusion Tables driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -68,6 +68,8 @@ protected:
 
     static CPLString    LaunderColName(const char* pszColName);
 
+    void                SetGeomFieldName();
+
   public:
                          OGRGFTLayer(OGRGFTDataSource* poDS);
                         ~OGRGFTLayer();
@@ -79,10 +81,6 @@ protected:
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference*GetSpatialRef();
-
-    virtual const char *        GetGeometryColumn();
-
     virtual OGRErr              SetNextByIndex( long nIndex );
 
     const char *        GetDefaultGeometryColumnName() { return "geometry"; }
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
index 6260482..cb7cef9 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgftdatasource.cpp 25483 2013-01-10 17:06:59Z warmerdam $
+ * $Id: ogrgftdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Google Fusion Table Translator
  * Purpose:  Implements OGRGFTDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftdatasource.cpp 25483 2013-01-10 17:06:59Z warmerdam $");
+CPL_CVSID("$Id: ogrgftdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define GDAL_API_KEY "AIzaSyA_2h1_wXMOLHNSVeo-jf1ACME-M1XMgP0"
 #define FUSION_TABLE_SCOPE "https://www.googleapis.com/Fauth/fusiontables"
@@ -535,7 +535,10 @@ OGRLayer * OGRGFTDataSource::ExecuteSQL( const char *pszSQLCommand,
                                           const char *pszDialect )
 
 {
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand,
                                           poSpatialFilter,
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
index 10b7d33..9d0d747 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgftdriver.cpp 22070 2011-03-29 21:56:51Z rouault $
+ * $Id: ogrgftdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 
 /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_reference.html */
 
-CPL_CVSID("$Id: ogrgftdriver.cpp 22070 2011-03-29 21:56:51Z rouault $");
+CPL_CVSID("$Id: ogrgftdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRGFT();
 
diff --git a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
index 73d4026..9317e61 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgftlayer.cpp 22268 2011-04-30 13:10:40Z rouault $
+ * $Id: ogrgftlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_gft.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogrgftlayer.cpp 22268 2011-04-30 13:10:40Z rouault $");
+CPL_CVSID("$Id: ogrgftlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRGFTLayer()                             */
@@ -525,25 +525,6 @@ int OGRGFTLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                         GetGeometryColumn()                          */
-/************************************************************************/
-
-const char *OGRGFTLayer::GetGeometryColumn()
-{
-    GetLayerDefn();
-    if (iGeometryField < 0)
-        return "";
-
-    if (iGeometryField == poFeatureDefn->GetFieldCount())
-    {
-        CPLAssert(bHiddenGeometryField);
-        return GetDefaultGeometryColumnName();
-    }
-
-    return poFeatureDefn->GetFieldDefn(iGeometryField)->GetNameRef();
-}
-
-/************************************************************************/
 /*                         ParseCSVResponse()                           */
 /************************************************************************/
 
@@ -648,20 +629,6 @@ CPLString OGRGFTLayer::PatchSQL(const char* pszSQL)
 }
 
 /************************************************************************/
-/*                          GetSpatialRef()                             */
-/************************************************************************/
-
-OGRSpatialReference* OGRGFTLayer::GetSpatialRef()
-{
-    GetLayerDefn();
-
-    if (iGeometryField < 0)
-        return NULL;
-
-    return poSRS;
-}
-
-/************************************************************************/
 /*                         LaunderColName()                             */
 /************************************************************************/
 
@@ -678,3 +645,23 @@ CPLString OGRGFTLayer::LaunderColName(const char* pszColName)
     }
     return osLaunderedColName;
 }
+
+/************************************************************************/
+/*                         SetGeomFieldName()                           */
+/************************************************************************/
+
+void OGRGFTLayer::SetGeomFieldName()
+{
+    if (iGeometryField >= 0 && poFeatureDefn->GetGeomFieldCount() > 0)
+    {
+        const char* pszGeomColName;
+        if (iGeometryField == poFeatureDefn->GetFieldCount())
+        {
+            CPLAssert(bHiddenGeometryField);
+            pszGeomColName = GetDefaultGeometryColumnName();
+        }
+        else
+            pszGeomColName = poFeatureDefn->GetFieldDefn(iGeometryField)->GetNameRef();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColName);
+    }
+}
diff --git a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
index 88612b6..e25fe91 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgftresultlayer.cpp 24343 2012-04-29 11:31:01Z rouault $
+ * $Id: ogrgftresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTResultLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftresultlayer.cpp 24343 2012-04-29 11:31:01Z rouault $");
+CPL_CVSID("$Id: ogrgftresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRGFTResultLayer()                           */
@@ -46,6 +46,7 @@ OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
     poFeatureDefn = new OGRFeatureDefn( "result" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbUnknown );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
 
 /************************************************************************/
@@ -284,6 +285,8 @@ int OGRGFTResultLayer::RunSQL()
             bGotAllRows = bEOF = TRUE;
     }
 
+    SetGeomFieldName();
+
     CPLHTTPDestroyResult(psResult);
 
     return TRUE;
diff --git a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
index 96c01ee..a348989 100644
--- a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgfttablelayer.cpp 25475 2013-01-09 09:09:59Z warmerdam $
+ * $Id: ogrgfttablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTTableLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgfttablelayer.cpp 25475 2013-01-09 09:09:59Z warmerdam $");
+CPL_CVSID("$Id: ogrgfttablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRGFTTableLayer()                           */
@@ -106,6 +106,7 @@ int OGRGFTTableLayer::FetchDescribe()
 {
     poFeatureDefn = new OGRFeatureDefn( osTableName );
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     const CPLString& osAuth = poDS->GetAccessToken();
     std::vector<CPLString> aosHeaderAndFirstDataLine;
@@ -294,6 +295,8 @@ int OGRGFTTableLayer::FetchDescribe()
             poFeatureDefn->SetGeomType( eType );
     }
 
+    SetGeomFieldName();
+
     return TRUE;
 }
 
@@ -547,6 +550,8 @@ OGRErr OGRGFTTableLayer::CreateField( OGRFieldDefn *poField,
     {
         poFeatureDefn = new OGRFeatureDefn( osTableName );
         poFeatureDefn->Reference();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        poFeatureDefn->GetGeomFieldDefn(0)->SetName(GetDefaultGeometryColumnName());
     }
 
     poFeatureDefn->AddFieldDefn(poField);
@@ -576,6 +581,8 @@ void OGRGFTTableLayer::CreateTableIfNecessary()
         /* In case CreateField() hasn't yet been called */
         poFeatureDefn = new OGRFeatureDefn( osTableName );
         poFeatureDefn->Reference();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        poFeatureDefn->GetGeomFieldDefn(0)->SetName(GetDefaultGeometryColumnName());
     }
 
     /* If there are longitude and latitude fields, use the latitude */
diff --git a/ogr/ogrsf_frmts/gme/GNUmakefile b/ogr/ogrsf_frmts/gme/GNUmakefile
new file mode 100644
index 0000000..f3fbf39
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/GNUmakefile
@@ -0,0 +1,16 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	\
+	ogrgmedriver.o ogrgmedatasource.o ogrgmelayer.o ogrgmejson.o
+
+CPPFLAGS	:=	$(JSON_INCLUDE) -I../geojson -I.. -I../.. \
+	$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_gme.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gme/makefile.vc b/ogr/ogrsf_frmts/gme/makefile.vc
new file mode 100644
index 0000000..d790593
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrgmedriver.obj ogrgmedatasource.obj ogrgmelayer.obj ogrgmejson.obj
+EXTRAFLAGS =	-I.. -I..\.. -I..\geojson -I..\geojson\libjson
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/gme/ogr_gme.h b/ogr/ogrsf_frmts/gme/ogr_gme.h
new file mode 100644
index 0000000..699d17d
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogr_gme.h
@@ -0,0 +1,209 @@
+/******************************************************************************
+ * $Id: ogr_gft.h 25483 2013-01-10 17:06:59Z warmerdam $
+ *
+ * Project:  Google Maps Engine (GME) API Driver
+ * Purpose:  GME driver declarations
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *           (derived from GFT driver by Even)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_GME_H_INCLUDED
+#define _OGR_GME_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "ogrgeojsonreader.h"
+#include "cpl_http.h"
+
+#include <map>
+#include <vector>
+
+#include <json.h>
+
+/************************************************************************/
+/*                             OGRGMELayer                              */
+/************************************************************************/
+class OGRGMEDataSource;
+
+class OGRGMELayer : public OGRLayer
+{
+    OGRGMEDataSource* poDS;
+
+    OGRFeatureDefn*    poFeatureDefn;
+    OGRSpatialReference *poSRS;
+
+    int                iGeometryField;
+    int                iGxIdField;
+
+    CPLString          osTableName;
+    CPLString          osTableId;
+    std::map<int, CPLString> omnosIdToGMEKey;
+    std::map<int, OGRFeature *> omnpoUpdatedFeatures;
+    std::map<int, OGRFeature *> omnpoInsertedFeatures;
+    std::vector<long> oListOfDeletedFeatures;
+    CPLString          osGeomColumnName;
+
+    CPLString          osWhere;
+    CPLString          osSelect;
+
+    json_object*       current_feature_page;
+    json_object*       current_features_array;
+    int                index_in_page;
+
+    bool               bDirty;
+    bool               bCreateTablePending;
+    bool               bInTransaction;
+    unsigned int       iBatchPatchSize;
+    OGRwkbGeometryType eGTypeForCreation;
+    CPLString          osProjectId;
+    CPLString          osDraftACL;
+    CPLString          osPublishedACL;
+
+    void               GetPageOfFeatures();
+
+    void               BuildWhere(void);
+
+    int                FetchDescribe();
+
+    OGRFeature        *GetNextRawFeature();
+    void               GetPageOfFEatures();
+    OGRErr             BatchPatch();
+    OGRErr             BatchInsert();
+    OGRErr             BatchDelete();
+    OGRErr             BatchRequest(const char *osMethod, std::map<int, OGRFeature *> &omnpoFeatures);
+    unsigned int       GetBatchPatchSize();
+    bool               CreateTableIfNotCreated();
+
+  public:
+    OGRGMELayer(OGRGMEDataSource* poDS, const char* pszTableId);
+    OGRGMELayer(OGRGMEDataSource* poDS, const char* pszTableName, char ** papszOptions);
+    ~OGRGMELayer();
+
+    virtual void       ResetReading();
+    void               SetBatchPatchSize(unsigned int iSize);
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual const char *GetName() { return osTableName.c_str(); }
+
+    virtual OGRFeature *GetNextFeature();
+
+    virtual const char *GetGeometryColumn() { return osGeomColumnName; }
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRErr      SetAttributeFilter( const char * pszWhere );
+
+    virtual OGRErr      SetIgnoredFields(const char ** papszFields );
+
+    virtual OGRErr      SyncToDisk();
+
+    virtual OGRErr      SetFeature( OGRFeature *poFeature );
+    virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature(long int);
+    virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+
+    virtual OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+
+    void                SetGeometryType(OGRwkbGeometryType eGType);
+};
+
+/************************************************************************/
+/*                           OGRGMEDataSource                           */
+/************************************************************************/
+
+class OGRGMEDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    int                 bReadWrite;
+
+    int                 bUseHTTPS;
+
+    CPLString           osAuth;
+    CPLString           osAccessToken;
+    CPLString           osRefreshToken;
+    CPLString           osTraceToken;
+    CPLString           osAPIKey;
+    CPLString           osSelect;
+    CPLString           osWhere;
+    CPLString           osProjectId;
+
+    void                DeleteLayer( const char *pszLayerName );
+
+    int                 bMustCleanPersistant;
+    int                 nRetries;
+
+  public:
+                        OGRGMEDataSource();
+                        ~OGRGMEDataSource();
+
+    int                 Open( const char * pszFilename,
+                              int bUpdate );
+
+    virtual const char* GetName() { return pszName; }
+
+    virtual int         GetLayerCount() { return nLayers; }
+    virtual OGRLayer*   GetLayer( int );
+
+    virtual OGRLayer   *CreateLayer( const char *pszName,
+                                     OGRSpatialReference *poSpatialRef = NULL,
+                                     OGRwkbGeometryType eGType = wkbUnknown,
+                                     char ** papszOptions = NULL );
+
+    virtual int         TestCapability( const char * );
+
+    CPLHTTPResult*      MakeRequest(const char *pszRequest,
+                                    const char *pszMoreOptions = NULL);
+    CPLHTTPResult*      PostRequest(const char *pszRequest,
+                                    const char *pszBody);
+    const CPLString&    GetAccessToken() const { return osAccessToken;}
+    const char*         GetAPIURL() const;
+    int                 IsReadWrite() const { return bReadWrite; }
+    void                AddHTTPOptions(CPLStringList &oOptions);
+    void                AddHTTPPostOptions(CPLStringList &oOptions);
+
+};
+
+/************************************************************************/
+/*                             OGRGMEDriver                             */
+/************************************************************************/
+
+class OGRGMEDriver : public OGRSFDriver
+{
+  public:
+                ~OGRGMEDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual OGRDataSource*      CreateDataSource( const char * pszName,
+                                                  char **papszOptions );
+    virtual int                 TestCapability( const char * );
+};
+
+#endif /* ndef _OGR_GME_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp b/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp
new file mode 100644
index 0000000..81e8692
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp
@@ -0,0 +1,600 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Google Maps Engine API Driver
+ * Purpose:  OGRGMEDataSource Implementation.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *           (derived from GFT driver by Even)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_gme.h"
+#include "ogrgmejson.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id$");
+
+#define GDAL_API_KEY "AIzaSyA_2h1_wXMOLHNSVeo-jf1ACME-M1XMgP0"
+#define GME_TABLE_SCOPE_RO "https://www.googleapis.com/auth/mapsengine.readonly"
+#define GME_TABLE_SCOPE "https://www.googleapis.com/auth/mapsengine"
+
+/************************************************************************/
+/*                          OGRGMEDataSource()                          */
+/************************************************************************/
+
+OGRGMEDataSource::OGRGMEDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+
+    bReadWrite = FALSE;
+    bUseHTTPS = FALSE;
+
+    bMustCleanPersistant = FALSE;
+    nRetries = 0;
+}
+
+/************************************************************************/
+/*                         ~OGRGMEDataSource()                          */
+/************************************************************************/
+
+OGRGMEDataSource::~OGRGMEDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (bMustCleanPersistant)
+    {
+        char** papszOptions = CSLAddString(NULL, CPLSPrintf("CLOSE_PERSISTENT=GME:%p", this));
+        CPLHTTPFetch( GetAPIURL(), papszOptions);
+        CSLDestroy(papszOptions);
+    }
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGMEDataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    //else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+    //    return TRUE;
+    //else
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRGMEDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                      OGRGMEGetOptionValue()                          */
+/************************************************************************/
+
+CPLString OGRGMEGetOptionValue(const char* pszFilename,
+                               const char* pszOptionName)
+{
+    CPLString osOptionName(pszOptionName);
+    osOptionName += "=";
+    const char* pszOptionValue = strstr(pszFilename, osOptionName);
+    if (!pszOptionValue)
+        return "";
+
+    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
+    if (pszSpace)
+        osOptionValue.resize(pszSpace - osOptionValue.c_str());
+    return osOptionValue;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRGMEDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (!EQUALN(pszFilename, "GME:", 4))
+        return FALSE;
+
+    bReadWrite = bUpdateIn;
+
+    pszName = CPLStrdup( pszFilename );
+
+    osAuth = OGRGMEGetOptionValue(pszFilename, "auth");
+    if (osAuth.size() == 0)
+        osAuth = CPLGetConfigOption("GME_AUTH", "");
+
+    osRefreshToken = OGRGMEGetOptionValue(pszFilename, "refresh");
+    if (osRefreshToken.size() == 0)
+        osRefreshToken = CPLGetConfigOption("GME_REFRESH_TOKEN", "");
+
+    osAPIKey = CPLGetConfigOption("GME_APIKEY", GDAL_API_KEY);
+
+    CPLString osTables = OGRGMEGetOptionValue(pszFilename, "tables");
+
+    osProjectId = OGRGMEGetOptionValue(pszFilename, "projectId");
+
+    osSelect = OGRGMEGetOptionValue(pszFilename, "select");
+    osWhere = OGRGMEGetOptionValue(pszFilename, "where");
+
+    CPLString osBatchPatchSize;
+    osBatchPatchSize = OGRGMEGetOptionValue(pszFilename, "batchpatchsize");
+    if (osBatchPatchSize.size() == 0) {
+        osBatchPatchSize = CPLGetConfigOption("GME_BATCH_PATCH_SIZE","50");
+    }
+    int iBatchPatchSize = atoi( osBatchPatchSize.c_str() );
+
+    bUseHTTPS = TRUE;
+
+    osAccessToken = OGRGMEGetOptionValue(pszFilename, "access");
+    if (osAccessToken.size() == 0)
+        osAccessToken = CPLGetConfigOption("GME_ACCESS_TOKEN","");
+    if (osAccessToken.size() == 0 && osRefreshToken.size() > 0)
+    {
+        osAccessToken.Seize(GOA2GetAccessToken(osRefreshToken,
+                                               GME_TABLE_SCOPE)); // TODO
+        if (osAccessToken.size() == 0) {
+            CPLDebug( "GME", "Cannot get access token");
+            return FALSE;
+        }
+    }
+
+    if (osAccessToken.size() == 0 && osAuth.size() > 0)
+    {
+        osRefreshToken.Seize(GOA2GetRefreshToken(osAuth, GME_TABLE_SCOPE)); // TODO
+        if (osRefreshToken.size() == 0)
+            CPLDebug( "GME", "Cannot get refresh token");
+            return FALSE;
+    }
+
+    if ((osAccessToken.size() ==0) && (osTables.size() == 0))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unauthenticated access requires explicit tables= parameter");
+        return FALSE;
+    }
+
+    osTraceToken = OGRGMEGetOptionValue(pszFilename, "trace");
+    if (osTraceToken.size() == 0) {
+        CPLDebug("GME", "Looking for GME_TRACE_TOKEN");
+        osTraceToken = CPLGetConfigOption("GME_TRACE_TOKEN", "");
+    }
+    if (osTraceToken.size() != 0) {
+      CPLDebug("GME", "Found trace token %s", osTraceToken.c_str());
+    }
+
+    if (osTables.size() != 0)
+    {
+        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
+        for(int i=0;papszTables && papszTables[i];i++)
+        {
+            papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+            OGRGMELayer *poGMELayer = new OGRGMELayer(this, papszTables[i]);
+            poGMELayer->SetBatchPatchSize(iBatchPatchSize);
+            if (poGMELayer->GetLayerDefn()) {
+                papoLayers[nLayers ++] = poGMELayer;
+            }
+            else {
+                delete poGMELayer;
+            }
+        }
+        CSLDestroy(papszTables);
+        if ( nLayers == 0 ) {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Could not find any tables.");
+            return FALSE;
+        }
+        CPLDebug("GME", "Found %d layers", nLayers);
+        return TRUE;
+    }
+    else if (osProjectId.size() != 0) {
+        CPLDebug("GME", "We have a projectId: %s. Use CreateLayer to create tables.",
+                 osProjectId.c_str());
+        return TRUE;
+    }
+    CPLDebug("GME", "No table no project, giving up!");
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           CreateLayer()                              */
+/************************************************************************/
+
+OGRLayer   *OGRGMEDataSource::CreateLayer( const char *pszName,
+                                           OGRSpatialReference *poSpatialRef,
+                                           OGRwkbGeometryType eGType,
+                                           char ** papszOptions )
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
+        return NULL;
+    }
+
+    if (osAccessToken.size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in unauthenticated mode");
+        return NULL;
+    }
+
+    if ((CSLFetchNameValue( papszOptions, "projectId" ) == NULL) && (osProjectId.size() != 0)) {
+        papszOptions = CSLAddNameValue( papszOptions, "projectId", osProjectId.c_str() );
+    }
+
+    osTraceToken = OGRGMEGetOptionValue(pszName, "trace");
+    if (osTraceToken.size() == 0) {
+      osTraceToken = CPLGetConfigOption("GME_TRACE_TOKEN", "");
+    }
+    if (osTraceToken.size() != 0) {
+      CPLDebug("GME", "Found trace token %s", osTraceToken.c_str());
+    }
+
+    OGRGMELayer* poLayer = new OGRGMELayer(this, pszName, papszOptions);
+    poLayer->SetGeometryType(eGType);
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            GetAPIURL()                               */
+/************************************************************************/
+
+const char*  OGRGMEDataSource::GetAPIURL() const
+{
+    const char* pszAPIURL = CPLGetConfigOption("GME_API_URL", NULL);
+    if (pszAPIURL)
+        return pszAPIURL;
+    else if (bUseHTTPS)
+        return "https://www.googleapis.com/mapsengine/v1";
+    else
+        return "http://www.googleapis.com/mapsengine/v1";
+}
+
+/************************************************************************/
+/*                          AddHTTPOptions()                            */
+/************************************************************************/
+
+void OGRGMEDataSource::AddHTTPOptions(CPLStringList &oOptions)
+{
+    bMustCleanPersistant = TRUE;
+
+    if (strlen(osAccessToken) > 0)
+        oOptions.AddString(
+            CPLSPrintf("HEADERS=Authorization: Bearer %s",
+                       osAccessToken.c_str()));
+
+    oOptions.AddString(CPLSPrintf("PERSISTENT=GME:%p", this));
+}
+
+/************************************************************************/
+/*                            MakeRequest()                             */
+/************************************************************************/
+
+CPLHTTPResult * OGRGMEDataSource::MakeRequest(const char *pszRequest,
+                                              const char *pszMoreOptions)
+{
+/* -------------------------------------------------------------------- */
+/*      Provide the API Key - used to rate limit access (see            */
+/*      GME_APIKEY config)                                              */
+/* -------------------------------------------------------------------- */
+    CPLString osQueryFields;
+
+    osQueryFields += "key=";
+    osQueryFields += osAPIKey;
+
+    if (pszMoreOptions)
+        osQueryFields += pszMoreOptions;
+
+/* -------------------------------------------------------------------- */
+/*      Collect the header options.                                     */
+/* -------------------------------------------------------------------- */
+    CPLStringList oOptions;
+    oOptions.AddString("CUSTOMREQUEST=GET");
+    AddHTTPOptions(oOptions);
+
+/* -------------------------------------------------------------------- */
+/*      Build URL                                                       */
+/* -------------------------------------------------------------------- */
+    CPLString osURL = GetAPIURL();
+    osURL += "/";
+    osURL += pszRequest;
+
+    if (osURL.find("?") == std::string::npos) {
+        osURL += "?";
+    } else {
+        osURL += "?";
+    }
+    osURL += osQueryFields;
+
+    // Trace the request if we have a tracing token
+    if (osTraceToken.size() != 0) {
+      CPLDebug("GME", "Using trace token %s", osTraceToken.c_str());
+      osURL += "&trace=";
+      osURL += osTraceToken;
+    }
+
+    CPLDebug( "GME", "Sleep for 1s to try and avoid qps limiting errors.");
+    CPLSleep( 1.0 );
+
+    CPLHTTPResult * psResult = CPLHTTPFetch(osURL, oOptions);
+
+/* -------------------------------------------------------------------- */
+/*      Check for some error conditions and report.  HTML Messages      */
+/*      are transformed info failure.                                   */
+/* -------------------------------------------------------------------- */
+    if (psResult && psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "GME", "MakeRequest HTML Response: %s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server");
+        if (nRetries < 5) {
+            CPLDebug("GME", "Sleeping 30s and retrying");
+            nRetries ++;
+            CPLSleep( 30.0 );
+            psResult = MakeRequest(pszRequest, pszMoreOptions);
+            if (psResult)
+                CPLDebug( "GME", "Got a result after %d retries", nRetries );
+            else
+                CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
+            nRetries--;
+        } else {
+            CPLDebug("GME", "I've waited too long on GME. Giving up!");
+            CPLHTTPDestroyResult(psResult);
+            psResult = NULL;
+        }
+        return psResult;
+    }
+    if (psResult && psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "GME", "MakeRequest Error Message: %s", psResult->pszErrBuf );
+        CPLDebug( "GME", "error doc:\n%s\n", psResult->pabyData ? (const char*)psResult->pabyData : "null");
+        json_object *error_response = OGRGMEParseJSON((const char *) psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        psResult = NULL;
+        if( error_response != NULL )
+        {
+            json_object *error_doc = json_object_object_get(error_response, "error");
+            json_object *errors_doc = json_object_object_get(error_doc, "errors");
+            array_list *errors_array = json_object_get_array(errors_doc);
+            int nErrors = array_list_length(errors_array);
+            for (int i = 0; i < nErrors; i++) {
+                json_object *error_obj = (json_object *)array_list_get_idx(errors_array, i);
+                const char* reason = OGRGMEGetJSONString(error_obj, "reason", "");
+                const char* domain = OGRGMEGetJSONString(error_obj, "domain", "");
+                const char* message = OGRGMEGetJSONString(error_obj, "message", "");
+                const char* locationType = OGRGMEGetJSONString(error_obj, "locationType", "");
+                const char* location = OGRGMEGetJSONString(error_obj, "location", "");
+                if ((nRetries < 10) && EQUAL(reason, "rateLimitExceeded")) {
+                    // Sleep nRetries * 1.0s and retry
+                    nRetries ++;
+                    CPLDebug( "GME", "Got a %s (%d) times.", reason, nRetries );
+                    CPLDebug( "GME", "Sleep for %2.2f to try and avoid qps limiting errors.", 1.0 * nRetries );
+                    CPLSleep( 1.0 * nRetries );
+                    psResult = MakeRequest(pszRequest, pszMoreOptions);
+                    if (psResult)
+                        CPLDebug( "GME", "Got a result after %d retries", nRetries );
+                    else
+                        CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
+                    nRetries = 0;
+                }
+                else if (EQUAL(reason, "authError")) {
+                        CPLDebug( "GME", "Failed to GET %s: %s", pszRequest, message );
+                        CPLError( CE_Failure, CPLE_OpenFailed, "GME: %s", message);
+                }
+                else if (EQUAL(reason, "backendError")) {
+                        CPLDebug( "GME", "Backend error retrying: GET %s: %s", pszRequest, message );
+                        psResult = MakeRequest(pszRequest, pszMoreOptions);
+                }
+                else {
+                    int code = 444;
+                    json_object *code_child = json_object_object_get(error_doc, "code");
+                    if (code_child != NULL )
+                        code = json_object_get_int(code_child);
+
+                    CPLDebug( "GME", "MakeRequest Error for %s: %s:%d", pszRequest, reason, code);
+                    CPLError( CE_Failure, CPLE_AppDefined, "GME: %s %s %s: %s - %s",
+                            domain, reason, locationType, location, message );
+                }
+            }
+            json_object_put(error_response);
+        }
+        return psResult;
+    }
+    else if (psResult && psResult->nStatus != 0)
+    {
+        CPLDebug( "GME", "MakeRequest Error Status:%d", psResult->nStatus );
+    }
+    return psResult;
+}
+
+/************************************************************************/
+/*                        AddHTTPPostOptions()                          */
+/************************************************************************/
+
+void OGRGMEDataSource::AddHTTPPostOptions(CPLStringList &oOptions)
+{
+    bMustCleanPersistant = TRUE;
+
+    if (strlen(osAccessToken) > 0)
+        oOptions.AddString(
+            CPLSPrintf("HEADERS=Content-type: application/json\n"
+                       "Authorization: Bearer %s",
+                       osAccessToken.c_str()));
+
+    oOptions.AddString(CPLSPrintf("PERSISTENT=GME:%p", this));
+}
+
+/************************************************************************/
+/*                            PostRequest()                             */
+/************************************************************************/
+
+CPLHTTPResult * OGRGMEDataSource::PostRequest(const char *pszRequest,
+                                              const char *pszBody)
+{
+/* -------------------------------------------------------------------- */
+/*      Provide the API Key - used to rate limit access (see            */
+/*      GME_APIKEY config)                                              */
+/* -------------------------------------------------------------------- */
+    CPLString osQueryFields;
+
+    osQueryFields += "key=";
+    osQueryFields += osAPIKey;
+
+/* -------------------------------------------------------------------- */
+/*      Collect the header options.                                     */
+/* -------------------------------------------------------------------- */
+    CPLStringList oOptions;
+    oOptions.AddString("CUSTOMREQUEST=POST");
+    CPLString osPostFields = "POSTFIELDS=";
+    osPostFields += pszBody;
+    oOptions.AddString(osPostFields);
+
+    AddHTTPPostOptions(oOptions);
+
+/* -------------------------------------------------------------------- */
+/*      Build URL                                                       */
+/* -------------------------------------------------------------------- */
+    CPLString osURL = GetAPIURL();
+    osURL += "/";
+    osURL += pszRequest;
+
+    if (osURL.find("?") == std::string::npos) {
+        osURL += "?";
+    } else {
+        osURL += "?";
+    }
+    osURL += osQueryFields;
+
+    // Trace the request if we have a tracing token
+    if (osTraceToken.size() != 0) {
+      CPLDebug("GME", "Using trace token %s", osTraceToken.c_str());
+      osURL += "&trace=";
+      osURL += osTraceToken;
+    }
+
+    CPLDebug( "GME", "Sleep for 1s to try and avoid qps limiting errors.");
+    CPLSleep( 1.0 );
+
+    CPLDebug( "GME", "Posting to %s.", osURL.c_str());
+    CPLHTTPResult * psResult = CPLHTTPFetch(osURL, oOptions);
+
+/* -------------------------------------------------------------------- */
+/*      Check for some error conditions and report.  HTML Messages      */
+/*      are transformed info failure.                                   */
+/* -------------------------------------------------------------------- */
+    if (psResult && psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "GME", "PostRequest HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server");
+        CPLHTTPDestroyResult(psResult);
+        psResult = NULL;
+    }
+    if (psResult && psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "GME", "PostRequest Error Message: %s", psResult->pszErrBuf );
+        CPLDebug( "GME", "error doc:\n%s\n", psResult->pabyData);
+        json_object *error_response = OGRGMEParseJSON((const char *) psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        psResult = NULL;
+        json_object *error_doc = json_object_object_get(error_response, "error");
+        json_object *errors_doc = json_object_object_get(error_doc, "errors");
+        array_list *errors_array = json_object_get_array(errors_doc);
+        int nErrors = array_list_length(errors_array);
+        for (int i = 0; i < nErrors; i++) {
+            json_object *error_obj = (json_object *)array_list_get_idx(errors_array, i);
+            const char* reason = OGRGMEGetJSONString(error_obj, "reason", "");
+            const char* domain = OGRGMEGetJSONString(error_obj, "domain", "");
+            const char* message = OGRGMEGetJSONString(error_obj, "message", "");
+            const char* locationType = OGRGMEGetJSONString(error_obj, "locationType", "");
+            const char* location = OGRGMEGetJSONString(error_obj, "location", "");
+            if ((nRetries < 10) && EQUAL(reason, "rateLimitExceeded")) {
+                // Sleep nRetries * 1.0s and retry
+                nRetries ++;
+                CPLDebug( "GME", "Got a %s (%d) times.", reason, nRetries );
+                CPLDebug( "GME", "Sleep for %2.2f to try and avoid qps limiting errors.", 1.0 * nRetries );
+                CPLSleep( 1.0 * nRetries );
+                psResult = PostRequest(pszRequest, pszBody);
+                if (psResult)
+                    CPLDebug( "GME", "Got a result after %d retries", nRetries );
+                else
+                    CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
+                nRetries = 0;
+            }
+	    else if (EQUAL(reason, "authError")) {
+                CPLDebug( "GME", "Failed to GET %s: %s", pszRequest, message );
+                CPLError( CE_Failure, CPLE_OpenFailed, "GME: %s", message);
+	    }
+	    else if (EQUAL(reason, "backendError")) {
+                CPLDebug( "GME", "Backend error retrying: GET %s: %s", pszRequest, message );
+                psResult = PostRequest(pszRequest, pszBody);
+	    }
+            else {
+                int code = 444;
+                json_object *code_child = json_object_object_get(error_doc, "code");
+                if (code_child != NULL )
+                    code = json_object_get_int(code_child);
+
+                CPLError( CE_Failure, CPLE_AppDefined, "GME: %s %s %s: %s - %s",
+                          domain, reason, locationType, location, message );
+                if ((code == 400) && (EQUAL(reason, "invalid")) && (EQUAL(location, "id"))) {
+                  CPLDebug("GME", "Got the notorious 400 - invalid id, retrying in 10s");
+                  CPLSleep( 10.0 );
+                  psResult = PostRequest(pszRequest, pszBody);
+                }
+                else {
+                    CPLDebug( "GME", "PostRequest Error for %s: %s:%d", pszRequest, reason, code);
+                }
+            }
+        }
+        return psResult;
+    }
+    else if (psResult && psResult->nStatus != 0)
+    {
+        CPLDebug( "GME", "PostRequest Error Status:%d", psResult->nStatus );
+    }
+    return psResult;
+}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp b/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp
new file mode 100644
index 0000000..c9656d4
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp
@@ -0,0 +1,115 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Google Maps Engine API Driver
+ * Purpose:  OGRGMEDriver Implementation.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *           (derived from GFT driver by Even)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_gme.h"
+
+CPL_CVSID("$Id$");
+
+extern "C" void RegisterOGRGME();
+
+/************************************************************************/
+/*                           ~OGRGMEDriver()                            */
+/************************************************************************/
+
+OGRGMEDriver::~OGRGMEDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRGMEDriver::GetName()
+
+{
+    return "GME";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRGMEDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRGMEDataSource   *poDS = new OGRGMEDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+
+/************************************************************************/
+/*                          CreateDataSource()                          */
+/************************************************************************/
+
+OGRDataSource *OGRGMEDriver::CreateDataSource( const char * pszName,
+                                               char **papszOptions )
+
+{
+    OGRGMEDataSource   *poDS = new OGRGMEDataSource();
+
+    if( !poDS->Open( pszName, TRUE ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGMEDriver::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, ODrCCreateDataSource))
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRGME()                           */
+/************************************************************************/
+
+void RegisterOGRGME()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRGMEDriver );
+}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmejson.cpp b/ogr/ogrsf_frmts/gme/ogrgmejson.cpp
new file mode 100644
index 0000000..ce5b6b3
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogrgmejson.cpp
@@ -0,0 +1,547 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Google Maps Engine API Driver
+ * Purpose:  GME GeoJSON helpper function Implementations.
+ * Author:   Wolf Beregnheim <wolf+grass at bergenheim.net>
+ *           (derived from Geo JSON driver by Mateusz)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrgmejson.h"
+#include <printbuf.h>
+
+static int json_gme_double_to_string(json_object *jso,
+                                     printbuf *pb,
+                                     int level,
+                                     int flags);
+
+/************************************************************************/
+/*                      OGRGMEFeatureToGeoJSON()                        */
+/************************************************************************/
+json_object* OGRGMEFeatureToGeoJSON(OGRFeature* poFeature)
+
+{
+    if( NULL == poFeature )
+        return NULL;
+
+    json_object* pjoFeature = json_object_new_object();
+    CPLAssert( NULL != pjoFeature );
+
+    json_object_object_add( pjoFeature, "type",
+                            json_object_new_string("Feature") );
+
+    /* -------------------------------------------------------------------- */
+    /*      Write feature geometry to GeoJSON "geometry" object.            */
+    /* -------------------------------------------------------------------- */
+    json_object* pjoGeometry = NULL;
+    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
+
+    pjoGeometry = OGRGMEGeometryToGeoJSON(poGeometry);
+    if ( NULL == pjoGeometry ) {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GME: NULL Geometry detected in feature %ld. Ignoring feature.",
+                  poFeature->GetFID() );
+        json_object_put( pjoFeature );
+        return NULL;
+    }
+    json_object_object_add( pjoFeature, "geometry", pjoGeometry );
+
+    /* -------------------------------------------------------------------- */
+    /*      Write feature attributes to GeoJSON "properties" object.        */
+    /* -------------------------------------------------------------------- */
+    json_object* pjoProps = NULL;
+
+    pjoProps = OGRGMEAttributesToGeoJSON( poFeature );
+    if ( pjoProps )
+        json_object_object_add( pjoFeature, "properties", pjoProps );
+
+    return pjoFeature;
+}
+
+/************************************************************************/
+/*                        OGRGMEGeometryToGeoJSON()                     */
+/************************************************************************/
+json_object* OGRGMEGeometryToGeoJSON(OGRGeometry* poGeometry)
+
+{
+    if ( NULL == poGeometry )
+        return NULL;
+
+    json_object* pjoGeometry = json_object_new_object();
+    CPLAssert( NULL != pjoGeometry );
+
+    /* -------------------------------------------------------------------- */
+    /*      Build "type" member of GeoJSOn "geometry" object                */
+    /*      and "coordinates" member of GeoJSOn "geometry" object.          */
+    /* -------------------------------------------------------------------- */
+    const char* pszType = NULL;
+    OGRwkbGeometryType eType = poGeometry->getGeometryType();
+    json_object* pjoCoordinates = NULL;
+    if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
+    {
+        pszType = "GeometryCollection";
+        json_object *pjoGeometries =
+            OGRGMEGeometryCollectionToGeoJSON(static_cast<OGRGeometryCollection*>(poGeometry));
+        if ( pjoGeometries ) {
+            json_object *pjoType = json_object_new_string(pszType);
+            json_object_object_add( pjoGeometry, "type", pjoType );
+            json_object_object_add( pjoGeometry, "geometries", pjoGeometries );
+        }
+        else {
+            json_object_put(pjoGeometry);
+            pjoGeometry = NULL;
+        }            
+    }
+    else 
+    {
+        if( wkbPoint == eType || wkbPoint25D == eType ) {
+            pszType = "Point";
+            pjoCoordinates = OGRGMEPointToGeoJSON( static_cast<OGRPoint*>(poGeometry) );
+        }
+        if( wkbMultiPoint == eType || wkbMultiPoint25D == eType ) {
+            pszType = "MultiPoint";
+            pjoCoordinates = OGRGMEMultiPointToGeoJSON( static_cast<OGRMultiPoint*>(poGeometry) );
+        }
+        else if( wkbLineString == eType || wkbLineString25D == eType ) {
+            pszType = "LineString";
+            pjoCoordinates = OGRGMELineStringToGeoJSON( static_cast<OGRLineString*>(poGeometry) );
+        }
+        else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType ) {
+            pszType = "MultiLineString";
+            pjoCoordinates = OGRGMEMultiLineStringToGeoJSON( static_cast<OGRMultiLineString*>(poGeometry) );
+        }
+        else if( wkbPolygon == eType || wkbPolygon25D == eType ) {
+            pszType = "Polygon";
+            pjoCoordinates = OGRGMEPolygonToGeoJSON( static_cast<OGRPolygon*>(poGeometry) );
+        }
+        else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType ) {
+            pszType = "MultiPolygon";
+            pjoCoordinates = OGRGMEMultiPolygonToGeoJSON( static_cast<OGRMultiPolygon*>(poGeometry) );
+        }
+        else {
+            CPLDebug( "GME", "Unsupported geometry type detected. Geometry is IGNORED." );
+        }
+
+        if ( pjoCoordinates && pszType ) {
+            json_object *pjoType = json_object_new_string(pszType);
+            json_object_object_add( pjoGeometry, "type", pjoType );
+            json_object_object_add( pjoGeometry, "coordinates", pjoCoordinates);
+        }
+        else {
+            json_object_put(pjoGeometry);
+            pjoGeometry = NULL;
+        }
+    }
+    return pjoGeometry;
+}
+
+/************************************************************************/
+/*                  OGRGMEGeometryCollectionToGeoJSON()                 */
+/************************************************************************/
+json_object* OGRGMEGeometryCollectionToGeoJSON(OGRGeometryCollection* poGeometryCollection)
+
+{
+    if ( NULL == poGeometryCollection )
+        return NULL;
+
+    /* Generate "geometries" object. */
+    json_object* pjoGeometries = NULL;
+    pjoGeometries = json_object_new_array();
+
+    for( int i = 0; i < poGeometryCollection->getNumGeometries(); ++i ) {
+        OGRGeometry* poGeometry = poGeometryCollection->getGeometryRef( i );
+        json_object* pjoGeometry = NULL;
+        pjoGeometry = OGRGMEGeometryToGeoJSON( poGeometry );
+        if ( NULL != poGeometry )
+            json_object_array_add( pjoGeometries, pjoGeometry );
+        else
+            CPLError( CE_Failure, CPLE_AppDefined, "GME: Ignoring NULL geometry" );
+    }
+    return pjoGeometries;
+}
+
+/************************************************************************/
+/*                           OGRGMEPointToGeoJSON                       */
+/************************************************************************/
+
+json_object* OGRGMEPointToGeoJSON( OGRPoint* poPoint )
+{
+    if( NULL == poPoint )
+        return NULL;
+
+    json_object* pjoCoordinates = NULL;
+
+    /* Generate "coordinates" object for 2D or 3D dimension. */
+    if( 3 == poPoint->getCoordinateDimension() ) {
+        pjoCoordinates = OGRGMECoordsToGeoJSON( poPoint->getX(),
+                                                poPoint->getY(),
+                                                poPoint->getZ() );
+    }
+    else if( 2 == poPoint->getCoordinateDimension() ) {
+        pjoCoordinates = OGRGMECoordsToGeoJSON( poPoint->getX(),
+                                                poPoint->getY() );
+    }
+    else {
+        CPLError( CE_Failure, CPLE_AppDefined, "GME: Found EMPTY point, ignoring" );
+    }
+
+    return pjoCoordinates;
+}
+
+/************************************************************************/
+/*                           OGRGMEMultiPointToGeoJSON                  */
+/************************************************************************/
+
+json_object* OGRGMEMultiPointToGeoJSON( OGRMultiPoint* poGeometry )
+{
+    if( NULL == poGeometry )
+        return NULL;
+
+    /* Generate "coordinates" object for 2D or 3D dimension. */
+    json_object* pjoMultiPoint = NULL;
+    pjoMultiPoint = json_object_new_array();
+
+    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
+        {
+            OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
+            CPLAssert( NULL != poGeom );
+            OGRPoint* poPoint = static_cast<OGRPoint*>(poGeom);
+
+            json_object* pjoPoint = NULL;
+            pjoPoint = OGRGMEPointToGeoJSON( poPoint );
+            if ( pjoPoint )
+                json_object_array_add( pjoMultiPoint, pjoPoint );
+        }
+
+    return pjoMultiPoint;
+}
+
+/************************************************************************/
+/*                           OGRGMELineStringToGeoJSON                  */
+/************************************************************************/
+
+json_object* OGRGMELineStringToGeoJSON( OGRLineString* poLine )
+{
+    if( NULL == poLine )
+        return NULL;
+
+    /* Generate "coordinates" object for 2D or 3D dimension. */
+    json_object* pjoLineString = NULL;
+    pjoLineString = OGRGMELineCoordsToGeoJSON( poLine );
+
+    return pjoLineString;
+}
+
+/************************************************************************/
+/*                           OGRGMEMultiLineStringToGeoJSON             */
+/************************************************************************/
+
+json_object* OGRGMEMultiLineStringToGeoJSON( OGRMultiLineString* poGeometry )
+{
+    CPLAssert( NULL != poGeometry );
+
+    /* Generate "coordinates" object for 2D or 3D dimension. */
+    json_object* pjoCoordinates = NULL;
+    pjoCoordinates = json_object_new_array();
+
+    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
+    {
+        OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
+        CPLAssert( NULL != poGeom );
+        OGRLineString* poLine = static_cast<OGRLineString*>(poGeom);
+
+        json_object* pjoLine = NULL;
+        pjoLine = OGRGMELineStringToGeoJSON( poLine );
+
+        json_object_array_add( pjoCoordinates, pjoLine );
+    }
+
+    return pjoCoordinates;
+}
+
+/************************************************************************/
+/*                           OGRGMEPolygonToGeoJSON                     */
+/************************************************************************/
+
+json_object* OGRGMEPolygonToGeoJSON( OGRPolygon* poPolygon )
+{
+    CPLAssert( NULL != poPolygon );
+
+    /* Generate "coordinates" array object. */
+    json_object* pjoCoordinates = NULL;
+    pjoCoordinates = json_object_new_array();
+
+    /* Exterior ring. */
+    OGRLinearRing* poRing = poPolygon->getExteriorRing();
+    if (poRing == NULL) {
+        json_object_put(pjoCoordinates);
+        return NULL;
+    }
+
+    json_object* pjoRing = NULL;
+    // If the linear ring is CW re-wind it CCW
+    if (poRing->isClockwise() ) {
+      poRing->reverseWindingOrder();;
+    }
+
+    pjoRing = OGRGMELineCoordsToGeoJSON( poRing );
+    json_object_array_add( pjoCoordinates, pjoRing );
+
+    /* Interior rings. */
+    const int nCount = poPolygon->getNumInteriorRings();
+    for( int i = 0; i < nCount; ++i ) {
+        poRing = poPolygon->getInteriorRing( i );
+        if (poRing == NULL)
+            continue;
+        // If the linear ring is CW re-wind it CCW
+        pjoRing = OGRGMELineCoordsToGeoJSON( poRing );
+        json_object_array_add( pjoCoordinates, pjoRing );
+    }
+
+    return pjoCoordinates;
+}
+
+/************************************************************************/
+/*                           OGRGMEMultiPolygonToGeoJSON                */
+/************************************************************************/
+
+json_object* OGRGMEMultiPolygonToGeoJSON( OGRMultiPolygon* poGeometry )
+{
+    CPLAssert( NULL != poGeometry );
+
+    /* Generate "coordinates" object for 2D or 3D dimension. */
+    json_object* pjoCoordinates = NULL;
+    pjoCoordinates = json_object_new_array();
+
+    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
+    {
+        OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
+        CPLAssert( NULL != poGeom );
+        OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
+
+        json_object* pjoPoly = NULL;
+        pjoPoly = OGRGMEPolygonToGeoJSON( poPoly );
+
+        json_object_array_add( pjoCoordinates, pjoPoly );
+    }
+
+    return pjoCoordinates;
+}
+
+/************************************************************************/
+/*                           OGRGMECoordsToGeoJSON                      */
+/************************************************************************/
+
+json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY )
+{
+    json_object* pjoCoords = NULL;
+    pjoCoords = json_object_new_array();
+    json_object_array_add( pjoCoords, json_object_new_gme_double( fX ) );
+    json_object_array_add( pjoCoords, json_object_new_gme_double( fY ) );
+
+    return pjoCoords;
+}
+
+json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY, double const& fZ )
+{
+    json_object* pjoCoords = NULL;
+    pjoCoords = json_object_new_array();
+    json_object_array_add( pjoCoords, json_object_new_gme_double( fX ) );
+    json_object_array_add( pjoCoords, json_object_new_gme_double( fY ) );
+    json_object_array_add( pjoCoords, json_object_new_gme_double( fZ ) );
+
+    return pjoCoords;
+}
+
+/************************************************************************/
+/*                           OGRGMELineCoordsToGeoJSON                  */
+/************************************************************************/
+
+json_object* OGRGMELineCoordsToGeoJSON( OGRLineString* poLine )
+{
+    json_object* pjoCoords = json_object_new_array();
+
+    const int nCount = poLine->getNumPoints();
+    for( int i = 0; i < nCount; ++i )
+    {
+        json_object* pjoPoint = NULL;
+        if( poLine->getCoordinateDimension() == 2 )
+            pjoPoint = OGRGMECoordsToGeoJSON( poLine->getX(i), poLine->getY(i) );
+        else
+            pjoPoint = OGRGMECoordsToGeoJSON( poLine->getX(i), poLine->getY(i), poLine->getZ(i) );
+        json_object_array_add( pjoCoords, pjoPoint );
+    }
+
+    return pjoCoords;
+}
+
+/************************************************************************/
+/*                          OGRGMEAttributesToGeoJSON                   */
+/************************************************************************/
+
+json_object* OGRGMEAttributesToGeoJSON( OGRFeature* poFeature )
+{
+    if ( NULL == poFeature )
+        return NULL;
+    json_object* pjoProperties = json_object_new_object();
+    CPLAssert( NULL != pjoProperties );
+
+    OGRFeatureDefn* poDefn = poFeature->GetDefnRef();
+    for( int nField = 0; nField < poDefn->GetFieldCount(); ++nField ) {
+        json_object* pjoProperty = NULL;
+        OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn( nField );
+        if ( NULL == poFieldDefn )
+            continue;
+        OGRFieldType eType = poFieldDefn->GetType();
+
+        if( !poFeature->IsFieldSet(nField) )
+            pjoProperty = NULL;
+
+        // In GME integers are encoded as strings.
+        else if( OFTInteger == eType )
+            pjoProperty = json_object_new_string( poFeature->GetFieldAsString( nField ) );
+
+        else if( OFTReal == eType )
+            pjoProperty = json_object_new_gme_double( poFeature->GetFieldAsDouble(nField) );
+
+        // Supported types are integer, double and string. So treating everything else as strings
+        else
+            pjoProperty = json_object_new_string( poFeature->GetFieldAsString(nField) );
+
+        json_object_object_add( pjoProperties, poFieldDefn->GetNameRef(), pjoProperty );
+    }
+    int nGxId = poFeature->GetFieldIndex("gx_id");
+    if (nGxId < 0) {
+        json_object* pjoProperty = NULL;
+        long nFID = poFeature->GetFID();
+
+        char acGxId[128];
+        snprintf(acGxId, 128, "GDAL-%ld", nFID);
+        CPLDebug("GME", "gx_id is not set, so adding \"gx_id\": \"%s\" field.",
+                 acGxId);
+
+        pjoProperty = json_object_new_string( acGxId );
+        json_object_object_add( pjoProperties, "gx_id", pjoProperty);
+    }
+
+    return pjoProperties;
+}
+
+/************************************************************************/
+/*                        json_object_new_gme_double()                  */
+/************************************************************************/
+
+json_object* json_object_new_gme_double(double dfVal)
+
+{
+    json_object* pjoD = json_object_new_double(dfVal);
+    json_object_set_serializer(pjoD, json_gme_double_to_string, NULL, NULL );
+
+    return pjoD;
+}
+
+/************************************************************************/
+/*                        json_gme_double_to_string()                   */
+/************************************************************************/
+
+static int json_gme_double_to_string(json_object *pjo,
+                                     printbuf *pb,
+                                     int level,
+                                     int flags)
+{
+  char buf[128], *p, *q;
+  int size;
+
+  size = snprintf(buf, 128, "%.8f", json_object_get_double(pjo));
+  p = strchr(buf, ',');
+  if (p) {
+    *p = '.';
+  } else {
+    p = strchr(buf, '.');
+  }
+  if (p) {
+    /* last useful digit, always keep 1 zero */
+    p++;
+    for (q=p ; *q ; q++) {
+      if (*q!='0') p=q;
+    }
+    /* drop trailing zeroes */
+    *(++p) = 0;
+    size = p-buf;
+  }
+  printbuf_memappend(pb, buf, size);
+  return size;
+}
+
+/************************************************************************/
+/*                       OGRGMEParseJSON()                              */
+/************************************************************************/
+
+json_object *OGRGMEParseJSON( const char* pszText )
+{
+    if( NULL != pszText )
+    {
+        json_tokener* jstok = NULL;
+        json_object* jsobj = NULL;
+
+        jstok = json_tokener_new();
+        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
+        if( jstok->err != json_tokener_success)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "JSON parsing error: %s (at offset %d)",
+                          json_tokener_errors[jstok->err], jstok->char_offset);
+
+            json_tokener_free(jstok);
+            return NULL;
+        }
+        json_tokener_free(jstok);
+
+        /* JSON tree is shared for while lifetime of the reader object
+         * and will be released in the destructor.
+         */
+        return jsobj;
+    }
+
+    return NULL;
+}
+
+
+/************************************************************************/
+/*                        OGRGMEGetJSONString()                         */
+/*                                                                      */
+/*      Fetch a string field from a json_object (only an immediate      */
+/*      child).                                                         */
+/************************************************************************/
+
+const char *OGRGMEGetJSONString(json_object *parent,
+                               const char *field,
+                               const char *default_value)
+{
+    json_object *child = json_object_object_get(parent, field);
+    if (child == NULL )
+        return default_value;
+
+    return json_object_get_string(child);
+}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmejson.h b/ogr/ogrsf_frmts/gme/ogrgmejson.h
new file mode 100644
index 0000000..7799f64
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogrgmejson.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Google Maps Engine (GME) API Driver
+ * Purpose:  GME Geo JSON helper functions.
+ * Author:   Wolf Bergenheim <wolf+grass at bergenheim.net>
+ *           (derived from the GeoJSON driver by Mateusz)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_GME_JSON_H_INCLUDED
+#define _OGR_GME_JSON_H_INCLUDED
+
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include <json.h>
+
+json_object* OGRGMEFeatureToGeoJSON(OGRFeature* poFeature);
+json_object* OGRGMEGeometryToGeoJSON(OGRGeometry* poGeometry);
+json_object* OGRGMEGeometryCollectionToGeoJSON(OGRGeometryCollection* poGeometryCollection);
+json_object* OGRGMEPointToGeoJSON( OGRPoint* poPoint );
+json_object* OGRGMEMultiPointToGeoJSON( OGRMultiPoint* poGeometry );
+json_object* OGRGMELineStringToGeoJSON( OGRLineString* poLine );
+json_object* OGRGMEMultiLineStringToGeoJSON( OGRMultiLineString* poGeometry );
+json_object* OGRGMEPolygonToGeoJSON( OGRPolygon* poPolygon );
+json_object* OGRGMEMultiPolygonToGeoJSON( OGRMultiPolygon* poGeometry );
+json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY );
+json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY, double const& fZ );
+json_object* OGRGMELineCoordsToGeoJSON( OGRLineString* poLine );
+json_object* OGRGMEAttributesToGeoJSON( OGRFeature* poFeature );
+
+json_object* json_object_new_gme_double(double dfVal);
+
+json_object* OGRGMEParseJSON( const char* pszText );
+const char*  OGRGMEGetJSONString(json_object *parent,
+                                 const char *field_name,
+                                 const char *default_value = NULL);
+
+#endif /* ndef _OGR_GME_JSON_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp b/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp
new file mode 100644
index 0000000..1c91782
--- /dev/null
+++ b/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp
@@ -0,0 +1,952 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Google Maps Engine API Driver
+ * Purpose:  OGRGMELayer Implementation.
+ * Author:   Wolf Beregnheim <wolf+grass at bergenheim.net>
+ *           Frank Warmerdam <warmerdam at pobox.com>
+ *           (derived from GFT driver by Even)
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_gme.h"
+#include "ogrgmejson.h"
+
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: ogrgmetablelayer.cpp 25475 2013-01-09 09:09:59Z warmerdam $");
+
+/************************************************************************/
+/*                            OGRGMELayer()                             */
+/************************************************************************/
+
+OGRGMELayer::OGRGMELayer(OGRGMEDataSource* poDS,
+                         const char* pszTableId)
+
+{
+    CPLDebug("GME", "Opening existing layer %s", pszTableId);
+    this->poDS = poDS;
+    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+    poFeatureDefn = NULL;
+    current_feature_page = NULL;
+    bDirty = false;
+    iBatchPatchSize = 50;
+    bCreateTablePending = false;
+    osTableId = pszTableId;
+    bInTransaction = false;
+}
+
+
+OGRGMELayer::OGRGMELayer(OGRGMEDataSource* poDS,
+                         const char* pszTableName,
+                         char ** papszOptions)
+
+{
+    CPLDebug("GME", "Creating new layer %s", pszTableName);
+    this->poDS = poDS;
+    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+    poFeatureDefn = NULL;
+    current_feature_page = NULL;
+    bDirty = false;
+    iBatchPatchSize = 50;
+    bCreateTablePending = true;
+    osTableName = pszTableName;
+    osProjectId = CSLFetchNameValue( papszOptions, "projectId" );
+    osDraftACL = CSLFetchNameValueDef( papszOptions, "draftAccessList", "Map Editors" );
+    osPublishedACL = CSLFetchNameValueDef( papszOptions, "publishedAccessList", "Map Viewers" );
+    // TODO: support tags and description
+}
+
+/************************************************************************/
+/*                            ~OGRGMELayer()                            */
+/************************************************************************/
+
+OGRGMELayer::~OGRGMELayer()
+
+{
+    SyncToDisk();
+    ResetReading();
+    if( poSRS )
+        poSRS->Release();
+    if( poFeatureDefn )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGMELayer::ResetReading()
+
+{
+    if (current_feature_page != NULL)
+    {
+        json_object_put(current_feature_page);
+        current_feature_page = NULL;
+        m_nFeaturesRead = 0;
+
+        // TODO - clear current page.
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGMELayer::TestCapability( const char * pszCap )
+
+{
+    if(EQUAL(pszCap,OLCStringsAsUTF8))
+        return TRUE;
+    else if(EQUAL(pszCap,OLCIgnoreFields))
+        return TRUE;
+    else if(EQUAL(pszCap,OLCRandomWrite))
+        return TRUE;
+    else if(EQUAL(pszCap,OLCTransactions))
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                             SyncToDisk()                             */
+/************************************************************************/
+
+OGRErr OGRGMELayer::SyncToDisk()
+
+{
+    CPLDebug("GME", "SyncToDisk()");
+    if (bDirty) {
+        if (omnpoInsertedFeatures.size() > 0) {
+            BatchInsert();
+        }
+        if (omnpoUpdatedFeatures.size() > 0) {
+            BatchPatch();
+        }
+        if (oListOfDeletedFeatures.size() > 0) {
+            BatchDelete();
+        }
+        bDirty = false;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           FetchDescribe()                            */
+/************************************************************************/
+
+int OGRGMELayer::FetchDescribe()
+{
+    CPLString osRequest = "tables/" + osTableId;
+
+    CPLHTTPResult *psDescribe = poDS->MakeRequest(osRequest);
+    if (psDescribe == NULL)
+        return FALSE;
+
+    CPLDebug("GME", "table doc = %s\n", psDescribe->pabyData);
+
+    json_object *table_doc =
+        OGRGMEParseJSON((const char *) psDescribe->pabyData);
+
+    CPLHTTPDestroyResult(psDescribe);
+
+    osTableName = OGRGMEGetJSONString(table_doc, "name");
+
+    poFeatureDefn = new OGRFeatureDefn(osTableName);
+    poFeatureDefn->Reference();
+
+    json_object *schema_doc = json_object_object_get(table_doc, "schema");
+    json_object *columns_doc = json_object_object_get(schema_doc, "columns");
+    array_list *column_list = json_object_get_array(columns_doc);
+
+    CPLString osLastGeomColumn;
+
+    int field_count = array_list_length(column_list);
+    for( int i = 0; i < field_count; i++ )
+    {
+        OGRwkbGeometryType eFieldGeomType = wkbNone;
+
+        json_object *field_obj = (json_object*)
+            array_list_get_idx(column_list, i);
+
+	const char* name = OGRGMEGetJSONString(field_obj, "name");
+        OGRFieldDefn oFieldDefn(name, OFTString);
+        const char *type = OGRGMEGetJSONString(field_obj, "type");
+
+        if (EQUAL(type, "integer"))
+            oFieldDefn.SetType(OFTInteger);
+        else if (EQUAL(type, "double"))
+            oFieldDefn.SetType(OFTReal);
+        else if (EQUAL(type, "boolean"))
+            oFieldDefn.SetType(OFTInteger);
+        else if (EQUAL(type, "string"))
+            oFieldDefn.SetType(OFTString);
+        else if (EQUAL(type, "string")) {
+            if (EQUAL(name, "gx_id")) {
+                iGxIdField = i;
+            }
+            oFieldDefn.SetType(OFTString);
+        }
+        else if (EQUAL(type, "points"))
+            eFieldGeomType = wkbPoint;
+        else if (EQUAL(type, "linestrings"))
+            eFieldGeomType = wkbLineString;
+        else if (EQUAL(type, "polygons"))
+            eFieldGeomType = wkbPolygon;
+        else if (EQUAL(type, "mixedGeometry"))
+            eFieldGeomType = wkbGeometryCollection;
+
+        if (eFieldGeomType == wkbNone)
+        {
+            poFeatureDefn->AddFieldDefn(&oFieldDefn);
+        }
+        else
+        {
+            CPLAssert(EQUAL(osGeomColumnName,""));
+            osGeomColumnName = oFieldDefn.GetNameRef();
+            poFeatureDefn->SetGeomType(eFieldGeomType);
+            poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        }
+    }
+
+    json_object_put(table_doc);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         GetPageOfFeatures()                          */
+/************************************************************************/
+
+void OGRGMELayer::GetPageOfFeatures()
+{
+    CPLString osNextPageToken;
+
+    if (current_feature_page != NULL)
+    {
+        osNextPageToken = OGRGMEGetJSONString(current_feature_page,
+                                              "nextPageToken", "");
+        json_object_put(current_feature_page);
+        current_feature_page = NULL;
+
+        // End of query results?
+        if (EQUAL(osNextPageToken,""))
+            return;
+    }
+
+    index_in_page = 0;
+    current_features_array = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch features.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLString osRequest = "tables/" + osTableId + "/features";
+    CPLString osMoreOptions = "&maxResults=1000";
+
+    if (!EQUAL(osNextPageToken,""))
+    {
+        osMoreOptions += "&pageToken=";
+        osMoreOptions += osNextPageToken;
+    }
+    if (!osSelect.empty()) {
+        CPLDebug( "GME", "found select=%s", osSelect.c_str());
+        osMoreOptions += "&select=";
+        osMoreOptions += osSelect;
+    }
+    if (!osWhere.empty()) {
+        CPLDebug( "GME Layer", "found where=%s", osWhere.c_str());
+        osMoreOptions += "&where=";
+        osMoreOptions += osWhere;
+    }
+
+    CPLHTTPResult *psFeaturesResult =
+        poDS->MakeRequest(osRequest, osMoreOptions);
+
+    if (psFeaturesResult == NULL) {
+        CPLDebug("GME", "Got NULL from MakeRequest. Something went wrong. You figure it out!");
+        current_feature_page = NULL;
+        return;
+    }
+    CPLDebug("GME",
+             "features doc = %s...",
+             psFeaturesResult->pabyData);
+
+/* -------------------------------------------------------------------- */
+/*      Parse result.                                                   */
+/* -------------------------------------------------------------------- */
+
+    current_feature_page =
+        OGRGMEParseJSON((const char *) psFeaturesResult->pabyData);
+    CPLHTTPDestroyResult(psFeaturesResult);
+
+    current_features_array =
+        json_object_object_get(current_feature_page, "features");
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRGMELayer::GetNextRawFeature()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Fetch a new page of features if needed.                         */
+/* -------------------------------------------------------------------- */
+    if (current_feature_page == NULL
+        || index_in_page >= json_object_array_length(current_features_array))
+    {
+        GetPageOfFeatures();
+    }
+
+    if (current_feature_page == NULL)
+    {
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Identify our json feature.                                      */
+/* -------------------------------------------------------------------- */
+    json_object *feature_obj =
+        json_object_array_get_idx(current_features_array, index_in_page++);
+    if (feature_obj == NULL) 
+        return NULL;
+
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+
+/* -------------------------------------------------------------------- */
+/*      Handle properties.                                              */
+/* -------------------------------------------------------------------- */
+    json_object *properties_obj =
+        json_object_object_get(feature_obj, "properties");
+    for (int iOGRField = 0;
+         iOGRField < poFeatureDefn->GetFieldCount(); 
+         iOGRField++ ) 
+    {
+        const char *pszValue = 
+            OGRGMEGetJSONString(
+                properties_obj, 
+                poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef(),
+                NULL);
+        if (pszValue != NULL) {
+            poFeature->SetField(iOGRField, pszValue);
+	}
+    }
+/* -------------------------------------------------------------------- */
+/*      Handle gx_id.                                                   */
+/* -------------------------------------------------------------------- */
+    const char *gx_id = OGRGMEGetJSONString(properties_obj, "gx_id");
+    CPLString gmeId(gx_id);
+    omnosIdToGMEKey[++m_nFeaturesRead] = gmeId;
+    poFeature->SetFID(m_nFeaturesRead);
+    CPLDebug("GME", "Mapping ids: \"%s\" to %d", gx_id, (int)m_nFeaturesRead);
+
+/* -------------------------------------------------------------------- */
+/*      Handle geometry.                                                */
+/* -------------------------------------------------------------------- */
+    json_object *geometry_obj =
+        json_object_object_get(feature_obj, "geometry");
+    OGRGeometry *poGeometry = NULL;
+
+    if (geometry_obj != NULL) 
+    {
+        poGeometry = OGRGeoJSONReadGeometry(geometry_obj);
+    }
+
+    if (poGeometry != NULL) 
+    {
+        poGeometry->assignSpatialReference(poSRS);
+        poFeature->SetGeometryDirectly(poGeometry);
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRGMELayer::GetNextFeature()
+{
+    OGRFeature *poFeature = NULL;
+    
+    while( TRUE )
+    {
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            break;
+
+        // incremeted in GetNextRawFeature()
+        // m_nFeaturesRead++;
+
+        if( (m_poFilterGeom == NULL
+             || poFeature->GetGeometryRef() == NULL 
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            break;
+
+        delete poFeature;
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRGMELayer::GetLayerDefn()
+{
+    if (poFeatureDefn == NULL)
+    {
+        if (osTableId.size() == 0)
+            return NULL;
+        if (!FetchDescribe())
+	    return NULL;
+    }
+
+    return poFeatureDefn;
+}
+
+
+/************************************************************************/
+/*                        SetAttributeFilter()                          */
+/************************************************************************/
+
+OGRErr OGRGMELayer::SetAttributeFilter( const char *pszWhere )
+{
+    OGRErr eErr;
+    eErr = OGRLayer::SetAttributeFilter(pszWhere);
+    if( eErr == OGRERR_NONE ) {
+        if ( pszWhere ) {
+            char * pszEscaped = CPLEscapeString(pszWhere, -1, CPLES_URL);
+            osWhere = CPLString(pszEscaped);
+            CPLFree(pszEscaped);
+        }
+        else {
+            osWhere = "";
+        }
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                       SetIgnoredFields()                             */
+/************************************************************************/
+
+OGRErr OGRGMELayer::SetIgnoredFields(const char ** papszFields )
+{
+    osSelect = "geometry";
+    OGRErr eErr;
+    eErr = OGRLayer::SetIgnoredFields(papszFields);
+
+    if( eErr == OGRERR_NONE ) {
+        for ( int iOGRField = 0; iOGRField < poFeatureDefn->GetFieldCount(); iOGRField++ )
+        {
+            if (!poFeatureDefn->GetFieldDefn(iOGRField)->IsIgnored()) {
+                osSelect += ",";
+                osSelect += poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef();
+            }
+        }
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                            BatchPatch()                              */
+/************************************************************************/
+
+OGRErr OGRGMELayer::BatchPatch()
+{
+    CPLDebug("GME", "BatchPatch() - <%d>", (int)oListOfDeletedFeatures.size() );
+    return BatchRequest("batchPatch", omnpoUpdatedFeatures);
+}
+
+/************************************************************************/
+/*                            BatchInsert()                             */
+/************************************************************************/
+
+OGRErr OGRGMELayer::BatchInsert()
+{
+    CPLDebug("GME", "BatchInsert() - <%d>", (int)oListOfDeletedFeatures.size() );
+    return BatchRequest("batchInsert", omnpoInsertedFeatures);
+}
+
+/************************************************************************/
+/*                            BatchDelete()                             */
+/************************************************************************/
+
+OGRErr OGRGMELayer::BatchDelete()
+{
+    json_object *pjoBatchDelete = json_object_new_object();
+    json_object *pjoGxIds = json_object_new_array();
+    std::vector<long>::const_iterator fit;
+    CPLDebug("GME", "BatchDelete() - <%d>", (int)oListOfDeletedFeatures.size() );
+    if (oListOfDeletedFeatures.size() == 0) {
+        CPLDebug("GME", "Empty list, not doing BatchDelete");
+        return OGRERR_NONE;
+    }
+    for ( fit = oListOfDeletedFeatures.begin(); fit != oListOfDeletedFeatures.end(); fit++)
+    {
+        long nFID = *fit;
+        if (nFID > 0) {
+            CPLString osGxId(omnosIdToGMEKey[nFID]);
+            CPLDebug("GME", "Deleting feature %ld -> '%s'", nFID, osGxId.c_str());
+            json_object *pjoGxId = json_object_new_string(osGxId.c_str());
+            omnosIdToGMEKey.erase(nFID);
+            json_object_array_add( pjoGxIds, pjoGxId );
+        }
+    }
+    oListOfDeletedFeatures.clear();
+    if (json_object_array_length(pjoGxIds) == 0)
+        return OGRERR_FAILURE;
+    json_object_object_add( pjoBatchDelete, "gx_ids", pjoGxIds );
+    const char *body =
+        json_object_to_json_string_ext(pjoBatchDelete,
+                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
+
+/* -------------------------------------------------------------------- */
+/*      POST changes                                                    */
+/* -------------------------------------------------------------------- */
+    CPLString osRequest = "tables/" + osTableId + "/features/batchDelete";
+    CPLHTTPResult *poBatchDeleteResult = poDS->PostRequest(osRequest, body);
+    if (poBatchDeleteResult) {
+        CPLDebug("GME", "batchDelete returned %d", poBatchDeleteResult->nStatus);
+        return OGRERR_NONE;
+    }
+    else {
+        CPLDebug("GME", "batchPatch failed, NULL was returned.");
+        CPLError(CE_Failure, CPLE_AppDefined, "Server error for batchDelete");
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            BatchRequest()                            */
+/************************************************************************/
+
+OGRErr OGRGMELayer::BatchRequest(const char *pszMethod, std::map<int, OGRFeature *> &omnpoFeatures)
+{
+    json_object *pjoBatchDoc = json_object_new_object();
+    json_object *pjoFeatures = json_object_new_array();
+    std::map<int, OGRFeature *>::const_iterator fit;
+    CPLDebug("GME", "BatchRequest('%s', <%d>)", pszMethod, (int)omnpoFeatures.size() );
+    if (omnpoFeatures.size() == 0) {
+        CPLDebug("GME", "Empty map, not doing '%s'", pszMethod);
+        return OGRERR_NONE;
+    }
+    for ( fit = omnpoFeatures.begin(); fit != omnpoFeatures.end(); fit++)
+    {
+        long nFID = fit->first;
+        OGRFeature *poFeature = fit->second;
+        CPLDebug("GME", "Processing feature: %ld", nFID );
+        json_object *pjoFeature = OGRGMEFeatureToGeoJSON(poFeature);
+
+        if (pjoFeature != NULL)
+            json_object_array_add( pjoFeatures, pjoFeature );
+        delete poFeature;
+    }
+    omnpoFeatures.clear();
+    if (json_object_array_length(pjoFeatures) == 0)
+        return OGRERR_FAILURE;
+    json_object_object_add( pjoBatchDoc, "features", pjoFeatures );
+    const char *body =
+        json_object_to_json_string_ext(pjoBatchDoc,
+                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
+
+/* -------------------------------------------------------------------- */
+/*      POST changes                                                    */
+/* -------------------------------------------------------------------- */
+    CPLString osRequest = "tables/" + osTableId + "/features/" + pszMethod;
+    CPLHTTPResult *psBatchResult = poDS->PostRequest(osRequest, body);
+    if (psBatchResult) {
+        CPLDebug("GME", "%s returned %d", pszMethod, psBatchResult->nStatus);
+        return OGRERR_NONE;
+    }
+    else {
+        CPLDebug("GME", "%s failed, NULL was returned.", pszMethod );
+        CPLError(CE_Failure, CPLE_AppDefined, "Server error for %s", pszMethod);
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                         SetBatchPatchSize()                          */
+/************************************************************************/
+
+void OGRGMELayer::SetBatchPatchSize(unsigned int iSize)
+
+{
+    iBatchPatchSize = iSize;
+}
+
+/************************************************************************/
+/*                         GetBatchPatchSize()                          */
+/************************************************************************/
+
+unsigned int OGRGMELayer::GetBatchPatchSize()
+
+{
+    CPLString osBatchPatchSize;
+    osBatchPatchSize = CPLGetConfigOption("GME_BATCH_PATCH_SIZE","0");
+    int iSize = atoi( osBatchPatchSize.c_str() );
+    if (iSize < 1)
+        return iBatchPatchSize;
+    else {
+        iBatchPatchSize = iSize;
+        return (unsigned int) iSize;
+    }
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRGMELayer::CreateFeature( OGRFeature *poFeature )
+
+{
+    if (!poFeature)
+        return OGRERR_FAILURE;
+    if (!CreateTableIfNotCreated()) {
+        return OGRERR_FAILURE;
+    }
+
+    long nFID = ++m_nFeaturesRead;
+    poFeature->SetFID(nFID);
+
+    int nGxId = poFeature->GetFieldIndex("gx_id");
+    CPLDebug("GME", "gx_id is field %d", iGxIdField);
+    CPLString osGxId;
+    CPLDebug("GME", "Inserting feature %ld as %s", poFeature->GetFID(), osGxId.c_str());
+    if (nGxId >= 0) {
+        iGxIdField = nGxId;
+        if(poFeature->IsFieldSet(iGxIdField)) {
+          osGxId = poFeature->GetFieldAsString(iGxIdField);
+          CPLDebug("GME", "Feature already has %ld gx_id='%s'", poFeature->GetFID(),
+                   osGxId.c_str());
+        }
+        else {
+            osGxId = CPLSPrintf("GDAL-%ld", nFID);
+            CPLDebug("GME", "Setting field %d as %s", iGxIdField, osGxId.c_str() );
+            poFeature->SetField( iGxIdField, osGxId.c_str() );
+        }
+    }
+    omnosIdToGMEKey[poFeature->GetFID()] = osGxId;
+    omnpoInsertedFeatures[nFID] = poFeature->Clone();
+
+    if (bInTransaction) {
+        CPLDebug("GME", "In Transaction, added feature to memory only");
+        bDirty = true;
+        return OGRERR_NONE;
+    }
+    else {
+        CPLDebug("GME", "Not in Transaction, BatchInsert()");
+        return BatchInsert();
+    }
+}
+
+/************************************************************************/
+/*                           SetFeature()                               */
+/************************************************************************/
+
+OGRErr OGRGMELayer::SetFeature( OGRFeature *poFeature )
+
+{
+    if (!poFeature)
+        return OGRERR_FAILURE;
+    long nFID = poFeature->GetFID();
+    if(bInTransaction) {
+        std::map<int, OGRFeature *>::const_iterator fit;
+        fit = omnpoInsertedFeatures.find(nFID);
+        if (fit != omnpoInsertedFeatures.end()) {
+            omnpoInsertedFeatures[nFID] = poFeature->Clone();
+            CPLDebug("GME", "Updated Feature %ld in Transaction", nFID);
+        }
+        else {
+            CPLDebug("GME", "In Transaction, add update to Transaction");
+            bDirty = true;
+            omnpoUpdatedFeatures[nFID] = poFeature->Clone();
+        }
+        return OGRERR_NONE;
+    }
+    else {
+        omnpoUpdatedFeatures[nFID] = poFeature->Clone();
+        CPLDebug("GME", "Not in Transaction, BatchPatch()");
+        return BatchPatch();
+    }
+}
+
+/************************************************************************/
+/*                           DeleteteFeature()                          */
+/************************************************************************/
+
+OGRErr OGRGMELayer::DeleteFeature( long nFID )
+{
+    if(bInTransaction) {
+        std::map<int, OGRFeature *>::iterator fit;
+        fit = omnpoInsertedFeatures.find(nFID);
+        if (fit != omnpoInsertedFeatures.end()) {
+            omnpoInsertedFeatures.erase(fit);
+            CPLDebug("GME", "Found %ld in omnpoInsertedFeatures", nFID);
+        }
+        else {
+            CPLDebug("GME", "In Transaction, adding feature to List");
+            bDirty = true;
+            oListOfDeletedFeatures.push_back(nFID); 
+        }
+        return OGRERR_NONE;
+    }
+    else {
+        CPLDebug("GME", "Not in Transaction, BatchDelete()");
+        return BatchDelete();
+    }
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRGMELayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
+{
+    CPLDebug("GME", "create field %s of type %s, pending = %d",
+             poField->GetNameRef(), OGRFieldDefn::GetFieldTypeName(poField->GetType()),
+             bCreateTablePending);
+    if (!bCreateTablePending) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot add field to table after schema is defined.");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeatureDefn == NULL) {
+        poFeatureDefn = new OGRFeatureDefn( osTableName );
+
+        poFeatureDefn->Reference();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        poFeatureDefn->GetGeomFieldDefn(0)->SetName("geometry");
+    }
+    poFeatureDefn->AddFieldDefn(poField);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                      CreateTableIfNotCreated()                       */
+/************************************************************************/
+
+bool OGRGMELayer::CreateTableIfNotCreated()
+{
+    if (!bCreateTablePending || (osTableId.size() != 0)) {
+        CPLDebug("GME", "Not creating table since already created");
+        CPLDebug("GME", "bCreateTablePending = %d osTableId ='%s'",
+                 bCreateTablePending, osTableId.c_str());
+        return true;
+    }
+    CPLDebug("GME", "Creating table...");
+
+    json_object *pjoCreateDoc = json_object_new_object();
+    json_object *pjoProjectId = json_object_new_string( osProjectId.c_str() );
+    json_object_object_add( pjoCreateDoc, "projectId", pjoProjectId );
+    json_object *pjoName = json_object_new_string( osTableName.c_str() );
+    json_object_object_add( pjoCreateDoc, "name",  pjoName );
+    json_object *pjoDraftACL = json_object_new_string( osDraftACL.c_str() );
+    json_object_object_add( pjoCreateDoc, "draftAccessList", pjoDraftACL );
+    json_object *pjoPublishedACL = json_object_new_string( osPublishedACL.c_str() );
+    json_object_object_add( pjoCreateDoc, "publishedAccessList", pjoPublishedACL );
+    json_object *pjoSchema = json_object_new_object();
+
+    json_object *pjoColumns = json_object_new_array();
+
+    poFeatureDefn->SetGeomType( eGTypeForCreation );
+
+    json_object *pjoGeometryColumn = json_object_new_object();
+    json_object *pjoGeometryName = json_object_new_string( "geometry" );
+    json_object *pjoGeometryType;
+    switch(eGTypeForCreation) {
+    case wkbPoint:
+    case wkbPoint25D:
+    case wkbMultiPoint:
+    case wkbMultiPoint25D:
+        pjoGeometryType = json_object_new_string( "points" );
+        break;
+    case wkbLineString:
+    case wkbLineString25D:
+    case wkbMultiLineString:
+    case wkbLinearRing:
+    case wkbMultiLineString25D:
+        pjoGeometryType = json_object_new_string( "lineStrings" );
+        break;
+    case wkbPolygon:
+    case wkbPolygon25D:
+    case wkbMultiPolygon:
+    case wkbGeometryCollection:
+    case wkbMultiPolygon25D:
+        pjoGeometryType = json_object_new_string( "polygons" );
+        break;
+    case wkbGeometryCollection25D:
+        pjoGeometryType = json_object_new_string( "mixedGeometry" );
+        break;
+    default:
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unsupported Geometry type. Defaulting to Points");
+        pjoGeometryType = json_object_new_string( "points" );
+        poFeatureDefn->SetGeomType( wkbPoint );
+    }
+    json_object_object_add( pjoGeometryColumn, "name", pjoGeometryName );
+    json_object_object_add( pjoGeometryColumn, "type", pjoGeometryType );
+    json_object_array_add( pjoColumns, pjoGeometryColumn );
+
+    for (int iOGRField = 0; iOGRField < poFeatureDefn->GetFieldCount(); iOGRField++ )
+    {
+        if (iOGRField == iGxIdField)
+            continue; // don't create the gx_id field.
+        json_object *pjoColumn = json_object_new_object();
+        json_object *pjoFieldName =
+            json_object_new_string( poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef() );
+        json_object *pjoFieldType;
+
+        switch(poFeatureDefn->GetFieldDefn(iOGRField)->GetType()) {
+        case OFTInteger:
+            pjoFieldType = json_object_new_string( "integer" );
+            break;
+        case OFTReal:
+            pjoFieldType = json_object_new_string( "double" );
+            break;
+        default:
+            pjoFieldType = json_object_new_string( "string" );
+        }
+        json_object_object_add( pjoColumn, "name", pjoFieldName );
+        json_object_object_add( pjoColumn, "type", pjoFieldType );
+        json_object_array_add( pjoColumns, pjoColumn );
+    }
+
+    json_object_object_add( pjoSchema, "columns", pjoColumns );
+    json_object_object_add( pjoCreateDoc, "schema", pjoSchema );
+    const char *body =
+        json_object_to_json_string_ext(pjoCreateDoc,
+                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
+
+    CPLDebug("GME", "Create Table Doc:\n%s", body);
+
+/* -------------------------------------------------------------------- */
+/*      POST changes                                                    */
+/* -------------------------------------------------------------------- */
+    CPLString osRequest = "tables";
+    CPLHTTPResult *poCreateResult = poDS->PostRequest(osRequest, body);
+    if( poCreateResult == NULL || poCreateResult->pabyData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Table creation failed.");
+        if( poCreateResult )
+            CPLHTTPDestroyResult(poCreateResult);
+        return false;
+    }
+    CPLDebug("GME", "CreateTable returned %d\n%s", poCreateResult->nStatus,
+             poCreateResult->pabyData);
+
+    json_object *pjoResponseDoc = OGRGMEParseJSON((const char *) poCreateResult->pabyData);
+
+    osTableId = OGRGMEGetJSONString(pjoResponseDoc, "id", "");
+    CPLHTTPDestroyResult(poCreateResult);
+    if (osTableId.size() == 0) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Table creation failed, or could not find table id.");
+        return false;
+    }
+
+    /*
+    OGRFieldDefn *poGxIdField = new OGRFieldDefn("gx_id", OFTString);
+
+    poFeatureDefn->AddFieldDefn(poGxIdField);
+    iGxIdField = poFeatureDefn->GetFieldCount() - 1;
+    CPLDebug("GME", "create field %s(%d) of type %s",
+             "gx_id", iGxIdField, OGRFieldDefn::GetFieldTypeName(OFTString));
+    */
+    bCreateTablePending = false;
+    CPLDebug("GME", "sleeping 3s to give GME time to create the table...");
+    CPLSleep( 3.0 );
+    return true;
+}
+
+/************************************************************************/
+/*                          SetGeometryType()                           */
+/************************************************************************/
+
+void OGRGMELayer::SetGeometryType(OGRwkbGeometryType eGType)
+{
+    eGTypeForCreation = eGType;
+}
+
+/************************************************************************/
+/*                         StartTransaction()                           */
+/************************************************************************/
+
+OGRErr OGRGMELayer::StartTransaction()
+{
+    if (bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Already in transaction");
+        return OGRERR_FAILURE;
+    }
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    bInTransaction = TRUE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRGMELayer::CommitTransaction()
+{
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+    bInTransaction = FALSE;
+    return SyncToDisk();
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRGMELayer::RollbackTransaction()
+{
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+    bInTransaction = FALSE;
+    omnpoUpdatedFeatures.clear();
+    omnpoInsertedFeatures.clear();
+    oListOfDeletedFeatures.clear();
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/gml/GNUmakefile b/ogr/ogrsf_frmts/gml/GNUmakefile
index 824336f..6dfe9f8 100644
--- a/ogr/ogrsf_frmts/gml/GNUmakefile
+++ b/ogr/ogrsf_frmts/gml/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 CORE_OBJ =	gmlpropertydefn.o gmlfeatureclass.o gmlfeature.o gmlreader.o \
 		parsexsd.o resolvexlinks.o hugefileresolver.o gmlutils.o \
-		gmlreadstate.o gmlhandler.o trstring.o gfstemplate.o
+		gmlreadstate.o gmlhandler.o trstring.o gfstemplate.o gmlregistry.o
 
 OGR_OBJ =	ogrgmldriver.o ogrgmldatasource.o ogrgmllayer.o
 
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index 51ac81e..4447a8f 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -88,6 +88,15 @@ field.  In some applications it is easier if all fields are just treated as
 string fields.  This can be accomplished by setting the configuration option
 <b>GML_FIELDTYPES</b> to the value <b>ALWAYS_STRING</b>.<p>
 
+Starting with GDAL 1.11, the <b>GML_ATTRIBUTES_TO_OGR_FIELDS</b> configuration
+option can be set to <b>YES</b> so that attributes of GML elements are also
+taken into account to create OGR fields.<p>
+
+Configuration options can be set via the CPLSetConfigOption() function or as
+environment variables.<p>
+
+<h2>Particular GML application schemas</h2>
+
 OGR 1.8.0 adds support for detecting feature attributes in nested GML elements
 (non-flat attribute hierarchy) that can be found in some GML profiles
 such as UK Ordnance Survey MasterMap. OGR 1.8.0 also brings support for reading
@@ -96,21 +105,35 @@ IntegerList, RealList and StringList field types when a GML element has several
 Since OGR 1.8.0, a specialized GML driver - the <a href="drv_nas.html">NAS</a> driver - is available to read
 German AAA GML Exchange Format (NAS/ALKIS).<p>
 
-Configuration options can be set via the CPLSetConfigOption() function or as
-environment variables.<p>
+Since OGR 1.8.0, the GML driver has partial support for reading AIXM or CityGML files.<p>
+
+Since OGR 1.11, the GML driver supports reading :
+<ul>
+ <li><a href="http://xml.nls.fi/XML/Schema/Maastotietojarjestelma/MTK/201202/Maastotiedot.xsd">Finnish National Land Survey GML files (a.k.a MTK GML) for topographic data.</a></li>
+ <li><a href="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/">Finnish National Land Survey GML files for cadastral data</a>.</li>
+ <li><a href="http://inspire.ec.europa.eu/schemas/cp/3.0/CadastralParcels.xsd">Cadastral data in Inspire GML schemas</a>.</li>
+ <li><a href="http://www.cuzk.cz/Uvod/Produkty-a-sluzby/RUIAN/2-Poskytovani-udaju-RUIAN-ISUI-VDP/Vymenny-format-RUIAN/Vymenny-format-RUIAN-%28VFR%29.aspx">Czech RUIAN Exchange Format (VFR)</a>.</li>
+</ul>
 
 <h2>Geometry reading</h2>
 
 When reading a feature, the driver will by default only take into account the
 last recognized GML geometry found (in case they are multiples) in the XML subtree describing the feature.<p>
 
+But, starting with OGR 1.11, if the .xsd schema is understood by the XSD parser and declares
+several geometry fields, or the .gfs file declares several geometry fields, multiple geometry
+fields will be reported by the GML driver according to
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">RFC 41</a>.<p>
+
 Starting with OGR 1.10, in case of multiple geometry occurences, if a geometry is in a <geometry> element,
 this will be the one selected. This will make default behaviour consistant with Inspire objects.<p>
 
+
 Starting with OGR 1.8.0, the user can change the .gfs file to select the appropriate
 geometry by specifying its path with the <GeometryElementPath> element. See the
 description of the .gfs syntax below.<p>
 
+
 <!-- Voluntary commented : a bit experimental for now and perhaps a better solution
      will emerge later -->
 <!--
@@ -340,6 +363,9 @@ OFF disables schema generation (and is implicit if XSISCHEMAURI is used).<p>
 
 <li> <b>PREFIX</b> (OGR >= 1.10) Defaults to 'ogr'. This is the prefix for the application target namespace.</p>
 
+<li> <b>STRIP_PREFIX</b> (OGR >= 1.11) Defaults to FALSE. Can be set to TRUE to avoid writing
+the prefix of the application target namespace in the GML file.</p>
+
 <li> <b>TARGET_NAMESPACE</b> (OGR >= 1.10) Defaults to 'http://ogr.maptools.org/'. This is the application target namespace.</p>
 
 <li> <b>FORMAT</b>: (OGR >= 1.8.0) This can be set to :
@@ -350,7 +376,11 @@ with a few variations with respect to what is recommanded by GML3 SF-0 profile,
 but that will be better accepted by some software (such as Deegree 3).</li>
 <li><i>GML3.2</i>(OGR >= 1.9.0) in order to write GML files that follow GML 3.2.1 SF-0 profile.</li>
 </ul><br>
-If not specified, GML2 will be used.<p>
+If not specified, GML2 will be used.<br><br>
+Note: starting with OGR 1.11, fields of type StringList, RealList or IntegerList can be written. This
+will cause to advertize the SF-1 profile in the .XSD schema (such types are not supported by SF-0).<br>
+
+<p>
 
 <li> <b>GML3_LONGSRS</b>=YES/NO. (OGR >= 1.8.0, only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. If YES, SRS with EPSG authority will
 be written with the "urn:ogc:def:crs:EPSG::" prefix.
@@ -358,6 +388,9 @@ In the case, if the SRS is a geographic SRS without explicit AXIS order, but tha
 imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
 If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.<p>
 
+<li> <b>WRITE_FEATURE_BOUNDED_BY</b>=YES/NO. (OGR >= 1.11, only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES.
+If set to NO, the <gml:boundedBy> element will not be written for each feature.<p>
+
 <li> <b>SPACE_INDENTATION</b>=YES/NO. (OGR >= 1.8.0) Default to YES. If YES, the output will be indented with spaces
 for more readability, but at the expense of file size.<p>
 
@@ -429,6 +462,34 @@ specify the wished field/geometry element that is a nested XML element. Nested f
  as specifying <GeometryElementPath> If GeometryElementPath is not specified, the
 GML driver will use the last recognized geometry element.<p>
 
+The <GeometryType> element can be specified to force the geometry type.
+Accepted values are : 0 (any geometry type), 1 (point), 2 (linestring), 3 (polygon),
+4 (multipoint), 5 (multilinestring), 6 (multipolygon), 7 (geometrycollection).<p>
+
+Starting with OGR 1.11, the <GeometryElementPath> and <GeometryType> can be
+specified as many times as there are geometry fields in the GML file. Another possibility
+is to define a <GeomPropertyDefn>element as many times as necessary:
+<pre>
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>LAYER</Name>
+    <ElementPath>LAYER</ElementPath>
+    <GeomPropertyDefn>
+        <Name>geometry</Name> <-- OGR geometry name -->
+        <ElementPath>geometry</ElementPath> <!-- XML element name possibly with '|' to specify the path -->
+        <Type>MultiPolygon</Type>
+    </GeomPropertyDefn>
+    <GeomPropertyDefn>
+        <Name>referencePoint</Name>
+        <ElementPath>referencePoint</ElementPath>
+        <Type>Point</Type>
+    </GeomPropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
+</pre>
+<p>
+
+
 The output of <i>ogrinfo test.gml -ro -al</i> is:
 <pre>
 Layer name: LAYER
@@ -446,7 +507,313 @@ OGRFeature(LAYER):0
   POINT (3 50)
 </pre>
 
-<h2>Example</h2>
+<h2>Advanced .gfs syntax (OGR >= 1.11)</h2>
+
+<h3>Specifying ElementPath to find objets embedded into top level objects</h3>
+
+Let's consider the following test.gml file :
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<gml:FeatureCollection xmlns:xlink="http://www.w3.org/1999/xlink"
+                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                       gml:id="foo" xmlns:gml="http://www.opengis.net/gml/3.2">
+  <gml:featureMember>
+    <TopLevelObject gml:id="TopLevelObject.1">
+      <content>
+        <Object gml:id="Object.1">
+          <geometry>
+            <gml:Polygon gml:id="Object.1.Geometry" srsName="urn:ogc:def:crs:EPSG::4326">
+              <gml:exterior>
+                <gml:LinearRing>
+                  <gml:posList srsDimension="2">48 2 49 2 49 3 48 3 48 2</gml:posList>
+                </gml:LinearRing>
+              </gml:exterior>
+            </gml:Polygon>
+          </geometry>
+          <foo>bar</foo>
+        </Object>
+      </content>
+      <content>
+        <Object gml:id="Object.2">
+          <geometry>
+            <gml:Polygon gml:id="Object.2.Geometry" srsName="urn:ogc:def:crs:EPSG::4326">
+              <gml:exterior>
+                <gml:LinearRing>
+                  <gml:posList srsDimension="2">-48 2 -49 2 -49 3 -48 3 -48 2</gml:posList>
+                </gml:LinearRing>
+              </gml:exterior>
+            </gml:Polygon>
+          </geometry>
+          <foo>baz</foo>
+        </Object>
+      </content>
+    </TopLevelObject>
+  </gml:featureMember>
+</gml:FeatureCollection>
+</pre>
+
+By default, only the TopLevelObject object would be reported and it would only
+use the second geometry. This is not the desired behaviour in that instance.
+You can edit the generated .gfs and modify it like the following in order to
+specify a full path to the element (top level XML element being omitted) :
+
+<pre>
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>Object</Name>
+    <ElementPath>featureMember|TopLevelObject|content|Object</ElementPath>
+    <GeometryType>3</GeometryType>
+    <PropertyDefn>
+      <Name>foo</Name>
+      <ElementPath>foo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
+</pre>
+
+<h3>Getting XML attributes as OGR fields</h3>
+
+The element at attribute syntax can be used in the <ElementPath>
+to specify that the value of attribute 'attribute' of element 'element' must
+be fetched.<p>
+
+Let's consider the following test.gml file :
+
+<pre>
+<?xml version="1.0" encoding="UTF-8"?>
+<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml">
+  <gml:featureMember>
+    <LAYER>
+      <length unit="m">5</length>
+    </LAYER>
+  </gml:featureMember>
+</gml:FeatureCollection>
+</pre>
+
+and the following associated .gfs file.
+
+<pre>
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>LAYER</Name>
+    <ElementPath>LAYER</ElementPath>
+    <GeometryType>100</GeometryType> <!-- no geometry -->
+    <PropertyDefn>
+      <Name>length</Name>
+      <ElementPath>length</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>length_unit</Name>
+      <ElementPath>length at unit</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
+</pre>
+
+The output of <i>ogrinfo test.gml -ro -al</i> is:
+
+<pre>
+Layer name: LAYER
+Geometry: None
+Feature Count: 1
+Layer SRS WKT:
+(unknown)
+gml_id: String (0.0)
+length: Real (0.0)
+length_unit: String (0.0)
+OGRFeature(LAYER):0
+  gml_id (String) = (null)
+  length (Real) = 5
+  length_unit (String) = m
+</pre>
+
+<h3>Using conditions on XML attributes</h3>
+
+A <Condition> element can be specified as a child element of a
+<PropertyDefn>. The content of the Condition follows a minimalistic
+XPath syntax. It must be of the form @attrname[=|!=]'attrvalue' [and|or other_cond]*.
+Note that 'and' and 'or' operators cannot be mixed (their precedence is not
+taken into account).<p>
+
+Several <PropertyDefn> can be defined with the same <ElementPath>, but with
+<Condition> that must be mutually exclusive.<p>
+
+Let's consider the following testcondition.gml file :
+
+<pre>
+<?xml version="1.0" encoding="utf-8" ?>
+<ogr:FeatureCollection
+     xmlns:ogr="http://ogr.maptools.org/"
+     xmlns:gml="http://www.opengis.net/gml">
+  <gml:featureMember>
+    <ogr:testcondition fid="testcondition.0">
+      <ogr:name lang="en">English name</ogr:name>
+      <ogr:name lang="fr">Nom francais</ogr:name>
+      <ogr:name lang="de">Deutsche name</ogr:name>
+    </ogr:testcondition>
+  </gml:featureMember>
+</ogr:FeatureCollection>
+</pre>
+
+and the following associated .gfs file.
+
+<pre>
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>testcondition</Name>
+    <ElementPath>testcondition</ElementPath>
+    <GeometryType>100</GeometryType>
+    <PropertyDefn>
+      <Name>name_en</Name>
+      <ElementPath>name</ElementPath>
+      <Condition>@lang='en'</Condition>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_fr</Name>
+      <ElementPath>name</ElementPath>
+      <Condition>@lang='fr'</Condition>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_others_lang</Name>
+      <ElementPath>name at lang</ElementPath>
+      <Condition>@lang!='en' and @lang!='fr'</Condition>
+      <Type>StringList</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name_others</Name>
+      <ElementPath>name</ElementPath>
+      <Condition>@lang!='en' and @lang!='fr'</Condition>
+      <Type>StringList</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
+</pre>
+
+The output of <i>ogrinfo testcondition.gml -ro -al</i> is:
+<pre>
+Layer name: testcondition
+Geometry: None
+Feature Count: 1
+Layer SRS WKT:
+(unknown)
+fid: String (0.0)
+name_en: String (0.0)
+name_fr: String (0.0)
+name_others_lang: StringList (0.0)
+name_others: StringList (0.0)
+OGRFeature(testcondition):0
+  fid (String) = testcondition.0
+  name_en (String) = English name
+  name_fr (String) = Nom francais
+  name_others_lang (StringList) = (1:de)
+  name_others (StringList) = (1:Deutsche name)
+</pre>
+
+<h2>Registry for GML application schemas (OGR >= 1.11)</h2>
+
+The "data" directory of the GDAL installation contains a "gml_registry.xml"
+file that links feature types of GML application schemas to .xsd or .gfs files
+that contain their definition. This is used in case no valid .gfs or .xsd file
+is found next to the GML file.<p>
+
+An alternate location for the registry file can be defined by setting its full
+pathname to the GML_REGISTRY configuration option.<p>
+
+An example of such a file is :
+<pre>
+<gml_registry>
+    <!-- Finnish National Land Survey cadastral data -->
+    <namespace prefix="ktjkiiwfs" uri="http://xml.nls.fi/ktjkiiwfs/2010/02" useGlobalSRSName="true">
+        <featureType elementName="KiinteistorajanSijaintitiedot"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/KiinteistorajanSijaintitiedot.xsd"/>
+        <featureType elementName="PalstanTunnuspisteenSijaintitiedot"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/palstanTunnuspisteenSijaintitiedot.xsd"/>
+        <featureType elementName="RekisteriyksikonTietoja"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/RekisteriyksikonTietoja.xsd"/>
+        <featureType elementName="PalstanTietoja"
+                 schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/PalstanTietoja.xsd"/>
+    </namespace>
+
+    <!-- Inspire CadastralParcels schema -->
+    <namespace prefix="cp" uri="urn:x-inspire:specification:gmlas:CadastralParcels:3.0" useGlobalSRSName="true">
+        <featureType elementName="BasicPropertyUnit"
+                     gfsSchemaLocation="inspire_cp_BasicPropertyUnit.gfs"/>
+        <featureType elementName="CadastralBoundary"
+                     gfsSchemaLocation="inspire_cp_CadastralBoundary.gfs"/>
+        <featureType elementName="CadastralParcel"
+                     gfsSchemaLocation="inspire_cp_CadastralParcel.gfs"/>
+        <featureType elementName="CadastralZoning"
+                     gfsSchemaLocation="inspire_cp_CadastralZoning.gfs"/>
+    </namespace>
+
+    <!-- Czech RUIAN (VFR) schema (v1) -->
+    <namespace prefix="vf"
+               uri="urn:cz:isvs:ruian:schemas:VymennyFormatTypy:v1 ../ruian/xsd/vymenny_format/VymennyFormatTypy.xsd"
+               useGlobalSRSName="true">
+        <featureType elementName="TypSouboru"
+                     elementValue="OB"
+                     gfsSchemaLocation="ruian_vf_ob_v1.gfs"/>
+        <featureType elementName="TypSouboru"
+                     elementValue="ST"
+                     gfsSchemaLocation="ruian_vf_st_v1.gfs"/>
+    </namespace>
+</gml_registry>
+</pre>
+
+XML schema definition (.xsd) files are pointed by the schemaLocation attribute,
+whereas OGR .gfs files are pointed by the gfsSchemaLocation attribute. In both
+cases, the filename can be a URL (http://, https://), an absolute filename,
+or a relative filename (relative to the location of gml_registry.xml).<p>
+
+The schema is used if and only if the namespace prefix and URI are
+found in the first bytes of the GML file
+(e.g. <i>xmlns:ktjkiiwfs="http://xml.nls.fi/ktjkiiwfs/2010/02"</i>),
+and that the feature type is also detected in the first bytes of the
+GML file (e.g. <i>ktjkiiwfs:KiinteistorajanSijaintitiedot</i>). If the
+element value is defined than the schema is used only if the feature
+type together with the value is found in the first bytes of the GML
+file (e.g. <i>vf:TypSouboru>OB_UKSH</i>). <p>
+
+<h2>Building junction tables</h2>
+
+The <a href="http://svn.osgeo.org/gdal/trunk/gdal/swig/python/samples/ogr_build_junction_table.py">ogr_build_junction_table.py</a>
+script can be used to build a <a href="http://en.wikipedia.org/wiki/Junction_table">junction table</a> from
+OGR layers that contain "XXXX_href" fields.
+
+Let's considering the following output of a GML file with links to other features :
+
+<pre>
+OGRFeature(myFeature):1
+  gml_id (String) = myFeature.1
+  [...]
+  otherFeature_href (StringList) = (2:#otherFeature.10,#otherFeature.20)
+
+OGRFeature(myFeature):2
+  gml_id (String) = myFeature.2
+  [...]
+  otherFeature_href (StringList) = (2:#otherFeature.30,#otherFeature.10)
+</pre>
+
+After running <pre>ogr2ogr -f PG PG:dbname=mydb my.gml</pre> to
+import it into PostGIS and <pre>python ogr_build_junction_table.py PG:dbname=mydb</pre>,
+a <i>myfeature_otherfeature</i> table will be created and will
+contain the following content :<p>
+
+<table border="1">
+<tr><th>myfeature_gml_id</th><th>otherfeature_gml_id</th></tr>
+<tr><td>myFeature.1</td><td>otherFeature.10</td></tr>
+<tr><td>myFeature.1</td><td>otherFeature.20</td></tr>
+<tr><td>myFeature.2</td><td>otherFeature.30</td></tr>
+<tr><td>myFeature.2</td><td>otherFeature.10</td></tr>
+</table>
+
+
+<h2>Examples</h2>
 
 The ogr2ogr utility can be used to dump the results of a Oracle query to
 GML:
@@ -470,6 +837,7 @@ ogr2ogr -f GML output.gml PG:'host=myserver dbname=warmerda' -sql "SELECT pop_19
 <ul>
 <li> <a href="http://www.opengeospatial.org/standards/gml">GML Specifications</a><p>
 <li> <a href="http://portal.opengeospatial.org/files/?artifact_id=15201">GML 3.1.1 simple features profile - OGC(R) 06-049r1</a><p>
+<li> <a href="https://portal.opengeospatial.org/files/?artifact_id=42729">Geography Markup Language (GML) simple features profile (with Corrigendum) (GML 3.2.1) - OGC(R) 10-100r3</a><p>
 <li> <a href="http://xml.apache.org/xerces2-j/index.html">Xerces</a><p>
 <li> <a href="drv_nas.html">NAS/ALKIS : specialized GML driver for cadastral data in Germany</a><p>
 </ul>
@@ -477,6 +845,7 @@ ogr2ogr -f GML output.gml PG:'host=myserver dbname=warmerda' -sql "SELECT pop_19
 <h2>Credits</h2>
 <ul>
 	<li>Implementation for <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> was contributed by A.Furieri, with funding from Regione Toscana</li>
+    <li>Support for cadastral data in Finnish National Land Survey GML and Inspire GML was funded by The Information Centre of the Ministry of Agriculture and Forestry (Tike)</li>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/gml/gfstemplate.cpp b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
index 80218f3..ce46c5f 100644
--- a/ogr/ogrsf_frmts/gml/gfstemplate.cpp
+++ b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $
+ * $Id: gfstemplate.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GML GFS template management
@@ -36,7 +36,7 @@
 #include "gmlreaderp.h"
 #include "ogr_gml.h"
 
-CPL_CVSID("$Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $");
+CPL_CVSID("$Id: gfstemplate.cpp 27132 2014-04-05 21:48:58Z rouault $");
 
 /************************************************************************/
 /*                        GFSTemplateItem                               */
@@ -85,8 +85,8 @@ public:
         if (poClass != NULL)
         {
             poClass->SetFeatureCount( pItem->GetCount() );
-            if ( pItem->GetGeomCount() == 0)
-                poClass->SetGeometryType( wkbNone );
+            if ( pItem->GetGeomCount() != 0 && poClass->GetGeometryPropertyCount() == 0 )
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown ) );
             m_bValid = TRUE;
         }
         pItem = pItem->GetNext();
diff --git a/ogr/ogrsf_frmts/gml/gmlfeature.cpp b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
index ad0ef2a..dd84fc6 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeature.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeature.cpp 25579 2013-01-29 18:53:52Z rouault $
+ * $Id: gmlfeature.cpp 27188 2014-04-14 23:26:49Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeature.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -207,6 +208,50 @@ void GMLFeature::SetGeometryDirectly( CPLXMLNode* psGeom )
 }
 
 /************************************************************************/
+/*                        SetGeometryDirectly()                         */
+/************************************************************************/
+
+void GMLFeature::SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom )
+
+{
+    if( nIdx == 0 && m_nGeometryCount <= 1 )
+    {
+        SetGeometryDirectly( psGeom );
+        return;
+    }
+    else if( nIdx > 0 && m_nGeometryCount <= 1 )
+    {
+        m_papsGeometry = (CPLXMLNode **) CPLMalloc(2 * sizeof(CPLXMLNode *));
+        m_papsGeometry[0] = m_apsGeometry[0];
+        m_papsGeometry[1] = NULL;
+        m_apsGeometry[0] = NULL;
+    }
+
+    if( nIdx >= m_nGeometryCount )
+    {
+        m_papsGeometry = (CPLXMLNode **) CPLRealloc(m_papsGeometry,
+            (nIdx + 2) * sizeof(CPLXMLNode *));
+        for( int i = m_nGeometryCount; i <= nIdx + 1; i++ )
+            m_papsGeometry[i] = NULL;
+        m_nGeometryCount = nIdx + 1;
+    }
+    if (m_papsGeometry[nIdx] != NULL)
+        CPLDestroyXMLNode(m_papsGeometry[nIdx]);
+    m_papsGeometry[nIdx] = psGeom;
+}
+
+/************************************************************************/
+/*                          GetGeometryRef()                            */
+/************************************************************************/
+
+const CPLXMLNode* GMLFeature::GetGeometryRef( int nIdx ) const
+{
+    if( nIdx < 0 || nIdx >= m_nGeometryCount )
+        return NULL;
+    return m_papsGeometry[nIdx];
+}
+
+/************************************************************************/
 /*                             AddGeometry()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
index f1f6f4f..d0427d5 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeatureclass.cpp 26144 2013-07-06 08:09:05Z rouault $
+ * $Id: gmlfeatureclass.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeatureClass.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,6 +31,7 @@
 #include "gmlreader.h"
 #include "cpl_conv.h"
 #include "ogr_core.h"
+#include "ogr_geometry.h"
 
 /************************************************************************/
 /*                          GMLFeatureClass()                           */
@@ -42,18 +44,16 @@ GMLFeatureClass::GMLFeatureClass( const char *pszName )
     n_nNameLen = strlen( m_pszName );
     m_pszElementName = NULL;
     n_nElementNameLen = 0;
-    m_pszGeometryElement = NULL;
     m_nPropertyCount = 0;
     m_papoProperty = NULL;
+    m_nGeometryPropertyCount = 0;
+    m_papoGeometryProperty = NULL;
     m_bSchemaLocked = FALSE;
 
     m_pszExtraInfo = NULL;
     m_bHaveExtents = FALSE;
     m_nFeatureCount = -1; // unknown
 
-    m_nGeometryType = 0; // wkbUnknown
-    m_nGeometryIndex = -1;
-
     m_pszSRSName = NULL;
     m_bSRSNameConsistant = TRUE;
 }
@@ -67,11 +67,13 @@ GMLFeatureClass::~GMLFeatureClass()
 {
     CPLFree( m_pszName );
     CPLFree( m_pszElementName );
-    CPLFree( m_pszGeometryElement );
 
     for( int i = 0; i < m_nPropertyCount; i++ )
         delete m_papoProperty[i];
     CPLFree( m_papoProperty );
+
+    ClearGeometryProperties();
+
     CPLFree( m_pszSRSName );
 }
 
@@ -127,8 +129,6 @@ int GMLFeatureClass::GetPropertyIndexBySrcElement( const char *pszElement, int n
     return -1;
 }
 
-
-
 /************************************************************************/
 /*                            AddProperty()                             */
 /************************************************************************/
@@ -154,6 +154,84 @@ int GMLFeatureClass::AddProperty( GMLPropertyDefn *poDefn )
 }
 
 /************************************************************************/
+/*                         GetGeometryProperty(int)                      */
+/************************************************************************/
+
+GMLGeometryPropertyDefn *GMLFeatureClass::GetGeometryProperty( int iIndex ) const
+{
+    if( iIndex < 0 || iIndex >= m_nGeometryPropertyCount )
+        return NULL;
+    else
+        return m_papoGeometryProperty[iIndex];
+}
+
+/************************************************************************/
+/*                   GetGeometryPropertyIndexBySrcElement()             */
+/************************************************************************/
+
+int GMLFeatureClass::GetGeometryPropertyIndexBySrcElement( const char *pszElement ) const
+
+{
+    for( int i = 0; i < m_nGeometryPropertyCount; i++ )
+        if( strcmp(pszElement,m_papoGeometryProperty[i]->GetSrcElement()) == 0)
+            return i;
+
+    return -1;
+}
+
+/************************************************************************/
+/*                         AddGeometryProperty()                        */
+/************************************************************************/
+
+int GMLFeatureClass::AddGeometryProperty( GMLGeometryPropertyDefn *poDefn )
+
+{
+    if( GetGeometryPropertyIndexBySrcElement(poDefn->GetSrcElement()) >= 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Field with same name (%s) already exists. Skipping newer ones",
+                 poDefn->GetSrcElement());
+        return -1;
+    }
+
+    m_nGeometryPropertyCount++;
+    m_papoGeometryProperty = (GMLGeometryPropertyDefn **)
+        CPLRealloc( m_papoGeometryProperty, sizeof(void*) * m_nGeometryPropertyCount );
+
+    m_papoGeometryProperty[m_nGeometryPropertyCount-1] = poDefn;
+
+    return m_nGeometryPropertyCount-1;
+}
+
+/************************************************************************/
+/*                       ClearGeometryProperties()                      */
+/************************************************************************/
+
+void GMLFeatureClass::ClearGeometryProperties()
+{
+    for( int i = 0; i < m_nGeometryPropertyCount; i++ )
+        delete m_papoGeometryProperty[i];
+    CPLFree( m_papoGeometryProperty );
+    m_nGeometryPropertyCount = 0;
+    m_papoGeometryProperty = NULL;
+}
+
+/************************************************************************/
+/*                         HasFeatureProperties()                       */
+/************************************************************************/
+
+int GMLFeatureClass::HasFeatureProperties()
+{
+    for( int i = 0; i < m_nPropertyCount; i++ )
+    {
+        if( m_papoProperty[i]->GetType() == GMLPT_FeatureProperty ||
+            m_papoProperty[i]->GetType() == GMLPT_FeaturePropertyList )
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                           SetElementName()                           */
 /************************************************************************/
 
@@ -192,20 +270,6 @@ size_t GMLFeatureClass::GetElementNameLen() const
 }
 
 /************************************************************************/
-/*                         SetGeometryElement()                         */
-/************************************************************************/
-
-void GMLFeatureClass::SetGeometryElement( const char *pszElement )
-
-{
-    CPLFree( m_pszGeometryElement );
-    if (pszElement)
-        m_pszGeometryElement = CPLStrdup( pszElement );
-    else
-        m_pszGeometryElement = NULL;
-}
-
-/************************************************************************/
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
@@ -357,25 +421,132 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
     CPLFree( m_pszName );
     m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
     n_nNameLen = strlen(m_pszName);
-    
+
     SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );
 
-    const char *pszGPath = CPLGetXMLValue( psRoot, "GeometryElementPath", "" );
-    
-    if( strlen( pszGPath ) > 0 )
-        SetGeometryElement( pszGPath );
+/* -------------------------------------------------------------------- */
+/*      Collect geometry properties.                                    */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psThis;
 
-    const char* pszGeometryType = CPLGetXMLValue( psRoot, "GeometryType", NULL );
-    if( pszGeometryType != NULL )
+    int bHasValidGeometryName = FALSE;
+    int bHasValidGeometryElementPath = FALSE;
+    int bHasFoundGeomType = FALSE;
+    int bHasFoundGeomElements = FALSE;
+    const char* pszGName = "";
+    const char* pszGPath = "";
+    int nGeomType = wkbUnknown;
+
+    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     {
-        int nGeomType = atoi(pszGeometryType) & (~wkb25DBit);
-        if ((nGeomType >= 0 && nGeomType <= 7) || nGeomType == 100)
-            SetGeometryType( atoi(pszGeometryType) );
-        else
+        if( psThis->eType == CXT_Element &&
+            EQUAL(psThis->pszValue, "GeomPropertyDefn") )
+        {
+            const char *pszName = CPLGetXMLValue( psThis, "Name", "" );
+            const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" );
+            const char *pszType = CPLGetXMLValue( psThis, "Type", NULL );
+            nGeomType = wkbUnknown;
+            if( pszType != NULL && !EQUAL(pszType, "0") )
+            {
+                nGeomType = atoi(pszType);
+                int nFlattenGeomType = nGeomType & (~wkb25DBit);
+                if( nGeomType != 0 && !(nFlattenGeomType >= 0 && nFlattenGeomType <= 7) )
+                {
+                    nGeomType = wkbUnknown;
+                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
+                            pszType);
+                }
+                else if( nGeomType == 0 )
+                    nGeomType = OGRFromOGCGeomType(pszType);
+            }
+            bHasFoundGeomElements = TRUE;
+            AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType ) );
+            bHasValidGeometryName = FALSE;
+            bHasValidGeometryElementPath = FALSE;
+            bHasFoundGeomType = FALSE;
+        }
+        else if( psThis->eType == CXT_Element &&
+            strcmp(psThis->pszValue, "GeometryName") == 0 )
         {
-            CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
-                     pszGeometryType);
+            bHasFoundGeomElements = TRUE;
+
+            if( bHasValidGeometryName )
+            {
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType ) );
+                bHasValidGeometryName = FALSE;
+                bHasValidGeometryElementPath = FALSE;
+                bHasFoundGeomType = FALSE;
+                pszGName = "";
+                pszGPath = "";
+                nGeomType = wkbUnknown;
+            }
+            pszGName = CPLGetXMLValue( psThis, NULL, "" );
+            bHasValidGeometryName = TRUE;
         }
+        else if( psThis->eType == CXT_Element &&
+            strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
+        {
+            bHasFoundGeomElements = TRUE;
+
+            if( bHasValidGeometryElementPath )
+            {
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType ) );
+                bHasValidGeometryName = FALSE;
+                bHasValidGeometryElementPath = FALSE;
+                bHasFoundGeomType = FALSE;
+                pszGName = "";
+                pszGPath = "";
+                nGeomType = wkbUnknown;
+            }
+            pszGPath = CPLGetXMLValue( psThis, NULL, "" );
+            bHasValidGeometryElementPath = TRUE;
+        }
+        else if( psThis->eType == CXT_Element &&
+                 strcmp(psThis->pszValue, "GeometryType") == 0 )
+        {
+            bHasFoundGeomElements = TRUE;
+
+            if( bHasFoundGeomType )
+            {
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType ) );
+                bHasValidGeometryName = FALSE;
+                bHasValidGeometryElementPath = FALSE;
+                bHasFoundGeomType = FALSE;
+                pszGName = "";
+                pszGPath = "";
+                nGeomType = wkbUnknown;
+            }
+            const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL );
+            nGeomType = wkbUnknown;
+            if( pszGeometryType != NULL && !EQUAL(pszGeometryType, "0") )
+            {
+                nGeomType = atoi(pszGeometryType);
+                int nFlattenGeomType = nGeomType & (~wkb25DBit);
+                if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") )
+                {
+                    bHasValidGeometryElementPath = FALSE;
+                    bHasFoundGeomType = FALSE;
+                    break;
+                }
+                else if( nGeomType != 0 && !(nFlattenGeomType >= 0 && nFlattenGeomType <= 7) )
+                {
+                    nGeomType = wkbUnknown;
+                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
+                            pszGeometryType);
+                }
+                else if( nGeomType == 0 )
+                    nGeomType = OGRFromOGCGeomType(pszGeometryType);
+            }
+            bHasFoundGeomType = TRUE;
+        }
+    }
+
+    /* If there was a dangling <GeometryElementPath> or <GeometryType> or */
+    /* that no explicit geometry information has been found, then add */
+    /* a geometry field */
+    if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements )
+    {
+        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType ) );
     }
 
     SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) );
@@ -412,13 +583,14 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 /* -------------------------------------------------------------------- */
 /*      Collect property definitions.                                   */
 /* -------------------------------------------------------------------- */
-    for( CPLXMLNode *psThis = psRoot->psChild;
-         psThis != NULL; psThis = psThis->psNext )
+    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     {
-        if( EQUAL(psThis->pszValue, "PropertyDefn") )
+        if( psThis->eType == CXT_Element &&
+            EQUAL(psThis->pszValue, "PropertyDefn") )
         {
             const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
             const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
+            const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL );
             GMLPropertyDefn *poPDefn;
 
             if( pszName == NULL )
@@ -458,6 +630,10 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 poPDefn->SetType( GMLPT_RealList );
             else if( EQUAL(pszType,"Complex") )
                 poPDefn->SetType( GMLPT_Complex );
+            else if( EQUAL(pszType,"FeatureProperty") )
+                poPDefn->SetType( GMLPT_FeatureProperty );
+            else if( EQUAL(pszType,"FeaturePropertyList") )
+                poPDefn->SetType( GMLPT_FeaturePropertyList );
             else
             {
                 CPLError( CE_Failure, CPLE_AppDefined, 
@@ -466,6 +642,8 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 delete poPDefn;
                 return FALSE;
             }
+            if( pszCondition != NULL )
+                poPDefn->SetCondition(pszCondition);
 
             AddProperty( poPDefn );
         }
@@ -491,16 +669,30 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
 
     CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
     CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
-    if( GetGeometryElement() != NULL && strlen(GetGeometryElement()) > 0 )
-        CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", 
-                                     GetGeometryElement() );
     
-    if( GetGeometryType() != 0 /* wkbUnknown */ )
+    if( m_nGeometryPropertyCount > 0 )
     {
-        char szValue[128];
+        GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0];
+        
+        if( strlen(poGeomFDefn->GetName()) > 0 )
+            CPLCreateXMLElementAndValue( psRoot, "GeometryName", 
+                                         poGeomFDefn->GetName() );
+
+        if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
+            CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", 
+                                         poGeomFDefn->GetSrcElement() );
+        
+        if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
+        {
+            char szValue[128];
 
-        sprintf( szValue, "%d", GetGeometryType() );
-        CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
+            sprintf( szValue, "%d", poGeomFDefn->GetType() );
+            CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
+        }
+    }
+    else
+    {
+        CPLCreateXMLElementAndValue( psRoot, "GeometryType", "100" );
     }
 
     const char* pszSRSName = GetSRSName();
@@ -598,6 +790,18 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
           case GMLPT_StringList:
             pszTypeName = "StringList";
             break;
+
+          /* should not happen in practise for now because this is not */
+          /* autodetected */
+          case GMLPT_FeatureProperty:
+            pszTypeName = "FeatureProperty";
+            break;
+
+          /* should not happen in practise for now because this is not */
+          /* autodetected */
+          case GMLPT_FeaturePropertyList:
+            pszTypeName = "FeaturePropertyList";
+            break;
         }
         CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName );
 
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index adbafad..db05127 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 25579 2013-01-29 18:53:52Z rouault $
+ * $Id: gmlhandler.cpp 27120 2014-04-03 20:33:49Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -241,6 +242,22 @@ char* GMLXercesHandler::GetAttributeValue(void* attr, const char* pszAttributeNa
     return NULL;
 }
 
+/************************************************************************/
+/*                    GetAttributeByIdx()                               */
+/************************************************************************/
+
+char* GMLXercesHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey)
+{
+    const Attributes* attrs = (const Attributes*) attr;
+    if( idx >= attrs->getLength() )
+    {
+        *ppszKey = NULL;
+        return NULL;
+    }
+    *ppszKey = tr_strdup(attrs->getQName(idx));
+    return tr_strdup(attrs->getValue(idx));
+}
+
 #endif
 
 #ifdef HAVE_EXPAT
@@ -405,6 +422,24 @@ char* GMLExpatHandler::GetAttributeValue(void* attr, const char* pszAttributeNam
     return NULL;
 }
 
+/************************************************************************/
+/*                    GetAttributeByIdx()                               */
+/************************************************************************/
+
+/* CAUTION: should be called with increasing idx starting from 0 and */
+/* no attempt to read beyond end of list */
+char* GMLExpatHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey)
+{
+    const char** papszIter = (const char** )attr;
+    if( papszIter[2 * idx] == NULL )
+    {
+        *ppszKey = NULL;
+        return NULL;
+    }
+    *ppszKey = CPLStrdup(papszIter[2 * idx]);
+    return CPLStrdup(papszIter[2 * idx+1]);
+}
+
 #endif
 
 
@@ -477,17 +512,21 @@ GMLHandler::GMLHandler( GMLReader *poReader )
     m_nGeomLen = 0;
     m_nGeometryDepth = 0;
     m_bAlreadyFoundGeometry = FALSE;
+    m_nGeometryPropertyIndex = 0;
 
     m_nDepthFeature = m_nDepth = 0;
     m_inBoundedByDepth = 0;
+
+    eAppSchemaType = APPSCHEMA_GENERIC;
+
     m_pszCityGMLGenericAttrName = NULL;
     m_inCityGMLGenericAttrDepth = 0;
-    m_bIsCityGML = FALSE;
-    m_bIsAIXM = FALSE;
+
     m_bReportHref = FALSE;
     m_pszHref = NULL;
     m_pszUom = NULL;
     m_pszValue = NULL;
+    m_pszKieli = NULL;
 
     pasGeometryNames = (GeometryNamesStruct*)CPLMalloc(
         GML_GEOMETRY_TYPE_COUNT * sizeof(GeometryNamesStruct));
@@ -521,6 +560,7 @@ GMLHandler::~GMLHandler()
     CPLFree( m_pszHref );
     CPLFree( m_pszUom );
     CPLFree( m_pszValue );
+    CPLFree( m_pszKieli );
     CPLFree( pasGeometryNames );
 }
 
@@ -538,6 +578,7 @@ OGRErr GMLHandler::startElement(const char *pszName, int nLenName, void* attr)
         case STATE_DEFAULT:             eRet = startElementDefault(pszName, nLenName, attr); break;
         case STATE_FEATURE:             eRet = startElementFeatureAttribute(pszName, nLenName, attr); break;
         case STATE_PROPERTY:            eRet = startElementFeatureAttribute(pszName, nLenName, attr); break;
+        case STATE_FEATUREPROPERTY:     eRet = startElementFeatureProperty(pszName, nLenName, attr); break;
         case STATE_GEOMETRY:            eRet = startElementGeometry(pszName, nLenName, attr); break;
         case STATE_IGNORED_FEATURE:     eRet = OGRERR_NONE; break;
         case STATE_BOUNDED_BY:          eRet = startElementBoundedBy(pszName, nLenName, attr); break;
@@ -561,6 +602,7 @@ OGRErr GMLHandler::endElement()
         case STATE_DEFAULT:             return endElementDefault(); break;
         case STATE_FEATURE:             return endElementFeature(); break;
         case STATE_PROPERTY:            return endElementAttribute(); break;
+        case STATE_FEATUREPROPERTY:     return endElementFeatureProperty(); break;
         case STATE_GEOMETRY:            return endElementGeometry(); break;
         case STATE_IGNORED_FEATURE:     return endElementIgnoredFeature(); break;
         case STATE_BOUNDED_BY:          return endElementBoundedBy(); break;
@@ -581,6 +623,7 @@ OGRErr GMLHandler::dataHandler(const char *data, int nLen)
         case STATE_DEFAULT:             return OGRERR_NONE; break;
         case STATE_FEATURE:             return OGRERR_NONE; break;
         case STATE_PROPERTY:            return dataHandlerAttribute(data, nLen); break;
+        case STATE_FEATUREPROPERTY:     return OGRERR_NONE; break;
         case STATE_GEOMETRY:            return dataHandlerGeometry(data, nLen); break;
         case STATE_IGNORED_FEATURE:     return OGRERR_NONE; break;
         case STATE_BOUNDED_BY:          return OGRERR_NONE; break;
@@ -651,7 +694,7 @@ OGRErr GMLHandler::startElementGeometry(const char *pszName, int nLenName, void*
     /* Some CityGML lack a srsDimension="3" in posList, such as in */
     /* http://www.citygml.org/fileadmin/count.php?f=fileadmin%2Fcitygml%2Fdocs%2FFrankfurt_Street_Setting_LOD3.zip */
     /* So we have to add it manually */
-    if (m_bIsCityGML && nLenName == 7 &&
+    if (eAppSchemaType == APPSCHEMA_CITYGML && nLenName == 7 &&
         strcmp(pszName, "posList") == 0 &&
         CPLGetXMLValue(psCurNode, "srsDimension", NULL) == NULL)
     {
@@ -701,6 +744,281 @@ OGRErr GMLHandler::startElementCityGMLGenericAttr(const char *pszName, int nLenN
 
     return OGRERR_NONE;
 }
+
+/************************************************************************/
+/*                       DealWithAttributes()                           */
+/************************************************************************/
+
+void GMLHandler::DealWithAttributes(const char *pszName, int nLenName, void* attr )
+{
+    GMLReadState *poState = m_poReader->GetState();
+    GMLFeatureClass *poClass = poState->m_poFeature->GetClass();
+
+    for(unsigned int idx=0; TRUE ;idx++)
+    {
+        char* pszAttrKey = NULL;
+        char* pszAttrVal = NULL;
+
+        pszAttrVal = GetAttributeByIdx(attr, idx, &pszAttrKey);
+        if( pszAttrVal == NULL )
+            break;
+
+        int nAttrIndex;
+        const char* pszAttrKeyNoNS = strchr(pszAttrKey, ':');
+        if( pszAttrKeyNoNS != NULL )
+            pszAttrKeyNoNS ++;
+
+        /* If attribute is referenced by the .gfs */
+        if( poClass->IsSchemaLocked() &&
+            ( (pszAttrKeyNoNS != NULL &&
+               (nAttrIndex =
+                 m_poReader->GetAttributeElementIndex( pszName, nLenName, pszAttrKeyNoNS )) != -1) ||
+              ((nAttrIndex =
+                 m_poReader->GetAttributeElementIndex( pszName, nLenName, pszAttrKey )) != -1 ) ) )
+        {
+            nAttrIndex = FindRealPropertyByCheckingConditions( nAttrIndex, attr );
+            if( nAttrIndex >= 0 )
+            {
+                m_poReader->SetFeaturePropertyDirectly( NULL, pszAttrVal, nAttrIndex );
+                pszAttrVal = NULL;
+            }
+        }
+
+        /* Hard-coded historic cases */
+        else if( strcmp(pszAttrKey, "xlink:href") == 0 )
+        {
+            if (m_bReportHref)
+            {
+                if( m_bInCurField )
+                {
+                    CPLFree(m_pszHref);
+                    m_pszHref = pszAttrVal;
+                    pszAttrVal = NULL;
+                }
+                else if( !poClass->IsSchemaLocked() ||
+                         (nAttrIndex =
+                            m_poReader->GetAttributeElementIndex( CPLSPrintf("%s_href", pszName ),
+                                                      nLenName + 5 )) != -1 )
+                {
+                    poState->PushPath( pszName, nLenName );
+                    CPLString osPropNameHref = poState->osPath + "_href";
+                    poState->PopPath();
+                    m_poReader->SetFeaturePropertyDirectly( osPropNameHref, pszAttrVal, nAttrIndex );
+                    pszAttrVal = NULL;
+                }
+            }
+        }
+        else if( strcmp(pszAttrKey, "uom") == 0 )
+        {
+            CPLFree(m_pszUom);
+            m_pszUom = pszAttrVal;
+            pszAttrVal = NULL;
+        }
+        else if( strcmp(pszAttrKey, "value") == 0 )
+        {
+            CPLFree(m_pszValue);
+            m_pszValue = pszAttrVal;
+            pszAttrVal = NULL;
+        }
+        else /* Get language in 'kieli' attribute of 'teksti' element */
+        if( eAppSchemaType == APPSCHEMA_MTKGML &&
+            nLenName == 6 && strcmp(pszName, "teksti") == 0 &&
+            strcmp(pszAttrKey, "kieli") == 0 )
+        {
+            CPLFree(m_pszKieli);
+            m_pszKieli = pszAttrVal;
+            pszAttrVal = NULL;
+        }
+
+        /* Should we report all attributes ? */
+        else if( m_poReader->ReportAllAttributes() && !poClass->IsSchemaLocked() )
+        {
+            m_poReader->SetFeaturePropertyDirectly(
+                CPLSPrintf("%s@%s", pszName, pszAttrKeyNoNS ? pszAttrKeyNoNS : pszAttrKey),
+                pszAttrVal, -1 );
+            pszAttrVal = NULL;
+        }
+
+        CPLFree(pszAttrKey);
+        CPLFree(pszAttrVal);
+    }
+
+#if 0
+    if( poClass->IsSchemaLocked() )
+    {
+        poState->PushPath( pszName, nLenName );
+        CPLString osPath = poState->osPath;
+        poState->PopPath();
+        /* Find fields that match an attribute that is missing */
+        for(int i=0; i < poClass->GetPropertyCount(); i++ )
+        {
+            GMLPropertyDefn* poProp = poClass->GetProperty(i);
+            const char* pszSrcElement = poProp->GetSrcElement();
+            if( poProp->GetType() == OFTStringList &&
+                poProp->GetSrcElementLen() > osPath.size() &&
+                strncmp(pszSrcElement, osPath, osPath.size()) == 0 &&
+                pszSrcElement[osPath.size()] == '@' )
+            {
+                char* pszAttrVal = GetAttributeValue(attr, pszSrcElement + osPath.size() + 1);
+                if( pszAttrVal == NULL )
+                {
+                    const char* pszCond = poProp->GetCondition();
+                    if( pszCond == NULL || IsConditionMatched(pszCond, attr) )
+                    {
+                        m_poReader->SetFeaturePropertyDirectly( NULL, CPLStrdup(""), i );
+                    }
+                }
+                else
+                    CPLFree(pszAttrVal);
+            }
+        }
+    }
+#endif
+}
+
+/************************************************************************/
+/*                        IsConditionMatched()                          */
+/************************************************************************/
+
+/* FIXME! 'and' / 'or' operators are evaluated left to right, without */
+/* and precedence rules between them ! */
+
+int GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
+{
+    if( pszCondition == NULL )
+        return TRUE;
+
+    int bSyntaxError = FALSE;
+    CPLString osCondAttr, osCondVal;
+    const char* pszIter = pszCondition;
+    int bOpEqual = TRUE;
+    while( *pszIter == ' ' )
+        pszIter ++;
+    if( *pszIter != '@' )
+        bSyntaxError = TRUE;
+    else
+    {
+        pszIter++;
+        while( *pszIter != '\0' &&
+               *pszIter != ' ' &&
+               *pszIter != '!' &&
+               *pszIter != '=' )
+        {
+            osCondAttr += *pszIter;
+            pszIter++;
+        }
+        while( *pszIter == ' ' )
+            pszIter ++;
+
+        if( *pszIter == '!' )
+        {
+            bOpEqual = FALSE;
+            pszIter ++;
+        }
+
+        if( *pszIter != '=' )
+            bSyntaxError = TRUE;
+        else
+        {
+            pszIter ++;
+            while( *pszIter == ' ' )
+                pszIter ++;
+            if( *pszIter != '\'' )
+                bSyntaxError = TRUE;
+            else
+            {
+                pszIter ++;
+                while( *pszIter != '\0' &&
+                       *pszIter != '\'' )
+                {
+                    osCondVal += *pszIter;
+                    pszIter++;
+                }
+                if( *pszIter != '\'' )
+                    bSyntaxError = TRUE;
+                else
+                {
+                    pszIter ++;
+                    while( *pszIter == ' ' )
+                        pszIter ++;
+                }
+            }
+        }
+    }
+
+    if( bSyntaxError )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Invalid condition : %s. Must be of the form @attrname[!]='attrvalue' [and|or other_cond]*. 'and' and 'or' operators cannot be mixed",
+                 pszCondition);
+        return FALSE;
+    }
+
+    char* pszVal = GetAttributeValue(attr, osCondAttr);
+    if( pszVal == NULL )
+        pszVal = CPLStrdup("");
+    int bCondMet = ((bOpEqual && strcmp(pszVal, osCondVal) == 0 ) ||
+                    (!bOpEqual && strcmp(pszVal, osCondVal) != 0 ));
+    CPLFree(pszVal);
+    if( *pszIter == '\0' )
+        return bCondMet;
+
+    if( strncmp(pszIter, "and", 3) == 0 )
+    {
+        pszIter += 3;
+        if( !bCondMet )
+            return FALSE;
+        return IsConditionMatched(pszIter, attr);
+    }
+
+    if( strncmp(pszIter, "or", 2) == 0 )
+    {
+        pszIter += 2;
+        if( bCondMet )
+            return TRUE;
+        return IsConditionMatched(pszIter, attr);
+    }
+
+    CPLError(CE_Failure, CPLE_NotSupported,
+                "Invalid condition : %s. Must be of the form @attrname[!]='attrvalue' [and|or other_cond]*. 'and' and 'or' operators cannot be mixed",
+                pszCondition);
+    return FALSE;
+}
+
+/************************************************************************/
+/*                FindRealPropertyByCheckingConditions()                */
+/************************************************************************/
+
+int GMLHandler::FindRealPropertyByCheckingConditions(int nIdx, void* attr)
+{
+    GMLReadState *poState = m_poReader->GetState();
+    GMLFeatureClass *poClass = poState->m_poFeature->GetClass();
+
+    GMLPropertyDefn* poProp = poClass->GetProperty(nIdx);
+    const char* pszCond = poProp->GetCondition();
+    if( pszCond != NULL && !IsConditionMatched(pszCond, attr) )
+    {
+        /* try other attributes with same source element, but with different */
+        /* condition */
+        const char* pszSrcElement = poProp->GetSrcElement();
+        nIdx = -1;
+        for(int i=m_nAttributeIndex+1; i < poClass->GetPropertyCount(); i++ )
+        {
+            poProp = poClass->GetProperty(i);
+            if( strcmp(poProp->GetSrcElement(), pszSrcElement) == 0 )
+            {
+                pszCond = poProp->GetCondition();
+                if( IsConditionMatched(pszCond, attr) )
+                {
+                    nIdx = i;
+                    break;
+                }
+            }
+        }
+    }
+    return nIdx;
+}
+
 /************************************************************************/
 /*                      startElementFeatureAttribute()                  */
 /************************************************************************/
@@ -722,9 +1040,25 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 
         /* If the <GeometryElementPath> is defined in the .gfs, use it */
         /* to read the appropriate geometry element */
-        const char* pszGeometryElement = poState->m_poFeature->GetClass()->GetGeometryElement();
-        if (pszGeometryElement != NULL)
-            bReadGeometry = strcmp(poState->osPath.c_str(), pszGeometryElement) == 0;
+        GMLFeatureClass* poClass = poState->m_poFeature->GetClass();
+        m_nGeometryPropertyIndex = 0;
+        if( poClass->IsSchemaLocked() &&
+            poClass->GetGeometryPropertyCount() == 0 )
+        {
+            bReadGeometry = FALSE;
+        }
+        else if( poClass->IsSchemaLocked() &&
+                 poClass->GetGeometryPropertyCount() == 1 &&
+                 poClass->GetGeometryProperty(0)->GetSrcElement()[0] == '\0' )
+        {
+            bReadGeometry = TRUE;
+        }
+        else if( poClass->IsSchemaLocked() &&
+                 poClass->GetGeometryPropertyCount() > 0 )
+        {
+            m_nGeometryPropertyIndex = poClass->GetGeometryPropertyIndexBySrcElement( poState->osPath.c_str() );
+            bReadGeometry = (m_nGeometryPropertyIndex >= 0);
+        }
         else if( m_poReader->FetchAllGeometries() )
         {
             bReadGeometry = TRUE;
@@ -733,7 +1067,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
         {
             /* AIXM special case: for RouteSegment, we only want to read Curve geometries */
             /* not 'start' and 'end' geometries */
-            if (m_bIsAIXM &&
+            if (eAppSchemaType == APPSCHEMA_AIXM &&
                 strcmp(poState->m_poFeature->GetClass()->GetName(), "RouteSegment") == 0)
                 bReadGeometry = strcmp( pszName, "Curve") == 0;
 
@@ -779,7 +1113,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 /* -------------------------------------------------------------------- */
 /*      Is it a CityGML generic attribute ?                             */
 /* -------------------------------------------------------------------- */
-    else if( m_bIsCityGML &&
+    else if( eAppSchemaType == APPSCHEMA_CITYGML &&
              m_poReader->IsCityGMLGenericAttributeElement( pszName, attr ) )
     {
         CPLFree(m_pszCityGMLGenericAttrName);
@@ -798,49 +1132,50 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
     else if( (m_nAttributeIndex =
                 m_poReader->GetAttributeElementIndex( pszName, nLenName )) != -1 )
     {
-        if(m_pszCurField)
+        GMLFeatureClass *poClass = poState->m_poFeature->GetClass();
+        if( poClass->IsSchemaLocked() &&
+            (poClass->GetProperty(m_nAttributeIndex)->GetType() == GMLPT_FeatureProperty ||
+             poClass->GetProperty(m_nAttributeIndex)->GetType() == GMLPT_FeaturePropertyList) )
         {
-            CPLFree(m_pszCurField);
-            m_pszCurField = NULL;
-            m_nCurFieldLen = m_nCurFieldAlloc = 0;
+            m_nAttributeDepth = m_nDepth;
+            PUSH_STATE(STATE_FEATUREPROPERTY);
         }
-        m_bInCurField = TRUE;
-        if (m_bReportHref)
+        else
         {
-            CPLFree(m_pszHref);
-            m_pszHref = GetAttributeValue(attr, "xlink:href");
-        }
-        CPLFree(m_pszUom);
-        m_pszUom = GetAttributeValue(attr, "uom");
-        CPLFree(m_pszValue);
-        m_pszValue = GetAttributeValue(attr, "value");
+            /* Is this a property with a condition on an attribute value ? */
+            if( poClass->IsSchemaLocked() )
+            {
+                m_nAttributeIndex = FindRealPropertyByCheckingConditions( m_nAttributeIndex, attr );
+            }
 
-        if (stateStack[nStackDepth] != STATE_PROPERTY)
-        {
-            m_nAttributeDepth = m_nDepth;
-            PUSH_STATE(STATE_PROPERTY);
+            if( m_nAttributeIndex >= 0 )
+            {
+                if(m_pszCurField)
+                {
+                    CPLFree(m_pszCurField);
+                    m_pszCurField = NULL;
+                    m_nCurFieldLen = m_nCurFieldAlloc = 0;
+                }
+                m_bInCurField = TRUE;
+
+                DealWithAttributes(pszName, nLenName, attr);
+
+                if (stateStack[nStackDepth] != STATE_PROPERTY)
+                {
+                    m_nAttributeDepth = m_nDepth;
+                    PUSH_STATE(STATE_PROPERTY);
+                }
+            }
+            /*else
+            {
+                DealWithAttributes(pszName, nLenName, attr);
+            }*/
         }
 
     }
-    else if( m_bReportHref && (m_nAttributeIndex =
-                m_poReader->GetAttributeElementIndex( CPLSPrintf("%s_href", pszName ),
-                                                      nLenName + 5 )) != -1 )
+    else
     {
-        if(m_pszCurField)
-        {
-            CPLFree(m_pszCurField);
-            m_pszCurField = NULL;
-            m_nCurFieldLen = m_nCurFieldAlloc = 0;
-        }
-        m_bInCurField = TRUE;
-        CPLFree(m_pszHref);
-        m_pszHref = GetAttributeValue(attr, "xlink:href");
-
-        if (stateStack[nStackDepth] != STATE_PROPERTY)
-        {
-            m_nAttributeDepth = m_nDepth;
-            PUSH_STATE(STATE_PROPERTY);
-        }
+        DealWithAttributes(pszName, nLenName, attr);
     }
 
     poState->PushPath( pszName, nLenName );
@@ -857,11 +1192,25 @@ OGRErr GMLHandler::startElementTop(const char *pszName, int nLenName, void* attr
 {
     if (strcmp(pszName, "CityModel") == 0 )
     {
-        m_bIsCityGML = TRUE;
+        eAppSchemaType = APPSCHEMA_CITYGML;
     }
     else if (strcmp(pszName, "AIXMBasicMessage") == 0)
     {
-        m_bIsAIXM = m_bReportHref = TRUE;
+        eAppSchemaType = APPSCHEMA_AIXM;
+        m_bReportHref = TRUE;
+    }
+    else if (strcmp(pszName, "Maastotiedot") == 0)
+    {
+        eAppSchemaType = APPSCHEMA_MTKGML;
+
+        char *pszSRSName = GetAttributeValue(attr, "srsName");
+        m_poReader->SetGlobalSRSName(pszSRSName);
+        CPLFree(pszSRSName);
+
+        m_bReportHref = TRUE;
+
+        /* the schemas of MTKGML don't have (string) width, so don't set it */
+        m_poReader->SetWidthFlag(FALSE);
     }
 
     stateStack[0] = STATE_DEFAULT;
@@ -880,11 +1229,42 @@ OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void*
 /*      Is it a feature?  If so push a whole new state, and return.     */
 /* -------------------------------------------------------------------- */
     int nClassIndex;
-    if( (nClassIndex = m_poReader->GetFeatureElementIndex( pszName, nLenName )) != -1 )
+    const char* pszFilteredClassName;
+
+    if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
+    {
+        m_inBoundedByDepth = m_nDepth;
+
+        PUSH_STATE(STATE_BOUNDED_BY);
+
+        return OGRERR_NONE;
+    }
+
+    else if( m_poReader->ShouldLookForClassAtAnyLevel() &&
+        ( pszFilteredClassName = m_poReader->GetFilteredClassName() ) != NULL )
+    {
+        if( strcmp(pszName, pszFilteredClassName) == 0 )
+        {
+            m_poReader->PushFeature( pszName, GetFID(attr), m_poReader->GetFilteredClassIndex() );
+
+            m_nDepthFeature = m_nDepth;
+
+            PUSH_STATE(STATE_FEATURE);
+
+            return OGRERR_NONE;
+        }
+    }
+
+    /* WFS 2.0 GetFeature documents have a wfs:FeatureCollection */
+    /* as a wfs:member of the top wfs:FeatureCollection. We don't want this */
+    /* wfs:FeatureCollection to be recognized as a feature */
+    else if( (!(nLenName == strlen("FeatureCollection") &&
+                strcmp(pszName, "FeatureCollection") == 0)) &&
+             (nClassIndex = m_poReader->GetFeatureElementIndex( pszName, nLenName, eAppSchemaType )) != -1 )
     {
         m_bAlreadyFoundGeometry = FALSE;
 
-        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
+        pszFilteredClassName = m_poReader->GetFilteredClassName();
         if ( pszFilteredClassName != NULL &&
              strcmp(pszName, pszFilteredClassName) != 0 )
         {
@@ -896,7 +1276,16 @@ OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void*
         }
         else
         {
-            m_poReader->PushFeature( pszName, GetFID(attr), nClassIndex );
+            if( eAppSchemaType == APPSCHEMA_MTKGML )
+            {
+                m_poReader->PushFeature( pszName, NULL, nClassIndex );
+
+                char* pszGID = GetAttributeValue(attr, "gid");
+                if( pszGID )
+                    m_poReader->SetFeaturePropertyDirectly( "gid", pszGID, -1, GMLPT_String );
+            }
+            else
+                m_poReader->PushFeature( pszName, GetFID(attr), nClassIndex );
 
             m_nDepthFeature = m_nDepth;
 
@@ -906,15 +1295,6 @@ OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void*
         }
     }
 
-    else if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
-    {
-        m_inBoundedByDepth = m_nDepth;
-
-        PUSH_STATE(STATE_BOUNDED_BY);
-
-        return OGRERR_NONE;
-    }
-
 /* -------------------------------------------------------------------- */
 /*      Push the element onto the current state's path.                 */
 /* -------------------------------------------------------------------- */
@@ -1061,16 +1441,46 @@ OGRErr GMLHandler::endElementGeometry()
         /* a bit specially because ElevatedPoint is aixm: stuff and */
         /* the srsDimension of the <gml:pos> can be set to TRUE although */
         /* they are only 2 coordinates in practice */
-        if ( m_bIsAIXM && psInterestNode != NULL &&
+        if ( eAppSchemaType == APPSCHEMA_AIXM && psInterestNode != NULL &&
             strcmp(psInterestNode->pszValue, "ElevatedPoint") == 0 )
         {
             psInterestNode = ParseAIXMElevationPoint(psInterestNode);
         }
+        else if ( eAppSchemaType == APPSCHEMA_MTKGML && psInterestNode != NULL )
+        {
+            if( strcmp(psInterestNode->pszValue, "Murtoviiva") == 0 )
+            {
+                CPLFree(psInterestNode->pszValue);
+                psInterestNode->pszValue = CPLStrdup("gml:LineString");
+            }
+            else if( strcmp(psInterestNode->pszValue, "Alue") == 0 )
+            {
+                CPLFree(psInterestNode->pszValue);
+                psInterestNode->pszValue = CPLStrdup("gml:Polygon");
+            }
+            else if( strcmp(psInterestNode->pszValue, "Piste") == 0 )
+            {
+                CPLFree(psInterestNode->pszValue);
+                psInterestNode->pszValue = CPLStrdup("gml:Point");
+            }
+        }
 
+        GMLFeature* poGMLFeature = m_poReader->GetState()->m_poFeature;
         if (m_poReader->FetchAllGeometries())
-            m_poReader->GetState()->m_poFeature->AddGeometry(psInterestNode);
+            poGMLFeature->AddGeometry(psInterestNode);
         else
-            m_poReader->GetState()->m_poFeature->SetGeometryDirectly(psInterestNode);
+        {
+            GMLFeatureClass* poClass = poGMLFeature->GetClass();
+            if( poClass->GetGeometryPropertyCount() > 1 )
+            {
+                poGMLFeature->SetGeometryDirectly(
+                    m_nGeometryPropertyIndex, psInterestNode);
+            }
+            else
+            {
+                poGMLFeature->SetGeometryDirectly(psInterestNode);
+            }
+        }
 
         POP_STATE();
     }
@@ -1149,6 +1559,13 @@ OGRErr GMLHandler::endElementAttribute()
             m_pszUom = NULL;
         }
 
+        if (m_pszKieli != NULL)
+        {
+            CPLString osPropName = poState->osPath + "_kieli";
+            m_poReader->SetFeaturePropertyDirectly( osPropName, m_pszKieli, -1 );
+            m_pszKieli = NULL;
+        }
+
         m_nCurFieldLen = m_nCurFieldAlloc = 0;
         m_bInCurField = FALSE;
         m_nAttributeIndex = -1;
@@ -1168,6 +1585,43 @@ OGRErr GMLHandler::endElementAttribute()
 }
 
 /************************************************************************/
+/*                    startElementFeatureProperty()                     */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementFeatureProperty(const char *pszName, int nLenName, void* attr )
+{
+    if (m_nDepth == m_nAttributeDepth + 1)
+    {
+        const char* pszGMLId = GetFID(attr);
+        if( pszGMLId != NULL )
+        {
+            m_poReader->SetFeaturePropertyDirectly( NULL,
+                                                    CPLStrdup(CPLSPrintf("#%s", pszGMLId)),
+                                                    m_nAttributeIndex );
+        }
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                      endElementFeatureProperty()                      */
+/************************************************************************/
+
+OGRErr GMLHandler::endElementFeatureProperty()
+
+{
+    if (m_nDepth == m_nAttributeDepth)
+    {
+        GMLReadState *poState = m_poReader->GetState();
+        poState->PopPath();
+
+        POP_STATE();
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                          endElementFeature()                         */
 /************************************************************************/
 OGRErr GMLHandler::endElementFeature()
@@ -1318,7 +1772,13 @@ int GMLHandler::IsGeometryElement( const char *pszElement )
             nFirst = nMiddle + 1;
     } while(nFirst <= nLast);
 
-    if (m_bIsAIXM && strcmp( pszElement, "ElevatedPoint") == 0)
+    if (eAppSchemaType == APPSCHEMA_AIXM && strcmp( pszElement, "ElevatedPoint") == 0)
+        return TRUE;
+
+    if( eAppSchemaType == APPSCHEMA_MTKGML &&
+        ( strcmp( pszElement, "Piste") == 0 ||
+          strcmp( pszElement, "Alue") == 0  ||
+          strcmp( pszElement, "Murtoviiva") == 0 ) )
         return TRUE;
 
     return FALSE;
diff --git a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
index 5988768..58da94f 100644
--- a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlpropertydefn.cpp 22954 2011-08-19 21:47:19Z rouault $
+ * $Id: gmlpropertydefn.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLPropertyDefn
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -53,7 +54,7 @@ GMLPropertyDefn::GMLPropertyDefn( const char *pszName,
     m_eType = GMLPT_Untyped;
     m_nWidth = 0; 
     m_nPrecision = 0;
-    m_nIndex = -1;
+    m_pszCondition = NULL;
 }
 
 /************************************************************************/
@@ -65,6 +66,7 @@ GMLPropertyDefn::~GMLPropertyDefn()
 {
     CPLFree( m_pszName );
     CPLFree( m_pszSrcElement );
+    CPLFree( m_pszCondition );
 }
 
 /************************************************************************/
@@ -88,13 +90,24 @@ void GMLPropertyDefn::SetSrcElement( const char *pszSrcElement )
 }
 
 /************************************************************************/
+/*                           SetCondition()                             */
+/************************************************************************/
+
+void GMLPropertyDefn::SetCondition( const char *pszCondition )
+{
+    CPLFree( m_pszCondition );
+    m_pszCondition = ( pszCondition != NULL ) ? CPLStrdup(pszCondition) : NULL;
+}
+
+/************************************************************************/
 /*                        AnalysePropertyValue()                        */
 /*                                                                      */
 /*      Examine the passed property value, and see if we need to        */
 /*      make the field type more specific, or more general.             */
 /************************************************************************/
 
-void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty )
+void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
+                                            int bSetWidth )
 
 {
 /* -------------------------------------------------------------------- */
@@ -157,11 +170,14 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty )
     
         if( m_eType == GMLPT_String )
         {
-            /* grow the Width to the length of the string passed in */
-            int nWidth;
-            nWidth = strlen(pszValue);
-            if ( m_nWidth < nWidth ) 
-                SetWidth( nWidth );
+            if( bSetWidth )
+            {
+                /* grow the Width to the length of the string passed in */
+                int nWidth;
+                nWidth = strlen(pszValue);
+                if ( m_nWidth < nWidth ) 
+                    SetWidth( nWidth );
+            }
         }
         else if( m_eType == GMLPT_Untyped || m_eType == GMLPT_Integer )
         {
@@ -176,3 +192,29 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty )
         }
     }
 }
+
+/************************************************************************/
+/*                       GMLGeometryPropertyDefn                        */
+/************************************************************************/
+
+GMLGeometryPropertyDefn::GMLGeometryPropertyDefn( const char *pszName,
+                                                  const char *pszSrcElement,
+                                                  int nType,
+                                                  int nAttributeIndex )
+{
+    m_pszName = (pszName == NULL || pszName[0] == '\0') ?
+                        CPLStrdup(pszSrcElement) : CPLStrdup(pszName);
+    m_pszSrcElement = CPLStrdup(pszSrcElement);
+    m_nGeometryType = nType;
+    m_nAttributeIndex = nAttributeIndex;
+}
+
+/************************************************************************/
+/*                       ~GMLGeometryPropertyDefn                       */
+/************************************************************************/
+
+GMLGeometryPropertyDefn::~GMLGeometryPropertyDefn()
+{
+    CPLFree(m_pszName);
+    CPLFree(m_pszSrcElement);
+}
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index 2e3b78d..ea8d7d7 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: gmlreader.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,6 +35,7 @@
 #include "gmlreaderp.h"
 #include "cpl_conv.h"
 #include <map>
+#include "cpl_multiproc.h"
 
 #define SUPPORT_GEOMETRY
 
@@ -98,8 +100,9 @@ IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
 
 #endif
 
-int GMLReader::m_bXercesInitialized = FALSE;
+int GMLReader::m_bXercesInitialized = -1;
 int GMLReader::m_nInstanceCount = 0;
+void *GMLReader::hMutex = NULL;
 
 /************************************************************************/
 /*                             GMLReader()                              */
@@ -128,9 +131,9 @@ GMLReader::GMLReader(int bUseExpatParserPreferably,
         CPLDebug("GML", "Using Xerces reader");
 #endif
 
-    m_nInstanceCount++;
     m_nClassCount = 0;
     m_papoClass = NULL;
+    m_bLookForClassAtAnyLevel = FALSE;
 
     m_bClassListLocked = FALSE;
 
@@ -170,11 +173,18 @@ GMLReader::GMLReader(int bUseExpatParserPreferably,
     m_bCanUseGlobalSRSName = FALSE;
 
     m_pszFilteredClassName = NULL;
+    m_nFilteredClassIndex = -1;
 
     m_bSequentialLayers = -1;
 	
     /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
     m_bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+
+    m_bSetWidthFlag = TRUE;
+
+    m_bReportAllAttributes = CSLTestBoolean(
+                    CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO"));
+
 }
 
 /************************************************************************/
@@ -192,13 +202,16 @@ GMLReader::~GMLReader()
 
     delete m_poRecycledState;
 
-    --m_nInstanceCount;
 #ifdef HAVE_XERCES
-    if( m_nInstanceCount == 0 && m_bXercesInitialized )
+    {
+    CPLMutexHolderD(&hMutex);
+    --m_nInstanceCount;
+    if( m_nInstanceCount == 0 && m_bXercesInitialized > 0 )
     {
         XMLPlatformUtils::Terminate();
         m_bXercesInitialized = FALSE;
     }
+    }
 #endif
 #ifdef HAVE_EXPAT
     CPLFree(pabyBuf);
@@ -290,7 +303,10 @@ int GMLReader::SetupParser()
 
 int GMLReader::SetupParserXerces()
 {
-    if( !m_bXercesInitialized )
+    {
+    CPLMutexHolderD(&hMutex);
+    m_nInstanceCount++;
+    if( m_bXercesInitialized < 0 )
     {
         try
         {
@@ -302,10 +318,14 @@ int GMLReader::SetupParserXerces()
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Exception initializing Xerces based GML reader.\n%s", 
                       tr_strdup(toCatch.getMessage()) );
+            m_bXercesInitialized = FALSE;
             return FALSE;
         }
         m_bXercesInitialized = TRUE;
     }
+    if( !m_bXercesInitialized )
+        return FALSE;
+    }
 
     // Cleanup any old parser.
     if( m_poSAXReader != NULL )
@@ -708,13 +728,19 @@ void GMLReader::PushFeature( const char *pszElement,
 /*      GML feature element?                                            */
 /************************************************************************/
 
-int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLength )
+int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLength,
+                                       GMLAppSchemaType eAppSchemaType )
 
 {
     const char *pszLast = m_poState->GetLastComponent();
     size_t      nLenLast = m_poState->GetLastComponentLen();
 
-    if( (nLenLast >= 6 && EQUAL(pszLast+nLenLast-6,"member")) ||
+    if( eAppSchemaType == APPSCHEMA_MTKGML )
+    {
+        if( m_poState->m_nPathLength != 1 )
+            return -1;
+    }
+    else if( (nLenLast >= 6 && EQUAL(pszLast+nLenLast-6,"member")) ||
         (nLenLast >= 7 && EQUAL(pszLast+nLenLast-7,"members")) )
     {
         /* Default feature name */
@@ -754,7 +780,22 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
             /* GML answer of MapServer WMS GetFeatureInfo request */
         }
         else
+        {
+            if( m_bClassListLocked )
+            {
+                for( int i = 0; i < m_nClassCount; i++ )
+                {
+                    if( m_poState->osPath.size() + 1 + nElementLength == m_papoClass[i]->GetElementNameLen() &&
+                        m_papoClass[i]->GetElementName()[m_poState->osPath.size()] == '|' &&
+                        memcmp(m_poState->osPath.c_str(), m_papoClass[i]->GetElementName(), m_poState->osPath.size()) == 0 &&
+                        memcmp(pszElement,m_papoClass[i]->GetElementName() + 1 + m_poState->osPath.size(), nElementLength) == 0 )
+                    {
+                        return i;
+                    }
+                }
+            }
             return -1;
+        }
     }
 
     // If the class list isn't locked, any element that is a featureMember
@@ -816,7 +857,8 @@ int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* a
 /*                       GetAttributeElementIndex()                     */
 /************************************************************************/
 
-int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen )
+int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen,
+                                         const char *pszAttrKey )
 
 {
     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
@@ -829,14 +871,33 @@ int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen )
     // Otherwise build the path to this element into a single string
     // and compare against known attributes.
     if( m_poState->m_nPathLength == 0 )
-        return poClass->GetPropertyIndexBySrcElement(pszElement, nLen);
+    {
+        if( pszAttrKey == NULL )
+            return poClass->GetPropertyIndexBySrcElement(pszElement, nLen);
+        else
+        {
+            int nFullLen = nLen + 1 + strlen(pszAttrKey);
+            osElemPath.reserve(nFullLen);
+            osElemPath.assign(pszElement, nLen);
+            osElemPath.append(1, '@');
+            osElemPath.append(pszAttrKey);
+            return poClass->GetPropertyIndexBySrcElement(osElemPath.c_str(), nFullLen);
+        }
+    }
     else
     {
         int nFullLen = nLen + m_poState->osPath.size() + 1;
+        if( pszAttrKey != NULL )
+            nFullLen += 1 + strlen(pszAttrKey);
         osElemPath.reserve(nFullLen);
         osElemPath.assign(m_poState->osPath);
         osElemPath.append(1, '|');
         osElemPath.append(pszElement, nLen);
+        if( pszAttrKey != NULL )
+        {
+            osElemPath.append(1, '@');
+            osElemPath.append(pszAttrKey);
+        }
         return poClass->GetPropertyIndexBySrcElement(osElemPath.c_str(), nFullLen);
     }
 }
@@ -941,6 +1002,9 @@ int GMLReader::AddClass( GMLFeatureClass *poNewClass )
         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     m_papoClass[m_nClassCount-1] = poNewClass;
 
+    if( poNewClass->HasFeatureProperties() )
+        m_bLookForClassAtAnyLevel = TRUE;
+
     return m_nClassCount-1;
 }
 
@@ -957,6 +1021,7 @@ void GMLReader::ClearClasses()
 
     m_nClassCount = 0;
     m_papoClass = NULL;
+    m_bLookForClassAtAnyLevel = FALSE;
 }
 
 /************************************************************************/
@@ -969,7 +1034,8 @@ void GMLReader::ClearClasses()
 
 void GMLReader::SetFeaturePropertyDirectly( const char *pszElement, 
                                             char *pszValue,
-                                            int iPropertyIn )
+                                            int iPropertyIn,
+                                            GMLPropertyType eType )
 
 {
     GMLFeature *poFeature = GetState()->m_poFeature;
@@ -1001,7 +1067,8 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
         {
             if( poClass->IsSchemaLocked() )
             {
-                CPLDebug("GML","Encountered property missing from class schema.");
+                CPLDebug("GML","Encountered property missing from class schema : %s.",
+                         pszElement);
                 CPLFree(pszValue);
                 return;
             }
@@ -1017,6 +1084,10 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
                     osFieldName = pszElement;
             }
 
+            size_t nPos = osFieldName.find("@");
+            if( nPos != std::string::npos )
+                osFieldName[nPos] = '_';
+
             // Does this conflict with an existing property name?
             while( poClass->GetProperty(osFieldName) != NULL )
             {
@@ -1027,6 +1098,8 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
 
             if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
                 poPDefn->SetType( GMLPT_String );
+            else if( eType != GMLPT_Untyped )
+                poPDefn->SetType( eType );
 
             if (poClass->AddProperty( poPDefn ) < 0)
             {
@@ -1048,7 +1121,7 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
     if( !poClass->IsSchemaLocked() )
     {
         poClass->GetProperty(iProperty)->AnalysePropertyValue(
-                             poFeature->GetProperty(iProperty));
+                             poFeature->GetProperty(iProperty), m_bSetWidthFlag );
     }
 }
 
@@ -1106,7 +1179,7 @@ int GMLReader::LoadClasses( const char *pszFile )
 
     VSIFCloseL( fp );
 
-    if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
+    if( strstr( pszWholeText, "<GMLFeatureClassList" ) == NULL )
     {
         VSIFree( pszWholeText );
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1236,7 +1309,7 @@ int GMLReader::SaveClasses( const char *pszFile )
 /*      looking for schema information.                                 */
 /************************************************************************/
 
-int GMLReader::PrescanForSchema( int bGetExtents )
+int GMLReader::PrescanForSchema( int bGetExtents, int bAnalyzeSRSPerFeature )
 
 {
     GMLFeature  *poFeature;
@@ -1252,7 +1325,6 @@ int GMLReader::PrescanForSchema( int bGetExtents )
 
     m_bCanUseGlobalSRSName = TRUE;
 
-    std::map<GMLFeatureClass*, int> osMapCountFeatureWithoutGeometry;
     GMLFeatureClass *poLastClass = NULL;
 
     m_bSequentialLayers = TRUE;
@@ -1276,17 +1348,12 @@ int GMLReader::PrescanForSchema( int bGetExtents )
             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
 
         const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
-        if (papsGeometry[0] == NULL)
+        if( papsGeometry != NULL && papsGeometry[0] != NULL )
         {
-            std::map<GMLFeatureClass*, int>::iterator oIter =
-                osMapCountFeatureWithoutGeometry.find(poClass);
-            if (oIter == osMapCountFeatureWithoutGeometry.end())
-                osMapCountFeatureWithoutGeometry[poClass] = 1;
-            else
-                oIter->second ++;
+            if( poClass->GetGeometryPropertyCount() == 0 )
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown ) );
         }
 
-
 #ifdef SUPPORT_GEOMETRY
         if( bGetExtents )
         {
@@ -1299,21 +1366,25 @@ int GMLReader::PrescanForSchema( int bGetExtents )
             {
                 double  dfXMin, dfXMax, dfYMin, dfYMax;
                 OGREnvelope sEnvelope;
+
                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
-                    poClass->GetGeometryType();
+                    poClass->GetGeometryProperty(0)->GetType();
 
-                const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry,
-                                                                        osWork,
-                                                                        m_bConsiderEPSGAsURN);
-                if (pszSRSName != NULL)
-                    m_bCanUseGlobalSRSName = FALSE;
-                poClass->MergeSRSName(pszSRSName);
+                if( bAnalyzeSRSPerFeature )
+                {
+                    const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry,
+                                                                            osWork,
+                                                                            m_bConsiderEPSGAsURN);
+                    if (pszSRSName != NULL)
+                        m_bCanUseGlobalSRSName = FALSE;
+                    poClass->MergeSRSName(pszSRSName);
+                }
 
                 // Merge geometry type into layer.
                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
                     eGType = wkbNone;
 
-                poClass->SetGeometryType( 
+                poClass->GetGeometryProperty(0)->SetType( 
                     (int) OGRMergeGeometryTypes(
                         eGType, poGeometry->getGeometryType() ) );
 
@@ -1356,49 +1427,49 @@ int GMLReader::PrescanForSchema( int bGetExtents )
 
         if (m_bCanUseGlobalSRSName)
             pszSRSName = m_pszGlobalSRSName;
-        
-        if (m_bInvertAxisOrderIfLatLong && GML_IsSRSLatLongOrder(pszSRSName))
+
+        OGRSpatialReference oSRS;
+        if (m_bInvertAxisOrderIfLatLong && GML_IsSRSLatLongOrder(pszSRSName) &&
+            oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
         {
-            OGRSpatialReference oSRS;
-            if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
+            OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
+            if( poGEOGCS != NULL )
+                poGEOGCS->StripNodes( "AXIS" );
+
+            OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
+            if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
+                poPROJCS->StripNodes( "AXIS" );
+
+            char* pszWKT = NULL;
+            if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE)
+                poClass->SetSRSName(pszWKT);
+            CPLFree(pszWKT);
+
+            /* So when we have computed the extent, we didn't know yet */
+            /* the SRS to use. Now we know it, we have to fix the extent */
+            /* order */
+            if (m_bCanUseGlobalSRSName)
             {
-                OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
-                if( poGEOGCS != NULL )
-                    poGEOGCS->StripNodes( "AXIS" );
-
-                OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
-                if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
-                    poPROJCS->StripNodes( "AXIS" );
-
-                char* pszWKT = NULL;
-                if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE)
-                    poClass->SetSRSName(pszWKT);
-                CPLFree(pszWKT);
-
-                /* So when we have computed the extent, we didn't know yet */
-                /* the SRS to use. Now we know it, we have to fix the extent */
-                /* order */
-                if (m_bCanUseGlobalSRSName)
-                {
-                    double  dfXMin, dfXMax, dfYMin, dfYMax;
-                    if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
-                        poClass->SetExtents( dfYMin, dfYMax, dfXMin, dfXMax );
-                }
+                double  dfXMin, dfXMax, dfYMin, dfYMax;
+                if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
+                    poClass->SetExtents( dfYMin, dfYMax, dfXMin, dfXMax );
             }
         }
-
-        std::map<GMLFeatureClass*, int>::iterator oIter =
-                osMapCountFeatureWithoutGeometry.find(poClass);
-        if (oIter != osMapCountFeatureWithoutGeometry.end() &&
-            oIter->second == poClass->GetFeatureCount())
+        else if( !bAnalyzeSRSPerFeature &&
+                 pszSRSName != NULL &&
+                 poClass->GetSRSName() == NULL &&
+                 oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE )
         {
-            poClass->SetGeometryType(wkbNone);
+            char* pszWKT = NULL;
+            if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE)
+                poClass->SetSRSName(pszWKT);
+            CPLFree(pszWKT);
         }
     }
 
     CleanupParser();
 
-    return m_nClassCount > 0;
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1420,7 +1491,15 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
 {
     if (m_pszGlobalSRSName == NULL && pszGlobalSRSName != NULL)
     {
-        if (strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
+        const char* pszVertCS_EPSG;
+        if( strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
+            (pszVertCS_EPSG = strstr(pszGlobalSRSName, ", EPSG:")) != NULL )
+        {
+            m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("EPSG:%d+%d",
+                    atoi(pszGlobalSRSName + 5),
+                    atoi(pszVertCS_EPSG + 7)));
+        }
+        else if (strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
             m_bConsiderEPSGAsURN)
         {
             m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
@@ -1441,5 +1520,19 @@ int GMLReader::SetFilteredClassName(const char* pszClassName)
 {
     CPLFree(m_pszFilteredClassName);
     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
+
+    m_nFilteredClassIndex = -1;
+    if( m_pszFilteredClassName != NULL )
+    {
+        for( int i = 0; i < m_nClassCount; i++ )
+        {
+            if( strcmp(m_papoClass[i]->GetElementName(), pszClassName) == 0 )
+            {
+                m_nFilteredClassIndex = i;
+                break;
+            }
+        }
+    }
+
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index c0fee9f..b131c4f 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 25120 2012-10-13 22:38:57Z rouault $
+ * $Id: gmlreader.h 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -44,7 +45,9 @@ typedef enum {
     GMLPT_Complex = 4,
     GMLPT_StringList = 5,
     GMLPT_IntegerList = 6, 
-    GMLPT_RealList = 7
+    GMLPT_RealList = 7,
+    GMLPT_FeatureProperty = 8,
+    GMLPT_FeaturePropertyList = 9
 } GMLPropertyType;
 
 /************************************************************************/
@@ -66,7 +69,7 @@ class CPL_DLL GMLPropertyDefn
     int               m_nPrecision;
     char             *m_pszSrcElement;
     size_t            m_nSrcElementLen;
-    int               m_nIndex;
+    char             *m_pszCondition;
 
 public:
     
@@ -84,16 +87,43 @@ public:
     void        SetSrcElement( const char *pszSrcElement );
     const char *GetSrcElement() const { return m_pszSrcElement; }
     size_t      GetSrcElementLen() const { return m_nSrcElementLen; }
-    void        SetAttributeIndex( int nIndex ) { m_nIndex = nIndex; }
-    int         GetAttributeIndex() const { return m_nIndex; }
 
-    void        AnalysePropertyValue( const GMLProperty* psGMLProperty );
+    void        SetCondition( const char *pszCondition );
+    const char *GetCondition() const { return m_pszCondition; }
+
+    void        AnalysePropertyValue( const GMLProperty* psGMLProperty,
+                                      int bSetWidth = TRUE );
 
     static bool IsSimpleType( GMLPropertyType eType )
     { return eType == GMLPT_String || eType == GMLPT_Integer || eType == GMLPT_Real; }
 };
 
 /************************************************************************/
+/*                    GMLGeometryPropertyDefn                           */
+/************************************************************************/
+
+class CPL_DLL GMLGeometryPropertyDefn
+{
+    char       *m_pszName;
+    char       *m_pszSrcElement;
+    int         m_nGeometryType;
+    int         m_nAttributeIndex;
+    
+public:
+        GMLGeometryPropertyDefn( const char *pszName, const char *pszSrcElement,
+                                 int nType, int nAttributeIndex = -1 );
+       ~GMLGeometryPropertyDefn();
+
+        const char *GetName() const { return m_pszName; } 
+
+        int GetType() const { return m_nGeometryType; }
+        void SetType(int nType) { m_nGeometryType = nType; }
+        const char *GetSrcElement() const { return m_pszSrcElement; }
+        
+        int GetAttributeIndex() const { return m_nAttributeIndex; }
+};
+
+/************************************************************************/
 /*                           GMLFeatureClass                            */
 /************************************************************************/
 class CPL_DLL GMLFeatureClass
@@ -102,9 +132,11 @@ class CPL_DLL GMLFeatureClass
     char        *m_pszElementName;
     int          n_nNameLen;
     int          n_nElementNameLen;
-    char        *m_pszGeometryElement;
     int         m_nPropertyCount;
     GMLPropertyDefn **m_papoProperty;
+    
+    int         m_nGeometryPropertyCount;
+    GMLGeometryPropertyDefn **m_papoGeometryProperty;
 
     int         m_bSchemaLocked;
 
@@ -118,9 +150,6 @@ class CPL_DLL GMLFeatureClass
     double      m_dfYMin;
     double      m_dfYMax;
 
-    int         m_nGeometryType;
-    int         m_nGeometryIndex;
-
     char       *m_pszSRSName;
     int         m_bSRSNameConsistant;
 
@@ -132,9 +161,6 @@ public:
     size_t      GetElementNameLen() const;
     void        SetElementName( const char *pszElementName );
 
-    const char *GetGeometryElement() const { return m_pszGeometryElement; }
-    void        SetGeometryElement( const char *pszElementName );
-
     const char *GetName() const { return m_pszName; }
     void        SetName(const char* pszNewName);
     int         GetPropertyCount() const { return m_nPropertyCount; }
@@ -143,8 +169,16 @@ public:
     GMLPropertyDefn *GetProperty( const char *pszName ) const 
         { return GetProperty( GetPropertyIndex(pszName) ); }
     int         GetPropertyIndexBySrcElement( const char *pszElement, int nLen ) const;
+    
+    int         GetGeometryPropertyCount() const { return m_nGeometryPropertyCount; }
+    GMLGeometryPropertyDefn *GetGeometryProperty( int iIndex ) const;
+    int         GetGeometryPropertyIndexBySrcElement( const char *pszElement ) const;
+
+    int         HasFeatureProperties();
 
     int         AddProperty( GMLPropertyDefn * );
+    int         AddGeometryProperty( GMLGeometryPropertyDefn * );
+    void        ClearGeometryProperties();
 
     int         IsSchemaLocked() const { return m_bSchemaLocked; }
     void        SetSchemaLocked( int bLock ) { m_bSchemaLocked = bLock; }
@@ -161,11 +195,6 @@ public:
     int         GetExtents( double *pdfXMin, double *pdfXMax, 
                             double *pdFYMin, double *pdfYMax );
 
-    int         GetGeometryType() const { return m_nGeometryType; }
-    void        SetGeometryType( int nNewType ) { m_nGeometryType = nNewType; }
-    int         GetGeometryAttributeIndex() const { return m_nGeometryIndex; }
-    void        SetGeometryAttributeIndex( int nGeometryIndex ) { m_nGeometryIndex = nGeometryIndex; }
-
     void        SetSRSName( const char* pszSRSName );
     void        MergeSRSName( const char* pszSRSName );
     const char *GetSRSName() { return m_pszSRSName; }
@@ -200,8 +229,10 @@ public:
     GMLFeatureClass*GetClass() const { return m_poClass; }
 
     void            SetGeometryDirectly( CPLXMLNode* psGeom );
+    void            SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom );
     void            AddGeometry( CPLXMLNode* psGeom );
     const CPLXMLNode* const * GetGeometryList() const { return m_papsGeometry; }
+    const CPLXMLNode* GetGeometryRef( int nIdx ) const;
 
     void            SetPropertyDirectly( int i, char *pszValue );
 
@@ -255,7 +286,7 @@ public:
                                    int pbSqlitIsTempFile,
                                    int iSqliteCacheMB ) = 0;
 
-    virtual int PrescanForSchema( int bGetExtents = TRUE ) = 0;
+    virtual int PrescanForSchema( int bGetExtents = TRUE, int bAnalyzeSRSPerFeature = TRUE ) = 0;
     virtual int PrescanForTemplate( void ) = 0;
 
     virtual int HasStoppedParsing() = 0;
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index c529afc..c719a47 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 25183 2012-10-27 18:09:53Z rouault $
+ * $Id: gmlreaderp.h 27120 2014-04-03 20:33:49Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -81,6 +82,7 @@ typedef enum
     STATE_DEFAULT,
     STATE_FEATURE,
     STATE_PROPERTY,
+    STATE_FEATUREPROPERTY,
     STATE_GEOMETRY,
     STATE_IGNORED_FEATURE,
     STATE_BOUNDED_BY,
@@ -93,6 +95,15 @@ typedef struct
     CPLXMLNode* psLastChild;
 } NodeLastChild;
 
+
+typedef enum
+{
+    APPSCHEMA_GENERIC,
+    APPSCHEMA_CITYGML,
+    APPSCHEMA_AIXM,
+    APPSCHEMA_MTKGML /* format of National Land Survey Finnish */
+} GMLAppSchemaType;
+
 class GMLHandler
 {
     char      *m_pszCurField;
@@ -108,6 +119,7 @@ class GMLHandler
     int        m_nGeomLen;
     int        m_nGeometryDepth;
     int        m_bAlreadyFoundGeometry;
+    int        m_nGeometryPropertyIndex;
 
     int        m_nDepth;
     int        m_nDepthFeature;
@@ -116,13 +128,12 @@ class GMLHandler
 
     char      *m_pszCityGMLGenericAttrName;
     int        m_inCityGMLGenericAttrDepth;
-    int        m_bIsCityGML;
 
     int        m_bReportHref;
-    int        m_bIsAIXM;
     char      *m_pszHref;
     char      *m_pszUom;
     char      *m_pszValue;
+    char      *m_pszKieli;
 
     GeometryNamesStruct* pasGeometryNames;
 
@@ -152,8 +163,16 @@ class GMLHandler
     OGRErr     startElementDefault(const char *pszName, int nLenName, void* attr);
     OGRErr     endElementDefault();
 
+    OGRErr     startElementFeatureProperty(const char *pszName, int nLenName, void* attr);
+    OGRErr     endElementFeatureProperty();
+    
+    void       DealWithAttributes(const char *pszName, int nLenName, void* attr );
+    int        IsConditionMatched(const char* pszCondition, void* attr);
+    int        FindRealPropertyByCheckingConditions(int nIdx, void* attr);
+
 protected:
     GMLReader  *m_poReader;
+    GMLAppSchemaType eAppSchemaType;
 
     int              nStackDepth;
     HandlerState     stateStack[STACK_SIZE];
@@ -174,6 +193,7 @@ public:
     virtual ~GMLHandler();
 
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName) = 0;
+    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey) = 0;
 };
 
 
@@ -283,6 +303,7 @@ public:
     virtual const char* GetFID(void* attr);
     virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
+    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey);
 };
 
 #endif
@@ -311,6 +332,7 @@ public:
     virtual const char* GetFID(void* attr);
     virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
+    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey);
 
     static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
                                         const char **ppszAttr);
@@ -368,6 +390,7 @@ private:
 
     int         m_nClassCount;
     GMLFeatureClass **m_papoClass;
+    int           m_bLookForClassAtAnyLevel;
 
     char          *m_pszFilename;
 
@@ -421,12 +444,17 @@ private:
     int           m_bCanUseGlobalSRSName;
 
     char         *m_pszFilteredClassName;
+    int           m_nFilteredClassIndex;
 
     int           m_bSequentialLayers;
 
     std::string   osElemPath;
 
     int           m_bFaceHoleNegative;
+    
+    int           m_bSetWidthFlag;
+    
+    int           m_bReportAllAttributes;
 
     int           ParseXMLHugeFile( const char *pszOutputFilename, 
                                     const int bSqliteIsTempFile,
@@ -467,7 +495,7 @@ public:
                                        int pbSqliteIsTempFile,
                                        int iSqliteCacheMB );
 
-    int              PrescanForSchema(int bGetExtents = TRUE );
+    int              PrescanForSchema(int bGetExtents = TRUE, int bAnalyzeSRSPerFeature = TRUE );
     int              PrescanForTemplate( void );
     int              ReArrangeTemplateClasses( GFSTemplateList *pCC );
     void             ResetReading();
@@ -478,8 +506,10 @@ public:
     void             PopState();
     void             PushState( GMLReadState * );
 
-    int         GetFeatureElementIndex( const char *pszElement, int nLen );
-    int         GetAttributeElementIndex( const char *pszElement, int nLen );
+    int              ShouldLookForClassAtAnyLevel() { return m_bLookForClassAtAnyLevel; }
+
+    int         GetFeatureElementIndex( const char *pszElement, int nLen, GMLAppSchemaType eAppSchemaType );
+    int         GetAttributeElementIndex( const char *pszElement, int nLen, const char* pszAttrKey = NULL );
     int         IsCityGMLGenericAttributeElement( const char *pszElement, void* attr );
 
     void        PushFeature( const char *pszElement, 
@@ -487,8 +517,11 @@ public:
                              int nClassIndex );
 
     void        SetFeaturePropertyDirectly( const char *pszElement,
-                                    char *pszValue,
-                                    int iPropertyIn );
+                                            char *pszValue,
+                                            int iPropertyIn,
+                                            GMLPropertyType eType = GMLPT_Untyped );
+
+    void        SetWidthFlag(int bFlag) { m_bSetWidthFlag = bFlag; }
 
     int         HasStoppedParsing() { return m_bStopParsing; }
 
@@ -501,8 +534,13 @@ public:
 
     int         SetFilteredClassName(const char* pszClassName);
     const char* GetFilteredClassName() { return m_pszFilteredClassName; }
+    int         GetFilteredClassIndex() { return m_nFilteredClassIndex; }
 
     int         IsSequentialLayers() const { return m_bSequentialLayers == TRUE; }
+    
+    int         ReportAllAttributes() const { return m_bReportAllAttributes; }
+
+    static void* hMutex;
 };
 
 #endif /* _CPL_GMLREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
index efa4a07..fa662b1 100644
--- a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlreadstate.cpp 22954 2011-08-19 21:47:19Z rouault $
+ * $Id: gmlreadstate.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReadState class.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.cpp b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
new file mode 100644
index 0000000..12290ec
--- /dev/null
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
@@ -0,0 +1,149 @@
+/******************************************************************************
+ * $Id: gmlregistry.cpp 27150 2014-04-09 19:59:33Z martinl $
+ *
+ * Project:  GML registry
+ * Purpose:  GML reader
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gmlregistry.h"
+
+/************************************************************************/
+/*                           Parse()                                    */
+/************************************************************************/
+
+int GMLRegistry::Parse()
+{
+    const char* pszFilename;
+    pszFilename = CPLGetConfigOption("GML_REGISTRY", NULL);
+    if( pszFilename == NULL )
+    {
+        pszFilename = CPLFindFile( "gdal", "gml_registry.xml" );
+    }
+    if( pszFilename == NULL )
+        return FALSE;
+    CPLXMLNode* psRootNode = CPLParseXMLFile(pszFilename);
+    if( psRootNode == NULL )
+        return FALSE;
+    CPLXMLNode *psRegistryNode = CPLGetXMLNode( psRootNode, "=gml_registry" );
+    if( psRegistryNode == NULL )
+    {
+        CPLDestroyXMLNode(psRootNode);
+        return FALSE;
+    }
+    CPLXMLNode* psIter = psRegistryNode->psChild;
+    while( psIter != NULL )
+    {
+        if( psIter->eType == CXT_Element &&
+            strcmp(psIter->pszValue, "namespace") == 0 )
+        {
+            GMLRegistryNamespace oNameSpace;
+            if( oNameSpace.Parse(pszFilename, psIter) )
+            {
+                aoNamespaces.push_back(oNameSpace);
+            }
+        }
+        psIter = psIter->psNext;
+    }
+    CPLDestroyXMLNode(psRootNode);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           Parse()                                    */
+/************************************************************************/
+
+int GMLRegistryNamespace::Parse(const char* pszRegistryFilename, CPLXMLNode* psNode)
+{
+    const char* pszPrefix = CPLGetXMLValue(psNode, "prefix", NULL);
+    const char* pszURI = CPLGetXMLValue(psNode, "uri", NULL);
+    if( pszPrefix == NULL || pszURI == NULL )
+        return FALSE;
+    osPrefix = pszPrefix;
+    osURI = pszURI;
+    const char* pszUseGlobalSRSName = CPLGetXMLValue(psNode, "useGlobalSRSName", NULL);
+    if( pszUseGlobalSRSName != NULL && strcmp(pszUseGlobalSRSName, "true") == 0 )
+        bUseGlobalSRSName = TRUE;
+
+    CPLXMLNode* psIter = psNode->psChild;
+    while( psIter != NULL )
+    {
+        if( psIter->eType == CXT_Element &&
+            strcmp(psIter->pszValue, "featureType") == 0 )
+        {
+            GMLRegistryFeatureType oFeatureType;
+            if( oFeatureType.Parse(pszRegistryFilename, psIter) )
+            {
+                aoFeatureTypes.push_back(oFeatureType);
+            }
+        }
+        psIter = psIter->psNext;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           Parse()                                    */
+/************************************************************************/
+
+int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* psNode)
+{
+    const char* pszElementName = CPLGetXMLValue(psNode, "elementName", NULL);
+    const char* pszElementValue = CPLGetXMLValue(psNode, "elementValue", NULL);
+    const char* pszSchemaLocation = CPLGetXMLValue(psNode, "schemaLocation", NULL);
+    const char* pszGFSSchemaLocation = CPLGetXMLValue(psNode, "gfsSchemaLocation", NULL);
+    if( pszElementName == NULL || (pszSchemaLocation == NULL && pszGFSSchemaLocation == NULL) )
+        return FALSE;
+    osElementName = pszElementName;
+
+    if( pszSchemaLocation != NULL )
+    {
+        if( strncmp(pszSchemaLocation, "http://", 7) != 0 &&
+            strncmp(pszSchemaLocation, "https://", 8) != 0 &&
+            CPLIsFilenameRelative(pszSchemaLocation ) )
+        {
+            pszSchemaLocation = CPLFormFilename(
+                CPLGetPath(pszRegistryFilename), pszSchemaLocation, NULL );
+        }
+        osSchemaLocation = pszSchemaLocation;
+    }
+    else if( pszGFSSchemaLocation != NULL )
+    {
+        if( strncmp(pszGFSSchemaLocation, "http://", 7) != 0 &&
+            strncmp(pszGFSSchemaLocation, "https://", 8) != 0 &&
+            CPLIsFilenameRelative(pszGFSSchemaLocation ) )
+        {
+            pszGFSSchemaLocation = CPLFormFilename(
+                CPLGetPath(pszRegistryFilename), pszGFSSchemaLocation, NULL );
+        }
+        osGFSSchemaLocation = pszGFSSchemaLocation;
+    }
+
+    if ( pszElementValue != NULL )
+    {
+        osElementValue = pszElementValue; 
+    }
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.h b/ogr/ogrsf_frmts/gml/gmlregistry.h
new file mode 100644
index 0000000..eaed077
--- /dev/null
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * $Id: gmlregistry.h 27150 2014-04-09 19:59:33Z martinl $
+ *
+ * Project:  GML registry
+ * Purpose:  GML reader
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _GMLREGISTRY_H_INCLUDED
+#define _GMLREGISTRY_H_INCLUDED
+
+#include "cpl_string.h"
+#include "cpl_minixml.h"
+
+#include <vector>
+
+class GMLRegistryFeatureType
+{
+    public:
+        CPLString                           osElementName;
+        CPLString                           osElementValue;
+        CPLString                           osSchemaLocation;
+        CPLString                           osGFSSchemaLocation;
+
+        int Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
+};
+
+class GMLRegistryNamespace
+{
+    public:
+        GMLRegistryNamespace() : bUseGlobalSRSName(FALSE) {}
+
+        CPLString                           osPrefix;
+        CPLString                           osURI;
+        int                                 bUseGlobalSRSName;
+        std::vector<GMLRegistryFeatureType> aoFeatureTypes;
+
+        int Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
+};
+
+class GMLRegistry
+{
+    public:
+        std::vector<GMLRegistryNamespace> aoNamespaces;
+
+        int Parse();
+};
+
+#endif /* _GMLREGISTRY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.cpp b/ogr/ogrsf_frmts/gml/gmlutils.cpp
index bdc3fd9..46248bb 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlutils.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gmlutils.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: gmlutils.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.h b/ogr/ogrsf_frmts/gml/gmlutils.h
index 69125c5..d8466d6 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.h
+++ b/ogr/ogrsf_frmts/gml/gmlutils.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gmlutils.h 23638 2011-12-22 21:02:56Z rouault $
+ * $Id: gmlutils.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
index 2fa3caf..6f9c705 100644
--- a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
+++ b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hugefileresolver.cpp 23675 2012-01-01 16:09:45Z rouault $
+ * $Id: hugefileresolver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::HugeFileResolver() method.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Alessandro Furieri
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -46,7 +47,7 @@
 
 #include <stack>
 
-CPL_CVSID("$Id: hugefileresolver.cpp 23675 2012-01-01 16:09:45Z rouault $");
+CPL_CVSID("$Id: hugefileresolver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /****************************************************/
 /*      SQLite is absolutely required in order to   */
@@ -179,7 +180,7 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     /* DB table: NODES / Insert cursor */
     osCommand = "INSERT OR IGNORE INTO nodes (gml_id, x, y, z) "
                 "VALUES (?, ?, ?, ?)";
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -195,7 +196,7 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
                 "node_from_z, node_to_id, node_to_x, "
                 "node_to_y, node_to_z) "
                 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -341,7 +342,7 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
                 "FROM gml_edges AS e "
                 "LEFT JOIN nodes AS n1 ON (n1.gml_id = e.node_from_id) "
                 "LEFT JOIN nodes AS n2 ON (n2.gml_id = e.node_to_id)";
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hQueryStmt, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hQueryStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -354,7 +355,7 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
                 "SET gml_resolved = ?, "
                 "gml_string = NULL "
                 "WHERE gml_id = ?";
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hUpdateStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -759,9 +760,9 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined, 
-                              "sqlite3_step() failed:\n  %s", 
-                              sqlite3_errmsg(helper->hDB) );
-                              return FALSE;
+                              "sqlite3_step() failed:\n  %s (gmlNodeFrom id=%s)", 
+                              sqlite3_errmsg(helper->hDB), pItem->gmlNodeFrom->c_str() );
+                    return FALSE;
                 }
             }
             if( pItem->gmlNodeTo != NULL )
@@ -779,9 +780,9 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined, 
-                              "sqlite3_step() failed:\n  %s", 
-                              sqlite3_errmsg(helper->hDB) );
-                              return FALSE;
+                              "sqlite3_step() failed:\n  %s (gmlNodeTo id=%s)", 
+                              sqlite3_errmsg(helper->hDB), pItem->gmlNodeTo->c_str() );
+                    return FALSE;
                 }
             }
         }
@@ -849,8 +850,8 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
         if( rc != SQLITE_OK && rc != SQLITE_DONE )
         {
             CPLError( CE_Failure, CPLE_AppDefined, 
-                      "sqlite3_step() failed:\n  %s", 
-                      sqlite3_errmsg(helper->hDB) );
+                      "sqlite3_step() failed:\n  %s (edge gml:id=%s)", 
+                      sqlite3_errmsg(helper->hDB), pItem->gmlId->c_str() );
             return FALSE;
         }
         pItem = pItem->pNext;
@@ -971,6 +972,8 @@ static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
     pItem->gmlTagValue = gmlFragment;
     pItem->gmlNodeFrom = NULL;
     pItem->gmlNodeTo = NULL;
+    pItem->bIsNodeFromHref = FALSE;
+    pItem->bIsNodeToHref = FALSE;
     pItem->bHasCoords = FALSE;
     pItem->bHasZ = FALSE;
     pItem->pNext = NULL;
@@ -1486,7 +1489,7 @@ static int gmlHugeResolveEdges( struct huge_helper *helper,
         pItem = pItem->pNext;
     }
     osCommand += ")";
-    rc = sqlite3_prepare( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1504,8 +1507,10 @@ static int gmlHugeResolveEdges( struct huge_helper *helper,
             const char *pszGmlText = NULL;
             pszGmlId = (const char *)sqlite3_column_text ( hStmtEdges, 0 );
             if( sqlite3_column_type( hStmtEdges, 1 ) != SQLITE_NULL )
+            {
                 pszGmlText = (const char *)sqlite3_column_text ( hStmtEdges, 1 );
-            gmlHugeSetHrefGmlText( helper, pszGmlId, pszGmlText );
+                gmlHugeSetHrefGmlText( helper, pszGmlId, pszGmlText );
+            }
         }
         else
         {
@@ -1623,7 +1628,7 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
     /* query cursor [Nodes] */
     osCommand = "SELECT gml_id, x, y, z "
                 "FROM nodes";
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hStmtNodes, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmtNodes, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
diff --git a/ogr/ogrsf_frmts/gml/makefile.vc b/ogr/ogrsf_frmts/gml/makefile.vc
index abcc7d7..ee14adb 100644
--- a/ogr/ogrsf_frmts/gml/makefile.vc
+++ b/ogr/ogrsf_frmts/gml/makefile.vc
@@ -1,7 +1,7 @@
 
 LL_OBJ	=	gmlpropertydefn.obj gmlfeatureclass.obj gmlfeature.obj \
 		gmlreader.obj parsexsd.obj resolvexlinks.obj hugefileresolver.obj gmlutils.obj \
-		gmlreadstate.obj gmlhandler.obj trstring.obj  gfstemplate.obj
+		gmlreadstate.obj gmlhandler.obj trstring.obj  gfstemplate.obj gmlregistry.obj
 OGR_OBJ	=	ogrgmldriver.obj ogrgmldatasource.obj ogrgmllayer.obj
 
 OBJ	=	$(LL_OBJ) $(OGR_OBJ)
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index 08d9571..3b96f5e 100644
--- a/ogr/ogrsf_frmts/gml/ogr_gml.h
+++ b/ogr/ogrsf_frmts/gml/ogr_gml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gml.h 24481 2012-05-20 12:50:29Z rouault $
+ * $Id: ogr_gml.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,7 +50,6 @@ typedef enum
 
 class OGRGMLLayer : public OGRLayer
 {
-    OGRSpatialReference *poSRS;
     OGRFeatureDefn     *poFeatureDefn;
 
     int                 iNextGMLId;
@@ -58,6 +58,7 @@ class OGRGMLLayer : public OGRLayer
     char                *pszFIDPrefix;
 
     int                 bWriter;
+    int                 bSameSRS;
 
     OGRGMLDataSource    *poDS;
 
@@ -69,11 +70,11 @@ class OGRGMLLayer : public OGRLayer
 
     int                 bFaceHoleNegative;
 
+    OGRGeometry        *ConvertGeomToMultiIfNecessary(OGRGeometry* poGeom);
+
   public:
                         OGRGMLLayer( const char * pszName, 
-                                     OGRSpatialReference *poSRS, 
                                      int bWriter,
-                                     OGRwkbGeometryType eType,
                                      OGRGMLDataSource *poDS );
 
                         ~OGRGMLLayer();
@@ -90,12 +91,10 @@ class OGRGMLLayer : public OGRLayer
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                     int bApproxOK = TRUE );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     int                 TestCapability( const char * );
-    
-    virtual const char *GetGeometryColumn();
 };
 
 /************************************************************************/
@@ -128,6 +127,9 @@ class OGRGMLDataSource : public OGRDataSource
     int                 bIsLongSRSRequired;
     int                 bWriteSpaceIndentation;
 
+    OGRSpatialReference* poWriteGlobalSRS;
+    int                 bWriteGlobalSRS;
+
     // input related parameters.
     CPLString           osFilename;
     CPLString           osXSDFilename;
@@ -141,7 +143,7 @@ class OGRGMLDataSource : public OGRDataSource
     int                 bExposeFid;
     int                 bIsWFS;
 
-    OGRSpatialReference* poGlobalSRS;
+    int                 bUseGlobalSRSName;
 
     int                 m_bInvertAxisOrderIfLatLong;
     int                 m_bConsiderEPSGAsURN;
@@ -158,7 +160,7 @@ class OGRGMLDataSource : public OGRDataSource
                         OGRGMLDataSource();
                         ~OGRGMLDataSource();
 
-    int                 Open( const char *, int bTestOpen );
+    int                 Open( const char * );
     int                 Create( const char *pszFile, char **papszOptions );
 
     const char          *GetName() { return pszName; }
@@ -200,6 +202,8 @@ class OGRGMLDataSource : public OGRDataSource
     void                SetLastReadLayer(OGRGMLLayer* poLayer) { poLastReadLayer = poLayer; }
 
     const char         *GetAppPrefix();
+    int                 RemoveAppPrefix();
+    int                 WriteFeatureBoundedBy();
 
     virtual OGRLayer *          ExecuteSQL( const char *pszSQLCommand,
                                             OGRGeometry *poSpatialFilter,
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index dfd63f3..de28acd 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 26148 2013-07-06 08:27:00Z rouault $
+ * $Id: ogrgmldatasource.cpp 27195 2014-04-16 11:03:12Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,10 +42,14 @@
 #include "cpl_http.h"
 #include "gmlutils.h"
 #include "ogr_p.h"
+#include "gmlregistry.h"
 
 #include <vector>
 
-CPL_CVSID("$Id: ogrgmldatasource.cpp 26148 2013-07-06 08:27:00Z rouault $");
+CPL_CVSID("$Id: ogrgmldatasource.cpp 27195 2014-04-16 11:03:12Z rouault $");
+
+static int ExtractSRSName(const char* pszXML, char* szSRSName,
+                          size_t sizeof_szSRSName);
 
 /************************************************************************/
 /*                   ReplaceSpaceByPct20IfNeeded()                      */
@@ -54,17 +59,18 @@ static CPLString ReplaceSpaceByPct20IfNeeded(const char* pszURL)
 {
     /* Replace ' ' by '%20' */
     CPLString osRet = pszURL;
-    const char* pszNeedle = strstr(pszURL, "text/xml; subtype=");
+    const char* pszNeedle = strstr(pszURL, "; ");
     if (pszNeedle)
     {
         char* pszTmp = (char*)CPLMalloc(strlen(pszURL) + 2 +1);
         int nBeforeNeedle = (int)(pszNeedle - pszURL);
         memcpy(pszTmp, pszURL, nBeforeNeedle);
-        strcpy(pszTmp + nBeforeNeedle, "text/xml;%20subtype=");
-        strcpy(pszTmp + nBeforeNeedle + strlen("text/xml;%20subtype="), pszNeedle + strlen("text/xml; subtype="));
+        strcpy(pszTmp + nBeforeNeedle, ";%20");
+        strcpy(pszTmp + nBeforeNeedle + strlen(";%20"), pszNeedle + strlen("; "));
         osRet = pszTmp;
         CPLFree(pszTmp);
     }
+
     return osRet;
 }
 
@@ -98,7 +104,9 @@ OGRGMLDataSource::OGRGMLDataSource()
     nBoundedByLocation = -1;
     bBBOX3D = FALSE;
 
-    poGlobalSRS = NULL;
+    poWriteGlobalSRS = NULL;
+    bWriteGlobalSRS = FALSE;
+    bUseGlobalSRSName = FALSE;
     bIsWFS = FALSE;
 
     eReadMode = STANDARD;
@@ -121,8 +129,10 @@ OGRGMLDataSource::~OGRGMLDataSource()
     if( fpOutput != NULL )
     {
         const char* pszPrefix = GetAppPrefix();
-
-        PrintLine( fpOutput, "</%s:FeatureCollection>", pszPrefix );
+        if( RemoveAppPrefix() )
+            PrintLine( fpOutput, "</FeatureCollection>" );
+        else
+            PrintLine( fpOutput, "</%s:FeatureCollection>", pszPrefix );
 
         if( bFpOutputIsNonSeekable)
         {
@@ -136,12 +146,12 @@ OGRGMLDataSource::~OGRGMLDataSource()
             && nBoundedByLocation != -1
             && VSIFSeekL( fpOutput, nBoundedByLocation, SEEK_SET ) == 0 )
         {
-            if (sBoundingRect.IsInit()  && IsGML3Output())
+            if (bWriteGlobalSRS && sBoundingRect.IsInit()  && IsGML3Output())
             {
                 int bCoordSwap = FALSE;
                 char* pszSRSName;
-                if (poGlobalSRS)
-                    pszSRSName = GML_GetSRSName(poGlobalSRS, IsLongSRSRequired(), &bCoordSwap);
+                if (poWriteGlobalSRS)
+                    pszSRSName = GML_GetSRSName(poWriteGlobalSRS, IsLongSRSRequired(), &bCoordSwap);
                 else
                     pszSRSName = CPLStrdup("");
                 char szLowerCorner[75], szUpperCorner[75];
@@ -161,7 +171,7 @@ OGRGMLDataSource::~OGRGMLDataSource()
                            (bBBOX3D) ? " srsDimension=\"3\"" : "", pszSRSName, szLowerCorner, szUpperCorner);
                 CPLFree(pszSRSName);
             }
-            else if (sBoundingRect.IsInit())
+            else if (bWriteGlobalSRS && sBoundingRect.IsInit())
             {
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL( fpOutput, "  ");
@@ -226,7 +236,7 @@ OGRGMLDataSource::~OGRGMLDataSource()
         delete poReader;
     }
 
-    delete poGlobalSRS;
+    delete poWriteGlobalSRS;
 
     delete poStoredGMLFeature;
 
@@ -238,11 +248,11 @@ OGRGMLDataSource::~OGRGMLDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
+int OGRGMLDataSource::Open( const char * pszNameIn )
 
 {
     VSILFILE   *fp;
-    char        szHeader[2048];
+    char        szHeader[4096];
     int         nNumberOfFeatures = 0;
     CPLString   osWithVsiGzip;
     const char *pszSchemaLocation = NULL;
@@ -267,57 +277,52 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
 /* -------------------------------------------------------------------- */
     fp = VSIFOpenL( pszFilename, "r" );
     if( fp == NULL )
-    {
-        if( !bTestOpen )
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open GML file `%s'.", 
-                      pszFilename );
-
         return FALSE;
-    }
 
     int bExpatCompatibleEncoding = FALSE;
     int bHas3D = FALSE;
     int bHintConsiderEPSGAsURN = FALSE;
+    int bAnalyzeSRSPerFeature = TRUE;
+
+    char szSRSName[128];
+    szSRSName[0] = '\0';
 
 /* -------------------------------------------------------------------- */
-/*      If we aren't sure it is GML, load a header chunk and check      */
-/*      for signs it is GML                                             */
+/*      Load a header chunk and check for signs it is GML               */
 /* -------------------------------------------------------------------- */
-    if( bTestOpen )
+
+    size_t nRead = VSIFReadL( szHeader, 1, sizeof(szHeader)-1, fp );
+    if (nRead <= 0)
+    {
+        VSIFCloseL( fp );
+        return FALSE;
+    }
+    szHeader[nRead] = '\0';
+
+    /* Might be a OS-Mastermap gzipped GML, so let be nice and try to open */
+    /* it transparently with /vsigzip/ */
+    if ( ((GByte*)szHeader)[0] == 0x1f && ((GByte*)szHeader)[1] == 0x8b &&
+            EQUAL(CPLGetExtension(pszFilename), "gz") &&
+            strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0 )
     {
-        size_t nRead = VSIFReadL( szHeader, 1, sizeof(szHeader)-1, fp );
+        VSIFCloseL( fp );
+        osWithVsiGzip = "/vsigzip/";
+        osWithVsiGzip += pszFilename;
+
+        pszFilename = osWithVsiGzip;
+
+        fp = VSIFOpenL( pszFilename, "r" );
+        if( fp == NULL )
+            return FALSE;
+
+        nRead = VSIFReadL( szHeader, 1, sizeof(szHeader) - 1, fp );
         if (nRead <= 0)
         {
             VSIFCloseL( fp );
             return FALSE;
         }
         szHeader[nRead] = '\0';
-
-        /* Might be a OS-Mastermap gzipped GML, so let be nice and try to open */
-        /* it transparently with /vsigzip/ */
-        if ( ((GByte*)szHeader)[0] == 0x1f && ((GByte*)szHeader)[1] == 0x8b &&
-             EQUAL(CPLGetExtension(pszFilename), "gz") &&
-             strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0 )
-        {
-            VSIFCloseL( fp );
-            osWithVsiGzip = "/vsigzip/";
-            osWithVsiGzip += pszFilename;
-
-            pszFilename = osWithVsiGzip;
-
-            fp = VSIFOpenL( pszFilename, "r" );
-            if( fp == NULL )
-                return FALSE;
-
-            nRead = VSIFReadL( szHeader, 1, sizeof(szHeader) - 1, fp );
-            if (nRead <= 0)
-            {
-                VSIFCloseL( fp );
-                return FALSE;
-            }
-            szHeader[nRead] = '\0';
-        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Check for a UTF-8 BOM and skip if found                         */
@@ -326,127 +331,144 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
 /*            Add BOM detection for other encodings.                    */
 /* -------------------------------------------------------------------- */
 
-        // Used to skip to actual beginning of XML data
-        char* szPtr = szHeader;
+    // Used to skip to actual beginning of XML data
+    char* szPtr = szHeader;
 
-        if( ( (unsigned char)szHeader[0] == 0xEF )
-            && ( (unsigned char)szHeader[1] == 0xBB )
-            && ( (unsigned char)szHeader[2] == 0xBF) )
-        {
-            szPtr += 3;
-        }
+    if( ( (unsigned char)szHeader[0] == 0xEF )
+        && ( (unsigned char)szHeader[1] == 0xBB )
+        && ( (unsigned char)szHeader[2] == 0xBF) )
+    {
+        szPtr += 3;
+    }
 
-        const char* pszEncoding = strstr(szPtr, "encoding=");
-        if (pszEncoding)
-            bExpatCompatibleEncoding = (pszEncoding[9] == '\'' || pszEncoding[9] == '"') &&
-                                       (EQUALN(pszEncoding + 10, "UTF-8", 5) ||
-                                        EQUALN(pszEncoding + 10, "ISO-8859-15", 11) ||
-                                        (EQUALN(pszEncoding + 10, "ISO-8859-1", 10) &&
-                                         pszEncoding[20] == pszEncoding[9])) ;
-        else
-            bExpatCompatibleEncoding = TRUE; /* utf-8 is the default */
+    const char* pszEncoding = strstr(szPtr, "encoding=");
+    if (pszEncoding)
+        bExpatCompatibleEncoding = (pszEncoding[9] == '\'' || pszEncoding[9] == '"') &&
+                                    (EQUALN(pszEncoding + 10, "UTF-8", 5) ||
+                                    EQUALN(pszEncoding + 10, "ISO-8859-15", 11) ||
+                                    (EQUALN(pszEncoding + 10, "ISO-8859-1", 10) &&
+                                        pszEncoding[20] == pszEncoding[9])) ;
+    else
+        bExpatCompatibleEncoding = TRUE; /* utf-8 is the default */
 
-        bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL || strstr(szPtr, "<gml:Z>") != NULL;
+    bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL || strstr(szPtr, "<gml:Z>") != NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Here, we expect the opening chevrons of GML tree root element   */
 /* -------------------------------------------------------------------- */
-        if( szPtr[0] != '<' 
-            || strstr(szPtr,"opengis.net/gml") == NULL )
-        {
-            VSIFCloseL( fp );
-            return FALSE;
-        }
+    if( szPtr[0] != '<' 
+        || strstr(szPtr,"opengis.net/gml") == NULL )
+    {
+        VSIFCloseL( fp );
+        return FALSE;
+    }
 
-        /* Ignore .xsd schemas */
-        if( strstr(szPtr, "<schema") != NULL
-            || strstr(szPtr, "<xs:schema") != NULL
-            || strstr(szPtr, "<xsd:schema") != NULL )
-        {
-            VSIFCloseL( fp );
-            return FALSE;
-        }
+    /* Ignore .xsd schemas */
+    if( strstr(szPtr, "<schema") != NULL
+        || strstr(szPtr, "<xs:schema") != NULL
+        || strstr(szPtr, "<xsd:schema") != NULL )
+    {
+        VSIFCloseL( fp );
+        return FALSE;
+    }
 
-        /* Ignore GeoRSS documents. They will be recognized by the GeoRSS driver */
-        if( strstr(szPtr, "<rss") != NULL && strstr(szPtr, "xmlns:georss") != NULL )
-        {
-            VSIFCloseL( fp );
-            return FALSE;
-        }
+    /* Ignore GeoRSS documents. They will be recognized by the GeoRSS driver */
+    if( strstr(szPtr, "<rss") != NULL && strstr(szPtr, "xmlns:georss") != NULL )
+    {
+        VSIFCloseL( fp );
+        return FALSE;
+    }
 
-        /* Small optimization: if we parse a <wfs:FeatureCollection>  and */
-        /* that numberOfFeatures is set, we can use it to set the FeatureCount */
-        /* but *ONLY* if there's just one class ! */
-        const char* pszFeatureCollection = strstr(szPtr, "wfs:FeatureCollection");
-        if (pszFeatureCollection == NULL)
-            pszFeatureCollection = strstr(szPtr, "gml:FeatureCollection"); /* GML 3.2.1 output */
-        if (pszFeatureCollection == NULL)
-        {
-            pszFeatureCollection = strstr(szPtr, "<FeatureCollection"); /* Deegree WFS 1.0.0 output */
-            if (pszFeatureCollection && strstr(szPtr, "xmlns:wfs=\"http://www.opengis.net/wfs\"") == NULL)
-                pszFeatureCollection = NULL;
-        }
-        if (pszFeatureCollection)
+    /* Ignore OGR WFS xml description files */
+    if( strstr(szPtr, "<OGRWFSDataSource>") != NULL )
+    {
+        VSIFCloseL( fp );
+        return FALSE;
+    }
+
+    /* Small optimization: if we parse a <wfs:FeatureCollection>  and */
+    /* that numberOfFeatures is set, we can use it to set the FeatureCount */
+    /* but *ONLY* if there's just one class ! */
+    const char* pszFeatureCollection = strstr(szPtr, "wfs:FeatureCollection");
+    if (pszFeatureCollection == NULL)
+        pszFeatureCollection = strstr(szPtr, "gml:FeatureCollection"); /* GML 3.2.1 output */
+    if (pszFeatureCollection == NULL)
+    {
+        pszFeatureCollection = strstr(szPtr, "<FeatureCollection"); /* Deegree WFS 1.0.0 output */
+        if (pszFeatureCollection && strstr(szPtr, "xmlns:wfs=\"http://www.opengis.net/wfs\"") == NULL)
+            pszFeatureCollection = NULL;
+    }
+    if (pszFeatureCollection)
+    {
+        bExposeGMLId = TRUE;
+        bIsWFS = TRUE;
+        const char* pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
+        if (pszNumberOfFeatures)
         {
-            bExposeGMLId = TRUE;
-            bIsWFS = TRUE;
-            const char* pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
-            if (pszNumberOfFeatures)
-            {
-                pszNumberOfFeatures += 17;
-                char ch = pszNumberOfFeatures[0];
-                if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
-                {
-                    nNumberOfFeatures = atoi(pszNumberOfFeatures + 1);
-                }
-            }
-            else if ((pszNumberOfFeatures = strstr(szPtr, "numberReturned=")) != NULL) /* WFS 2.0.0 */
+            pszNumberOfFeatures += 17;
+            char ch = pszNumberOfFeatures[0];
+            if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
             {
-                pszNumberOfFeatures += 15;
-                char ch = pszNumberOfFeatures[0];
-                if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
-                {
-                    /* 'unknown' might be a valid value in a corrected version of WFS 2.0 */
-                    /* but it will also evaluate to 0, that is considered as unknown, so nothing */
-                    /* particular to do */
-                    nNumberOfFeatures = atoi(pszNumberOfFeatures + 1);
-                }
+                nNumberOfFeatures = atoi(pszNumberOfFeatures + 1);
             }
         }
-        else if (strncmp(pszFilename, "/vsimem/tempwfs_", strlen("/vsimem/tempwfs_")) == 0)
+        else if ((pszNumberOfFeatures = strstr(szPtr, "numberReturned=")) != NULL) /* WFS 2.0.0 */
         {
-            /* http://regis.intergraph.com/wfs/dcmetro/request.asp? returns a <G:FeatureCollection> */
-            /* Who knows what servers can return ? Ok, so when in the context of the WFS driver */
-            /* always expose the gml:id to avoid later crashes */
-            bExposeGMLId = TRUE;
-            bIsWFS = TRUE;
-        }
-        else
-        {
-            bExposeGMLId = strstr(szPtr, " gml:id=\"") != NULL ||
-                           strstr(szPtr, " gml:id='") != NULL;
-            bExposeFid = strstr(szPtr, " fid=\"") != NULL ||
-                         strstr(szPtr, " fid='") != NULL;
-            
-            const char* pszExposeGMLId = CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL);
-            if (pszExposeGMLId)
-                bExposeGMLId = CSLTestBoolean(pszExposeGMLId);
-
-            const char* pszExposeFid = CPLGetConfigOption("GML_EXPOSE_FID", NULL);
-            if (pszExposeFid)
-                bExposeFid = CSLTestBoolean(pszExposeFid);
+            pszNumberOfFeatures += 15;
+            char ch = pszNumberOfFeatures[0];
+            if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
+            {
+                /* 'unknown' might be a valid value in a corrected version of WFS 2.0 */
+                /* but it will also evaluate to 0, that is considered as unknown, so nothing */
+                /* particular to do */
+                nNumberOfFeatures = atoi(pszNumberOfFeatures + 1);
+            }
         }
+    }
+    else if (strncmp(pszFilename, "/vsimem/tempwfs_", strlen("/vsimem/tempwfs_")) == 0)
+    {
+        /* http://regis.intergraph.com/wfs/dcmetro/request.asp? returns a <G:FeatureCollection> */
+        /* Who knows what servers can return ? Ok, so when in the context of the WFS driver */
+        /* always expose the gml:id to avoid later crashes */
+        bExposeGMLId = TRUE;
+        bIsWFS = TRUE;
+    }
+    else
+    {
+        bExposeGMLId = strstr(szPtr, " gml:id=\"") != NULL ||
+                        strstr(szPtr, " gml:id='") != NULL;
+        bExposeFid = strstr(szPtr, " fid=\"") != NULL ||
+                        strstr(szPtr, " fid='") != NULL;
+        
+        const char* pszExposeGMLId = CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL);
+        if (pszExposeGMLId)
+            bExposeGMLId = CSLTestBoolean(pszExposeGMLId);
 
-        bHintConsiderEPSGAsURN = strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
+        const char* pszExposeFid = CPLGetConfigOption("GML_EXPOSE_FID", NULL);
+        if (pszExposeFid)
+            bExposeFid = CSLTestBoolean(pszExposeFid);
+    }
 
-        pszSchemaLocation = strstr(szPtr, "schemaLocation=");
-        if (pszSchemaLocation)
-            pszSchemaLocation += strlen("schemaLocation=");
+    bHintConsiderEPSGAsURN = strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
 
-        if (bIsWFS && EQUALN(pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")))
-            bCheckAuxFile = FALSE;
+    /* MTKGML */
+    if( strstr(szPtr, "<Maastotiedot") != NULL )
+    {
+        if( strstr(szPtr, "http://xml.nls.fi/XML/Namespace/Maastotietojarjestelma/SiirtotiedostonMalli/2011-02") == NULL )
+            CPLDebug("GML", "Warning: a MTKGML file was detected, but its namespace is unknown");
+        bAnalyzeSRSPerFeature = FALSE;
+        bUseGlobalSRSName = TRUE;
+        if( !ExtractSRSName(szPtr, szSRSName, sizeof(szSRSName)) )
+            strcpy(szSRSName, "EPSG:3067");
     }
 
+    pszSchemaLocation = strstr(szPtr, "schemaLocation=");
+    if (pszSchemaLocation)
+        pszSchemaLocation += strlen("schemaLocation=");
+
+    if (bIsWFS && EQUALN(pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")))
+        bCheckAuxFile = FALSE;
+
 /* -------------------------------------------------------------------- */
 /*      We assume now that it is GML.  Instantiate a GMLReader on it.   */
 /* -------------------------------------------------------------------- */
@@ -519,6 +541,9 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
 
     FindAndParseBoundedBy(fp);
 
+    if( szSRSName[0] != '\0' )
+        poReader->SetGlobalSRSName(szSRSName);
+
 /* -------------------------------------------------------------------- */
 /*      Resolve the xlinks in the source file and save it with the      */
 /*      extension ".resolved.gml". The source file will to set to that. */
@@ -606,6 +631,7 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
             {
                 // we assume an errors have been reported.
                 VSIFCloseL(fp);
+                CPLFree( pszXlinkResolvedFilename );
                 return FALSE;
             }
         }
@@ -704,14 +730,102 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
         }
         else
         {
-            if ( VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+            if ( strncmp(osXSDFilename, "http://", 7) == 0 ||
+                 strncmp(osXSDFilename, "https://", 8) == 0 ||
+                 VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
             {
                 bHasFoundXSD = TRUE;
             }
         }
 
+        /* If not found, try if there is a schema in the gml_registry.xml */
+        /* that might match a declared namespace and featuretype */
+        if( !bHasFoundXSD )
+        {
+            GMLRegistry oRegistry;
+            if( oRegistry.Parse() )
+            {
+                CPLString osHeader(szHeader);
+                for( size_t iNS = 0; iNS < oRegistry.aoNamespaces.size(); iNS ++ )
+                {
+                    GMLRegistryNamespace& oNamespace = oRegistry.aoNamespaces[iNS];
+                    const char* pszNSToFind =
+                                CPLSPrintf("xmlns:%s", oNamespace.osPrefix.c_str());
+                    const char* pszURIToFind =
+                                CPLSPrintf("\"%s\"", oNamespace.osURI.c_str());
+                    if( osHeader.ifind(pszNSToFind) != std::string::npos &&
+                        strstr(szHeader, pszURIToFind) != NULL )
+                    {
+                        if( oNamespace.bUseGlobalSRSName )
+                            bUseGlobalSRSName = TRUE;
+                        
+                        for( size_t iTypename = 0;
+                                    iTypename < oNamespace.aoFeatureTypes.size();
+                                    iTypename ++ )
+                        {
+                            const char* pszElementToFind = NULL;
+                            
+                            GMLRegistryFeatureType& oFeatureType =
+                                        oNamespace.aoFeatureTypes[iTypename];
+                            
+                            if ( oFeatureType.osElementValue.size() ) 
+                                pszElementToFind = CPLSPrintf("%s:%s>%s",
+                                                              oNamespace.osPrefix.c_str(),
+                                                              oFeatureType.osElementName.c_str(),
+                                                              oFeatureType.osElementValue.c_str());
+                            else
+                                pszElementToFind = CPLSPrintf("%s:%s",
+                                                              oNamespace.osPrefix.c_str(),
+                                                              oFeatureType.osElementName.c_str());
+
+                            /* Case sensitive test since in a CadastralParcel feature */
+                            /* there is a property basicPropertyUnit xlink, not to be */
+                            /* confused with a top-level BasicPropertyUnit feature... */
+                            if( osHeader.find(pszElementToFind) != std::string::npos )
+                            {
+                                if( oFeatureType.osSchemaLocation.size() )
+                                {
+                                    osXSDFilename = oFeatureType.osSchemaLocation;
+                                    if( strncmp(osXSDFilename, "http://", 7) == 0 ||
+                                        strncmp(osXSDFilename, "https://", 8) == 0 ||
+                                        VSIStatExL( osXSDFilename, &sXSDStatBuf,
+                                                    VSI_STAT_EXISTS_FLAG ) == 0 )
+                                    {
+                                        bHasFoundXSD = TRUE;
+                                        bHaveSchema = TRUE;
+                                        CPLDebug("GML", "Found %s for %s:%s in registry",
+                                                osXSDFilename.c_str(), 
+                                                oNamespace.osPrefix.c_str(),
+                                                oFeatureType.osElementName.c_str());
+                                    }
+                                    else
+                                    {
+                                        CPLDebug("GML", "Cannot open %s", osXSDFilename.c_str());
+                                    }
+                                }
+                                else
+                                {
+                                    bHaveSchema = poReader->LoadClasses(
+                                        oFeatureType.osGFSSchemaLocation );
+                                    if( bHaveSchema )
+                                    {
+                                        CPLDebug("GML", "Found %s for %s:%s in registry",
+                                                oFeatureType.osGFSSchemaLocation.c_str(), 
+                                                oNamespace.osPrefix.c_str(),
+                                                oFeatureType.osElementName.c_str());
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
         /* For WFS, try to fetch the application schema */
-        if( bIsWFS && pszSchemaLocation != NULL && 
+        if( bIsWFS && !bHaveSchema && pszSchemaLocation != NULL && 
             (pszSchemaLocation[0] == '\'' || pszSchemaLocation[0] == '"') &&
              strchr(pszSchemaLocation + 1, pszSchemaLocation[0]) != NULL )
         {
@@ -735,7 +849,8 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
                 {
                     for(int i=0;i<nTokens;i+=2)
                     {
-                        char* pszLocation = CPLUnescapeString(papszTokens[i+1], NULL, CPLES_URL);
+                        const char* pszEscapedURL = papszTokens[i+1];
+                        char* pszLocation = CPLUnescapeString(pszEscapedURL, NULL, CPLES_URL);
                         CPLString osLocation = pszLocation;
                         CPLFree(pszLocation);
                         if (osLocation.ifind("typename=") != std::string::npos &&
@@ -747,8 +862,7 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
                             if (!bHasFoundXSD && CPLHTTPEnabled() &&
                                 CSLTestBoolean(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES")))
                             {
-                                CPLString osEscaped = ReplaceSpaceByPct20IfNeeded(osLocation);
-                                CPLHTTPResult* psResult = CPLHTTPFetch(osEscaped, NULL);
+                                CPLHTTPResult* psResult = CPLHTTPFetch(pszEscapedURL, NULL);
                                 if (psResult)
                                 {
                                     if (psResult->nStatus == 0 && psResult->pabyData != NULL)
@@ -774,34 +888,49 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
             CPLFree(pszSchemaLocationTmp1);
         }
 
+        int bHasFeatureProperties = FALSE;
         if( bHasFoundXSD )
         {
             std::vector<GMLFeatureClass*> aosClasses;
             bHaveSchema = GMLParseXSD( osXSDFilename, aosClasses );
-            if (bHaveSchema)
+            if( bHaveSchema )
             {
                 CPLDebug("GML", "Using %s", osXSDFilename.c_str());
-
                 std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
                 std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
                 while (iter != eiter)
                 {
                     GMLFeatureClass* poClass = *iter;
+
+                    if( poClass->HasFeatureProperties() )
+                    {
+                        bHasFeatureProperties = TRUE;
+                        break;
+                    }
+                    iter ++;
+                }
+
+                iter = aosClasses.begin();
+                while (iter != eiter)
+                {
+                    GMLFeatureClass* poClass = *iter;
                     iter ++;
 
                     /* We have no way of knowing if the geometry type is 25D */
                     /* when examining the xsd only, so if there was a hint */
                     /* it is, we force to 25D */
-                    if (bHas3D)
+                    if (bHas3D && poClass->GetGeometryPropertyCount() == 1)
                     {
-                        poClass->SetGeometryType(
-                            poClass->GetGeometryType() | wkb25DBit);
+                        poClass->GetGeometryProperty(0)->SetType(
+                            poClass->GetGeometryProperty(0)->GetType() | wkb25DBit);
                     }
 
                     int bAddClass = TRUE;
                     /* If typenames are declared, only register the matching classes, in case */
-                    /* the XSD contains more layers */
-                    if (papszTypeNames != NULL)
+                    /* the XSD contains more layers, but not if feature classes contain */
+                    /* feature properties, in which case we will have embedded features that */
+                    /* will be reported as top-level features */
+                    if( papszTypeNames != NULL && !bHasFeatureProperties )
                     {
                         bAddClass = FALSE;
                         char** papszIter = papszTypeNames;
@@ -841,6 +970,7 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
                     else
                         delete poClass;
                 }
+
                 poReader->SetClassListLocked( TRUE );
             }
         }
@@ -848,7 +978,8 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
         if (bHaveSchema && bIsWFS)
         {
             /* For WFS, we can assume sequential layers */
-            if (poReader->GetClassCount() > 1 && pszReadMode == NULL)
+            if (poReader->GetClassCount() > 1 && pszReadMode == NULL &&
+                !bHasFeatureProperties)
             {
                 CPLDebug("GML", "WFS output. Using SEQUENTIAL_LAYERS read mode");
                 eReadMode = SEQUENTIAL_LAYERS;
@@ -869,7 +1000,7 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
 /* -------------------------------------------------------------------- */
     if( !bHaveSchema )
     {
-        if( !poReader->PrescanForSchema( TRUE ) )
+        if( !poReader->PrescanForSchema( TRUE, bAnalyzeSRSPerFeature ) )
         {
             // we assume an errors have been reported.
             return FALSE;
@@ -939,6 +1070,9 @@ int OGRGMLDataSource::Open( const char * pszNameIn, int bTestOpen )
         }
     }
 
+    if (bIsWFS && poReader->GetClassCount() == 1)
+        bUseGlobalSRSName = TRUE;
+
     while( nLayers < poReader->GetClassCount() )
     {
         papoLayers[nLayers] = TranslateGMLSchema(poReader->GetClass(nLayers));
@@ -958,12 +1092,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
 
 {
     OGRGMLLayer *poLayer;
-    OGRwkbGeometryType eGType 
-        = (OGRwkbGeometryType) poClass->GetGeometryType();
 
-    if( poClass->GetFeatureCount() == 0 )
-        eGType = wkbUnknown;
-    
 /* -------------------------------------------------------------------- */
 /*      Create an empty layer.                                          */
 /* -------------------------------------------------------------------- */
@@ -979,7 +1108,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
             poSRS = NULL;
         }
     }
-    else if (bIsWFS && poReader->GetClassCount() == 1)
+    else
     {
         pszSRSName = GetGlobalSRSName();
         if (pszSRSName)
@@ -1023,9 +1152,25 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         }
     }
 
-    poLayer = new OGRGMLLayer( poClass->GetName(), poSRS, FALSE,
-                               eGType, this );
-    delete poSRS;
+    /* Report a COMPD_CS only if GML_REPORT_COMPD_CS is explicitely set to TRUE */
+    if( poSRS != NULL &&
+        !CSLTestBoolean(CPLGetConfigOption("GML_REPORT_COMPD_CS", "FALSE")) )
+    {
+        OGR_SRSNode *poCOMPD_CS = poSRS->GetAttrNode( "COMPD_CS" );
+        if( poCOMPD_CS != NULL )
+        {
+            OGR_SRSNode* poCandidateRoot = poCOMPD_CS->GetNode( "PROJCS" );
+            if( poCandidateRoot == NULL )
+                poCandidateRoot = poCOMPD_CS->GetNode( "GEOGCS" );
+            if( poCandidateRoot != NULL )
+            {
+                poSRS->SetRoot(poCandidateRoot->Clone());
+            }
+        }
+    }
+
+
+    poLayer = new OGRGMLLayer( poClass->GetName(), FALSE, this );
 
 /* -------------------------------------------------------------------- */
 /*      Added attributes (properties).                                  */
@@ -1041,7 +1186,20 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     }
 
-    for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
+    int iField;
+    for( iField = 0; iField < poClass->GetGeometryPropertyCount(); iField++ )
+    {
+        GMLGeometryPropertyDefn *poProperty = poClass->GetGeometryProperty( iField );
+        OGRGeomFieldDefn oField( poProperty->GetName(), (OGRwkbGeometryType)poProperty->GetType() );
+        if( poClass->GetGeometryPropertyCount() == 1 && poClass->GetFeatureCount() == 0 )
+        {
+            oField.SetType(wkbUnknown);
+        }
+        oField.SetSpatialRef(poSRS);
+        poLayer->GetLayerDefn()->AddGeomFieldDefn( &oField );
+    }
+
+    for( iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     {
         GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
         OGRFieldType eFType;
@@ -1060,6 +1218,8 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
             eFType = OFTIntegerList;
         else if( poProperty->GetType() == GMLPT_RealList )
             eFType = OFTRealList;
+        else if( poProperty->GetType() == GMLPT_FeaturePropertyList )
+            eFType = OFTStringList;
         else
             eFType = OFTString;
         
@@ -1074,6 +1234,9 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     }
 
+    if( poSRS != NULL )
+        poSRS->Release();
+
     return poLayer;
 }
 
@@ -1083,7 +1246,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
 
 const char *OGRGMLDataSource::GetGlobalSRSName()
 {
-    if (poReader->CanUseGlobalSRSName() || bIsWFS)
+    if (poReader->CanUseGlobalSRSName() || bUseGlobalSRSName)
         return poReader->GetGlobalSRSName();
     else
         return NULL;
@@ -1172,7 +1335,10 @@ int OGRGMLDataSource::Create( const char *pszFilename,
     const char* pszPrefix = GetAppPrefix();
     const char* pszTargetNameSpace = CSLFetchNameValueDef(papszOptions,"TARGET_NAMESPACE", "http://ogr.maptools.org/");
 
-    PrintLine( fpOutput, "<%s:FeatureCollection", pszPrefix );
+    if( RemoveAppPrefix() )
+        PrintLine( fpOutput, "<FeatureCollection" );
+    else
+        PrintLine( fpOutput, "<%s:FeatureCollection", pszPrefix );
 
     if (IsGML32Output())
         PrintLine( fpOutput, "%s",
@@ -1205,8 +1371,13 @@ int OGRGMLDataSource::Create( const char *pszFilename,
         CPLFree( pszBasename );
     }
 
-    PrintLine( fpOutput,
+    if( RemoveAppPrefix() )
+        PrintLine( fpOutput,
+                "     xmlns=\"%s\"", pszTargetNameSpace );
+    else
+        PrintLine( fpOutput,
                 "     xmlns:%s=\"%s\"", pszPrefix, pszTargetNameSpace );
+
     if (IsGML32Output())
         PrintLine( fpOutput, "%s",
                 "     xmlns:gml=\"http://www.opengis.net/gml/3.2\">" );
@@ -1285,15 +1456,24 @@ OGRGMLDataSource::CreateLayer( const char * pszLayerName,
     if (nLayers == 0)
     {
         if (poSRS)
-            poGlobalSRS = poSRS->Clone();
+            poWriteGlobalSRS = poSRS->Clone();
+        bWriteGlobalSRS = TRUE;
     }
-    else
+    else if( bWriteGlobalSRS )
     {
-        if (poSRS == NULL ||
-            (poGlobalSRS != NULL && !poSRS->IsSame(poGlobalSRS)))
+        if( poWriteGlobalSRS != NULL )
+        {
+            if (poSRS == NULL || !poSRS->IsSame(poWriteGlobalSRS))
+            {
+                delete poWriteGlobalSRS;
+                poWriteGlobalSRS = NULL;
+                bWriteGlobalSRS = FALSE;
+            }
+        }
+        else
         {
-            delete poGlobalSRS;
-            poGlobalSRS = NULL;
+            if( poSRS != NULL )
+                bWriteGlobalSRS = FALSE;
         }
     }
 
@@ -1302,7 +1482,20 @@ OGRGMLDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRGMLLayer *poLayer;
 
-    poLayer = new OGRGMLLayer( pszCleanLayerName, poSRS, TRUE, eType, this );
+    poLayer = new OGRGMLLayer( pszCleanLayerName, TRUE, this );
+    poLayer->GetLayerDefn()->SetGeomType(eType);
+    if( eType != wkbNone )
+    {
+        poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetName("geometryProperty");
+        if( poSRS != NULL )
+        {
+            /* Clone it since mapogroutput assumes that it can destroys */
+            /* the SRS it has passed to use, instead of deferencing it */
+            poSRS = poSRS->Clone();
+            poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+            poSRS->Dereference();
+        }
+    }
 
     CPLFree( pszCleanLayerName );
 
@@ -1326,6 +1519,8 @@ int OGRGMLDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -1414,10 +1609,34 @@ void OGRGMLDataSource::InsertHeader()
 /*      file "down" enough to insert the schema at the beginning.       */
 /* ==================================================================== */
 
+/* ==================================================================== */
+/*      Detect if there are fields of List types.                       */
+/* ==================================================================== */
+    int iLayer;
+    int bHasListFields = FALSE;
+
+    for( iLayer = 0; !bHasListFields && iLayer < GetLayerCount(); iLayer++ )
+    {
+        OGRFeatureDefn *poFDefn = GetLayer(iLayer)->GetLayerDefn();
+        for( int iField = 0; !bHasListFields && iField < poFDefn->GetFieldCount(); iField++ )
+        {
+            OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
+
+            if( poFieldDefn->GetType() == OFTIntegerList ||
+                poFieldDefn->GetType() == OFTRealList ||
+                poFieldDefn->GetType() == OFTStringList )
+            {
+                bHasListFields = TRUE;
+            }
+        } /* next field */
+    } /* next layer */
+
 /* -------------------------------------------------------------------- */
 /*      Emit the start of the schema section.                           */
 /* -------------------------------------------------------------------- */
     const char* pszPrefix = GetAppPrefix();
+    if( pszPrefix[0] == '\0' )
+        pszPrefix = "ogr";
     const char* pszTargetNameSpace = CSLFetchNameValueDef(papszCreateOptions,"TARGET_NAMESPACE", "http://ogr.maptools.org/");
 
     if (IsGML3Output())
@@ -1460,7 +1679,7 @@ void OGRGMLDataSource::InsertHeader()
             PrintLine( fpSchema,
                     "  <xs:appinfo source=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\">");
             PrintLine( fpSchema,
-                    "    <gmlsf:ComplianceLevel>0</gmlsf:ComplianceLevel>");
+                    "    <gmlsf:ComplianceLevel>%d</gmlsf:ComplianceLevel>", (bHasListFields) ? 1 : 0);
             PrintLine( fpSchema,
                     "  </xs:appinfo>");
             PrintLine( fpSchema,
@@ -1480,7 +1699,7 @@ void OGRGMLDataSource::InsertHeader()
                 PrintLine( fpSchema,
                         "  <xs:appinfo source=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\">");
                 PrintLine( fpSchema,
-                        "    <gmlsf:ComplianceLevel>0</gmlsf:ComplianceLevel>");
+                        "    <gmlsf:ComplianceLevel>%d</gmlsf:ComplianceLevel>", (bHasListFields) ? 1 : 0);
                 PrintLine( fpSchema,
                         "    <gmlsf:GMLProfileSchema>http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd</gmlsf:GMLProfileSchema>");
                 PrintLine( fpSchema,
@@ -1589,7 +1808,6 @@ void OGRGMLDataSource::InsertHeader()
 /* ==================================================================== */
 /*      Define the schema for each layer.                               */
 /* ==================================================================== */
-    int iLayer;
 
     for( iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
     {
@@ -1618,55 +1836,58 @@ void OGRGMLDataSource::InsertHeader()
         PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">");
         PrintLine( fpSchema, "      <xs:sequence>");
 
-/* -------------------------------------------------------------------- */
-/*      Define the geometry attribute.                                  */
-/* -------------------------------------------------------------------- */
-        const char* pszGeometryTypeName = "GeometryPropertyType";
-        switch(wkbFlatten(poFDefn->GetGeomType()))
+        for( int iGeomField = 0; iGeomField < poFDefn->GetGeomFieldCount(); iGeomField++ )
         {
-            case wkbPoint:
-                pszGeometryTypeName = "PointPropertyType";
-                break;
-            case wkbLineString:
-                if (IsGML3Output())
-                    pszGeometryTypeName = "CurvePropertyType";
-                else
-                    pszGeometryTypeName = "LineStringPropertyType";
-                break;
-            case wkbPolygon:
-                if (IsGML3Output())
-                    pszGeometryTypeName = "SurfacePropertyType";
-                else
-                    pszGeometryTypeName = "PolygonPropertyType";
-                break;
-            case wkbMultiPoint:
-                pszGeometryTypeName = "MultiPointPropertyType";
-                break;
-            case wkbMultiLineString:
-                if (IsGML3Output())
-                    pszGeometryTypeName = "MultiCurvePropertyType";
-                else
-                    pszGeometryTypeName = "MultiLineStringPropertyType";
-                break;
-            case wkbMultiPolygon:
-                if (IsGML3Output())
-                    pszGeometryTypeName = "MultiSurfacePropertyType";
-                else
-                    pszGeometryTypeName = "MultiPolygonPropertyType";
-                break;
-            case wkbGeometryCollection:
-                pszGeometryTypeName = "MultiGeometryPropertyType";
-                break;
-            default:
-                break;
-        }
+            OGRGeomFieldDefn *poFieldDefn = poFDefn->GetGeomFieldDefn(iGeomField);
+
+    /* -------------------------------------------------------------------- */
+    /*      Define the geometry attribute.                                  */
+    /* -------------------------------------------------------------------- */
+            const char* pszGeometryTypeName = "GeometryPropertyType";
+            switch(wkbFlatten(poFieldDefn->GetType()))
+            {
+                case wkbPoint:
+                    pszGeometryTypeName = "PointPropertyType";
+                    break;
+                case wkbLineString:
+                    if (IsGML3Output())
+                        pszGeometryTypeName = "CurvePropertyType";
+                    else
+                        pszGeometryTypeName = "LineStringPropertyType";
+                    break;
+                case wkbPolygon:
+                    if (IsGML3Output())
+                        pszGeometryTypeName = "SurfacePropertyType";
+                    else
+                        pszGeometryTypeName = "PolygonPropertyType";
+                    break;
+                case wkbMultiPoint:
+                    pszGeometryTypeName = "MultiPointPropertyType";
+                    break;
+                case wkbMultiLineString:
+                    if (IsGML3Output())
+                        pszGeometryTypeName = "MultiCurvePropertyType";
+                    else
+                        pszGeometryTypeName = "MultiLineStringPropertyType";
+                    break;
+                case wkbMultiPolygon:
+                    if (IsGML3Output())
+                        pszGeometryTypeName = "MultiSurfacePropertyType";
+                    else
+                        pszGeometryTypeName = "MultiPolygonPropertyType";
+                    break;
+                case wkbGeometryCollection:
+                    pszGeometryTypeName = "MultiGeometryPropertyType";
+                    break;
+                default:
+                    break;
+            }
 
-        if (poFDefn->GetGeomType() != wkbNone)
-        {
             PrintLine( fpSchema,
-                "        <xs:element name=\"geometryProperty\" type=\"gml:%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\"/>", pszGeometryTypeName );
+                "        <xs:element name=\"%s\" type=\"gml:%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\"/>",
+                       poFieldDefn->GetNameRef(), pszGeometryTypeName );
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Emit each of the attributes.                                    */
 /* -------------------------------------------------------------------- */
@@ -1679,7 +1900,8 @@ void OGRGMLDataSource::InsertHeader()
             else if( !IsGML3Output() && strcmp(poFieldDefn->GetNameRef(), "fid") == 0 )
                 continue;
 
-            if( poFieldDefn->GetType() == OFTInteger )
+            if( poFieldDefn->GetType() == OFTInteger ||
+                poFieldDefn->GetType() == OFTIntegerList  )
             {
                 int nWidth;
 
@@ -1688,7 +1910,8 @@ void OGRGMLDataSource::InsertHeader()
                 else
                     nWidth = 16;
 
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\">", poFieldDefn->GetNameRef());
+                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"%s\">",
+                           poFieldDefn->GetNameRef(), poFieldDefn->GetType() == OFTIntegerList ? "unbounded": "1" );
                 PrintLine( fpSchema, "          <xs:simpleType>");
                 PrintLine( fpSchema, "            <xs:restriction base=\"xs:integer\">");
                 PrintLine( fpSchema, "              <xs:totalDigits value=\"%d\"/>", nWidth);
@@ -1696,14 +1919,16 @@ void OGRGMLDataSource::InsertHeader()
                 PrintLine( fpSchema, "          </xs:simpleType>");
                 PrintLine( fpSchema, "        </xs:element>");
             }
-            else if( poFieldDefn->GetType() == OFTReal )
+            else if( poFieldDefn->GetType() == OFTReal ||
+                     poFieldDefn->GetType() == OFTRealList  )
             {
                 int nWidth, nDecimals;
 
                 nWidth = poFieldDefn->GetWidth();
                 nDecimals = poFieldDefn->GetPrecision();
 
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\">",  poFieldDefn->GetNameRef());
+                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"%s\">",
+                           poFieldDefn->GetNameRef(), poFieldDefn->GetType() == OFTRealList ? "unbounded": "1" );
                 PrintLine( fpSchema, "          <xs:simpleType>");
                 PrintLine( fpSchema, "            <xs:restriction base=\"xs:decimal\">");
                 if (nWidth > 0)
@@ -1715,9 +1940,11 @@ void OGRGMLDataSource::InsertHeader()
                 PrintLine( fpSchema, "          </xs:simpleType>");
                 PrintLine( fpSchema, "        </xs:element>");
             }
-            else if( poFieldDefn->GetType() == OFTString )
+            else if( poFieldDefn->GetType() == OFTString ||
+                     poFieldDefn->GetType() == OFTStringList )
             {
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\">",  poFieldDefn->GetNameRef());
+                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"%s\">", 
+                           poFieldDefn->GetNameRef(), poFieldDefn->GetType() == OFTStringList ? "unbounded": "1" );
                 PrintLine( fpSchema, "          <xs:simpleType>");
                 PrintLine( fpSchema, "            <xs:restriction base=\"xs:string\">");
                 if( poFieldDefn->GetWidth() != 0 )
@@ -1922,6 +2149,31 @@ void OGRGMLDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
 }
 
 /************************************************************************/
+/*                          ExtractSRSName()                            */
+/************************************************************************/
+
+static int ExtractSRSName(const char* pszXML, char* szSRSName,
+                          size_t sizeof_szSRSName)
+{
+    szSRSName[0] = '\0';
+
+    const char* pszSRSName = strstr(pszXML, "srsName=\"");
+    if( pszSRSName != NULL )
+    {
+        pszSRSName += 9;
+        const char* pszEndQuote = strchr(pszSRSName, '"');
+        if (pszEndQuote != NULL &&
+            (size_t)(pszEndQuote - pszSRSName) < sizeof_szSRSName)
+        {
+            memcpy(szSRSName, pszSRSName, pszEndQuote - pszSRSName);
+            szSRSName[pszEndQuote - pszSRSName] = '\0';
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                         FindAndParseBoundedBy()                      */
 /************************************************************************/
 
@@ -1974,19 +2226,7 @@ void OGRGMLDataSource::FindAndParseBoundedBy(VSILFILE* fp)
         /* e.g. http://geoserv.weichand.de:8080/geoserver/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAME=bvv:gmd_ex */
         if( bIsWFS )
         {
-            pszSRSName = strstr(pszXML, "srsName=\"");
-            if( pszSRSName != NULL )
-            {
-                pszSRSName += 9;
-                const char* pszEndQuote = strchr(pszSRSName, '"');
-                if (pszEndQuote != NULL &&
-                    (size_t)(pszEndQuote - pszSRSName) < sizeof(szSRSName))
-                {
-                    memcpy(szSRSName, pszSRSName, pszEndQuote - pszSRSName);
-                    szSRSName[pszEndQuote - pszSRSName] = '\0';
-                }
-                pszSRSName = NULL;
-            }
+            ExtractSRSName(pszXML, szSRSName, sizeof(szSRSName));
         }
 
         pszEndBoundedBy[strlen("</gml:boundedBy>")] = '\0';
@@ -2087,3 +2327,26 @@ const char* OGRGMLDataSource::GetAppPrefix()
 {
     return CSLFetchNameValueDef(papszCreateOptions, "PREFIX", "ogr");
 }
+
+/************************************************************************/
+/*                            RemoveAppPrefix()                         */
+/************************************************************************/
+
+int OGRGMLDataSource::RemoveAppPrefix()
+{
+    if( CSLTestBoolean(CSLFetchNameValueDef(
+            papszCreateOptions, "STRIP_PREFIX", "FALSE")) )
+        return TRUE;
+    const char* pszPrefix = GetAppPrefix();
+    return( pszPrefix[0] == '\0' );
+}
+
+/************************************************************************/
+/*                        WriteFeatureBoundedBy()                       */
+/************************************************************************/
+
+int OGRGMLDataSource::WriteFeatureBoundedBy()
+{
+    return CSLTestBoolean(CSLFetchNameValueDef(
+                    papszCreateOptions, "WRITE_FEATURE_BOUNDED_BY", "TRUE"));
+}
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
index 2b223a2..81309d3 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogrgmldriver.cpp 26591 2013-11-07 20:41:38Z rouault $
  *
  * Project:  OGR
  * Purpose:  OGRGMLDriver implementation
@@ -29,8 +29,10 @@
 
 #include "ogr_gml.h"
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
+#include "gmlreaderp.h"
 
-CPL_CVSID("$Id: ogrgmldriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrgmldriver.cpp 26591 2013-11-07 20:41:38Z rouault $");
 
 /************************************************************************/
 /*                          ~OGRGMLDriver()                           */
@@ -39,6 +41,9 @@ CPL_CVSID("$Id: ogrgmldriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 OGRGMLDriver::~OGRGMLDriver()
 
 {
+    if( GMLReader::hMutex != NULL )
+        CPLDestroyMutex( GMLReader::hMutex );
+    GMLReader::hMutex = NULL;
 }
 
 /************************************************************************/
@@ -66,8 +71,7 @@ OGRDataSource *OGRGMLDriver::Open( const char * pszFilename,
 
     poDS = new OGRGMLDataSource();
 
-    if( !poDS->Open( pszFilename, TRUE )
-        || poDS->GetLayerCount() == 0 )
+    if( !poDS->Open( pszFilename ) )
     {
         delete poDS;
         return NULL;
diff --git a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
index eed9458..f631813 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmllayer.cpp 25271 2012-11-30 22:10:18Z rouault $
+ * $Id: ogrgmllayer.cpp 27146 2014-04-09 17:01:52Z martinl $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,23 +36,17 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgmllayer.cpp 25271 2012-11-30 22:10:18Z rouault $");
+CPL_CVSID("$Id: ogrgmllayer.cpp 27146 2014-04-09 17:01:52Z martinl $");
 
 /************************************************************************/
 /*                           OGRGMLLayer()                              */
 /************************************************************************/
 
 OGRGMLLayer::OGRGMLLayer( const char * pszName,
-                          OGRSpatialReference *poSRSIn, int bWriterIn,
-                          OGRwkbGeometryType eReqType,
+                          int bWriterIn,
                           OGRGMLDataSource *poDSIn )
 
 {
-    if( poSRSIn == NULL )
-        poSRS = NULL;
-    else
-        poSRS = poSRSIn->Clone();
-    
     iNextGMLId = 0;
     nTotalGMLCount = -1;
     bInvalidFIDFound = FALSE;
@@ -65,9 +60,10 @@ OGRGMLLayer::OGRGMLLayer( const char * pszName,
     else
       poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( eReqType );
+    poFeatureDefn->SetGeomType( wkbNone );
 
     bWriter = bWriterIn;
+    bSameSRS = FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Reader's should get the corresponding GMLFeatureClass and       */
@@ -101,9 +97,6 @@ OGRGMLLayer::~OGRGMLLayer()
     if( poFeatureDefn )
         poFeatureDefn->Release();
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     GML_BuildOGRGeometryFromList_DestroyCache(hCacheSRS);
 }
 
@@ -133,8 +126,48 @@ void OGRGMLLayer::ResetReading()
     iNextGMLId = 0;
     poDS->GetReader()->ResetReading();
     CPLDebug("GML", "ResetReading()");
-    if (poDS->GetLayerCount() > 1 && poDS->GetReadMode() == STANDARD)
-        poDS->GetReader()->SetFilteredClassName(poFClass->GetName());
+    if ( poDS->GetLayerCount() > 1 && poDS->GetReadMode() == STANDARD )
+    {
+        const char* pszElementName = poFClass->GetElementName();
+        const char* pszLastPipe = strrchr( pszElementName, '|' );
+        if ( pszLastPipe != NULL )
+            pszElementName = pszLastPipe + 1;
+        poDS->GetReader()->SetFilteredClassName(pszElementName);
+    }
+}
+
+/************************************************************************/
+/*                     ConvertGeomToMultiIfNecessary()                  */
+/************************************************************************/
+
+OGRGeometry* OGRGMLLayer::ConvertGeomToMultiIfNecessary(OGRGeometry* poGeom)
+{
+    OGRwkbGeometryType eType = poGeom->getGeometryType();
+    OGRwkbGeometryType eLayerType = GetGeomType();
+    OGRGeometryCollection* poNewGeom = NULL;
+    if (eType == wkbPoint && eLayerType == wkbMultiPoint)
+    {
+        poNewGeom = new OGRMultiPoint();
+    }
+    else if (eType == wkbLineString && eLayerType == wkbMultiLineString)
+    {
+        poNewGeom = new OGRMultiLineString();
+    }
+    else if (eType == wkbPolygon && eLayerType == wkbMultiPolygon)
+    {
+        poNewGeom = new OGRMultiPolygon();
+    }
+
+    if( poNewGeom != NULL )
+    {
+        OGRSpatialReference* poGeomSRS = poGeom->getSpatialReference();
+        poNewGeom->addGeometryDirectly(poGeom);
+        if( poGeomSRS != NULL )
+            poNewGeom->assignSpatialReference(poGeomSRS);
+        poGeom = poNewGeom;
+    }
+
+    return poGeom;
 }
 
 /************************************************************************/
@@ -144,8 +177,7 @@ void OGRGMLLayer::ResetReading()
 OGRFeature *OGRGMLLayer::GetNextFeature()
 
 {
-    GMLFeature  *poGMLFeature = NULL;
-    OGRGeometry *poGeom = NULL;
+    int i;
 
     if (bWriter)
     {
@@ -167,17 +199,8 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* ==================================================================== */
     while( TRUE )
     {
-/* -------------------------------------------------------------------- */
-/*      Cleanup last feature, and get a new raw gml feature.            */
-/* -------------------------------------------------------------------- */
-        if( poGMLFeature != NULL )
-            delete poGMLFeature;
-
-        if( poGeom != NULL )
-        {
-            delete poGeom;
-            poGeom = NULL;
-        }
+        GMLFeature  *poGMLFeature = NULL;
+        OGRGeometry *poGeom = NULL;
 
         poGMLFeature = poDS->PeekStoredGMLFeature();
         if (poGMLFeature != NULL)
@@ -208,7 +231,10 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                 return NULL;
             }
             else
+            {
+                delete poGMLFeature;
                 continue;
+            }
         }
 
 /* -------------------------------------------------------------------- */
@@ -232,7 +258,8 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         }
         else if( iNextGMLId == 0 )
         {
-            int i = strlen( pszGML_FID )-1, j = 0;
+            int j = 0;
+            i = strlen( pszGML_FID )-1;
             while( i >= 0 && pszGML_FID[i] >= '0'
                           && pszGML_FID[i] <= '9' && j<8)
                 i--, j++;
@@ -279,11 +306,23 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /*      Does it satisfy the spatial query, if there is one?             */
 /* -------------------------------------------------------------------- */
 
+        OGRGeometry** papoGeometries = NULL;
         const CPLXMLNode* const * papsGeometry = poGMLFeature->GetGeometryList();
-        if (papsGeometry[0] != NULL)
+
+        if( poFeatureDefn->GetGeomFieldCount() > 1 )
         {
+            papoGeometries = (OGRGeometry**)
+                CPLCalloc( poFeatureDefn->GetGeomFieldCount(), sizeof(OGRGeometry*) );
             const char* pszSRSName = poDS->GetGlobalSRSName();
-            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, TRUE,
+            for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+            {
+                const CPLXMLNode* psGeom = poGMLFeature->GetGeometryRef(i);
+                if( psGeom != NULL )
+                {
+                    const CPLXMLNode* myGeometryList[2];
+                    myGeometryList[0] = psGeom;
+                    myGeometryList[1] = NULL;
+                    poGeom = GML_BuildOGRGeometryFromList(myGeometryList, TRUE,
                                                   poDS->GetInvertAxisOrderIfLatLong(),
                                                   pszSRSName,
                                                   poDS->GetConsiderEPSGAsURN(),
@@ -291,36 +330,57 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                                                   hCacheSRS,
                                                   bFaceHoleNegative );
 
-            /* Force single geometry to multigeometry if needed to match layer geometry type */
-            if (poGeom != NULL)
-            {
-                OGRwkbGeometryType eType = poGeom->getGeometryType();
-                OGRwkbGeometryType eLayerType = GetGeomType();
-                OGRGeometryCollection* poNewGeom = NULL;
-                if (eType == wkbPoint && eLayerType == wkbMultiPoint)
-                {
-                    poNewGeom = new OGRMultiPoint();
-                }
-                else if (eType == wkbLineString && eLayerType == wkbMultiLineString)
-                {
-                    poNewGeom = new OGRMultiLineString();
-                }
-                else if (eType == wkbPolygon && eLayerType == wkbMultiPolygon)
-                {
-                    poNewGeom = new OGRMultiPolygon();
+                    /* Force single geometry to multigeometry if needed to match layer geometry type */
+                    if (poGeom != NULL)
+                    {
+                        papoGeometries[i] = ConvertGeomToMultiIfNecessary(poGeom);
+                        poGeom = NULL;
+                    }
+                    else
+                    // We assume the createFromGML() function would have already
+                    // reported the error.
+                    {
+                        for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+                        {
+                            delete papoGeometries[i];
+                        }
+                        CPLFree(papoGeometries);
+                        delete poGMLFeature;
+                        return NULL;
+                    }
                 }
+            }
 
-                if( poNewGeom != NULL )
+            if( m_poFilterGeom != NULL &&
+                m_iGeomFieldFilter >= 0 &&
+                m_iGeomFieldFilter < poFeatureDefn->GetGeomFieldCount() &&
+                papoGeometries[m_iGeomFieldFilter] &&
+                !FilterGeometry( papoGeometries[m_iGeomFieldFilter] ) )
+            {
+                for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
                 {
-                    OGRSpatialReference* poGeomSRS = poGeom->getSpatialReference();
-                    poNewGeom->addGeometryDirectly(poGeom);
-                    if( poGeomSRS != NULL )
-                        poNewGeom->assignSpatialReference(poGeomSRS);
-                    poGeom = poNewGeom;
+                    delete papoGeometries[i];
                 }
+                CPLFree(papoGeometries);
+                delete poGMLFeature;
+                continue;
+            }
+        }
+        else if (papsGeometry[0] != NULL)
+        {
+            const char* pszSRSName = poDS->GetGlobalSRSName();
+            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, TRUE,
+                                                  poDS->GetInvertAxisOrderIfLatLong(),
+                                                  pszSRSName,
+                                                  poDS->GetConsiderEPSGAsURN(),
+                                                  poDS->GetSecondaryGeometryOption(),
+                                                  hCacheSRS,
+                                                  bFaceHoleNegative );
 
-                if (poSRS != NULL)
-                    poGeom->assignSpatialReference(poSRS);
+            /* Force single geometry to multigeometry if needed to match layer geometry type */
+            if (poGeom != NULL)
+            {
+                poGeom = ConvertGeomToMultiIfNecessary(poGeom);
             }
             else
             // We assume the createFromGML() function would have already
@@ -331,7 +391,11 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             }
 
             if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
+            {
+                delete poGMLFeature;
+                delete poGeom;
                 continue;
+            }
         }
 
         
@@ -340,7 +404,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
         int iField;
         int iDstField = 0;
-        OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
+        OGRFeature *poOGRFeature = new OGRFeature( poFeatureDefn );
 
         poOGRFeature->SetFID( nFID );
         if (poDS->ExposeId())
@@ -369,7 +433,6 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
               {
                   int nCount = psGMLProperty->nSubProperties;
                   int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
-                  int i;
 
                   for( i = 0; i < nCount; i++ )
                       panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]);
@@ -383,7 +446,6 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
               {
                   int nCount = psGMLProperty->nSubProperties;
                   double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
-                  int i;
 
                   for( i = 0; i < nCount; i++ )
                       padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]);
@@ -394,6 +456,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
               break;
 
               case GMLPT_StringList:
+              case GMLPT_FeaturePropertyList:
               {
                   poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties );
               }
@@ -405,10 +468,34 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             }
         }
 
+        delete poGMLFeature;
+        poGMLFeature = NULL;
+
         /* Assign the geometry before the attribute filter because */
         /* the attribute filter may use a special field like OGR_GEOMETRY */
-        poOGRFeature->SetGeometryDirectly( poGeom );
-        poGeom = NULL;
+        if( papoGeometries != NULL )
+        {
+            for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+            {
+                poOGRFeature->SetGeomFieldDirectly( i, papoGeometries[i] );
+            }
+            CPLFree(papoGeometries);
+            papoGeometries = NULL;
+        }
+        else
+            poOGRFeature->SetGeometryDirectly( poGeom );
+
+        /* Assign SRS */
+        for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        {
+            poGeom = poOGRFeature->GetGeomFieldRef(i);
+            if( poGeom != NULL )
+            {
+                OGRSpatialReference* poSRS = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
+                if (poSRS != NULL)
+                    poGeom->assignSpatialReference(poSRS);
+            }
+        }
         
 /* -------------------------------------------------------------------- */
 /*      Test against the attribute query.                               */
@@ -423,7 +510,6 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Wow, we got our desired feature. Return it.                     */
 /* -------------------------------------------------------------------- */
-        delete poGMLFeature;
 
         return poOGRFeature;
     }
@@ -466,6 +552,9 @@ OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 {
     double dfXMin, dfXMax, dfYMin, dfYMax;
 
+    if( GetGeomType() == wkbNone )
+        return OGRERR_FAILURE;
+
     if( poFClass != NULL && 
         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
     {
@@ -481,6 +570,41 @@ OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 }
 
 /************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+static void GMLWriteField(OGRGMLDataSource* poDS,
+                          VSILFILE *fp,
+                          int bWriteSpaceIndentation,
+                          const char* pszPrefix,
+                          int bRemoveAppPrefix,
+                          OGRFieldDefn* poFieldDefn,
+                          const char* pszVal )
+
+{
+    const char* pszFieldName = poFieldDefn->GetNameRef();
+
+    while( *pszVal == ' ' )
+        pszVal++;
+
+    if (bWriteSpaceIndentation)
+        VSIFPrintfL(fp, "      ");
+
+    if( bRemoveAppPrefix )
+        poDS->PrintLine( fp, "<%s>%s</%s>",
+                        pszFieldName,
+                        pszVal,
+                        pszFieldName);
+    else
+        poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
+                        pszPrefix,
+                        pszFieldName,
+                        pszVal,
+                        pszPrefix,
+                        pszFieldName);
+}
+
+/************************************************************************/
 /*                           CreateFeature()                            */
 /************************************************************************/
 
@@ -491,6 +615,7 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
     VSILFILE *fp = poDS->GetOutputFP();
     int bWriteSpaceIndentation = poDS->WriteSpaceIndentation();
     const char* pszPrefix = poDS->GetAppPrefix();
+    int bRemoveAppPrefix = poDS->RemoveAppPrefix();
 
     if( !bWriter )
         return OGRERR_FAILURE;
@@ -498,27 +623,54 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "  ");
     if (bIsGML3Output)
-        poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix );
+    {
+        if( bRemoveAppPrefix ) 
+            poDS->PrintLine( fp, "<featureMember>" );
+        else
+            poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix );
+    }
     else
         poDS->PrintLine( fp, "<gml:featureMember>" );
 
+    if( iNextGMLId == 0 )
+    {
+        bSameSRS = TRUE;
+        for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
+        {
+            OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0);
+            OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
+            OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef();
+            OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
+            if( poSRS0 != NULL && poSRS == NULL )
+                bSameSRS = FALSE;
+            else if( poSRS0 == NULL && poSRS != NULL )
+                bSameSRS = FALSE;
+            else if( poSRS0 != NULL && poSRS != NULL &&
+                     poSRS0 != poSRS && !poSRS0->IsSame(poSRS) )
+            {
+                bSameSRS = FALSE;
+            }
+        }
+    }
+
     if( poFeature->GetFID() == OGRNullFID )
         poFeature->SetFID( iNextGMLId++ );
 
     int nGMLIdIndex = -1;
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "    ");
+    VSIFPrintfL(fp, "<");
+    if( !bRemoveAppPrefix ) 
+        VSIFPrintfL(fp, "%s:", pszPrefix);
     if (bIsGML3Output)
     {
         nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id");
         if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
-            poDS->PrintLine( fp, "<%s:%s gml:id=\"%s\">",
-                             pszPrefix,
+            poDS->PrintLine( fp, "%s gml:id=\"%s\">",
                              poFeatureDefn->GetName(),
                              poFeature->GetFieldAsString(nGMLIdIndex) );
         else
-            poDS->PrintLine( fp, "<%s:%s gml:id=\"%s.%ld\">",
-                             pszPrefix,
+            poDS->PrintLine( fp, "%s gml:id=\"%s.%ld\">",
                              poFeatureDefn->GetName(),
                              poFeatureDefn->GetName(),
                              poFeature->GetFID() );
@@ -528,79 +680,102 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
         nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid");
         if (bUseOldFIDFormat)
         {
-            poDS->PrintLine( fp, "<%s:%s fid=\"F%ld\">",
-                             pszPrefix,
+            poDS->PrintLine( fp, "%s fid=\"F%ld\">",
                              poFeatureDefn->GetName(),
                              poFeature->GetFID() );
         }
         else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
         {
-            poDS->PrintLine( fp, "<%s:%s fid=\"%s\">",
-                             pszPrefix,
+            poDS->PrintLine( fp, "%s fid=\"%s\">",
                              poFeatureDefn->GetName(),
                              poFeature->GetFieldAsString(nGMLIdIndex) );
         }
         else
         {
-            poDS->PrintLine( fp, "<%s:%s fid=\"%s.%ld\">",
-                             pszPrefix,
+            poDS->PrintLine( fp, "%s fid=\"%s.%ld\">",
                              poFeatureDefn->GetName(),
                              poFeatureDefn->GetName(),
                              poFeature->GetFID() );
         }
     }
 
-    // Write out Geometry - for now it isn't indented properly.
-    /* GML geometries don't like very much the concept of empty geometry */
-    OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if( poGeom != NULL && !poGeom->IsEmpty())
+
+    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
     {
-        char    *pszGeometry;
-        OGREnvelope3D sGeomBounds;
+        OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
 
-        int nCoordDimension = poGeom->getCoordinateDimension();
+        // Write out Geometry - for now it isn't indented properly.
+        /* GML geometries don't like very much the concept of empty geometry */
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField);
+        if( poGeom != NULL && !poGeom->IsEmpty())
+        {
+            char    *pszGeometry;
+            OGREnvelope3D sGeomBounds;
 
-        poGeom->getEnvelope( &sGeomBounds );
-        poDS->GrowExtents( &sGeomBounds, nCoordDimension );
+            int nCoordDimension = poGeom->getCoordinateDimension();
 
-        if (poGeom->getSpatialReference() == NULL && poSRS != NULL)
-            poGeom->assignSpatialReference(poSRS);
+            poGeom->getEnvelope( &sGeomBounds );
+            if( bSameSRS )
+                poDS->GrowExtents( &sGeomBounds, nCoordDimension );
 
-        if (bIsGML3Output)
-        {
-            int bCoordSwap;
+            if (poGeom->getSpatialReference() == NULL && poFieldDefn->GetSpatialRef() != NULL)
+                poGeom->assignSpatialReference(poFieldDefn->GetSpatialRef());
 
-            char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
-            char szLowerCorner[75], szUpperCorner[75];
-            if (bCoordSwap)
+            if (bIsGML3Output && poDS->WriteFeatureBoundedBy())
             {
-                OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension);
-                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension);
+                int bCoordSwap;
+
+                char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
+                char szLowerCorner[75], szUpperCorner[75];
+                if (bCoordSwap)
+                {
+                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension);
+                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension);
+                }
+                else
+                {
+                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension);
+                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension);
+                }
+                if (bWriteSpaceIndentation)
+                    VSIFPrintfL(fp, "      ");
+                poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
+                                (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner);
+                CPLFree(pszSRSName);
             }
-            else
+
+            char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
+            if (bIsGML3Output && !poDS->IsLongSRSRequired())
+                papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
+            if (poDS->IsGML32Output())
             {
-                OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension);
-                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension);
+                if( poFeatureDefn->GetGeomFieldCount() > 1 )
+                    papszOptions = CSLAddString(papszOptions,
+                        CPLSPrintf("GMLID=%s.%s.%ld",
+                                   poFeatureDefn->GetName(),
+                                   poFieldDefn->GetNameRef(),
+                                   poFeature->GetFID()));
+                else
+                    papszOptions = CSLAddString(papszOptions,
+                        CPLSPrintf("GMLID=%s.geom.%ld",
+                                   poFeatureDefn->GetName(), poFeature->GetFID()));
             }
+            pszGeometry = poGeom->exportToGML(papszOptions);
+            CSLDestroy(papszOptions);
             if (bWriteSpaceIndentation)
                 VSIFPrintfL(fp, "      ");
-            poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
-                             (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner);
-            CPLFree(pszSRSName);
+            if( bRemoveAppPrefix )
+                poDS->PrintLine( fp, "<%s>%s</%s>",
+                                 poFieldDefn->GetNameRef(),
+                                 pszGeometry,
+                                 poFieldDefn->GetNameRef() );
+            else
+                poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
+                                 pszPrefix, poFieldDefn->GetNameRef(),
+                                 pszGeometry,
+                                 pszPrefix, poFieldDefn->GetNameRef() );
+            CPLFree( pszGeometry );
         }
-
-        char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
-        if (bIsGML3Output && !poDS->IsLongSRSRequired())
-            papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
-        if (poDS->IsGML32Output())
-            papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.geom.%ld", poFeatureDefn->GetName(), poFeature->GetFID()));
-        pszGeometry = poGeom->exportToGML(papszOptions);
-        CSLDestroy(papszOptions);
-        if (bWriteSpaceIndentation)
-            VSIFPrintfL(fp, "      ");
-        poDS->PrintLine( fp, "<%s:geometryProperty>%s</%s:geometryProperty>",
-                         pszPrefix, pszGeometry, pszPrefix );
-        CPLFree( pszGeometry );
     }
 
     // Write all "set" fields. 
@@ -611,39 +786,81 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
 
         if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
         {
-            const char *pszRaw = poFeature->GetFieldAsString( iField );
-
-            while( *pszRaw == ' ' )
-                pszRaw++;
-
-            char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
+            if (poFieldDefn->GetType() == OFTStringList )
+            {
+                char ** papszIter =  poFeature->GetFieldAsStringList( iField );
+                while( papszIter != NULL && *papszIter != NULL )
+                {
+                    char *pszEscaped = OGRGetXML_UTF8_EscapedString( *papszIter );
+                    GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
+                                  bRemoveAppPrefix, poFieldDefn, pszEscaped);
+                    CPLFree( pszEscaped );
 
-            if (poFieldDefn->GetType() == OFTReal)
+                    papszIter ++;
+                }
+            }
+            else if (poFieldDefn->GetType() == OFTIntegerList )
             {
-                /* Use point as decimal separator */
-                char* pszComma = strchr(pszEscaped, ',');
-                if (pszComma)
-                    *pszComma = '.';
+                int nCount = 0;
+                const int* panVals = poFeature->GetFieldAsIntegerList( iField, &nCount );
+                for(int i = 0; i < nCount; i++)
+                {
+                    GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
+                                  bRemoveAppPrefix, poFieldDefn, CPLSPrintf("%d", panVals[i]));
+                }
+            }
+            else if (poFieldDefn->GetType() == OFTRealList )
+            {
+                int nCount = 0;
+                const double* padfVals = poFeature->GetFieldAsDoubleList( iField, &nCount );
+                for(int i = 0; i < nCount; i++)
+                {
+                    char szBuffer[80];
+                    snprintf( szBuffer, sizeof(szBuffer), "%.15g", padfVals[i]);
+                    /* Use point as decimal separator */
+                    char* pszComma = strchr(szBuffer, ',');
+                    if (pszComma)
+                        *pszComma = '.';
+                    GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
+                                  bRemoveAppPrefix, poFieldDefn, szBuffer);
+                }
             }
+            else
+            {
+                const char *pszRaw = poFeature->GetFieldAsString( iField );
 
-            if (bWriteSpaceIndentation)
-                VSIFPrintfL(fp, "      ");
-            poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
-                             pszPrefix,
-                             poFieldDefn->GetNameRef(), pszEscaped,
-                             pszPrefix,
-                             poFieldDefn->GetNameRef());
-            CPLFree( pszEscaped );
+                char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
+
+                if (poFieldDefn->GetType() == OFTReal)
+                {
+                    /* Use point as decimal separator */
+                    char* pszComma = strchr(pszEscaped, ',');
+                    if (pszComma)
+                        *pszComma = '.';
+                }
+
+                GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
+                              bRemoveAppPrefix, poFieldDefn, pszEscaped);
+                CPLFree( pszEscaped );
+            }
         }
     }
 
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "    ");
-    poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() );
+    if( bRemoveAppPrefix )
+        poDS->PrintLine( fp, "</%s>", poFeatureDefn->GetName() );
+    else
+        poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() );
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "  ");
     if (bIsGML3Output)
-        poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix );
+    {
+        if( bRemoveAppPrefix )
+            poDS->PrintLine( fp, "</featureMember>" );
+        else
+            poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix );
+    }
     else
         poDS->PrintLine( fp, "</gml:featureMember>" );
 
@@ -663,6 +880,9 @@ int OGRGMLLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCreateField) )
         return bWriter && iNextGMLId == 0;
 
+    else if( EQUAL(pszCap,OLCCreateGeomField) )
+        return bWriter && iNextGMLId == 0;
+
     else if( EQUAL(pszCap,OLCFastGetExtent) )
     {
         double  dfXMin, dfXMax, dfYMin, dfYMax;
@@ -735,23 +955,45 @@ OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
+/*                          CreateGeomField()                           */
 /************************************************************************/
 
-OGRSpatialReference *OGRGMLLayer::GetSpatialRef()
+OGRErr OGRGMLLayer::CreateGeomField( OGRGeomFieldDefn *poField, int bApproxOK )
 
 {
-    return poSRS;
-}
+    if( !bWriter || iNextGMLId != 0 )
+        return OGRERR_FAILURE;
 
-/************************************************************************/
-/*                         GetGeometryColumn()                          */
-/************************************************************************/
+/* -------------------------------------------------------------------- */
+/*      Enforce XML naming semantics on element name.                   */
+/* -------------------------------------------------------------------- */
+    OGRGeomFieldDefn oCleanCopy( poField );
+    char *pszName = CPLStrdup( poField->GetNameRef() );
+    CPLCleanXMLElementName( pszName );
+    
+    if( strcmp(pszName,poField->GetNameRef()) != 0 )
+    {
+        if( !bApproxOK )
+        {
+            CPLFree( pszName );
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Unable to create field with name '%s', it would not\n"
+                      "be valid as an XML element name.",
+                      poField->GetNameRef() );
+            return OGRERR_FAILURE;
+        }
 
-const char* OGRGMLLayer::GetGeometryColumn()
-{
-    if( poFClass == NULL || poFClass->GetGeometryElement() == NULL )
-        return "";
+        oCleanCopy.SetName( pszName );
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "Field name '%s' adjusted to '%s' to be a valid\n"
+                  "XML element name.",
+                  poField->GetNameRef(), pszName );
+    }
 
-    return poFClass->GetGeometryElement();
+    CPLFree( pszName );
+
+    
+    poFeatureDefn->AddGeomFieldDefn( &oCleanCopy );
+
+    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.cpp b/ogr/ogrsf_frmts/gml/parsexsd.cpp
index f62fcc1..6a7fd7a 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.cpp
+++ b/ogr/ogrsf_frmts/gml/parsexsd.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: parsexsd.cpp 25731 2013-03-11 13:08:34Z tamas $
+ * $Id: parsexsd.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,6 +32,9 @@
 #include "cpl_error.h"
 #include "cpl_conv.h"
 #include "ogr_core.h"
+#include "cpl_string.h"
+#include "cpl_http.h"
+#include <set>
 
 /************************************************************************/
 /*                              StripNS()                               */
@@ -190,6 +194,22 @@ static int CheckMinMaxOccursCardinality(CPLXMLNode* psNode)
            (pszMaxOccurs == NULL || EQUAL(pszMaxOccurs, "1"));
 }
 
+/************************************************************************/
+/*                     GetListTypeFromSingleType()                      */
+/************************************************************************/
+
+static GMLPropertyType GetListTypeFromSingleType(GMLPropertyType eType)
+{
+    if( eType == GMLPT_String )
+        return GMLPT_StringList;
+    if( eType == GMLPT_Integer )
+        return GMLPT_IntegerList;
+    if( eType == GMLPT_Real )
+        return GMLPT_RealList;
+    if( eType == GMLPT_FeatureProperty )
+        return GMLPT_FeaturePropertyList;
+    return eType;
+}
 
 /************************************************************************/
 /*                      ParseFeatureType()                              */
@@ -310,6 +330,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
         /* not as a simpleType definition */
         const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
         const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
+        const char* pszMaxOccurs = CPLGetXMLValue( psAttrDef, "maxOccurs", NULL );
         if (pszType != NULL)
         {
             const char* pszStrippedNSType = StripNS(pszType);
@@ -317,7 +338,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 
             GMLPropertyType gmlType = GMLPT_Untyped;
             if (EQUAL(pszStrippedNSType, "string") ||
-                EQUAL(pszStrippedNSType, "Character"))
+                EQUAL(pszStrippedNSType, "Character") ||
+                EQUAL(pszStrippedNSType, "boolean"))
                 gmlType = GMLPT_String;
             /* TODO: Would be nice to have a proper date type */
             else if (EQUAL(pszStrippedNSType, "date") ||
@@ -333,6 +355,10 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                      EQUAL(pszStrippedNSType, "integer") ||
                      EQUAL(pszStrippedNSType, "long"))
                 gmlType = GMLPT_Integer;
+            else if (strcmp(pszType, "gml:FeaturePropertyType") == 0 )
+            {
+                gmlType = GMLPT_FeatureProperty;
+            }
             else if (strncmp(pszType, "gml:", 4) == 0)
             {
                 const AssocNameType* psIter = apsPropertyTypes;
@@ -340,19 +366,11 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 {
                     if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                     {
-                        if (poClass->GetGeometryAttributeIndex() != -1)
-                        {
-                            CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
-                        }
-                        else
-                        {
-                            poClass->SetGeometryElement(pszElementName);
-                            poClass->SetGeometryType(psIter->eType);
-                            poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                            pszElementName, pszElementName, psIter->eType, nAttributeIndex ) );
+
+                        nAttributeIndex ++;
 
-                            nAttributeIndex ++;
-                        }
-                        
                         break;
                     }
 
@@ -367,7 +385,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                     return NULL;
                 }
 
-                if (poClass->GetGeometryAttributeIndex() == -1)
+                if (poClass->GetGeometryPropertyCount() == 0)
                     bGotUnrecognizedType = TRUE;
 
                 continue;
@@ -377,9 +395,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
             {
-                poClass->SetGeometryElement(pszElementName);
-                poClass->SetGeometryType(wkbMultiPoint);
-                poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPoint, nAttributeIndex ) );
 
                 nAttributeIndex ++;
                 continue;
@@ -387,9 +404,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
             {
-                poClass->SetGeometryElement(pszElementName);
-                poClass->SetGeometryType(wkbMultiLineString);
-                poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiLineString, nAttributeIndex ) );
 
                 nAttributeIndex ++;
                 continue;
@@ -398,9 +414,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                      strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
             {
-                poClass->SetGeometryElement(pszElementName);
-                poClass->SetGeometryType(wkbMultiPolygon);
-                poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex ) );
 
                 nAttributeIndex ++;
                 continue;
@@ -409,9 +424,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */
             else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0)
             {
-                poClass->SetGeometryElement(pszElementName);
-                poClass->SetGeometryType(wkbMultiPolygon);
-                poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex ) );
 
                 nAttributeIndex ++;
                 continue;
@@ -431,11 +445,18 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 
             if (pszElementName == NULL)
                 pszElementName = "unnamed";
+            const char* pszPropertyName = pszElementName;
+            if( gmlType == GMLPT_FeatureProperty )
+            {
+                pszPropertyName = CPLSPrintf("%s_href", pszElementName);
+            }
             GMLPropertyDefn *poProp = new GMLPropertyDefn(
-                pszElementName, pszElementName );
+                pszPropertyName, pszElementName );
+
+            if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "unbounded") == 0 )
+                gmlType = GetListTypeFromSingleType(gmlType);
 
             poProp->SetType( gmlType );
-            poProp->SetAttributeIndex( nAttributeIndex );
             poProp->SetWidth( nWidth );
             poProp->SetPrecision( nPrecision );
 
@@ -461,15 +482,15 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 {
                     if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                     {
-                        if (poClass->GetGeometryAttributeIndex() != -1)
+                        if (poClass->GetGeometryPropertyCount() > 0)
                         {
                             OGRwkbGeometryType eNewType = psIter->eType;
-                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryType();
+                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryProperty(0)->GetType();
                             if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
                                 (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
                                 (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
                             {
-                                poClass->SetGeometryType(eNewType);
+                                poClass->GetGeometryProperty(0)->SetType(eNewType);
                             }
                             else
                             {
@@ -478,9 +499,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                         }
                         else
                         {
-                            poClass->SetGeometryElement(pszElementName);
-                            poClass->SetGeometryType(psIter->eType);
-                            poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                            poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                                pszElementName, pszElementName, psIter->eType, nAttributeIndex ) );
 
                             nAttributeIndex ++;
                         }
@@ -499,7 +519,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                     return NULL;
                 }
 
-                if (poClass->GetGeometryAttributeIndex() == -1)
+                if (poClass->GetGeometryPropertyCount() == 0)
                     bGotUnrecognizedType = TRUE;
 
                 continue;
@@ -524,9 +544,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 CheckMinMaxOccursCardinality(psComplexTypeSequence) &&
                 strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 )
             {
-                poClass->SetGeometryElement(pszElementName);
-                poClass->SetGeometryType(wkbUnknown);
-                poClass->SetGeometryAttributeIndex( nAttributeIndex );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbUnknown, nAttributeIndex ) );
 
                 nAttributeIndex ++;
 
@@ -548,10 +567,13 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
         GMLPropertyType eType = GMLPT_Untyped;
         int nWidth = 0, nPrecision = 0;
         GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision);
+
+        if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "unbounded") == 0 )
+            eType = GetListTypeFromSingleType(eType);
+
         poProp->SetType( eType );
         poProp->SetWidth( nWidth );
         poProp->SetPrecision( nPrecision );
-        poProp->SetAttributeIndex( nAttributeIndex );
 
         if (poClass->AddProperty( poProp ) < 0)
             delete poProp;
@@ -559,13 +581,12 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             nAttributeIndex ++;
     }
 
-    /* Only report wkbNone if we didn't find a known geometry type */
-    /* and there were not any unknown types (in case this unknown type */
-    /* would be a geometry type) */
-    if (poClass->GetGeometryAttributeIndex() == -1 &&
-        !bGotUnrecognizedType)
+    /* If we have found an unknown types, let's be on the side of caution and */
+    /* create a geometry field */
+    if( poClass->GetGeometryPropertyCount() == 0 &&
+        bGotUnrecognizedType )
     {
-        poClass->SetGeometryType(wkbNone);
+        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown ) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -577,6 +598,154 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 }
 
 /************************************************************************/
+/*                         GMLParseXMLFile()                            */
+/************************************************************************/
+
+static
+CPLXMLNode* GMLParseXMLFile(const char* pszFilename)
+{
+    if( strncmp(pszFilename, "http://", 7) == 0 ||
+        strncmp(pszFilename, "https://", 8) == 0 )
+    {
+        CPLXMLNode* psRet = NULL;
+        CPLHTTPResult* psResult = CPLHTTPFetch( pszFilename, NULL );
+        if( psResult != NULL )
+        {
+            if( psResult->pabyData != NULL )
+            {
+                psRet = CPLParseXMLString( (const char*) psResult->pabyData );
+            }
+            CPLHTTPDestroyResult(psResult);
+        }
+        return psRet;
+    }
+    else
+    {
+        return CPLParseXMLFile(pszFilename);
+    }
+}
+
+/************************************************************************/
+/*                       CPLGetFirstChildNode()                         */
+/************************************************************************/
+
+static
+CPLXMLNode* CPLGetFirstChildNode( CPLXMLNode* psNode )
+{
+    if( psNode == NULL )
+        return NULL;
+    CPLXMLNode* psIter = psNode->psChild;
+    while( psIter != NULL )
+    {
+        if( psIter->eType == CXT_Element )
+            return psIter;
+        psIter = psIter->psNext;
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                          CPLGetLastNode()                            */
+/************************************************************************/
+
+static
+CPLXMLNode* CPLGetLastNode( CPLXMLNode* psNode )
+{
+    if( psNode == NULL )
+        return NULL;
+    CPLXMLNode* psIter = psNode;
+    while( psIter->psNext != NULL )
+        psIter = psIter->psNext;
+    return psIter;
+}
+
+/************************************************************************/
+/*                       CPLXMLSchemaResolveInclude()                   */
+/************************************************************************/
+
+static
+void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
+                                 CPLXMLNode *psSchemaNode )
+{
+    std::set<CPLString> osAlreadyIncluded;
+
+    int bTryAgain;
+    do
+    {
+        CPLXMLNode *psThis;
+        CPLXMLNode *psLast = NULL;
+        bTryAgain = FALSE;
+
+        for( psThis = psSchemaNode->psChild; 
+            psThis != NULL; psThis = psThis->psNext )
+        {
+            if( psThis->eType == CXT_Element &&
+                EQUAL(psThis->pszValue,"include") )
+            {
+                const char* pszSchemaLocation = 
+                        CPLGetXMLValue(psThis, "schemaLocation", NULL);
+                if( pszSchemaLocation != NULL &&
+                    osAlreadyIncluded.count( pszSchemaLocation) == 0 )
+                {
+                    osAlreadyIncluded.insert( pszSchemaLocation );
+
+                    if( strncmp(pszSchemaLocation, "http://", 7) != 0 &&
+                        strncmp(pszSchemaLocation, "https://", 8) != 0 &&
+                        CPLIsFilenameRelative(pszSchemaLocation ) )
+                    {
+                        pszSchemaLocation = CPLFormFilename(
+                            CPLGetPath(pszMainSchemaLocation), pszSchemaLocation, NULL );
+                    }
+
+                    CPLXMLNode *psIncludedXSDTree =
+                                GMLParseXMLFile( pszSchemaLocation );
+                    if( psIncludedXSDTree != NULL )
+                    {
+                        CPLStripXMLNamespace( psIncludedXSDTree, NULL, TRUE );
+                        CPLXMLNode *psIncludedSchemaNode =
+                                CPLGetXMLNode( psIncludedXSDTree, "=schema" );
+                        if( psIncludedSchemaNode != NULL )
+                        {
+                            /* Substitute de <include> node by its content */
+                            CPLXMLNode* psFirstChildElement =
+                                CPLGetFirstChildNode(psIncludedSchemaNode);
+                            if( psFirstChildElement != NULL )
+                            {
+                                CPLXMLNode* psCopy = CPLCloneXMLTree(psFirstChildElement);
+                                if( psLast != NULL )
+                                    psLast->psNext = psCopy;
+                                else
+                                    psSchemaNode->psChild = psCopy;
+                                CPLXMLNode* psNext = psThis->psNext;
+                                psThis->psNext = NULL;
+                                CPLDestroyXMLNode(psThis);
+                                psThis = CPLGetLastNode(psCopy);
+                                psThis->psNext = psNext;
+
+                                /* In case the included schema also contains */
+                                /* includes */
+                                bTryAgain = TRUE;
+                            }
+
+                        }
+                        CPLDestroyXMLNode( psIncludedXSDTree );
+                    }
+                }
+            }
+
+            psLast = psThis;
+        }
+    } while( bTryAgain );
+
+    const char* pszSchemaOutputName =
+        CPLGetConfigOption("GML_SCHEMA_OUTPUT_NAME", NULL);
+    if( pszSchemaOutputName != NULL )
+    {
+        CPLSerializeXMLTreeToFile( psSchemaNode, pszSchemaOutputName );
+    }
+}
+
+/************************************************************************/
 /*                          GMLParseXSD()                               */
 /************************************************************************/
 
@@ -590,7 +759,7 @@ int GMLParseXSD( const char *pszFile,
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psXSDTree = CPLParseXMLFile( pszFile );
+    CPLXMLNode *psXSDTree = GMLParseXMLFile( pszFile );
     
     if( psXSDTree == NULL )
         return FALSE;
@@ -611,6 +780,13 @@ int GMLParseXSD( const char *pszFile,
     }
 
 /* ==================================================================== */
+/*      Process each include directive.                                 */
+/* ==================================================================== */
+    CPLXMLSchemaResolveInclude( pszFile, psSchemaNode );
+
+    //CPLSerializeXMLTreeToFile(psSchemaNode, "/vsistdout/");
+
+/* ==================================================================== */
 /*      Process each feature class definition.                          */
 /* ==================================================================== */
     CPLXMLNode *psThis;
@@ -678,6 +854,17 @@ int GMLParseXSD( const char *pszFile,
             /* without any _Type or Type suffix */
             /* e.g. : http://apollo.erdas.com/erdas-apollo/vector/Cherokee?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=iwfs:Air */
         }
+
+        /* <element name="RekisteriyksikonPalstanTietoja" type="ktjkiiwfs:PalstanTietojaType" substitutionGroup="gml:_Feature" /> */
+        else if(  strlen(pszType) > 4 &&
+                  strcmp(pszType + strlen(pszType) - 4, "Type") == 0 &&
+                  strlen(pszName) > strlen(pszType) - 4 &&
+                  strncmp(pszName + strlen(pszName) - (strlen(pszType) - 4),
+                          pszType,
+                          strlen(pszType) - 4) == 0 )
+        {
+        }
+
         else if( !EQUALN(pszType,pszName,strlen(pszName))
             || !(EQUAL(pszType+strlen(pszName),"_Type") ||
                     EQUAL(pszType+strlen(pszName),"Type")) )
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.h b/ogr/ogrsf_frmts/gml/parsexsd.h
index 89e198b..6ae0d8a 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.h
+++ b/ogr/ogrsf_frmts/gml/parsexsd.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: parsexsd.h 20341 2010-08-17 20:27:09Z rouault $
+ * $Id: parsexsd.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
index b30d1ab..984bb9b 100644
--- a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
+++ b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $
+ * $Id: resolvexlinks.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::ResolveXlinks() method.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Chaitanya kumar CH
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "gmlreader.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $");
+CPL_CVSID("$Id: resolvexlinks.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #include "gmlreaderp.h"
 #include "cpl_conv.h"
@@ -269,11 +270,12 @@ static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
                               && pszURL[nPathLen - 1] != '\\';
                  nPathLen--);
 
-            if( strncmp( pszURL, psChild->psChild->pszValue, nPathLen ) != 0 )
+            const char* pszDash = strchr( psChild->psChild->pszValue, '#' );
+            if( pszDash != NULL &&
+                strncmp( pszURL, psChild->psChild->pszValue, nPathLen ) != 0 )
             {
             //different path
-                int nURLLen = strchr( psChild->psChild->pszValue, '#' ) -
-                              psChild->psChild->pszValue;
+                int nURLLen = pszDash - psChild->psChild->pszValue;
                 char *pszURLWithoutID = (char *)CPLMalloc( (nURLLen+1) * sizeof(char));
                 strncpy( pszURLWithoutID, psChild->psChild->pszValue, nURLLen );
                 pszURLWithoutID[nURLLen] = '\0';
diff --git a/ogr/ogrsf_frmts/gmt/ogr_gmt.h b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
index a0bfd60..a38d9e3 100644
--- a/ogr/ogrsf_frmts/gmt/ogr_gmt.h
+++ b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
@@ -86,8 +86,6 @@ class OGRGmtLayer : public OGRLayer
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     int                 TestCapability( const char * );
 };
 
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
index 0cd5590..6e76328 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
@@ -161,6 +161,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     if( osGeometryType == "POINT" )
         poFeatureDefn->SetGeomType( wkbPoint );
@@ -647,6 +648,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 /*      Create feature.                                                 */
 /* -------------------------------------------------------------------- */
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    poGeom->assignSpatialReference(poSRS);
     poFeature->SetGeometryDirectly( poGeom );
     poFeature->SetFID( iNextFID++ );
 
@@ -1085,13 +1087,3 @@ OGRErr OGRGmtLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
         }
     }
 }
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRGmtLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
diff --git a/ogr/ogrsf_frmts/gpkg/GNUmakefile b/ogr/ogrsf_frmts/gpkg/GNUmakefile
new file mode 100644
index 0000000..04f807c
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/GNUmakefile
@@ -0,0 +1,21 @@
+
+include ../../../GDALmake.opt
+
+OBJ	= ogrgeopackagedriver.o ogrgeopackagedatasource.o ogrgeopackagelayer.o ogrgeopackageutility.o
+
+ifeq ($(SQLITE_HAS_COLUMN_METADATA),yes)
+CPPFLAGS +=  -DSQLITE_HAS_COLUMN_METADATA
+endif
+
+CPPFLAGS := -I.. $(GDAL_INCLUDE) $(SQLITE_INC) $(CPPFLAGS)
+
+default: $(O_OBJ:.o=.$(OBJ_EXT))
+
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ): ogr_geopackage.h ogrgeopackageutility.h
+
+
+
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
new file mode 100644
index 0000000..2cdc345
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
@@ -0,0 +1,105 @@
+<html>
+<head>
+<title>GeoPackage</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>GeoPackage</h1>
+
+<p>This driver implements support for access to spatial tables in the 
+<a href="http://opengis.github.io/geopackage/">OGC GeoPackage format standard</a>.
+The GeoPackage standard uses a SQLite database file as a generic container, and the standard defines:
+</p>
+<ul>
+  <li>Expected metadata tables (<code>gpkg_contents</code>, <code>gpkg_spatial_ref_sys</code>, <code>gpkg_geometry_columns</code>)</li>
+  <li>Binary format encoding for geometries in spatial tables (basically a GPKG standard header object followed by ISO standard well-known binary (WKB))</li>
+  <li>Naming and conventions for extensions (extended feature types) and indexes (how to use SQLite r-tree in an interoperable manner)</li>
+</ul>
+<p>This driver reads and writes SQLite files from the file system, so it must be run by a user with read/write access to the files it is working with.</p>
+
+<h2>Limitations</h2>
+
+<ul>
+<li>GeoPackage only supports one geometry column per table.</li>
+<li>This driver does not currently implement the GeoPackage index extension.</li>
+<li>GeoPackage does not currently support non-spatial tables.</li>
+</ul>
+
+<h2>SQL</h2>
+
+<p>The driver supports OGR attribute filters, and users are expected
+  to provide filters in the SQLite dialect, as they will be executed directly
+  against the database.
+</p>
+
+<h2>Creation Issues</h2>
+
+<p>When creating a new GeoPackage file, the driver will attempt to
+  force the database into a UTF-8 mode for text handling, satisfying 
+  the OGR strict UTF-8 capability. For pre-existing files, the driver
+  will work with whatever it's given.</p>
+
+<h3>Dataset Creation Options</h3>
+
+<p>None</p>
+
+<h3>Layer Creation Options</h3>
+
+<ul>
+<li><b>GEOMETRY_COLUMN</b>: Column to use for the geometry column.</li>
+<li><b>FID</b>: Column name to use for the OGR FID (primary key in the SQLite database).</li>
+<li><b>OVERWRITE</b>: If set to "YES" will delete any existing layers that have the same name as the layer being created.</li>
+<li><b>SPATIAL_INDEX</b>: [NOT IMPLEMENTED] If set to "YES" will create a spatial index for this layer.</li>
+
+</ul>
+
+<h3>Examples</h3>
+
+<ul>
+<li>
+Simple translation of a single shapefile into GeoPackage.  The table 'abc' will
+be created with the features from abc.shp and attributes from abc.dbf. 
+The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as it will be created.
+<pre>
+% ogr2ogr -f GPKG filename.gpkg abc.shp
+</pre>
+</li>
+
+<li>
+Translation of a directory of shapefiles into a GeoSpackage. Each file will end
+up as a new table within the GPKG file.
+The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as it will be created.
+<pre>
+% ogr2ogr -f GPKG filename.gpkg ./path/to/dir
+</pre>
+</li>
+
+<li>
+Translation of a PostGIS database into a GeoPackage. Each table in the database will end up
+as a table in the GPKG file.
+The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as it will be created.
+<pre>
+% ogr2ogr -f GPKG filename.gpkg PG:'dbname=mydatabase host=localhost'
+</pre>
+</li>
+
+</ul>
+
+<h3>FAQs</h3>
+
+<ul>
+  <li> <b>...</b><br>
+...
+</li>
+</ul>
+
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://sqlite.org/">SQLite</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/gpkg/makefile.vc b/ogr/ogrsf_frmts/gpkg/makefile.vc
new file mode 100644
index 0000000..6cd8c0a
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/makefile.vc
@@ -0,0 +1,21 @@
+
+OBJ	=	ogrgeopackagedriver.obj ogrgeopackagedatasource.obj \
+        ogrgeopackagelayer.obj ogrgeopackageutility.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS = -I.. -I..\.. $(SQLITE_INC) $(SPATIALITE_412_OR_LATER_EXTRAFLAGS)
+
+!IFDEF SPATIALITE_412_OR_LATER
+SPATIALITE_412_OR_LATER_EXTRAFLAGS = -DSPATIALITE_412_OR_LATER
+!ENDIF
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
+	-del *.exe
+
diff --git a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
new file mode 100644
index 0000000..15133fd
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
@@ -0,0 +1,179 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Definition of classes for OGR GeoPackage driver.
+ * Author:   Paul Ramsey, pramsey at boundlessgeo.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_GEOPACKAGE_H_INCLUDED
+#define _OGR_GEOPACKAGE_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "sqlite3.h"
+
+#define UNDEFINED_SRID 0
+
+/************************************************************************/
+/*                           OGRGeoPackageDriver                        */
+/************************************************************************/
+
+class OGRGeoPackageDriver : public OGRSFDriver
+{
+    public:
+                            ~OGRGeoPackageDriver();
+        const char*         GetName();
+        OGRDataSource*      Open( const char *, int );
+        OGRDataSource*      CreateDataSource( const char * pszFilename, char **papszOptions );
+        OGRErr              DeleteDataSource( const char * pszFilename );
+        int                 TestCapability( const char * );
+};
+
+
+/************************************************************************/
+/*                           OGRGeoPackageDataSource                    */
+/************************************************************************/
+
+class OGRGeoPackageDataSource : public OGRDataSource
+{
+    char*               m_pszFileName;
+    OGRLayer**          m_papoLayers;
+    int                 m_nLayers;
+    int                 m_bUpdate;
+    int                 m_bUtf8;
+    sqlite3*            m_poDb;
+    
+    
+    public:
+                            OGRGeoPackageDataSource();
+                            ~OGRGeoPackageDataSource();
+
+        virtual const char* GetName() { return m_pszFileName; }
+        virtual int         GetLayerCount() { return m_nLayers; }
+        int                 Open( const char * pszFilename, int bUpdate );
+        int                 Create( const char * pszFilename, char **papszOptions );
+        OGRLayer*           GetLayer( int iLayer );
+        int                 DeleteLayer( int iLayer );
+        OGRLayer*           CreateLayer( const char * pszLayerName,
+                                         OGRSpatialReference * poSpatialRef,
+                                         OGRwkbGeometryType eGType,
+                                         char **papszOptions );
+        int                 TestCapability( const char * );
+
+        virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect );
+        virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+        int                 IsUpdatable() { return m_bUpdate; }
+        int                 GetSrsId( const OGRSpatialReference * poSRS );
+        const char*         GetSrsName( const OGRSpatialReference * poSRS );
+        OGRSpatialReference* GetSpatialRef( int iSrsId );
+        sqlite3*            GetDatabaseHandle();
+        virtual int         GetUTF8() { return m_bUtf8; }
+        OGRErr              AddColumn( const char * pszTableName, 
+                                       const char * pszColumnName, 
+                                       const char * pszColumnType );
+
+    private:
+    
+        OGRErr              PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected);
+        bool                CheckApplicationId(const char * pszFileName);
+        OGRErr              SetApplicationId();
+    
+};
+
+
+/************************************************************************/
+/*                           OGRGeoPackageLayer                         */
+/************************************************************************/
+
+class OGRGeoPackageLayer : public OGRLayer
+{
+    char*                       m_pszTableName;
+    char*                       m_pszFidColumn;
+    int                         m_iSrs;
+    OGRGeoPackageDataSource*    m_poDS;
+    OGREnvelope*                m_poExtent;
+    CPLString                   m_soColumns;
+    CPLString                   m_soFilter;
+    OGRBoolean                  m_bExtentChanged;
+    OGRFeatureDefn*             m_poFeatureDefn;
+    sqlite3_stmt*               m_poQueryStatement;
+    sqlite3_stmt*               m_poUpdateStatement;
+    sqlite3_stmt*               m_poInsertStatement;
+    sqlite3_stmt*               m_poFidStatement;    
+    
+    public:
+    
+                        OGRGeoPackageLayer( OGRGeoPackageDataSource *poDS,
+                                            const char * pszTableName );
+                        ~OGRGeoPackageLayer();
+
+    /************************************************************************/
+    /* OGR API methods */
+                        
+    OGRFeatureDefn*     GetLayerDefn() { return m_poFeatureDefn; }
+    int                 TestCapability( const char * );
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    void                ResetReading();
+	OGRErr				CreateFeature( OGRFeature *poFeater );
+    OGRErr              SetFeature( OGRFeature *poFeature );
+    OGRErr              DeleteFeature(long nFID);
+    OGRErr              SetAttributeFilter( const char *pszQuery );
+    OGRErr              SyncToDisk();
+    OGRFeature*         GetNextFeature();
+    OGRFeature*         GetFeature(long nFID);
+    const char*         GetFIDColumn();	
+    OGRErr              StartTransaction();
+    OGRErr              CommitTransaction();
+    OGRErr              RollbackTransaction();
+    int                 GetFeatureCount( int );
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    
+    // void                SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn );
+
+    OGRErr              ReadTableDefinition();
+
+    /************************************************************************/
+    /* GPKG methods */
+    
+    private:
+    
+    OGRErr              ReadFeature( sqlite3_stmt *poQuery, OGRFeature **ppoFeature );
+    OGRErr              UpdateExtent( const OGREnvelope *poExtent );
+    OGRErr              SaveExtent();
+    OGRErr              BuildColumns();
+    OGRBoolean          IsGeomFieldSet( OGRFeature *poFeature );
+    CPLString           FeatureGenerateUpdateSQL( OGRFeature *poFeature );
+    CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature );
+    OGRErr              FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt );
+    OGRErr              FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt );
+    OGRErr              FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount );
+
+};
+
+
+
+#endif /* _OGR_GEOPACKAGE_H_INCLUDED */
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
new file mode 100644
index 0000000..68c6de9
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -0,0 +1,1102 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Implements OGRGeoPackageDataSource class
+ * Author:   Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFpszFileNameTWARE.
+ ****************************************************************************/
+
+#include "ogr_geopackage.h"
+#include "ogrgeopackageutility.h"
+
+/* 1.1.1: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the application id */
+/* http://opengis.github.io/geopackage/#_file_format */
+/* 0x47503130 = 1196437808 */
+#define GPKG_APPLICATION_ID 1196437808
+
+/* "GP10" in ASCII bytes */
+static const char aGpkgId[4] = {0x47, 0x50, 0x31, 0x30};
+static const size_t szGpkgIdPos = 68;
+
+/* Cannnot count on the "PRAGMA application_id" command existing */
+/* it is a very recent addition to SQLite. */
+bool OGRGeoPackageDataSource::CheckApplicationId(const char * pszFileName)
+{
+    CPLAssert( m_poDb == NULL );
+    
+    char aFileId[4];
+
+    VSILFILE *fp = VSIFOpenL( pszFileName, "rb" );
+
+    /* Should never happen (always called after existence check) but just in case */
+    if ( ! fp ) return FALSE;
+
+    /* application_id is 4 bytes at offset 68 in the header */
+    VSIFSeekL(fp, szGpkgIdPos, SEEK_SET);
+    VSIFReadL(aFileId, 4, 1, fp);
+
+    VSIFCloseL(fp);
+    
+    for ( int i = 0; i < 4; i++ )
+    {
+        if ( aFileId[i] != aGpkgId[i] )
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/* Only recent versions of SQLite will let us muck with application_id */
+/* via a PRAGMA statement, so we have to write directly into the */
+/* file header here. */
+/* We do this at the *end* of initialization so that there is */
+/* data to write down to a file, and we'll have a writeable file */
+/* once we close the SQLite connection */
+OGRErr OGRGeoPackageDataSource::SetApplicationId()
+{
+    CPLAssert( m_poDb != NULL );
+    CPLAssert( m_pszFileName != NULL );
+
+    /* Have to flush the file before f***ing with the header */
+    sqlite3_close(m_poDb);
+    m_poDb = NULL;
+
+    size_t szWritten = 0;
+
+    /* Open for modification, write to application id area */
+    VSILFILE *pfFile = VSIFOpenL( m_pszFileName, "rb+" );
+    if( pfFile == NULL )
+        return OGRERR_FAILURE;
+    VSIFSeekL(pfFile, szGpkgIdPos, SEEK_SET);
+    szWritten = VSIFWriteL(aGpkgId, 1, 4, pfFile);
+    VSIFCloseL(pfFile);
+
+    /* If we didn't write out exactly four bytes, something */
+    /* terrible has happened */
+    if ( szWritten != 4 )
+    {
+        return OGRERR_FAILURE;
+    }
+
+    /* And re-open the file */
+    if ( sqlite3_open(m_pszFileName, &m_poDb) != SQLITE_OK )
+        return OGRERR_FAILURE;
+
+    return OGRERR_NONE;
+}
+
+
+/* Returns the first row of first column of SQL as integer */
+OGRErr OGRGeoPackageDataSource::PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected)
+{
+    CPLAssert( pszPragma != NULL );
+    CPLAssert( pszExpected != NULL );
+    CPLAssert( nRowsExpected >= 0 );
+    
+    char *pszErrMsg = NULL;
+    int nRowCount, nColCount, rc;
+    char **papszResult;
+
+    rc = sqlite3_get_table(
+        m_poDb,
+        CPLSPrintf("PRAGMA %s", pszPragma),
+        &papszResult, &nRowCount, &nColCount, &pszErrMsg );
+    
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "unable to execute PRAGMA %s", pszPragma);
+        return OGRERR_FAILURE;
+    }
+    
+    if ( nRowCount != nRowsExpected )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "bad result for PRAGMA %s, got %d rows, expected %d", pszPragma, nRowCount, nRowsExpected);
+        return OGRERR_FAILURE;        
+    }
+    
+    if ( nRowCount > 0 && ! EQUAL(papszResult[1], pszExpected) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "invalid %s (expected '%s', got '%s')",
+                  pszPragma, pszExpected, papszResult[1]);
+        return OGRERR_FAILURE;
+    }
+    
+    sqlite3_free_table(papszResult);
+    
+    return OGRERR_NONE; 
+}
+
+
+OGRSpatialReference* OGRGeoPackageDataSource::GetSpatialRef(int iSrsId)
+{
+    SQLResult oResult;
+    
+    /* Should we do something special with undefined SRS ? */
+    if( iSrsId == 0 || iSrsId == -1 )
+    {
+        return NULL;
+    }
+    
+    CPLString oSQL;
+    oSQL.Printf("SELECT definition FROM gpkg_spatial_ref_sys WHERE srs_id = %d", iSrsId);
+    
+    OGRErr err = SQLQuery(m_poDb, oSQL.c_str(), &oResult);
+
+    if ( err != OGRERR_NONE || oResult.nRowCount != 1 )
+    {
+        SQLResultFree(&oResult);
+        CPLError( CE_Warning, CPLE_AppDefined, "unable to read srs_id '%d' from gpkg_spatial_ref_sys",
+                  iSrsId);
+        return NULL;
+    }
+    
+    const char *pszWkt = SQLResultGetValue(&oResult, 0, 0);
+    if ( ! pszWkt )
+    {
+        SQLResultFree(&oResult);
+        CPLError( CE_Warning, CPLE_AppDefined, "null definition for srs_id '%d' in gpkg_spatial_ref_sys",
+                  iSrsId);
+        return NULL;
+    }
+    
+    OGRSpatialReference *poSpatialRef = new OGRSpatialReference(pszWkt);
+    
+    if ( poSpatialRef == NULL )
+    {
+        SQLResultFree(&oResult);
+        CPLError( CE_Warning, CPLE_AppDefined, "unable to parse srs_id '%d' well-known text '%s'",
+                  iSrsId, pszWkt);
+        return NULL;
+    }
+    
+    SQLResultFree(&oResult);
+    return poSpatialRef;
+}
+
+const char * OGRGeoPackageDataSource::GetSrsName(const OGRSpatialReference * poSRS)
+{
+    const OGR_SRSNode *node;
+    
+    /* Projected coordinate system? */
+    if ( (node = poSRS->GetAttrNode("PROJCS")) )
+    {
+        return node->GetChild(0)->GetValue();
+    }
+    /* Geographic coordinate system? */
+    else if ( (node = poSRS->GetAttrNode("GEOGCS")) )
+    {
+        return node->GetChild(0)->GetValue();
+    }
+    /* Something odd! return empty. */
+    else
+    {
+        return "Unnamed SRS";
+    }
+}
+
+int OGRGeoPackageDataSource::GetSrsId(const OGRSpatialReference * cpoSRS)
+{
+    char *pszWKT = NULL;
+    char *pszSQL = NULL;
+    int nSRSId = UNDEFINED_SRID;
+    const char* pszAuthorityName;
+    int nAuthorityCode = 0;
+    OGRErr err;
+    OGRBoolean bCanUseAuthorityCode = FALSE;
+
+    if( cpoSRS == NULL )
+        return UNDEFINED_SRID;
+
+    OGRSpatialReference *poSRS = cpoSRS->Clone();
+
+    poSRS->morphFromESRI();
+    pszAuthorityName = poSRS->GetAuthorityName(NULL);
+
+    if ( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
+    {
+        // Try to force identify an EPSG code                                    
+        poSRS->AutoIdentifyEPSG();
+
+        pszAuthorityName = poSRS->GetAuthorityName(NULL);
+        if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
+        {
+            const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
+            if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
+            {
+                /* Import 'clean' SRS */
+                poSRS->importFromEPSG( atoi(pszAuthorityCode) );
+
+                pszAuthorityName = poSRS->GetAuthorityName(NULL);
+            }
+        }
+    }
+    // Check whether the EPSG authority code is already mapped to a
+    // SRS ID.                                                         
+    if ( pszAuthorityName != NULL && strlen(pszAuthorityName) > 0 )
+    {
+        // For the root authority name 'EPSG', the authority code
+        // should always be integral
+        nAuthorityCode = atoi( poSRS->GetAuthorityCode(NULL) );
+
+        pszSQL = sqlite3_mprintf(
+                         "SELECT srs_id FROM gpkg_spatial_ref_sys WHERE "
+                         "upper(organization) = upper('%q') AND organization_coordsys_id = %d",
+                         pszAuthorityName, nAuthorityCode );
+        
+        nSRSId = SQLGetInteger(m_poDb, pszSQL, &err);
+        sqlite3_free(pszSQL);
+        
+        // Got a match? Return it!
+        if ( OGRERR_NONE == err )
+        {
+            delete poSRS;
+            return nSRSId;
+        }
+        
+        // No match, but maybe we can use the nAuthorityCode as the nSRSId?
+        pszSQL = sqlite3_mprintf(
+                         "SELECT Count(*) FROM gpkg_spatial_ref_sys WHERE "
+                         "srs_id = %d", nAuthorityCode );
+        
+        // Yep, we can!
+        if ( ! SQLGetInteger(m_poDb, pszSQL, &err) && err == OGRERR_NONE )
+            bCanUseAuthorityCode = TRUE;
+    }
+
+    // Translate SRS to WKT.                                           
+    if( poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
+    {
+        delete poSRS;
+        CPLFree(pszWKT);
+        return UNDEFINED_SRID;
+    }
+
+    // Reuse the authority code number as SRS_ID if we can
+    if ( bCanUseAuthorityCode )
+    {
+        nSRSId = nAuthorityCode;
+    }
+    // Otherwise, generate a new SRS_ID number (max + 1)
+    else
+    {
+        // Get the current maximum srid in the srs table.                  
+        int nMaxSRSId = SQLGetInteger(m_poDb, "SELECT MAX(srs_id) FROM gpkg_spatial_ref_sys", &err);
+        if ( OGRERR_NONE != err )
+        {
+            CPLFree(pszWKT);
+            delete poSRS;
+            return UNDEFINED_SRID;        
+        }
+
+        nSRSId = nMaxSRSId + 1;
+    }
+    
+    // Add new SRS row to gpkg_spatial_ref_sys
+    if( pszAuthorityName != NULL && nAuthorityCode > 0 )
+    {
+        pszSQL = sqlite3_mprintf(
+                 "INSERT INTO gpkg_spatial_ref_sys "
+                 "(srs_name,srs_id,organization,organization_coordsys_id,definition) "
+                 "VALUES ('%s', %d, upper('%s'), %d, '%q')",
+                 GetSrsName(poSRS), nSRSId, pszAuthorityName, nAuthorityCode, pszWKT
+                 );
+    }
+    else
+    {
+        pszSQL = sqlite3_mprintf(
+                 "INSERT INTO gpkg_spatial_ref_sys "
+                 "(srs_name,srs_id,organization,organization_coordsys_id,definition) "
+                 "VALUES ('%s', %d, upper('%s'), %d, '%q')",
+                 GetSrsName(poSRS), nSRSId, "NONE", nSRSId, pszWKT
+                 );
+    }
+
+    // Add new row to gpkg_spatial_ref_sys
+    err = SQLCommand(m_poDb, pszSQL);
+
+    // Free everything that was allocated.
+    CPLFree(pszWKT);    
+    sqlite3_free(pszSQL);
+    delete poSRS;
+    
+    return nSRSId;
+}
+
+
+/************************************************************************/
+/*                        OGRGeoPackageDataSource()                     */
+/************************************************************************/
+
+OGRGeoPackageDataSource::OGRGeoPackageDataSource()
+{
+    m_pszFileName = NULL;
+    m_papoLayers = NULL;
+    m_nLayers = 0;
+    m_bUtf8 = FALSE;
+    m_poDb = NULL;
+    m_bUpdate = FALSE;
+}
+
+/************************************************************************/
+/*                       ~OGRGeoPackageDataSource()                     */
+/************************************************************************/
+
+OGRGeoPackageDataSource::~OGRGeoPackageDataSource()
+{
+    for( int i = 0; i < m_nLayers; i++ )
+        delete m_papoLayers[i];
+        
+    if ( m_poDb )
+        sqlite3_close(m_poDb);
+
+    CPLFree( m_papoLayers );
+    CPLFree( m_pszFileName );
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRGeoPackageDataSource::Open(const char * pszFilename, int bUpdate )
+{
+    int i;
+    OGRErr err;
+
+    CPLAssert( m_nLayers == 0 );
+    CPLAssert( m_poDb == NULL );
+    CPLAssert( m_pszFileName == NULL );
+
+    m_bUpdate = bUpdate;
+
+    /* Requirement 3: File name has to end in "gpkg" */
+    /* http://opengis.github.io/geopackage/#_file_extension_name */
+    int nLen = strlen(pszFilename);
+    if(! (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gpkg")) )
+        return FALSE;
+
+    /* Check that the filename exists and is a file */
+    VSIStatBuf stat;
+    if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISREG(stat.st_mode) )
+        return FALSE;
+
+    /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) */
+    /* in the application id */
+    /* http://opengis.github.io/geopackage/#_file_format */
+    if ( ! CheckApplicationId(pszFilename) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "bad application_id on '%s'", pszFilename);
+        return FALSE;
+    }
+
+    /* See if we can open the SQLite database */
+    int rc = sqlite3_open( pszFilename, &m_poDb );
+    if ( rc != SQLITE_OK )
+    {
+        m_poDb = NULL;
+        CPLError( CE_Failure, CPLE_OpenFailed, "sqlite3_open(%s) failed: %s",
+                  pszFilename, sqlite3_errmsg( m_poDb ) );
+        return FALSE;
+    }
+    
+    /* Filename is good, store it for future reference */
+    m_pszFileName = CPLStrdup( pszFilename );
+
+    /* Requirement 6: The SQLite PRAGMA integrity_check SQL command SHALL return “ok” */
+    /* http://opengis.github.io/geopackage/#_file_integrity */
+    if ( OGRERR_NONE != PragmaCheck("integrity_check", "ok", 1) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pragma integrity_check on '%s' failed", pszFilename);
+        return FALSE;
+    }
+    
+    /* Requirement 7: The SQLite PRAGMA foreign_key_check() SQL with no */
+    /* parameter value SHALL return an empty result set */
+    /* http://opengis.github.io/geopackage/#_file_integrity */
+    if ( OGRERR_NONE != PragmaCheck("foreign_key_check", "", 0) ) 
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pragma foreign_key_check on '%s' failed", pszFilename);
+        return FALSE; 
+    }
+
+    /* OGR UTF-8 capability, we'll advertise UTF-8 support if we have it */
+    if ( OGRERR_NONE == PragmaCheck("encoding", "UTF-8", 1) ) 
+    {
+        m_bUtf8 = TRUE;
+    }
+    else
+    {
+        m_bUtf8 = FALSE;
+    }
+
+    /* Check for requirement metadata tables */
+    /* Requirement 10: gpkg_spatial_ref_sys must exist */
+    /* Requirement 13: gpkg_contents must exist */
+    /* Requirement 21: gpkg_geometry_columns must exist */
+    static std::string aosGpkgTables[] = {
+        "gpkg_geometry_columns",
+        "gpkg_spatial_ref_sys",
+        "gpkg_contents"
+    };
+    
+    for ( i = 0; i < 3; i++ )
+    {
+        SQLResult oResult;
+        char *pszSQL = sqlite3_mprintf("pragma table_info('%s')", aosGpkgTables[i].c_str());
+        err = SQLQuery(m_poDb, pszSQL, &oResult);
+        sqlite3_free(pszSQL);
+        
+        if  ( err != OGRERR_NONE )
+            return FALSE;
+            
+        if ( oResult.nRowCount <= 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "required GeoPackage table '%s' is missing", aosGpkgTables[i].c_str());
+            SQLResultFree(&oResult);
+            return FALSE;
+        }
+        
+        SQLResultFree(&oResult);
+    }
+        
+    /* Load layer definitions for all tables in gpkg_contents & gpkg_geometry_columns */
+    SQLResult oResult;
+    std::string osSQL = 
+        "SELECT c.table_name, c.identifier, c.min_x, c.min_y, c.max_x, c.max_y "
+        "FROM gpkg_geometry_columns g JOIN gpkg_contents c ON (g.table_name = c.table_name)"
+        "WHERE c.data_type = 'features'";
+        
+    err = SQLQuery(m_poDb, osSQL.c_str(), &oResult);
+    if  ( err != OGRERR_NONE )
+    {
+        SQLResultFree(&oResult);
+        return FALSE;
+    }
+
+    if ( oResult.nRowCount > 0 )
+    {
+        m_papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRGeoPackageLayer*) * oResult.nRowCount);
+
+        for ( i = 0; i < oResult.nRowCount; i++ )
+        {
+            const char *pszTableName = SQLResultGetValue(&oResult, 0, i);
+            if ( ! pszTableName )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "unable to read table name for layer(%d)", i);            
+                continue;
+            }
+            OGRGeoPackageLayer *poLayer = new OGRGeoPackageLayer(this, pszTableName);
+            if( OGRERR_NONE != poLayer->ReadTableDefinition() )
+            {
+                delete poLayer;
+                CPLError(CE_Warning, CPLE_AppDefined, "unable to read table definition for '%s'", pszTableName);            
+                continue;
+            }
+            m_papoLayers[m_nLayers++] = poLayer;
+        }
+    }
+    
+    SQLResultFree(&oResult);
+
+    return TRUE;
+}
+
+
+
+/************************************************************************/
+/*                          GetDatabaseHandle()                         */
+/************************************************************************/
+
+sqlite3* OGRGeoPackageDataSource::GetDatabaseHandle()
+{
+    return m_poDb;
+}
+
+/************************************************************************/
+/*                                Create()                              */
+/************************************************************************/
+
+int OGRGeoPackageDataSource::Create( const char * pszFilename, char **papszOptions )
+{
+    CPLString osCommand;
+    const char *pszSpatialRefSysRecord;
+
+	/* The OGRGeoPackageDriver has already confirmed that the pszFilename */
+	/* is not already in use, so try to create the file */
+    int rc = sqlite3_open( pszFilename, &m_poDb );
+    if ( rc != SQLITE_OK )
+    {
+        m_poDb = NULL;
+        CPLError( CE_Failure, CPLE_OpenFailed, "sqlite3_open(%s) failed: %s",
+                  pszFilename, sqlite3_errmsg( m_poDb ) );
+        return FALSE;
+    }
+
+    m_pszFileName = CPLStrdup(pszFilename);
+    m_bUpdate = TRUE;
+
+    /* OGR UTF-8 support. If we set the UTF-8 Pragma early on, it */
+    /* will be written into the main file and supported henceforth */
+    SQLCommand(m_poDb, "PRAGMA encoding = \"UTF-8\"");
+
+    /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the application id */
+    /* http://opengis.github.io/geopackage/#_file_format */
+    const char *pszPragma = CPLSPrintf("PRAGMA application_id = %d", GPKG_APPLICATION_ID);
+    
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszPragma) )
+        return FALSE;
+        
+    /* Requirement 10: A GeoPackage SHALL include a gpkg_spatial_ref_sys table */
+    /* http://opengis.github.io/geopackage/#spatial_ref_sys */
+    const char *pszSpatialRefSys = 
+        "CREATE TABLE gpkg_spatial_ref_sys ("
+        "srs_name TEXT NOT NULL,"
+        "srs_id INTEGER NOT NULL PRIMARY KEY,"
+        "organization TEXT NOT NULL,"
+        "organization_coordsys_id INTEGER NOT NULL,"
+        "definition  TEXT NOT NULL,"
+        "description TEXT"
+        ")";
+        
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszSpatialRefSys) )
+        return FALSE;
+
+    /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
+    /* contain a record for EPSG:4326, the geodetic WGS84 SRS */
+    /* http://opengis.github.io/geopackage/#spatial_ref_sys */
+    pszSpatialRefSysRecord = 
+        "INSERT INTO gpkg_spatial_ref_sys ("
+        "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+        ") VALUES ("
+        "'WGS 84 geodetic', 4326, 'EPSG', 4326, '"
+        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
+        "', 'longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid'"
+        ")";  
+          
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszSpatialRefSysRecord) )
+        return FALSE;
+
+    /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
+    /* contain a record with an srs_id of -1, an organization of “NONE”, */
+    /* an organization_coordsys_id of -1, and definition “undefined” */
+    /* for undefined Cartesian coordinate reference systems */
+    /* http://opengis.github.io/geopackage/#spatial_ref_sys */
+    pszSpatialRefSysRecord = 
+        "INSERT INTO gpkg_spatial_ref_sys ("
+        "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+        ") VALUES ("
+        "'Undefined cartesian SRS', -1, 'NONE', -1, 'undefined', 'undefined cartesian coordinate reference system'"
+        ")"; 
+           
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszSpatialRefSysRecord) )
+        return FALSE;
+
+    /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
+    /* contain a record with an srs_id of 0, an organization of “NONE”, */
+    /* an organization_coordsys_id of 0, and definition “undefined” */
+    /* for undefined geographic coordinate reference systems */
+    /* http://opengis.github.io/geopackage/#spatial_ref_sys */
+    pszSpatialRefSysRecord = 
+        "INSERT INTO gpkg_spatial_ref_sys ("
+        "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+        ") VALUES ("
+        "'Undefined geographic SRS', 0, 'NONE', 0, 'undefined', 'undefined geographic coordinate reference system'"
+        ")"; 
+           
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszSpatialRefSysRecord) )
+        return FALSE;
+    
+    /* Requirement 13: A GeoPackage file SHALL include a gpkg_contents table */
+    /* http://opengis.github.io/geopackage/#_contents */
+    const char *pszContents =
+        "CREATE TABLE gpkg_contents ("
+        "table_name TEXT NOT NULL PRIMARY KEY,"
+        "data_type TEXT NOT NULL,"
+        "identifier TEXT UNIQUE,"
+        "description TEXT DEFAULT '',"
+        "last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ',CURRENT_TIMESTAMP)),"
+        "min_x DOUBLE, min_y DOUBLE,"
+        "max_x DOUBLE, max_y DOUBLE,"
+        "srs_id INTEGER,"
+        "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys(srs_id)"
+        ")";
+        
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszContents) )
+        return FALSE;
+
+    /* Requirement 21: A GeoPackage with a gpkg_contents table row with a “features” */
+    /* data_type SHALL contain a gpkg_geometry_columns table or updateable view */
+    /* http://opengis.github.io/geopackage/#_geometry_columns */
+    const char *pszGeometryColumns =        
+        "CREATE TABLE gpkg_geometry_columns ("
+        "table_name TEXT NOT NULL,"
+        "column_name TEXT NOT NULL,"
+        "geometry_type_name TEXT NOT NULL,"
+        "srs_id INTEGER NOT NULL,"
+        "z TINYINT NOT NULL,"
+        "m TINYINT NOT NULL,"
+        "CONSTRAINT pk_geom_cols PRIMARY KEY (table_name, column_name),"
+        "CONSTRAINT uk_gc_table_name UNIQUE (table_name),"
+        "CONSTRAINT fk_gc_tn FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
+        "CONSTRAINT fk_gc_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
+        ")";
+        
+    if ( OGRERR_NONE != SQLCommand(m_poDb, pszGeometryColumns) )
+        return FALSE;
+
+    /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) */
+    /* in the application id field of the SQLite database header */
+    /* We have to do this after there's some content so the database file */
+    /* is not zero length */
+    SetApplicationId();
+
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                              AddColumn()                             */
+/************************************************************************/
+
+OGRErr OGRGeoPackageDataSource::AddColumn(const char *pszTableName, const char *pszColumnName, const char *pszColumnType)
+{
+    char *pszSQL;
+    
+    pszSQL = sqlite3_mprintf("ALTER TABLE %s ADD COLUMN %s %s", 
+                             pszTableName, pszColumnName, pszColumnType);
+
+    OGRErr err = SQLCommand(m_poDb, pszSQL);
+    sqlite3_free(pszSQL);
+    
+    return err;
+}
+
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer* OGRGeoPackageDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= m_nLayers )
+        return NULL;
+    else
+        return m_papoLayers[iLayer];
+}
+
+
+/************************************************************************/
+/*                           CreateLayer()                              */
+/* Options:                                                             */
+/*   FID = primary key name                                             */
+/*   OVERWRITE = YES|NO, overwrite existing layer?                      */
+/*   SPATIAL_INDEX = YES|NO, TBD                                        */
+/************************************************************************/
+
+OGRLayer* OGRGeoPackageDataSource::CreateLayer( const char * pszLayerName,
+                                      OGRSpatialReference * poSpatialRef,
+                                      OGRwkbGeometryType eGType,
+                                      char **papszOptions )
+{
+    int iLayer;
+    OGRErr err;
+    
+    if( !m_bUpdate )
+        return NULL;
+
+    /* Read GEOMETRY_COLUMN option */
+    const char* pszGeomColumnName = CSLFetchNameValue(papszOptions, "GEOMETRY_COLUMN");
+    if (pszGeomColumnName == NULL)
+        pszGeomColumnName = "geom";
+    
+    /* Read FID option */
+    const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
+    if (pszFIDColumnName == NULL)
+        pszFIDColumnName = "fid";
+
+    if ( strspn(pszFIDColumnName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The primary key (%s) name may not contain special characters or spaces", 
+                 pszFIDColumnName);
+        return NULL;
+    }
+
+    /* Avoiding gpkg prefixes is not an official requirement, but seems wise */
+    if (strncmp(pszLayerName, "gpkg", 4) == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The layer name may not begin with 'gpkg' as it is a reserved geopackage prefix");
+        return NULL;
+    }
+
+    /* Pre-emptively try and avoid sqlite3 syntax errors due to  */
+    /* illegal characters */
+    if ( strspn(pszLayerName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The layer name may not contain special characters or spaces");
+        return NULL;
+    }
+
+    /* Check for any existing layers that already use this name */
+    for( iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if( EQUAL(pszLayerName, m_papoLayers[iLayer]->GetName()) )
+        {
+            const char *pszOverwrite = CSLFetchNameValue(papszOptions,"OVERWRITE");
+            if( pszOverwrite != NULL && CSLTestBoolean(pszOverwrite) )
+            {
+                DeleteLayer( iLayer );
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Layer %s already exists, CreateLayer failed.\n"
+                          "Use the layer creation option OVERWRITE=YES to "
+                          "replace it.",
+                          pszLayerName );
+                return NULL;
+            }
+        }
+    }
+
+    /* Read our SRS_ID from the OGRSpatialReference */
+    int nSRSId = UNDEFINED_SRID;
+    if( poSpatialRef != NULL )
+        nSRSId = GetSrsId( poSpatialRef );
+        
+    /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */
+    /* row SHALL be one of the uppercase geometry type names specified in */
+    /* Geometry Types (Normative). */
+    const char *pszGeometryType = OGRToOGCGeomType(eGType);
+    
+    /* Create the table! */
+    char *pszSQL = NULL;
+    if ( eGType != wkbNone )
+    {
+        pszSQL = sqlite3_mprintf(
+            "CREATE TABLE %s ( "
+            "%s INTEGER PRIMARY KEY AUTOINCREMENT, "
+            "%s %s )",
+             pszLayerName, pszFIDColumnName, pszGeomColumnName, pszGeometryType);
+    }
+    else
+    {
+        pszSQL = sqlite3_mprintf(
+            "CREATE TABLE %s ( "
+            "%s INTEGER PRIMARY KEY AUTOINCREMENT )",
+             pszLayerName, pszFIDColumnName);
+    }
+    
+    err = SQLCommand(m_poDb, pszSQL);
+    sqlite3_free(pszSQL);
+    if ( OGRERR_NONE != err )
+        return NULL;
+
+    /* Only spatial tables need to be registered in the metadata (hmmm) */
+    if ( eGType != wkbNone )
+    {
+        /* Requirement 27: The z value in a gpkg_geometry_columns table row */
+        /* SHALL be one of 0 (none), 1 (mandatory), or 2 (optional) */
+        int bGeometryTypeHasZ = wkb25DBit & eGType;
+
+        /* Update gpkg_geometry_columns with the table info */
+        pszSQL = sqlite3_mprintf(
+            "INSERT INTO gpkg_geometry_columns "
+            "(table_name,column_name,geometry_type_name,srs_id,z,m)"
+            " VALUES "
+            "('%q','%q','%q',%d,%d,%d)",
+            pszLayerName,pszGeomColumnName,pszGeometryType,
+            nSRSId,bGeometryTypeHasZ,0);
+    
+        err = SQLCommand(m_poDb, pszSQL);
+        sqlite3_free(pszSQL);
+        if ( err != OGRERR_NONE )
+            return NULL;
+
+        /* Update gpkg_contents with the table info */
+        pszSQL = sqlite3_mprintf(
+            "INSERT INTO gpkg_contents "
+            "(table_name,data_type,identifier,last_change,srs_id)"
+            " VALUES "
+            "('%q','features','%q',strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',CURRENT_TIMESTAMP),%d)",
+            pszLayerName, pszLayerName, nSRSId);
+    
+        err = SQLCommand(m_poDb, pszSQL);
+        sqlite3_free(pszSQL);
+        if ( err != OGRERR_NONE )
+            return NULL;
+
+    }
+
+    /* This is where spatial index logic will go in the future */
+    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
+    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    if( eGType != wkbNone && bCreateSpatialIndex )
+    {
+        /* This is where spatial index logic will go in the future */
+    }
+    
+    /* The database is now all set up, so create a blank layer and read in the */
+    /* info from the database. */
+    OGRGeoPackageLayer *poLayer = new OGRGeoPackageLayer(this, pszLayerName);
+    
+    if( OGRERR_NONE != poLayer->ReadTableDefinition() )
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    m_papoLayers = (OGRLayer**)CPLRealloc(m_papoLayers,  sizeof(OGRGeoPackageLayer*) * (m_nLayers+1));
+    m_papoLayers[m_nLayers++] = poLayer;
+    return poLayer;
+}
+
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+int OGRGeoPackageDataSource::DeleteLayer( int iLayer )
+{
+    char *pszSQL;
+
+    if( !m_bUpdate || iLayer < 0 || iLayer >= m_nLayers )
+        return OGRERR_FAILURE;
+
+    CPLString osLayerName = m_papoLayers[iLayer]->GetLayerDefn()->GetName();
+
+    CPLDebug( "GPKG", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    /* Delete the layer object and remove the gap in the layers list */
+    delete m_papoLayers[iLayer];
+    memmove( m_papoLayers + iLayer, m_papoLayers + iLayer + 1,
+             sizeof(void *) * (m_nLayers - iLayer - 1) );
+    m_nLayers--;
+
+    if (osLayerName.size() == 0)
+        return OGRERR_NONE;
+
+    pszSQL = sqlite3_mprintf(
+            "DROP TABLE %s",
+             osLayerName.c_str());
+    
+    SQLCommand(m_poDb, pszSQL);
+    sqlite3_free(pszSQL);
+
+    pszSQL = sqlite3_mprintf(
+            "DELETE FROM gpkg_geometry_columns WHERE table_name = '%s'",
+             osLayerName.c_str());
+    
+    SQLCommand(m_poDb, pszSQL);
+    sqlite3_free(pszSQL);
+    
+    pszSQL = sqlite3_mprintf(
+             "DELETE FROM gpkg_contents WHERE table_name = '%s'",
+              osLayerName.c_str());
+
+    SQLCommand(m_poDb, pszSQL);
+    sqlite3_free(pszSQL);
+
+    return OGRERR_NONE;
+}
+
+
+
+/************************************************************************/
+/*                       TestCapability()                               */
+/************************************************************************/
+
+int OGRGeoPackageDataSource::TestCapability( const char * pszCap )
+{
+    if ( EQUAL(pszCap,ODsCCreateLayer) ||
+         EQUAL(pszCap,ODsCDeleteLayer) )
+    {
+         return m_bUpdate;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRGeoPackageDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                          OGRGeometry *poSpatialFilter,
+                                          const char *pszDialect )
+
+{
+    if( EQUALN(pszSQLCommand, "SELECT ", 7) ||
+        (pszDialect != NULL && EQUAL(pszDialect,"OGRSQL")) )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
+                                          poSpatialFilter, 
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Prepare statement.                                              */
+/* -------------------------------------------------------------------- */
+    int rc;
+    sqlite3_stmt *hSQLStmt = NULL;
+
+    CPLString osSQLCommand = pszSQLCommand;
+
+#if 0
+    /* This will speed-up layer creation */
+    /* ORDER BY are costly to evaluate and are not necessary to establish */
+    /* the layer definition. */
+    int bUseStatementForGetNextFeature = TRUE;
+    int bEmptyLayer = FALSE;
+
+    if( osSQLCommand.ifind("SELECT ") == 0 &&
+        osSQLCommand.ifind(" UNION ") == std::string::npos &&
+        osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
+        osSQLCommand.ifind(" EXCEPT ") == std::string::npos )
+    {
+        size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
+        if( nOrderByPos != std::string::npos )
+        {
+            osSQLCommand.resize(nOrderByPos);
+            bUseStatementForGetNextFeature = FALSE;
+        }
+    }
+#endif
+
+    rc = sqlite3_prepare( m_poDb, osSQLCommand.c_str(), osSQLCommand.size(),
+                          &hSQLStmt, NULL );
+
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s", 
+                pszSQLCommand, sqlite3_errmsg(m_poDb) );
+
+        if( hSQLStmt != NULL )
+        {
+            sqlite3_finalize( hSQLStmt );
+        }
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we get a resultset?                                          */
+/* -------------------------------------------------------------------- */
+    rc = sqlite3_step( hSQLStmt );
+    if( rc != SQLITE_ROW )
+    {
+        if ( rc != SQLITE_DONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
+                  pszSQLCommand, sqlite3_errmsg(m_poDb) );
+
+            sqlite3_finalize( hSQLStmt );
+            return NULL;
+        }
+        
+        if( EQUAL(pszSQLCommand, "VACUUM") )
+        {
+            sqlite3_finalize( hSQLStmt );
+            /* VACUUM rewrites the DB, so we need to reset the application id */
+            SetApplicationId();
+            return NULL;
+        }
+        
+        if( EQUALN(pszSQLCommand, "ALTER TABLE ", strlen("ALTER TABLE ")) )
+        {
+            char **papszTokens = CSLTokenizeString( pszSQLCommand );
+            /* ALTER TABLE src_table RENAME TO dst_table */
+            if( CSLCount(papszTokens) == 6 && EQUAL(papszTokens[3], "RENAME") &&
+                EQUAL(papszTokens[4], "TO") )
+            {
+                const char* pszSrcTableName = papszTokens[2];
+                const char* pszDstTableName = papszTokens[5];
+                OGRLayer* poSrcLayer = GetLayerByName(pszSrcTableName);
+                if( poSrcLayer )
+                {
+                    /* We also need to update GeoPackage metadata tables */
+                    char* pszSQL;
+                    pszSQL = sqlite3_mprintf(
+                            "UPDATE gpkg_geometry_columns SET table_name = '%s' WHERE table_name = '%s'",
+                            pszDstTableName, pszSrcTableName);
+                    
+                    SQLCommand(m_poDb, pszSQL);
+                    sqlite3_free(pszSQL);
+                    
+                    pszSQL = sqlite3_mprintf(
+                            "UPDATE gpkg_contents SET table_name = '%s' WHERE table_name = '%s'",
+                            pszDstTableName, pszSrcTableName);
+
+                    SQLCommand(m_poDb, pszSQL);
+                    sqlite3_free(pszSQL);
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+
+        if( !EQUALN(pszSQLCommand, "SELECT ", 7) )
+        {
+            sqlite3_finalize( hSQLStmt );
+            return NULL;
+        }
+#if 0
+        bUseStatementForGetNextFeature = FALSE;
+        bEmptyLayer = TRUE;
+#endif
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create layer.                                                   */
+/* -------------------------------------------------------------------- */
+#if 0
+    OGRSQLiteSelectLayer *poLayer = NULL;
+        
+    CPLString osSQL = pszSQLCommand;
+    poLayer = new OGRGeopackageSelectLayer( this, osSQL, hSQLStmt,
+                                        bUseStatementForGetNextFeature, bEmptyLayer, TRUE );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( 0, poSpatialFilter );
+    
+    return poLayer;
+#else
+    return OGRDataSource::ExecuteSQL( pszSQLCommand, 
+                                          poSpatialFilter, 
+                                          pszDialect );
+#endif
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRGeoPackageDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
new file mode 100644
index 0000000..efb3dfe
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Implements GeoPackageDriver.
+ * Author:   Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_geopackage.h"
+
+// g++ -g -Wall -fPIC -shared -o ogr_geopackage.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpkg ogr/ogrsf_frmts/gpkg/*.c* -L. -lgdal 
+
+
+
+/************************************************************************/
+/*                        ~OGRGeoPackageDriver()                         */
+/************************************************************************/
+
+OGRGeoPackageDriver::~OGRGeoPackageDriver()
+{
+} 
+
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRGeoPackageDriver::GetName()
+{
+    return "GPKG";
+}
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRGeoPackageDriver::Open( const char * pszFilename, int bUpdate )
+{
+    OGRGeoPackageDataSource   *poDS = new OGRGeoPackageDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+
+/************************************************************************/
+/*                                CreateDataSource()                    */
+/************************************************************************/
+
+OGRDataSource *OGRGeoPackageDriver::CreateDataSource( const char * pszFilename, char **papszOptions )
+{
+	/* First, ensure there isn't any such file yet. */
+    VSIStatBufL sStatBuf;
+
+    if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "A file system object called '%s' already exists.",
+                  pszFilename );
+
+        return NULL;
+    }
+	
+    OGRGeoPackageDataSource   *poDS = new OGRGeoPackageDataSource();
+
+    if( !poDS->Create( pszFilename, papszOptions ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         DeleteDataSource()                           */
+/************************************************************************/
+
+OGRErr OGRGeoPackageDriver::DeleteDataSource( const char *pszFilename )
+{
+    if (VSIUnlink( pszFilename ) == 0)
+        return OGRERR_NONE;
+    else
+        return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                         TestCapability()                             */
+/************************************************************************/
+
+int OGRGeoPackageDriver::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODrCCreateDataSource) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODrCDeleteDataSource) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+/************************************************************************/
+/*                         RegisterOGRGeoPackage()                       */
+/************************************************************************/
+
+void RegisterOGRGeoPackage()
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRGeoPackageDriver );
+}
+
+
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
new file mode 100644
index 0000000..de7a442
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
@@ -0,0 +1,1277 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Implements OGRGeoPackageLayer class
+ * Author:   Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_geopackage.h"
+#include "ogrgeopackageutility.h"
+
+//----------------------------------------------------------------------
+// SaveExtent()
+// 
+// Write the current contents of the layer envelope down to the
+// gpkg_contents metadata table.
+//
+OGRErr OGRGeoPackageLayer::SaveExtent()
+{
+    if ( !m_poDS->IsUpdatable() || ! m_bExtentChanged || ! m_poExtent ) 
+        return OGRERR_NONE;
+
+    sqlite3* poDb = m_poDS->GetDatabaseHandle();
+
+    if ( ! poDb ) return OGRERR_FAILURE;
+
+    char *pszSQL = sqlite3_mprintf(
+                "UPDATE gpkg_contents SET "
+                "min_x = %g, min_y = %g, "
+                "max_x = %g, max_y = %g "
+                "WHERE table_name = '%q' AND "
+                "Lower(data_type) = 'features'",
+                m_poExtent->MinX, m_poExtent->MinY,
+                m_poExtent->MaxX, m_poExtent->MaxY,
+                m_pszTableName);
+
+    OGRErr err = SQLCommand(poDb, pszSQL);
+    sqlite3_free(pszSQL);
+    m_bExtentChanged = FALSE;
+    
+    return err;
+}
+
+//----------------------------------------------------------------------
+// UpdateExtent()
+// 
+// Expand the layer envelope if necessary to reflect the bounds
+// of new features being added to the layer.
+//
+OGRErr OGRGeoPackageLayer::UpdateExtent( const OGREnvelope *poExtent )
+{
+    if ( ! m_poExtent )
+    {
+        m_poExtent = new OGREnvelope( *poExtent );
+    }
+    m_poExtent->Merge( *poExtent );
+    m_bExtentChanged = TRUE;
+    return OGRERR_NONE;
+}
+
+//----------------------------------------------------------------------
+// BuildColumns()
+// 
+// Save a list of columns (fid, geometry, attributes) suitable
+// for use in a SELECT query that retrieves all fields.
+//
+OGRErr OGRGeoPackageLayer::BuildColumns()
+{
+    if ( ! m_poFeatureDefn || ! m_pszFidColumn )
+    {
+        return OGRERR_FAILURE;
+    }
+
+    /* Always start with a primary key */
+    CPLString soColumns = m_pszFidColumn;
+
+    /* Add a geometry column if there is one (just one) */
+    if ( m_poFeatureDefn->GetGeomFieldCount() )
+    {
+        soColumns += ", ";
+        soColumns += m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+    }
+
+    /* Add all the attribute columns */
+    for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        soColumns += ", ";
+        soColumns += m_poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+    }
+
+    m_soColumns = soColumns;    
+    return OGRERR_NONE;    
+}
+
+//----------------------------------------------------------------------
+// ReadFeature()
+// 
+// Convert a row in a statement into an OGRFeature.
+//
+OGRErr OGRGeoPackageLayer::ReadFeature( sqlite3_stmt *poQuery, OGRFeature **ppoFeature )
+{
+    int iColOffset = 0;
+    
+    if ( ! m_poFeatureDefn )
+        return OGRERR_FAILURE;
+
+    OGRFeature *poFeature = new OGRFeature( m_poFeatureDefn );
+    
+    /* Primary key is always first column in our SQL call */
+    poFeature->SetFID(sqlite3_column_int(poQuery, iColOffset++));
+    
+    /* If a geometry column exists, it's next */
+    /* Add a geometry column if there is one (just the first one) */
+    if ( m_poFeatureDefn->GetGeomFieldCount() )
+    {
+        if ( sqlite3_column_type(poQuery, iColOffset) != SQLITE_NULL )
+        {
+            OGRSpatialReference* poSrs = m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef();
+            int iGpkgSize = sqlite3_column_bytes(poQuery, iColOffset);
+            GByte *pabyGpkg = (GByte *)sqlite3_column_blob(poQuery, iColOffset);
+            OGRGeometry *poGeom = GPkgGeometryToOGR(pabyGpkg, iGpkgSize, poSrs);
+            if ( ! poGeom )
+            {
+                delete poFeature;
+                CPLError( CE_Failure, CPLE_AppDefined, "Unable to read geometry");
+                return OGRERR_FAILURE;
+            }
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+        iColOffset++;
+    }
+    
+    /* Read all the attribute columns */
+    for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        int j = iColOffset+i;
+
+        switch(sqlite3_column_type(poQuery, j))
+        {
+            case SQLITE_INTEGER:
+            {
+                int iVal = sqlite3_column_int(poQuery, j);
+                poFeature->SetField(i, iVal);
+                break;
+            }
+            case SQLITE_FLOAT:
+            {
+                double dVal = sqlite3_column_double(poQuery, j);
+                poFeature->SetField(i, dVal);
+                break;
+            }
+            case SQLITE_BLOB:
+            {
+                int iBlobSize = sqlite3_column_bytes(poQuery, j);
+                GByte *pabyBlob = (GByte *)sqlite3_column_blob(poQuery, j);
+                poFeature->SetField(i, iBlobSize, pabyBlob);
+                break;
+            }
+            case SQLITE_TEXT:
+            {
+                const char *pszVal = (const char *)sqlite3_column_text(poQuery, j);
+                poFeature->SetField(i, pszVal);
+                break;
+            }
+            default: /* SQLITE_NULL */
+            {
+                /* Do nothing for NULL fields */
+                break;
+            }
+        }
+    }
+    
+    /* Pass result back to the caller */
+    *ppoFeature = poFeature;
+
+    return OGRERR_NONE;
+}
+
+
+
+//----------------------------------------------------------------------
+// IsGeomFieldSet()
+// 
+// Utility method to determine if there is a non-Null geometry
+// in an OGRGeometry.
+//
+OGRBoolean OGRGeoPackageLayer::IsGeomFieldSet( OGRFeature *poFeature )
+{
+    if ( poFeature->GetDefnRef()->GetGeomFieldCount() && 
+         poFeature->GetGeomFieldRef(0) )
+    {
+        return TRUE;        
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+OGRErr OGRGeoPackageLayer::FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount )
+{
+    int nColCount = 1;
+    int err;
+    
+    if ( ! (poFeature && poStmt && pnColCount) )
+        return OGRERR_FAILURE;
+
+    OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
+    
+    /* Bind data values to the statement, here bind the blob for geometry */
+    if ( poFeatureDefn->GetGeomFieldCount() )
+    {
+        GByte *pabyWkb = NULL;
+
+        /* Non-NULL geometry */
+        if ( poFeature->GetGeomFieldRef(0) )
+        {
+            size_t szWkb;
+            pabyWkb = GPkgGeometryFromOGR(poFeature->GetGeomFieldRef(0), m_iSrs, &szWkb);
+            err = sqlite3_bind_blob(poStmt, nColCount++, pabyWkb, szWkb, CPLFree);
+        }
+        /* NULL geometry */
+        else
+        {
+            err = sqlite3_bind_null(poStmt, nColCount++);
+        }
+        if ( err != SQLITE_OK )
+        {
+            if ( pabyWkb )
+                CPLFree(pabyWkb);
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "failed to bind geometry to statement");        
+            return OGRERR_FAILURE;            
+        }
+    }
+
+    /* Bind the attributes using appropriate SQLite data types */
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i); 
+        
+        if( poFeature->IsFieldSet(i) )
+        {
+            switch(SQLiteFieldFromOGR(poFieldDefn->GetType()))
+            {
+                case SQLITE_INTEGER:
+                {
+                    err = sqlite3_bind_int(poStmt, nColCount++, poFeature->GetFieldAsInteger(i));
+                    break;
+                }
+                case SQLITE_FLOAT:
+                {
+                    err = sqlite3_bind_double(poStmt, nColCount++, poFeature->GetFieldAsDouble(i));
+                    break;
+                }
+                case SQLITE_BLOB:
+                {
+                    int szBlob;
+                    GByte *pabyBlob = poFeature->GetFieldAsBinary(i, &szBlob);
+                    err = sqlite3_bind_blob(poStmt, nColCount++, pabyBlob, szBlob, NULL);
+                    break;
+                }
+                default:
+                {
+                    const char *pszVal = poFeature->GetFieldAsString(i);
+                    err = sqlite3_bind_text(poStmt, nColCount++, pszVal, strlen(pszVal), SQLITE_TRANSIENT);
+                    break;
+                }            
+            }            
+        }
+        else
+        {
+            err = sqlite3_bind_null(poStmt, nColCount++);
+        }
+    }
+    
+    *pnColCount = nColCount;
+    return OGRERR_NONE;
+}
+
+//----------------------------------------------------------------------
+// FeatureBindUpdateParameters()
+// 
+// Selectively bind the values of an OGRFeature to a prepared 
+// statement, prior to execution. Carefully binds exactly the 
+// same parameters that have been set up by FeatureGenerateUpdateSQL()
+// as bindable.
+//
+OGRErr OGRGeoPackageLayer::FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt )
+{
+
+    int nColCount;
+    OGRErr err = FeatureBindParameters( poFeature, poStmt, &nColCount );
+    if ( err != OGRERR_NONE )
+        return err;
+
+    /* Bind the FID to the "WHERE" clause */
+    err = sqlite3_bind_int(poStmt, nColCount, poFeature->GetFID());    
+    if ( err != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to bind FID '%ld' to statement", poFeature->GetFID());
+        return OGRERR_FAILURE;       
+    }
+    
+    return OGRERR_NONE;
+}
+
+
+//----------------------------------------------------------------------
+// FeatureBindInsertParameters()
+// 
+// Selectively bind the values of an OGRFeature to a prepared 
+// statement, prior to execution. Carefully binds exactly the 
+// same parameters that have been set up by FeatureGenerateInsertSQL()
+// as bindable.
+//
+OGRErr OGRGeoPackageLayer::FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt )
+{    
+    int nColCount;
+    return FeatureBindParameters( poFeature, poStmt, &nColCount );
+}   
+
+
+//----------------------------------------------------------------------
+// FeatureGenerateInsertSQL()
+// 
+// Build a SQL INSERT statement that references all the columns in
+// the OGRFeatureDefn, then prepare it for repeated use in a prepared
+// statement. All statements start off with geometry (if it exists)
+// then reference each column in the order it appears in the OGRFeatureDefn.
+// FeatureBindParameters operates on the expectation of this
+// column ordering.
+//
+CPLString OGRGeoPackageLayer::FeatureGenerateInsertSQL( OGRFeature *poFeature )
+{
+    OGRBoolean bNeedComma = FALSE;
+    OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
+
+    /* Set up our SQL string basics */
+    CPLString osSQLFront;
+    osSQLFront.Printf("INSERT INTO %s ( ", m_pszTableName);
+
+    CPLString osSQLBack;
+    osSQLBack = ") VALUES (";
+    
+    if ( poFeatureDefn->GetGeomFieldCount() )
+    {
+        osSQLFront += poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+        osSQLBack += "?";
+        bNeedComma = TRUE;
+    }
+
+    /* Add attribute column names (except FID) to the SQL */
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( !bNeedComma )
+        {
+            bNeedComma = TRUE;
+        }
+        else 
+        {
+            osSQLFront += ", ";
+            osSQLBack += ", ";
+        }
+
+        osSQLFront += poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        osSQLBack += "?";        
+    }
+    
+    osSQLBack += ")";
+
+    return osSQLFront + osSQLBack;
+}
+
+
+//----------------------------------------------------------------------
+// FeatureGenerateUpdateSQL()
+// 
+// Build a SQL UPDATE statement that references all the columns in
+// the OGRFeatureDefn, then prepare it for repeated use in a prepared
+// statement. All statements start off with geometry (if it exists)
+// then reference each column in the order it appears in the OGRFeatureDefn.
+// FeatureBindParameters operates on the expectation of this
+// column ordering.
+
+//
+CPLString OGRGeoPackageLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeature )
+{
+    OGRBoolean bNeedComma = FALSE;
+    OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
+
+    /* Set up our SQL string basics */
+    CPLString osUpdate;
+    osUpdate.Printf("UPDATE %s SET ", m_pszTableName);
+    
+    if ( poFeatureDefn->GetGeomFieldCount() > 0 )
+    {
+        osUpdate += poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+        osUpdate += "=?";
+        bNeedComma = TRUE;
+    }
+
+    /* Add attribute column names (except FID) to the SQL */
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( !bNeedComma )
+            bNeedComma = TRUE;
+        else 
+            osUpdate += ", ";
+
+        osUpdate += poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        osUpdate += "=?";
+    }
+    
+    CPLString osWhere;
+    osWhere.Printf(" WHERE %s = ?", m_pszFidColumn);
+
+    return osUpdate + osWhere;
+}
+
+
+//----------------------------------------------------------------------
+// ReadTableDefinition()
+// 
+// Initialization routine. Read all the metadata about a table, 
+// starting from just the table name. Reads information from GPKG
+// metadata tables and from SQLite table metadata. Uses it to 
+// populate OGRSpatialReference information and OGRFeatureDefn objects, 
+// among others.
+//
+OGRErr OGRGeoPackageLayer::ReadTableDefinition()
+{
+    OGRErr err;
+    SQLResult oResultTable;
+    SQLResult oResultContents;
+    SQLResult oResultGeomCols;
+    char* pszSQL;
+    OGRBoolean bReadExtent = FALSE;
+    sqlite3* poDb = m_poDS->GetDatabaseHandle();
+
+    /* Check that the table name is registered in gpkg_contents */
+    pszSQL = sqlite3_mprintf(
+                "SELECT table_name, data_type, identifier, "
+                "description, min_x, min_y, max_x, max_y, srs_id "
+                "FROM gpkg_contents "
+                "WHERE table_name = '%q' AND "
+                "Lower(data_type) = 'features'",
+                m_pszTableName);
+                
+    err = SQLQuery(poDb, pszSQL, &oResultContents);
+    sqlite3_free(pszSQL);
+    
+    /* gpkg_contents query has to work */
+    /* gpkg_contents.table_name is supposed to be unique */
+    if ( err != OGRERR_NONE || oResultContents.nRowCount != 1 )
+    {
+        if ( err != OGRERR_NONE )
+            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg );
+        else if ( oResultContents.nRowCount != 1 )
+            CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_contents", m_pszTableName );
+        else
+            CPLError( CE_Failure, CPLE_AppDefined, "error reading gpkg_contents" );
+            
+        SQLResultFree(&oResultContents);
+        return err;        
+    }
+
+    const char *pszMinX = SQLResultGetValue(&oResultContents, 4, 0);
+    const char *pszMinY = SQLResultGetValue(&oResultContents, 5, 0);
+    const char *pszMaxX = SQLResultGetValue(&oResultContents, 6, 0);
+    const char *pszMaxY = SQLResultGetValue(&oResultContents, 7, 0);
+    
+	/* All the extrema have to be non-NULL for this to make sense */
+    OGREnvelope oExtent;
+    if ( pszMinX && pszMinY && pszMaxX && pszMaxY )
+    {
+        oExtent.MinX = atof(pszMinX);
+        oExtent.MinY = atof(pszMinY);
+        oExtent.MaxX = atof(pszMaxX);
+        oExtent.MaxY = atof(pszMaxY);
+        bReadExtent = TRUE;
+    }
+
+    /* Done with info from gpkg_contents now */
+    SQLResultFree(&oResultContents);
+
+    /* Check that the table name is registered in gpkg_geometry_columns */
+    pszSQL = sqlite3_mprintf(
+                "SELECT table_name, column_name, "
+                "geometry_type_name, srs_id, z "
+                "FROM gpkg_geometry_columns "
+                "WHERE table_name = '%q'",
+                m_pszTableName);
+                
+    err = SQLQuery(poDb, pszSQL, &oResultGeomCols);
+    sqlite3_free(pszSQL);
+
+    /* gpkg_geometry_columns query has to work */
+    /* gpkg_geometry_columns.table_name is supposed to be unique */
+    if ( err != OGRERR_NONE || oResultGeomCols.nRowCount != 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultGeomCols.pszErrMsg );
+        SQLResultFree(&oResultGeomCols);
+        return err;
+    }
+
+    /* Use the "PRAGMA TABLE_INFO()" call to get table definition */
+    /*  #|name|type|nullable|default|pk */
+    /*  0|id|integer|0||1 */
+    /*  1|name|varchar|0||0 */    
+    pszSQL = sqlite3_mprintf("pragma table_info('%q')", m_pszTableName);
+    err = SQLQuery(poDb, pszSQL, &oResultTable);
+    sqlite3_free(pszSQL);
+
+    if ( err != OGRERR_NONE || oResultTable.nRowCount == 0 )
+    {
+        if( oResultTable.pszErrMsg != NULL )
+            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultTable.pszErrMsg );
+        else
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot find table %s", m_pszTableName );
+        err = OGRERR_FAILURE;
+        SQLResultFree(&oResultGeomCols);
+        SQLResultFree(&oResultTable);
+        return err;
+    }
+    
+    /* Populate feature definition from table description */
+    m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
+    m_poFeatureDefn->Reference();
+    
+    const char *pszGeomColsType = SQLResultGetValue(&oResultGeomCols, 2, 0);
+    int iSrsId = SQLResultGetValueAsInteger(&oResultGeomCols, 3, 0);
+    int bHasZ = SQLResultGetValueAsInteger(&oResultGeomCols, 4, 0);
+    int iRecord;
+    OGRBoolean bFidFound = FALSE;
+    m_iSrs = iSrsId;
+    
+    for ( iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
+    {
+        const char *pszName = SQLResultGetValue(&oResultTable, 1, iRecord);
+        const char *pszType = SQLResultGetValue(&oResultTable, 2, iRecord);
+        OGRBoolean bFid = SQLResultGetValueAsInteger(&oResultTable, 5, iRecord);
+        OGRFieldType oType = GPkgFieldToOGR(pszType);
+
+        /* Not a standard field type... */
+        if ( oType > OFTMaxType )
+        {
+            /* Maybe it's a geometry type? */
+            OGRwkbGeometryType oGeomType = GPkgGeometryTypeToWKB(pszType, bHasZ);
+            if ( oGeomType != wkbNone )
+            {
+                OGRwkbGeometryType oGeomTypeGeomCols = GPkgGeometryTypeToWKB(pszGeomColsType, bHasZ);
+                /* Enforce consistency between table and metadata */
+                if ( oGeomType != oGeomTypeGeomCols )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, 
+                             "geometry column type in '%s.%s' is not consistent with type in gpkg_geometry_columns", 
+                             m_pszTableName, pszName);
+                    SQLResultFree(&oResultTable);
+                    SQLResultFree(&oResultGeomCols);
+                    return OGRERR_FAILURE;
+                }
+                
+                if ( m_poFeatureDefn->GetGeomFieldCount() == 0 )
+                {
+                    OGRGeomFieldDefn oGeomField(pszName, oGeomType);
+                    m_poFeatureDefn->AddGeomFieldDefn(&oGeomField);
+                }
+                else if ( m_poFeatureDefn->GetGeomFieldCount() == 1 )
+                {
+                    m_poFeatureDefn->GetGeomFieldDefn(0)->SetType(oGeomType);
+                    m_poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszName);
+                    
+                    /* Read the SRS */
+                    OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(iSrsId);
+                    if ( poSRS )
+                    {
+                        m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+                        poSRS->Dereference();
+                    }
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, 
+                             "table '%s' has multiple geometry fields? not legal in gpkg", 
+                             m_pszTableName);
+                    SQLResultFree(&oResultTable);
+                    SQLResultFree(&oResultGeomCols);
+                    return OGRERR_FAILURE;
+                }
+
+            }
+            else
+            {
+                // CPLError( CE_Failure, CPLE_AppDefined, "invalid field type '%s'", pszType );
+                // SQLResultFree(&oResultTable);
+                CPLError(CE_Warning, CPLE_AppDefined, 
+                         "geometry column '%s' of type '%s' ignored", pszName, pszType);
+            }
+            
+        }
+        else
+        {
+            /* Is this the FID column? */
+            if ( bFid )
+            {
+                bFidFound = TRUE;
+                m_pszFidColumn = CPLStrdup(pszName);
+            }
+            else
+            {
+                OGRFieldDefn oField(pszName, oType);
+                m_poFeatureDefn->AddFieldDefn(&oField);
+            }
+        }
+    }
+
+    /* Wait, we didn't find a FID? */
+    /* Game over, all valid tables must have a FID */
+    if ( ! bFidFound )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "no primary key defined for table '%s'", m_pszTableName);
+        return OGRERR_FAILURE;
+        
+    }
+
+    if ( bReadExtent )
+    {
+        m_poExtent = new OGREnvelope(oExtent);
+    }
+
+    SQLResultFree(&oResultTable);
+    SQLResultFree(&oResultGeomCols);
+
+    /* Update the columns string */
+    BuildColumns();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                      OGRGeoPackageLayer()                            */
+/************************************************************************/
+
+OGRGeoPackageLayer::OGRGeoPackageLayer(
+                    OGRGeoPackageDataSource *poDS,
+                    const char * pszTableName)
+{
+    m_pszTableName = CPLStrdup(pszTableName);
+    m_pszFidColumn = NULL;
+    m_iSrs = 0;
+    m_poDS = poDS;
+    m_poExtent = NULL;
+    m_bExtentChanged = FALSE;
+    m_poFeatureDefn = NULL;
+    m_poQueryStatement = NULL;
+    m_poUpdateStatement = NULL;
+    m_poInsertStatement = NULL;
+    m_poFidStatement = NULL;
+    m_soColumns = "";
+    m_soFilter = "";
+}
+
+
+/************************************************************************/
+/*                      ~OGRGeoPackageLayer()                           */
+/************************************************************************/
+
+OGRGeoPackageLayer::~OGRGeoPackageLayer()
+{
+    /* Save metadata back to the database */
+    SaveExtent();
+
+    /* Clean up resources in memory */
+    if ( m_pszTableName )
+        CPLFree( m_pszTableName );
+    
+    if ( m_pszFidColumn )
+        CPLFree( m_pszFidColumn );
+    
+    if ( m_poExtent )
+        delete m_poExtent;
+    
+    if ( m_poQueryStatement )
+        sqlite3_finalize(m_poQueryStatement);
+
+    if ( m_poUpdateStatement )
+        sqlite3_finalize(m_poUpdateStatement);
+
+    if ( m_poInsertStatement )
+        sqlite3_finalize(m_poInsertStatement);
+    
+    if ( m_poFidStatement )
+        sqlite3_finalize(m_poFidStatement);
+        
+    if ( m_poFeatureDefn )
+        m_poFeatureDefn->Release();
+}
+
+
+/************************************************************************/
+/*                      CreateField()                                   */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
+{
+    if( !m_poDS->IsUpdatable() )
+    {
+        return OGRERR_FAILURE;
+    }
+    
+    if ( ! m_poFeatureDefn || ! m_pszTableName )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "feature definition or table name is null");
+        return OGRERR_FAILURE;
+    }
+
+    OGRErr err = m_poDS->AddColumn(m_pszTableName, 
+                                   poField->GetNameRef(),
+                                   GPkgFieldFromOGR(poField->GetType()));
+
+    if ( err != OGRERR_NONE )
+        return err;
+    
+    m_poFeatureDefn->AddFieldDefn( poField );
+    ResetReading();
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                      CreateFeature()                                 */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::CreateFeature( OGRFeature *poFeature )
+{
+    if( !m_poDS->IsUpdatable() )
+    {
+        return OGRERR_FAILURE;
+    }
+
+    if ( ! m_poFeatureDefn || ! m_pszTableName )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "feature definition or table name is null");
+        return OGRERR_FAILURE;
+    }
+
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to CreateFeature()" );
+        return OGRERR_FAILURE;
+    }
+
+    if ( ! m_poInsertStatement ) 
+    {
+        /* Construct a SQL INSERT statement from the OGRFeature */
+        /* Only work with fields that are set */
+        /* Do not stick values into SQL, use placeholder and bind values later */    
+        CPLString osCommand = FeatureGenerateInsertSQL(poFeature);
+        
+        /* Prepare the SQL into a statement */
+        sqlite3 *poDb = m_poDS->GetDatabaseHandle();
+        int err = sqlite3_prepare_v2(poDb, osCommand, -1, &m_poInsertStatement, NULL);
+        if ( err != SQLITE_OK )
+        {
+            m_poInsertStatement = NULL;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "failed to prepare SQL: %s", osCommand.c_str());        
+            return OGRERR_FAILURE;
+        }        
+    }
+    
+    /* Bind values onto the statement now */
+    OGRErr errOgr = FeatureBindInsertParameters(poFeature, m_poInsertStatement);
+    if ( errOgr != OGRERR_NONE )
+        return errOgr;
+
+    /* From here execute the statement and check errors */
+    int err = sqlite3_step(m_poInsertStatement);
+    if ( ! (err == SQLITE_OK || err == SQLITE_DONE) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to execute insert");
+        return OGRERR_FAILURE; 
+    }
+
+    sqlite3_reset(m_poInsertStatement);
+    sqlite3_clear_bindings(m_poInsertStatement);
+
+    /* Update the layer extents with this new object */
+    if ( IsGeomFieldSet(poFeature) )
+    {
+        OGREnvelope oEnv;
+        poFeature->GetGeomFieldRef(0)->getEnvelope(&oEnv);
+        UpdateExtent(&oEnv);
+    }
+
+    /* Read the latest FID value */
+    int iFid;
+    if ( (iFid = sqlite3_last_insert_rowid(m_poDS->GetDatabaseHandle())) )
+    {
+        poFeature->SetFID(iFid);
+    }
+    else
+    {
+        poFeature->SetFID(OGRNullFID);
+    }
+    
+    /* All done! */
+	return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                          SetFeature()                                */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::SetFeature( OGRFeature *poFeature )
+{
+    if( !m_poDS->IsUpdatable() )
+    {
+        return OGRERR_FAILURE;
+    }
+    
+    if ( ! m_poFeatureDefn || ! m_pszTableName )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "feature definition or table name is null");
+        return OGRERR_FAILURE;
+    }
+
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to CreateFeature()" );
+        return OGRERR_FAILURE;
+    }
+
+    /* No FID? We can't set, we have to create */
+    if ( poFeature->GetFID() == OGRNullFID )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FID required on features given to SetFeature()." );
+        return OGRERR_FAILURE;
+    }
+
+    if ( ! m_poUpdateStatement )
+    {
+        /* Construct a SQL INSERT statement from the OGRFeature */
+        /* Only work with fields that are set */
+        /* Do not stick values into SQL, use placeholder and bind values later */    
+        CPLString osCommand = FeatureGenerateUpdateSQL(poFeature);
+
+        /* Prepare the SQL into a statement */
+        int err = sqlite3_prepare_v2(m_poDS->GetDatabaseHandle(), osCommand, -1, &m_poUpdateStatement, NULL);
+        if ( err != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "failed to prepare SQL: %s", osCommand.c_str());        
+            return OGRERR_FAILURE;
+        }
+    }
+
+    /* Bind values onto the statement now */
+    OGRErr errOgr = FeatureBindUpdateParameters(poFeature, m_poUpdateStatement);
+    if ( errOgr != OGRERR_NONE )
+        return errOgr;
+
+    /* From here execute the statement and check errors */
+    int err = sqlite3_step(m_poUpdateStatement);
+    if ( ! (err == SQLITE_OK || err == SQLITE_DONE) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to execute update");
+        return OGRERR_FAILURE;       
+    }
+
+    sqlite3_reset(m_poUpdateStatement);
+    sqlite3_clear_bindings(m_poUpdateStatement);
+
+    /* Only update the envelope if we changed something */
+    if (sqlite3_changes(m_poDS->GetDatabaseHandle()) )
+    {
+        /* Update the layer extents with this new object */
+        if ( IsGeomFieldSet(poFeature) )
+        {
+            OGREnvelope oEnv;
+            poFeature->GetGeomFieldRef(0)->getEnvelope(&oEnv);
+            UpdateExtent(&oEnv);
+        }
+    }
+
+    /* All done! */
+	return OGRERR_NONE;
+}
+
+
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    if( pszQuery == NULL )
+        m_soFilter.Clear();
+    else
+        m_soFilter = pszQuery;
+
+    ResetReading();
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                      ResetReading()                                  */
+/************************************************************************/
+
+void OGRGeoPackageLayer::ResetReading()
+{
+    if ( m_poQueryStatement )
+    {
+        sqlite3_finalize(m_poQueryStatement);
+        m_poQueryStatement = NULL;
+    }
+
+    if ( m_poInsertStatement )
+    {
+        sqlite3_finalize(m_poInsertStatement);
+        m_poInsertStatement = NULL;
+    }
+
+    if ( m_poUpdateStatement )
+    {
+        sqlite3_finalize(m_poUpdateStatement);
+        m_poUpdateStatement = NULL;
+    }
+    
+    if ( m_poFidStatement )
+    {
+        sqlite3_finalize(m_poFidStatement);
+        m_poFidStatement = NULL;
+    }
+    
+    BuildColumns();
+    return;
+}
+
+
+/************************************************************************/
+/*                        GetNextFeature()                              */
+/************************************************************************/
+
+OGRFeature* OGRGeoPackageLayer::GetNextFeature()
+{
+    /* There is no active query statement set up, */
+    /* so job #1 is to prepare the statement. */
+    if ( ! m_poQueryStatement )
+    {
+        /* Append the attribute filter, if there is one */
+        CPLString soSQL;
+        if ( m_soFilter.length() > 0 )
+            soSQL.Printf("SELECT %s FROM %s WHERE %s", m_soColumns.c_str(), m_pszTableName, m_soFilter.c_str());
+        else
+            soSQL.Printf("SELECT %s FROM %s ", m_soColumns.c_str(), m_pszTableName);
+
+        int err = sqlite3_prepare(m_poDS->GetDatabaseHandle(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
+        if ( err != SQLITE_OK )
+        {
+            m_poQueryStatement = NULL;
+            CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());            
+            return NULL;
+        }
+    }
+    
+    while ( TRUE )
+    {
+        int err = sqlite3_step(m_poQueryStatement);
+        
+        /* Nothing left in statement? NULL return indicates to caller */
+        /* that there are no features left */
+        if ( err == SQLITE_DONE )
+        {
+            return NULL;
+        }
+        /* Got a row, let's read it */
+        else if ( err == SQLITE_ROW )
+        {
+            OGRFeature *poFeature;
+            
+            /* Fetch the feature */
+            if ( ReadFeature(m_poQueryStatement, &poFeature) != OGRERR_NONE )
+                return NULL;
+            
+            if( (m_poFilterGeom == NULL || FilterGeometry(poFeature->GetGeometryRef()) ) &&
+                (m_poAttrQuery  == NULL || m_poAttrQuery->Evaluate(poFeature)) )
+            {
+                return poFeature;                
+            }
+
+            /* This feature doesn't pass the filters */
+            /* So delete it and loop again to try the next row */
+            delete poFeature;
+        }
+        else 
+        {
+            /* Got neither a row, nor the end of the query. */
+            /* Something terrible has happened, break out of loop */
+            /* CPLError( CE_Failure, CPLE_AppDefined, "unable to step through query statement"); */
+            return NULL;
+        }
+
+    }
+
+}	
+
+/************************************************************************/
+/*                        GetFeature()                                  */
+/************************************************************************/
+
+OGRFeature* OGRGeoPackageLayer::GetFeature(long nFID)
+{
+    /* No FID, no answer. */
+    if (nFID == OGRNullFID)
+        return NULL;
+    
+    /* Clear out any existing query */
+    ResetReading();
+
+    /* No filters apply, just use the FID */
+    CPLString soSQL;
+    soSQL.Printf("SELECT %s FROM %s WHERE %s = %ld",
+                 m_soColumns.c_str(), m_pszTableName, m_pszFidColumn, nFID);
+
+    int err = sqlite3_prepare(m_poDS->GetDatabaseHandle(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
+    if ( err != SQLITE_OK )
+    {
+        m_poQueryStatement = NULL;
+        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());            
+        return NULL;
+    }
+    
+    /* Should be only one or zero results */
+    err = sqlite3_step(m_poQueryStatement);
+        
+    /* Nothing left in statement? NULL return indicates to caller */
+    /* that there are no features left */
+    if ( err == SQLITE_DONE )
+        return NULL;
+
+    /* Aha, got one */
+    if ( err == SQLITE_ROW )
+    {
+        OGRFeature *poFeature;
+        
+        /* Fetch the feature */
+        if ( ReadFeature(m_poQueryStatement, &poFeature) != OGRERR_NONE )
+            return NULL;
+            
+        if ( poFeature )
+            return poFeature;                
+        else 
+            return NULL;
+    }
+    
+    /* Error out on all other return codes */
+    return NULL;
+}
+
+/************************************************************************/
+/*                        DeleteFeature()                               */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::DeleteFeature(long nFID)	
+{
+    if( !m_poDS->IsUpdatable() )
+    {
+        return OGRERR_FAILURE;
+    }
+    
+    /* No FID, no answer. */
+    if (nFID == OGRNullFID)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "delete feature called with null FID");
+        return OGRERR_FAILURE;
+    }
+    
+    /* Clear out any existing query */
+    ResetReading();
+
+    /* No filters apply, just use the FID */
+    CPLString soSQL;
+    soSQL.Printf("DELETE FROM %s WHERE %s = %ld",
+                 m_pszTableName, m_pszFidColumn, nFID);
+
+    
+    return SQLCommand(m_poDS->GetDatabaseHandle(), soSQL.c_str());
+}
+
+/************************************************************************/
+/*                      GetFIDColumn()                                  */
+/************************************************************************/
+
+const char* OGRGeoPackageLayer::GetFIDColumn()
+{
+    if ( ! m_pszFidColumn )
+        return "";
+    else
+        return m_pszFidColumn;
+}
+
+/************************************************************************/
+/*                        SyncToDisk()                                  */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::SyncToDisk()
+{
+    SaveExtent();
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        StartTransaction()                            */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::StartTransaction()
+{
+    return SQLCommand(m_poDS->GetDatabaseHandle(), "BEGIN");
+}
+
+
+/************************************************************************/
+/*                        CommitTransaction()                           */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::CommitTransaction()
+{
+    return SQLCommand(m_poDS->GetDatabaseHandle(), "COMMIT");
+}
+
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::RollbackTransaction()
+{
+    return SQLCommand(m_poDS->GetDatabaseHandle(), "ROLLBACK");
+}
+
+
+/************************************************************************/
+/*                        GetFeatureCount()                             */
+/************************************************************************/
+
+int OGRGeoPackageLayer::GetFeatureCount( int bForce )
+{
+    if( m_poFilterGeom != NULL )
+        return OGRLayer::GetFeatureCount(bForce);
+
+    /* Ignore bForce, because we always do a full count on the database */
+    OGRErr err;
+    CPLString soSQL;
+    if ( m_soFilter.length() > 0 )
+        soSQL.Printf("SELECT Count(*) FROM %s WHERE %s", m_pszTableName, m_soFilter.c_str());
+    else
+        soSQL.Printf("SELECT Count(*) FROM %s ", m_pszTableName);
+
+    /* Just run the query directly and get back integer */
+    int iFeatureCount = SQLGetInteger(m_poDS->GetDatabaseHandle(), soSQL.c_str(), &err);
+
+    /* Generic implementation uses -1 for error condition, so we will too */
+    if ( err == OGRERR_NONE )
+        return iFeatureCount;
+    else
+        return -1;
+}
+
+
+/************************************************************************/
+/*                        GetExtent()                                   */
+/************************************************************************/
+
+OGRErr OGRGeoPackageLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    /* Extent already calculated! We're done. */
+    if ( m_poExtent != NULL )
+    {
+        if ( psExtent )
+        {
+            *psExtent = *m_poExtent;            
+        }
+        return OGRERR_NONE;
+    }
+
+    /* User is OK with expensive calculation, fall back to */
+    /* default implementation (scan all features) and save */
+    /* the result for later */
+    if ( bForce )
+    {
+        OGRErr err = OGRLayer::GetExtent(psExtent, bForce);
+        if ( err != OGRERR_NONE )
+            return err;
+    
+        *m_poExtent = *psExtent;
+        return SaveExtent();
+    }
+
+    return OGRERR_FAILURE;
+}
+
+
+
+/************************************************************************/
+/*                      TestCapability()                                */
+/************************************************************************/
+
+int OGRGeoPackageLayer::TestCapability ( const char * pszCap )
+{
+    if ( EQUAL(pszCap, OLCCreateField) ||
+         EQUAL(pszCap, OLCSequentialWrite) ||
+         EQUAL(pszCap, OLCDeleteFeature) ||
+         EQUAL(pszCap, OLCRandomWrite) )
+    {
+        return m_poDS->IsUpdatable();
+    }
+    else if ( EQUAL(pszCap, OLCRandomRead) ||
+              EQUAL(pszCap, OLCTransactions) )
+    {
+        return TRUE;
+    }
+    else if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+    {
+        return m_poDS->GetUTF8();
+    }
+    else if ( EQUAL(pszCap, OLCFastGetExtent) )
+    {
+        if ( m_poExtent && ! m_poFilterGeom )
+            return TRUE;
+        else
+            return FALSE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
new file mode 100644
index 0000000..6fc9f80
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
@@ -0,0 +1,614 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Utility functions for OGR GeoPackage driver.
+ * Author:   Paul Ramsey, pramsey at boundlessgeo.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+ 
+ 
+#include "ogrgeopackageutility.h"
+#include "ogr_p.h"
+
+/* Runs a SQL command and ignores the result (good for INSERT/UPDATE/CREATE) */
+OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
+{
+    CPLAssert( poDb != NULL );
+    CPLAssert( pszSQL != NULL );
+
+    char *pszErrMsg = NULL;
+    int rc = sqlite3_exec(poDb, pszSQL, NULL, NULL, &pszErrMsg);
+    
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "sqlite3_exec(%s) failed: %s",
+                  pszSQL, pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+    
+    return OGRERR_NONE;
+}
+
+
+OGRErr SQLResultInit(SQLResult * poResult)
+{
+    poResult->papszResult = NULL;
+    poResult->pszErrMsg = NULL;
+    poResult->nRowCount = 0;
+    poResult->nColCount = 0;
+    poResult->rc = 0;
+    return OGRERR_NONE;
+}
+
+
+OGRErr SQLQuery(sqlite3 * poDb, const char * pszSQL, SQLResult * poResult)
+{
+    CPLAssert( poDb != NULL );
+    CPLAssert( pszSQL != NULL );
+    CPLAssert( poResult != NULL );
+
+    SQLResultInit(poResult);
+
+    poResult->rc = sqlite3_get_table(
+        poDb, pszSQL,
+        &(poResult->papszResult), 
+        &(poResult->nRowCount), 
+        &(poResult->nColCount), 
+        &(poResult->pszErrMsg) );
+    
+    if( poResult->rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "sqlite3_get_table(%s) failed: %s", pszSQL, poResult->pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+
+OGRErr SQLResultFree(SQLResult * poResult)
+{
+    if ( poResult->papszResult )
+        sqlite3_free_table(poResult->papszResult);
+
+    if ( poResult->pszErrMsg )
+        sqlite3_free(poResult->pszErrMsg);
+        
+    return OGRERR_NONE;
+}
+
+const char* SQLResultGetColumn(const SQLResult * poResult, int iColNum)
+{
+    if ( ! poResult ) 
+        return NULL;
+        
+    if ( iColNum < 0 || iColNum >= poResult->nColCount )
+        return NULL;
+    
+    return poResult->papszResult[iColNum];
+}
+
+const char* SQLResultGetValue(const SQLResult * poResult, int iColNum, int iRowNum)
+{
+    if ( ! poResult ) 
+        return NULL;
+
+    int nCols = poResult->nColCount;
+    int nRows = poResult->nRowCount;    
+        
+    if ( iColNum < 0 || iColNum >= nCols )
+        return NULL;
+
+    if ( iRowNum < 0 || iRowNum >= nRows )
+        return NULL;
+        
+    return poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
+}
+
+int SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum)
+{
+    if ( ! poResult ) 
+        return 0;
+        
+    int nCols = poResult->nColCount;
+    int nRows = poResult->nRowCount;
+    
+    if ( iColNum < 0 || iColNum >= nCols )
+        return 0;
+
+    if ( iRowNum < 0 || iRowNum >= nRows )
+        return 0;
+    
+    char *pszValue = poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
+    if ( ! pszValue )
+        return 0;
+
+    return atoi(pszValue);
+}
+
+/* Returns the first row of first column of SQL as integer */
+int SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
+{
+    CPLAssert( poDb != NULL );
+    
+    sqlite3_stmt *poStmt;
+    int rc, i;
+    
+    /* Prepare the SQL */
+    rc = sqlite3_prepare_v2(poDb, pszSQL, strlen(pszSQL), &poStmt, NULL);
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
+                  pszSQL, sqlite3_errmsg( poDb ) );
+        if ( err ) *err = OGRERR_FAILURE;
+        return 0;
+    }
+    
+    /* Execute and fetch first row */
+    rc = sqlite3_step(poStmt);
+    if ( rc != SQLITE_ROW )
+    {
+        if ( err ) *err = OGRERR_FAILURE;
+        return 0;
+    }
+    
+    /* Read the integer from the row */
+    i = sqlite3_column_int(poStmt, 0);
+    sqlite3_finalize(poStmt);
+    
+    if ( err ) *err = OGRERR_NONE;
+    return i;
+}
+
+
+/* Requirement 20: A GeoPackage SHALL store feature table geometries */
+/* with the basic simple feature geometry types (Geometry, Point, */
+/* LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, */
+/* GeomCollection) */
+/* http://opengis.github.io/geopackage/#geometry_types */
+OGRwkbGeometryType GPkgGeometryTypeToWKB(const char *pszGpkgType, int bHasZ)
+{
+    OGRwkbGeometryType oType;
+    
+    if ( EQUAL("Geometry", pszGpkgType) )
+        oType = wkbUnknown;
+    else if ( EQUAL("Point", pszGpkgType) )
+        oType =  wkbPoint;
+    else if ( EQUAL("LineString", pszGpkgType) )
+        oType =  wkbLineString;
+    else if ( EQUAL("Polygon", pszGpkgType) )
+        oType =  wkbPolygon;
+    else if ( EQUAL("MultiPoint", pszGpkgType) )
+        oType =  wkbMultiPoint;
+    else if ( EQUAL("MultiLineString", pszGpkgType) )
+        oType =  wkbMultiLineString;
+    else if ( EQUAL("MultiPolygon", pszGpkgType) )
+        oType =  wkbMultiPolygon;
+    else if ( EQUAL("GeometryCollection", pszGpkgType) )
+        oType =  wkbGeometryCollection;
+    else
+        oType =  wkbNone;
+
+    if ( (oType != wkbNone) && bHasZ )
+    {
+        unsigned int oi = oType;
+        oi &= wkb25DBit;
+        oType = (OGRwkbGeometryType)oi;
+    }
+
+    return oType;
+}
+
+/* Requirement 20: A GeoPackage SHALL store feature table geometries */
+/* with the basic simple feature geometry types (Geometry, Point, */
+/* LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, */
+/* GeomCollection) */
+/* http://opengis.github.io/geopackage/#geometry_types */
+const char* GPkgGeometryTypeFromWKB(OGRwkbGeometryType oType)
+{
+    oType = wkbFlatten(oType);
+    
+    switch(oType)
+    {
+        case wkbPoint:
+            return "point";
+        case wkbLineString:
+            return "linestring";
+        case wkbPolygon:
+            return "polygon";
+        case wkbMultiPoint:
+            return "multipoint";
+        case wkbMultiLineString:
+            return "multilinestring";
+        case wkbMultiPolygon:
+            return "multipolygon";
+        case wkbGeometryCollection:
+            return "geometrycollection";
+        default:
+            return NULL;
+    }
+}
+
+/* Requirement 5: The columns of tables in a GeoPackage SHALL only be */
+/* declared using one of the data types specified in table GeoPackage */
+/* Data Types. */
+/* http://opengis.github.io/geopackage/#table_column_data_types */
+OGRFieldType GPkgFieldToOGR(const char *pszGpkgType)
+{
+    /* Integer types */
+    if ( STRNCASECMP("INTEGER", pszGpkgType, 7) == 0 )
+        return OFTInteger;
+    else if ( STRNCASECMP("INT", pszGpkgType, 3) == 0 )
+        return OFTInteger;
+    else if ( STRNCASECMP("MEDIUMINT", pszGpkgType, 9) == 0 )
+        return OFTInteger;
+    else if ( STRNCASECMP("SMALLINT", pszGpkgType, 8) == 0 )
+        return OFTInteger;
+    else if ( STRNCASECMP("TINYINT", pszGpkgType, 7) == 0 )
+        return OFTInteger;
+    else if ( STRNCASECMP("BOOLEAN", pszGpkgType, 7) == 0 )
+        return OFTInteger;
+
+    /* Real types */
+    else if ( STRNCASECMP("FLOAT", pszGpkgType, 5) == 0 )
+        return OFTReal;
+    else if ( STRNCASECMP("DOUBLE", pszGpkgType, 6) == 0 )
+        return OFTReal;
+    else if ( STRNCASECMP("REAL", pszGpkgType, 4) == 0 )
+        return OFTReal;
+        
+    /* String/binary types */
+    else if ( STRNCASECMP("TEXT", pszGpkgType, 4) == 0 )
+        return OFTString;
+    else if ( STRNCASECMP("BLOB", pszGpkgType, 4) == 0 )
+        return OFTBinary;
+        
+    /* Date types */
+    else if ( STRNCASECMP("DATE", pszGpkgType, 4) == 0 )
+        return OFTDate;
+    else if ( STRNCASECMP("DATETIME", pszGpkgType, 8) == 0 )
+        return OFTDateTime;
+
+    /* Illegal! */
+    else 
+        return (OGRFieldType)(OFTMaxType + 1);
+}
+
+/* Requirement 5: The columns of tables in a GeoPackage SHALL only be */
+/* declared using one of the data types specified in table GeoPackage */
+/* Data Types. */
+/* http://opengis.github.io/geopackage/#table_column_data_types */
+const char* GPkgFieldFromOGR(OGRFieldType nType)
+{
+    switch(nType)
+    {
+        case OFTInteger:
+            return "INTEGER";
+        case OFTReal:
+            return "REAL";
+        case OFTString:
+            return "TEXT";
+        case OFTBinary:
+            return "BLOB";
+        case OFTDate:
+            return "DATE";
+        case OFTDateTime:
+            return "DATETIME";
+        default:
+            return NULL;
+    }
+}
+
+
+int SQLiteFieldFromOGR(OGRFieldType nType)
+{
+    switch(nType)
+    {
+        case OFTInteger:
+            return SQLITE_INTEGER;
+        case OFTReal:
+            return SQLITE_FLOAT;
+        case OFTString:
+            return SQLITE_TEXT;
+        case OFTBinary:
+            return SQLITE_BLOB;
+        case OFTDate:
+            return SQLITE_TEXT;
+        case OFTDateTime:
+            return SQLITE_TEXT;
+        default:
+            return 0;
+    }
+}
+
+
+
+
+/* Requirement 19: A GeoPackage SHALL store feature table geometries 
+*  with or without optional elevation (Z) and/or measure (M) values in SQL 
+*  BLOBs using the Standard GeoPackageBinary format specified in table GeoPackage 
+*  SQL Geometry Binary Format and clause Geometry Encoding.
+*
+*  http://opengis.github.io/geopackage/#gpb_format
+*
+*   GeoPackageBinaryHeader {
+*     byte[2] magic = 0x4750; 
+*     byte version;           
+*     byte flags;             
+*     int32 srs_id;
+*     double[] envelope;      
+*    }
+* 
+*   StandardGeoPackageBinary {
+*     GeoPackageBinaryHeader header; 
+*     WKBGeometry geometry;          
+*   }
+*
+*  Flags byte contents:
+*  Bit 7: Reserved for future
+*  Bit 6: Reserved for future
+*  Bit 5: Using Extended GPKG Binary?
+*  Bit 4: Geometry is Empty?
+*  Bit 3,2,1: Envelope contents (0 none, 1=X/Y, 2=X/Y/Z, 3=X/Y/M, 4=X/Y/Z/M)
+*  Bit 0: Byte order of header (0=big/XDR, 1=little/NDR)
+*
+*/
+
+GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *pszWkb)
+{
+    CPLAssert( poGeometry != NULL );
+    
+    GByte *pabyPtr;
+    GByte byFlags = 0;
+    GByte byEnv = 1;
+    OGRwkbByteOrder eByteOrder = (OGRwkbByteOrder)CPL_IS_LSB;
+    OGRErr err;
+    OGRBoolean bPoint = (wkbFlatten(poGeometry->getGeometryType()) == wkbPoint);
+    OGRBoolean bEmpty = poGeometry->IsEmpty();
+    int iDims = poGeometry->getCoordinateDimension();
+
+    /* Header has 8 bytes for sure, and optional extra space for bounds */
+    size_t szHeader = 2+1+1+4;    
+    if ( ! bPoint && ! bEmpty )
+    {
+        szHeader += 8*2*iDims;
+    }
+    
+    /* Total BLOB size is header + WKB size */
+    size_t szWkb = szHeader + poGeometry->WkbSize();
+    GByte *pabyWkb = (GByte *)CPLMalloc(szWkb);
+    if (pszWkb)
+        *pszWkb = szWkb;
+    
+    /* Header Magic */
+    pabyWkb[0] = 0x47;
+    pabyWkb[1] = 0x50;
+
+    /* GPKG BLOB Version */
+    pabyWkb[2] = 0;
+    
+    /* Extended? No. */
+
+    /* Envelope dimensionality? */
+
+    /* Don't write envelope for point type */
+    if ( bPoint )
+        byEnv = 0; 
+    else
+        /* 3D envelope for 3D data */      
+        if ( iDims == 3 )
+            byEnv = 2;
+        /* 2D envelope otherwise */      
+        else
+            byEnv = 1;
+    
+    /* Empty? No envelope then. */
+    if ( bEmpty )
+    {
+        byEnv = 0;
+        /* Set empty flag */
+        byFlags |= (1 << 4);
+    }
+    
+    /* Set envelope flags */
+    byFlags |= (byEnv << 1);
+
+    /* Byte order of header? */
+    /* Use native endianness */
+    byFlags |= eByteOrder;
+
+    /* Write flags byte */
+    pabyWkb[3] = byFlags;
+    
+    /* Write srs_id */
+    memcpy(pabyWkb+4, &iSrsId, 4);
+    
+    /* Write envelope */
+    if ( ! bEmpty && ! bPoint )
+    {
+        double *padPtr = (double*)(pabyWkb+8);
+        if ( iDims == 3 )
+        {
+            OGREnvelope3D oEnv3d;
+            poGeometry->getEnvelope(&oEnv3d);
+            padPtr[0] = oEnv3d.MinX;
+            padPtr[1] = oEnv3d.MaxX;
+            padPtr[2] = oEnv3d.MinY;
+            padPtr[3] = oEnv3d.MaxY;
+            padPtr[4] = oEnv3d.MinZ;
+            padPtr[5] = oEnv3d.MaxZ;
+        }
+        else
+        {
+            OGREnvelope oEnv;
+            poGeometry->getEnvelope(&oEnv);
+            padPtr[0] = oEnv.MinX;
+            padPtr[1] = oEnv.MaxX;
+            padPtr[2] = oEnv.MinY;
+            padPtr[3] = oEnv.MaxY;
+        }
+    }
+    
+    pabyPtr = pabyWkb + szHeader;
+    
+    /* Use the wkbVariantIso for ISO SQL/MM output (differs for 3d geometry) */
+    err = poGeometry->exportToWkb(eByteOrder, pabyPtr, wkbVariantIso);
+    if ( err != OGRERR_NONE )
+    {
+        CPLFree(pabyWkb);
+        return NULL;
+    }
+    
+    return pabyWkb; 
+}
+
+
+OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader)
+{
+    CPLAssert( pabyGpkg != NULL );
+    CPLAssert( poHeader != NULL );
+
+    /* Magic (match required) */
+    if ( pabyGpkg[0] != 0x47 || 
+         pabyGpkg[1] != 0x50 ||
+         pabyGpkg[2] != 0 )  /* Version (only 0 supported at this time)*/
+    {
+        return OGRERR_FAILURE;
+    }
+
+    /* Flags */
+    GByte byFlags = pabyGpkg[3];
+    poHeader->bEmpty = (byFlags & (0x01 << 4)) >> 4;
+    poHeader->bExtended = (byFlags & (0x01 << 5)) >> 5;
+    poHeader->eByteOrder = (OGRwkbByteOrder)(byFlags & 0x01);
+    OGRBoolean bSwap = OGR_SWAP(poHeader->eByteOrder);
+
+    /* Envelope */
+    int iEnvelope = (byFlags & (0x07 << 1)) >> 1;
+    if ( iEnvelope == 1 )
+        poHeader->iDims = 2; /* 2D envelope */
+    else if ( iEnvelope == 2 )
+        poHeader->iDims = 3; /* 3D envelope */
+    else 
+        poHeader->iDims = 0; /* No envelope */
+
+    /* SrsId */
+    int iSrsId;
+    memcpy(&iSrsId, pabyGpkg+4, 4);    
+    if ( bSwap )
+    {
+        iSrsId = CPL_SWAP32(iSrsId);
+    }
+    poHeader->iSrsId = iSrsId;
+    
+    /* Envelope */
+    double *padPtr = (double*)(pabyGpkg+8);
+    if ( poHeader->iDims == 2 )
+    {
+        poHeader->MinX = padPtr[0];
+        poHeader->MaxX = padPtr[1];
+        poHeader->MinY = padPtr[2];
+        poHeader->MaxY = padPtr[3];
+        if ( bSwap )
+        {
+            CPL_SWAPDOUBLE(&(poHeader->MinX));
+            CPL_SWAPDOUBLE(&(poHeader->MaxX));
+            CPL_SWAPDOUBLE(&(poHeader->MinY));
+            CPL_SWAPDOUBLE(&(poHeader->MaxY));
+        }
+    }
+    if ( poHeader->iDims == 3 )
+    {
+        poHeader->MinZ = padPtr[4];
+        poHeader->MaxZ = padPtr[5];
+        if ( bSwap )
+        {
+            CPL_SWAPDOUBLE(&(poHeader->MinZ));
+            CPL_SWAPDOUBLE(&(poHeader->MaxZ));
+        }
+    }
+    
+    /* Header size in byte stream */
+    poHeader->szHeader = 8 + 8*2*(poHeader->iDims);
+    
+    return OGRERR_NONE;
+}
+
+OGRGeometry* GPkgGeometryToOGR(GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs)
+{
+    CPLAssert( pabyGpkg != NULL );
+    
+    GPkgHeader oHeader;
+    OGRGeometry *poGeom;
+    
+    /* Read header */
+    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, &oHeader);
+    if ( err != OGRERR_NONE )
+        return NULL;
+
+    /* WKB pointer */
+    GByte *pabyWkb = pabyGpkg + oHeader.szHeader;
+    size_t szWkb = szGpkg - oHeader.szHeader;
+
+    /* Parse WKB */
+    err = OGRGeometryFactory::createFromWkb(pabyWkb, poSrs, &poGeom, szWkb);
+    if ( err != OGRERR_NONE )
+        return NULL;
+
+    return poGeom;
+}
+
+
+OGRErr GPkgEnvelopeToOGR(GByte *pabyGpkg, size_t szGpkg, OGREnvelope *poEnv)
+{
+    CPLAssert( poEnv != NULL );
+    CPLAssert( pabyGpkg != NULL );
+    
+    GPkgHeader oHeader;
+
+    /* Read header */
+    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, &oHeader);
+    if ( err != OGRERR_NONE )
+        return err;
+
+    if ( oHeader.bEmpty || oHeader.iDims == 0 )
+    {
+        return OGRERR_FAILURE;
+    }
+    
+    poEnv->MinX = oHeader.MinX;
+    poEnv->MaxX = oHeader.MaxX;
+    poEnv->MinY = oHeader.MinY;
+    poEnv->MaxY = oHeader.MaxY;
+    
+    // if ( oHeader.iDims == 3 )
+    // {
+    //     poEnv->MinZ = oHeader.MinZ;
+    //     poEnv->MaxZ = oHeader.MaxZ;
+    // }
+    
+    return OGRERR_NONE;
+}
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
new file mode 100644
index 0000000..26c27fb
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Utility header for OGR GeoPackage driver.
+ * Author:   Paul Ramsey, pramsey at boundlessgeo.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsf_frmts.h"
+#include "sqlite3.h"
+
+#ifndef _OGR_GEOPACKAGEUTILITY_H_INCLUDED
+#define _OGR_GEOPACKAGEUTILITY_H_INCLUDED
+
+typedef struct 
+{
+    char** papszResult;
+    int nRowCount;
+    int nColCount;
+    char *pszErrMsg;
+    int rc;
+} SQLResult;
+
+typedef struct 
+{
+    OGRBoolean bEmpty;
+    OGRBoolean bExtended;
+    OGRwkbByteOrder eByteOrder;
+    int iSrsId;
+    int iDims;
+    double MinX, MaxX, MinY, MaxY, MinZ, MaxZ;
+    size_t szHeader;
+} GPkgHeader;
+
+
+OGRErr              SQLCommand(sqlite3 *poDb, const char * pszSQL);
+int                 SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err);
+
+OGRErr              SQLResultInit(SQLResult * poResult);
+OGRErr              SQLQuery(sqlite3 *poDb, const char * pszSQL, SQLResult * poResult);
+const char*         SQLResultGetColumn(const SQLResult * poResult, int iColumnNum);
+const char*         SQLResultGetValue(const SQLResult * poResult, int iColumnNum, int iRowNum);
+int                 SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum);
+OGRErr              SQLResultFree(SQLResult * poResult);
+
+int                 SQLiteFieldFromOGR(OGRFieldType nType);
+
+OGRFieldType        GPkgFieldToOGR(const char *pszGpkgType);
+const char*         GPkgFieldFromOGR(OGRFieldType nType);
+OGRwkbGeometryType  GPkgGeometryTypeToWKB(const char *pszGpkgType, int bHasZ);
+const char*         GPkgGeometryTypeFromWKB(OGRwkbGeometryType oType);
+
+GByte*              GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *szWkb);
+OGRGeometry*        GPkgGeometryToOGR(GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs);
+OGRErr              GPkgEnvelopeToOGR(GByte *pabyGpkg, size_t szGpkg, OGREnvelope *poEnv);
+
+OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader);
+
+#endif
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
index 02a64d4..10c5c64 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
+++ b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_gpsbabel.h 25526 2013-01-19 20:41:08Z rouault $
+ * $Id: ogr_gpsbabel.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/GPSBabel driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
index 3b83269..7263633 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgpsbabeldatasource.cpp 25598 2013-02-05 22:24:35Z rouault $
+ * $Id: ogrgpsbabeldatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +35,7 @@
 
 #include <string.h>
 
-CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 25598 2013-02-05 22:24:35Z rouault $");
+CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      OGRGPSBabelDataSource()                         */
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
index beabfc5..3d37c41 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
index 7c075dd..c9affec 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgpsbabelwritedatasource.cpp 25598 2013-02-05 22:24:35Z rouault $
+ * $Id: ogrgpsbabelwritedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelWriteDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "cpl_error.h"
 #include "cpl_spawn.h"
 
-CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 25598 2013-02-05 22:24:35Z rouault $");
+CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                    OGRGPSBabelWriteDataSource()                      */
diff --git a/ogr/ogrsf_frmts/gpx/ogr_gpx.h b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
index 660a6ed..fc15ed3 100644
--- a/ogr/ogrsf_frmts/gpx/ogr_gpx.h
+++ b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_gpx.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_gpx.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Definition of classes for OGR .gpx driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -144,8 +144,6 @@ class OGRGPXLayer : public OGRLayer
     
     int                 TestCapability( const char * );
     
-    OGRSpatialReference *GetSpatialRef();
-    
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
index 76641db..e18129b 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgpxdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
+ * $Id: ogrgpxdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgpxdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
+CPL_CVSID("$Id: ogrgpxdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define SPACE_FOR_METADATA 160
 
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
index 41f8d3d..0bcb666 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgpxdriver.cpp 15805 2008-11-23 21:42:01Z rouault $
+ * $Id: ogrgpxdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_gpx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgpxdriver.cpp 15805 2008-11-23 21:42:01Z rouault $");
+CPL_CVSID("$Id: ogrgpxdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRGPXDriver()                            */
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
index 8c0f4c6..eb6bf6a 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrgpxlayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrgpxlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXLayer class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "cpl_minixml.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgpxlayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrgpxlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define FLD_TRACK_FID       0
 #define FLD_TRACK_SEG_ID    1
@@ -285,6 +285,8 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
         "       UNIT[\"degree\",0.01745329251994328,"
         "           AUTHORITY[\"EPSG\",\"9122\"]],"
         "           AUTHORITY[\"EPSG\",\"4326\"]]");
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     poFeature = NULL;
 
@@ -1068,16 +1070,6 @@ OGRFeature *OGRGPXLayer::GetNextFeature()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRGPXLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                  OGRGPX_GetXMLCompatibleTagName()                    */
 /************************************************************************/
 
@@ -1811,7 +1803,8 @@ int OGRGPXLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCSequentialWrite) )
         return bWriteMode;
-
+    else if( EQUAL(pszCap,OLCCreateField) )
+        return bWriteMode;
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
 
diff --git a/ogr/ogrsf_frmts/grass/GNUmakefile b/ogr/ogrsf_frmts/grass/GNUmakefile
index 96f59ed..0e168a3 100644
--- a/ogr/ogrsf_frmts/grass/GNUmakefile
+++ b/ogr/ogrsf_frmts/grass/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrgrassdriver.o ogrgrassdatasource.o ogrgrasslayer.o
 
-CPPFLAGS	:=	-DUSE_CPL -DGRASS_GISBASE=\"$(GRASS_GISBASE)\" -I.. -I../.. $(GRASS_INCLUDE) $(GDAL_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:=	-DUSE_CPL -DGRASS_GISBASE=\"$(GRASS_GISBASE)\" -I.. -I../.. $(GRASS_INCLUDE) $(GDAL_INCLUDE) $(PG_INC) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/grass/drv_grass.html b/ogr/ogrsf_frmts/grass/drv_grass.html
index 29e17a9..3252428 100644
--- a/ogr/ogrsf_frmts/grass/drv_grass.html
+++ b/ogr/ogrsf_frmts/grass/drv_grass.html
@@ -1,115 +1,131 @@
 <html>
 <head>
-<title>GRASS</title>
+<title>GRASS Vector Format</title>
 </head>
 
 <body bgcolor="#ffffff">
 
-<h1>GRASS</h1>
+<h1>GRASS Vector Format</h1>
 
 GRASS driver can read GRASS (version 6.0 and higher) vector maps.
-Each GRASS vector map is represented as one datasource. 
-A GRASS vector map may have 0, 1 or more layers. 
-<P>
-GRASS points are represented as wkbPoint, lines and boundaries
-as wkbLineString and areas as wkbPolygon. wkbMulti* and
-wkbGeometryCollection are not used.
-More feature types can be mixed in one layer. If a layer contains 
-only features of one type, it is set appropriately and can be retrieved 
-by OGRLayer::GetLayerDefn();
-<P>
-If a geometry has more categories of the same layer attached, its 
+Each GRASS vector map is represented as one datasource.  A GRASS
+vector map may have 0, 1 or more layers.
+
+<p>
+GRASS points are represented as wkbPoint, lines and boundaries as
+wkbLineString and areas as wkbPolygon. wkbMulti* and
+wkbGeometryCollection are not used.  More feature types can be mixed
+in one layer. If a layer contains only features of one type, it is set
+appropriately and can be retrieved by OGRLayer::GetLayerDefn();
+
+<p>
+If a geometry has more categories of the same layer attached, its
 represented as more features (one for each category).
-<P>
+
+<p>
 Both 2D and 3D maps are supported.
 
 <h2>Datasource name</h2>
+
 Datasource name is full path to 'head' file in GRASS vector directory.
 Using names of GRASS enviroment variables it can be expressed:
-<PRE>
+<pre>
    $GISDBASE/$LOCATION_NAME/$MAPSET/vector/mymap/head
-</PRE>
+</pre>
 where 'mymap' is name of a vector map. For example:
-<PRE>
+<pre>
    /home/cimrman/grass_data/jizerky/jara/vector/liptakov/head
-</PRE>
+</pre>
 
 <h2>Layer names</h2>
-Usualy layer numbers are used as layer names. Layer number 0 is 
-used for all features without any category. It is possible to 
-optionaly give names to GRASS layers linked to database 
-however currently this is not supported by grass modules.
-A layer name can be added in 'dbln' vector file as '/name'
-after layer number, for example to original record:
-<PRE>
+
+Usualy layer numbers are used as layer names. Layer number 0 is used
+for all features without any category. It is possible to optionaly
+give names to GRASS layers linked to database however currently this
+is not supported by grass modules.  A layer name can be added in
+'dbln' vector file as '/name' after layer number, for example to
+original record:
+
+<pre>
 1 rivers cat $GISDBASE/$LOCATION_NAME/$MAPSET/dbf/ dbf
-</PRE>
+</pre>
 it is possible to assign name 'rivers'
-<PRE>
+<pre>
 1/rivers rivers cat $GISDBASE/$LOCATION_NAME/$MAPSET/dbf/ dbf
-</PRE>
+</pre>
 the layer 1 will be listed is layer 'rivers'.
 
 <h2>Attribute filter</h2>
-If a layer has attributes stored in a database, the query is passed 
-to the underlaying database driver. That means, that SQL conditions
-which can be used depend on the driver and database to which the layer 
-is linked. For example, DBF driver has currently very limited 
-set of SQL expressions and PostgreSQL offeres very rich set of 
-SQL expressions.
+
+If a layer has attributes stored in a database, the query is passed to
+the underlaying database driver. That means, that SQL conditions which
+can be used depend on the driver and database to which the layer is
+linked. For example, DBF driver has currently very limited set of SQL
+expressions and PostgreSQL offeres very rich set of SQL expressions.
+
+<p>
+If a layer has no attributes linked and it has only categories, OGR
+internal SQL engine is used to evaluate the expression.  Category is
+an integer number attached to geometry, it is sort of ID, but it is
+not FID as more features in one layer can have the same category.
+
 <p>
-If a layer has no attributes linked and it has only categories,
-OGR internal SQL engine is used to evaluate the expression.
-Category is an integer number attached to geometry, it is sort of ID,
-but it is not FID as more features in one layer can have the same category.
-<P>
 Evaluation is done once when the attribute filter is set.
 
 <h2>Spatial filter</h2>
-Bounding boxes of features stored in topology structure are used 
-to evaluate if a features matches current spatial filter.
-<P>
+
+Bounding boxes of features stored in topology structure are used to
+evaluate if a features matches current spatial filter.
+
+<p>
 Evaluation is done once when the spatial filter is set.
 
 <h2>GISBASE</h2>
-GISBASE is full path to the directory where GRASS is installed.
-By default, GRASS driver is using the path given to gdal configure script.
-A different directory can be forced by setting GISBASE enviroment variable.
-GISBASE is used to find GRASS database drivers.
+
+GISBASE is full path to the directory where GRASS is installed.  By
+default, GRASS driver is using the path given to gdal configure
+script.  A different directory can be forced by setting GISBASE
+enviroment variable.  GISBASE is used to find GRASS database drivers.
 
 <h2>Missing topology</h2>
-GRASS driver can read GRASS vector files if topology is available (AKA level 2).
-If an error is reported, telling that the topology is not available, it is necessary
-to build topology within GRASS using v.build module.
+
+GRASS driver can read GRASS vector files if topology is available (AKA
+level 2).  If an error is reported, telling that the topology is not
+available, it is necessary to build topology within GRASS using
+v.build module.
 
 <h2>Random access</h2>
-If random access (GetFeature instead of GetNextFeature) is used on layer 
-with attributes, the reading of features can be quite slow. It is because the driver 
-has to query attributes by category for each feature (to avoid using a lot of memory)
-and random access to database is usually slow. This can be improved on GRASS
-side optimizing/writing file based (DBF,SQLite) drivers.
+
+If random access (GetFeature instead of GetNextFeature) is used on
+layer with attributes, the reading of features can be quite slow. It
+is because the driver has to query attributes by category for each
+feature (to avoid using a lot of memory) and random access to database
+is usually slow. This can be improved on GRASS side optimizing/writing
+file based (DBF,SQLite) drivers.
 
 <h2>Known problem</h2>
-Because of bug in GRASS library, it is impossible to start/stop database
-drivers in FIFO order and FILO order must be used. The GRASS driver for OGR
-is written with this limit in mind and drivers are always closed if not used 
-and if a driver remains opened kill() is used to terminate it.
-It can happen however in rare cases, that the driver will try to stop
-database driver which is not the last opened and an application hangs.
-This can happen if sequential read (GetNextFeature) of a layer is not 
-finished (reading is stopped before last available feature is reached),
-features from another layer are read and then the reading of the first layer 
-is finished, because in that case kill() is not used.
+
+Because of bug in GRASS library, it is impossible to start/stop
+database drivers in FIFO order and FILO order must be used. The GRASS
+driver for OGR is written with this limit in mind and drivers are
+always closed if not used and if a driver remains opened kill() is
+used to terminate it.  It can happen however in rare cases, that the
+driver will try to stop database driver which is not the last opened
+and an application hangs.  This can happen if sequential read
+(GetNextFeature) of a layer is not finished (reading is stopped before
+last available feature is reached), features from another layer are
+read and then the reading of the first layer is finished, because in
+that case kill() is not used.
 
 <h2>See Also</h2>
+
 <ul>
-<li> <a href="http://grass.itc.it">GRASS home page</a><p>
+<li> <a href="http://grass.osgeo.org">GRASS GIS home page</a><p>
 </ul>
 
-<HR>
+<hr>
 Development of this driver was financially supported by Faunalia 
 (<a href="http://www.faunalia.it/">www.faunalia.it</a>).
 
-
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
index 565af4a..9298c45 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgrassdatasource.cpp 20157 2010-07-28 19:32:04Z rouault $
+ * $Id: ogrgrassdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Radim Blazek <radim.blazek at gmail.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgrassdatasource.cpp 20157 2010-07-28 19:32:04Z rouault $");
+CPL_CVSID("$Id: ogrgrassdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         Grass2CPLErrorHook()                         */
@@ -188,7 +189,9 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
 /*      Open GRASS vector map                                           */
 /* -------------------------------------------------------------------- */
+#if GRASS_VERSION_MAJOR  < 7
     Vect_set_fatal_error ( GV_FATAL_PRINT ); // Print error and continue
+#endif
     Vect_set_open_level (2);
     int level = Vect_open_old ( &map, pszMap, pszMapset);
 
diff --git a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
index d0b6533..0e2462f 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgrasslayer.cpp 20157 2010-07-28 19:32:04Z rouault $
+ * $Id: ogrgrasslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Radim Blazek <radim.blazek at gmail.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogrgrass.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgrasslayer.cpp 20157 2010-07-28 19:32:04Z rouault $");
+CPL_CVSID("$Id: ogrgrasslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRGRASSLayer()                            */
diff --git a/ogr/ogrsf_frmts/gtm/gtm.cpp b/ogr/ogrsf_frmts/gtm/gtm.cpp
index 47182f8..b815e5a 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtm.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gtm.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtmfile.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gtm/gtm.h b/ogr/ogrsf_frmts/gtm/gtm.h
index d158806..f8b57aa 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.h
+++ b/ogr/ogrsf_frmts/gtm/gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtm.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gtm.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtm file.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
index ad95e8f..de4672a 100644
--- a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmtracklayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
+ * $Id: gtmtracklayer.cpp 26464 2013-09-13 21:06:03Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of GTMTrackLayer class.
@@ -81,6 +81,7 @@ GTMTrackLayer::GTMTrackLayer( const char* pszName,
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType ( wkbLineString );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     /* We implement just name, type, and color for tracks, if others
        needed feel free to append more parameters and implement the
diff --git a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
index d10e65b..d28058b 100644
--- a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmwaypointlayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
+ * $Id: gtmwaypointlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of gtmwaypoint class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -81,6 +82,7 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType ( wkbPoint );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     /* We implement just name, comment, and icon, if others needed feel
        free to append more parameters */
diff --git a/ogr/ogrsf_frmts/gtm/ogr_gtm.h b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
index 6f1c102..6b978cf 100644
--- a/ogr/ogrsf_frmts/gtm/ogr_gtm.h
+++ b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gtm.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_gtm.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Declarations for OGR wrapper classes for GTM, and OGR->GTM
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -90,7 +91,6 @@ public:
     // OGRLayer Interface
     //
     OGRFeatureDefn* GetLayerDefn();
-    OGRSpatialReference* GetSpatialRef() {return poSRS;}
     virtual void ResetReading() = 0;
     virtual OGRFeature* GetNextFeature() = 0;
     virtual int GetFeatureCount(int bForce = TRUE) = 0;
diff --git a/ogr/ogrsf_frmts/htf/ogr_htf.h b/ogr/ogrsf_frmts/htf/ogr_htf.h
index d9fb7c7..29db8ca 100644
--- a/ogr/ogrsf_frmts/htf/ogr_htf.h
+++ b/ogr/ogrsf_frmts/htf/ogr_htf.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_htf.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_htf.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Definition of classes for OGR .htf driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -69,8 +69,6 @@ protected:
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
     void    SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
 
@@ -142,8 +140,6 @@ protected:
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * ) { return FALSE; }
-
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
index f0b883c..38b2de8 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrhtfdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
+ * $Id: ogrhtfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrhtfdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
+CPL_CVSID("$Id: ogrhtfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRHTFDataSource()                          */
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
index 4cba0a5..0f2de65 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrhtfdriver.cpp 20735 2010-10-03 13:40:34Z rouault $
+ * $Id: ogrhtfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_htf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrhtfdriver.cpp 20735 2010-10-03 13:40:34Z rouault $");
+CPL_CVSID("$Id: ogrhtfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRHTF();
 
diff --git a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
index 8bf2b70..c7ab582 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrhtflayer.cpp 20766 2010-10-05 09:07:28Z rouault $
+ * $Id: ogrhtflayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrhtflayer.cpp 20766 2010-10-05 09:07:28Z rouault $");
+CPL_CVSID("$Id: ogrhtflayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRHTFLayer()                             */
@@ -67,6 +67,7 @@ OGRHTFPolygonLayer::OGRHTFPolygonLayer( const char* pszFilename, int nZone, int
     poFeatureDefn = new OGRFeatureDefn( "polygon" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPolygon  );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     OGRFieldDefn    oField1( "DESCRIPTION", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
@@ -93,6 +94,7 @@ OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone, in
     poFeatureDefn = new OGRFeatureDefn( "sounding" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint  );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     this->nTotalSoundings = nTotalSoundings;
     bHasFPK = FALSE;
diff --git a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
index ac3f204..5b6e8d0 100644
--- a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridbdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogridbdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogridbdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogridbdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $");
 /************************************************************************/
 /*                         OGRIDBDataSource()                          */
 /************************************************************************/
@@ -279,9 +279,9 @@ OGRLayer * OGRIDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic imlplementation for OGRSQL dialect.                 */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
index 1e7f3c2..52a0b17 100644
--- a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridbtablelayer.cpp 14412 2008-05-09 15:02:27Z warmerdam $
+ * $Id: ogridbtablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBTableLayer class, access to an existing table
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_idb.h"
 
-CPL_CVSID("$Id: ogridbtablelayer.cpp 14412 2008-05-09 15:02:27Z warmerdam $");
+CPL_CVSID("$Id: ogridbtablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $");
 /************************************************************************/
 /*                          OGRIDBTableLayer()                         */
 /************************************************************************/
@@ -378,6 +378,9 @@ OGRFeature *OGRIDBTableLayer::GetFeature( long nFeatureId )
 OGRErr OGRIDBTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( (pszQuery == NULL && this->pszQuery == NULL)
         || (pszQuery != NULL && this->pszQuery != NULL 
             && EQUAL(pszQuery,this->pszQuery)) )
diff --git a/ogr/ogrsf_frmts/idrisi/generate_test_files.c b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
index 6a5b107..a7b4288 100644
--- a/ogr/ogrsf_frmts/idrisi/generate_test_files.c
+++ b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
index fc66d9c..4a13f04 100644
--- a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
+++ b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_idrisi.h 24397 2012-05-07 20:11:28Z rouault $
+ * $Id: ogr_idrisi.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Idrisi Translator
  * Purpose:  Definition of classes for OGR Idrisi driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -76,8 +76,6 @@ protected:
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
     void SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
 
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
index 428ebc0..d709518 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogridrisidatasource.cpp 24397 2012-05-07 20:11:28Z rouault $
+ * $Id: ogridrisidatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "idrisi.h"
 
-CPL_CVSID("$Id: ogridrisidatasource.cpp 24397 2012-05-07 20:11:28Z rouault $");
+CPL_CVSID("$Id: ogridrisidatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRIdrisiDataSource()                         */
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
index 129df51..25f6774 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_idrisi.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogridrisidriver.cpp 23040 2011-09-04 14:42:12Z rouault $");
+CPL_CVSID("$Id: ogridrisidriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // g++ ogr/ogrsf_frmts/idrisi/*.cpp -Wall -g -fPIC -shared -o ogr_Idrisi.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/idrisi -Iogr/ogrsf_frmts -Ifrmts/idrisi
 
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
index 1462920..5aebc90 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogridrisilayer.cpp 25795 2013-03-24 13:16:52Z rouault $
+ * $Id: ogridrisilayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogridrisilayer.cpp 25795 2013-03-24 13:16:52Z rouault $");
+CPL_CVSID("$Id: ogridrisilayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRIdrisiLayer()                             */
@@ -63,6 +63,7 @@ OGRIdrisiLayer::OGRIdrisiLayer( const char* pszFilename,
 
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     poFeatureDefn->SetGeomType( eGeomType );
 
     OGRFieldDefn oFieldDefn("id", OFTReal);
diff --git a/ogr/ogrsf_frmts/ili/GNUmakefile b/ogr/ogrsf_frmts/ili/GNUmakefile
index 534d55a..5959635 100644
--- a/ogr/ogrsf_frmts/ili/GNUmakefile
+++ b/ogr/ogrsf_frmts/ili/GNUmakefile
@@ -1,13 +1,11 @@
 
 
-SUBDIRS-yes     := iom
-
 include ../../../GDALmake.opt
 
 OBJ	=	ogrili1driver.o ogrili1datasource.o ogrili1layer.o \
                 ogrili2driver.o ogrili2datasource.o ogrili2layer.o \
                 ili1reader.o ili2reader.o ili2handler.o \
-                iomhelper.o ilihelper.o
+                ilihelper.o imdreader.o
 
 ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
@@ -15,9 +13,9 @@ endif
 
 CPPFLAGS :=	-I.. -I../.. $(GDAL_INCLUDE) $(XERCES_INCLUDE) $(CPPFLAGS)
 
-default:	$(foreach d,$(SUBDIRS-yes),$(d)-target)	$(O_OBJ:.o=.$(OBJ_EXT))
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
-clean: $(foreach d,$(SUBDIRS-yes),$(d)-clean)
+clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ):	ogr_ili1.h ogr_ili2.h iomhelper.h ili1reader.h ili1readerp.h ili2reader.h ili2readerp.h
+$(O_OBJ):	ogr_ili1.h ogr_ili2.h ilihelper.h imdreader.h ili1reader.h ili1readerp.h ili2reader.h ili2readerp.h
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.cpp b/ogr/ogrsf_frmts/ili/ili1reader.cpp
index 45f34a7..c2e7234 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili1reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1reader.cpp 24610 2012-06-25 15:21:32Z pka $
+ * $Id: ili1reader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Implementation of ILI1Reader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,6 @@
 #include "ogr_geos.h"
 
 #include "ilihelper.h"
-#include "iomhelper.h"
 #include "ili1reader.h"
 #include "ili1readerp.h"
 
@@ -46,11 +46,11 @@
 
 #ifndef POLYGONIZE_AREAS
 #  if defined(__GNUC_PREREQ)
-#    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 2.1.0
+#    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 3.1.0
 #  endif
 #endif
 
-CPL_CVSID("$Id: ili1reader.cpp 24610 2012-06-25 15:21:32Z pka $");
+CPL_CVSID("$Id: ili1reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 //
 // ILI1Reader
@@ -63,23 +63,19 @@ ILI1Reader::ILI1Reader() {
   nLayers = 0;
   papoLayers = NULL;
   curLayer = NULL;
-  metaLayer = NULL;
   codeBlank = '_';
   codeUndefined = '@';
   codeContinue = '\\';
   SetArcDegrees(1);
-
 }
 
 ILI1Reader::~ILI1Reader() {
- int i;
- if (fpItf) VSIFClose( fpItf );
+  int i;
+  if (fpItf) VSIFClose( fpItf );
 
- for(i=0;i<nLayers;i++)
+  for(i=0;i<nLayers;i++)
      delete papoLayers[i];
- CPLFree(papoLayers);
-
- delete metaLayer;
+  CPLFree(papoLayers);
 }
 
 void ILI1Reader::SetArcDegrees(double arcDegrees) {
@@ -93,315 +89,47 @@ int ILI1Reader::OpenFile( const char *pszFilename ) {
     fpItf = VSIFOpen( pszFilename, "r" );
     if( fpItf == NULL )
     {
-          CPLError( CE_Failure, CPLE_OpenFailed,
-                    "Failed to open ILI file `%s'.",
-                    pszFilename );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open ILI file `%s'.",
+                  pszFilename );
 
         return FALSE;
     }
     return TRUE;
 }
 
-int ILI1Reader::HasMultiplePointGeom(const char* layername) {
-    if (metaLayer != NULL) {
-        OGRFeature *metaFeature = NULL;
-        metaLayer->ResetReading();
-        int i = -1;
-        while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
-            if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
-              i++;
-            }
-            delete metaFeature;
-        }
-        return i;
-    } else {
-        return -1;
-    }
-}
-
-char* ILI1Reader::GetPointLayerName(const char* layername, char* newlayername) {
-    static char geomlayername[512];
-    geomlayername[0] = '\0';
-    strcat(geomlayername, layername);
-    strcat(geomlayername, "__");
-    strcat(geomlayername, newlayername);
-    return geomlayername;
-}
-
 const char* ILI1Reader::GetLayerNameString(const char* topicname, const char* tablename) {
-    static char layername[512];
-    layername[0] = '\0';
-    strcat(layername, topicname);
-    strcat(layername, "__");
-    strcat(layername, tablename);
-    return layername;
-}
 
-const char* ILI1Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
-    static char layername[512];
-    IOM_OBJECT topic = GetAttrObj(model, table, "container");
-    layername[0] = '\0';
-    strcat(layername, iom_getattrvalue(topic, "name"));
-    strcat(layername, "__");
-    strcat(layername, iom_getattrvalue(table, "name"));
-    return layername;
+    return CPLSPrintf("%s__%s", topicname, tablename);
 }
 
-void ILI1Reader::AddCoord(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT modelele, IOM_OBJECT typeobj) {
-  unsigned int dim = ::GetCoordDim(model, typeobj);
-  for (unsigned int i=0; i<dim; i++) {
-    OGRFieldDefn fieldDef(CPLSPrintf("%s_%d", iom_getattrvalue(modelele, "name"), i), OFTReal);
-    layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-    //CPLDebug( "AddCoord   OGR_ILI", "Field %s: OFTReal", fieldDef.GetNameRef());
-  }
-}
+int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS) {
 
-OGRILI1Layer* ILI1Reader::AddGeomTable(const char* datalayername, const char* geomname, OGRwkbGeometryType eType) {
-  static char layername[512];
-  layername[0] = '\0';
-  strcat(layername, datalayername);
-  strcat(layername, "_");
-  strcat(layername, geomname);
-
-  OGRILI1Layer* geomlayer = new OGRILI1Layer(layername, NULL, 0, eType, NULL);
-  AddLayer(geomlayer);
-  OGRFieldDefn fieldDef("_TID", OFTString);
-  geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-  if (eType == wkbPolygon)
+  poImdReader->ReadModel(pszModelFilename);
+  for (FeatureDefnInfos::const_iterator it = poImdReader->featureDefnInfos.begin(); it != poImdReader->featureDefnInfos.end(); ++it)
   {
-     OGRFieldDefn fieldDefRef("_RefTID", OFTString);
-     geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDefRef);
-  }
-  OGRFieldDefn fieldDef2("ILI_Geometry", OFTString); //in write mode only?
-  geomlayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
-  return geomlayer;
-}
-
-void ILI1Reader::AddField(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT obj) {
-  const char* typenam = "Reference";
-  if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
-  //CPLDebug( "OGR_ILI", "Field %s: %s", iom_getattrvalue(obj, "name"), typenam);
-  if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
-    OGRILI1Layer* polyLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbPolygon);
-    layer->SetSurfacePolyLayer(polyLayer);
-    //TODO: add line attributes to geometry
-  } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
-    IOM_OBJECT controlPointDomain = GetAttrObj(model, GetTypeObj(model, obj), "controlPointDomain");
-    if (controlPointDomain) {
-      AddCoord(layer, model, obj, GetTypeObj(model, controlPointDomain));
-      layer->GetLayerDefn()->SetGeomType(wkbPoint);
-    }
-    OGRILI1Layer* areaLineLayer = AddGeomTable(layer->GetLayerDefn()->GetName(), iom_getattrvalue(obj, "name"), wkbMultiLineString);
-#ifdef POLYGONIZE_AREAS
-    OGRILI1Layer* areaLayer = new OGRILI1Layer(CPLSPrintf("%s__Areas",layer->GetLayerDefn()->GetName()), NULL, 0, wkbPolygon, NULL);
-    AddLayer(areaLayer);
-    areaLayer->SetAreaLayers(layer, areaLineLayer);
-#endif
-  } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
-    layer->GetLayerDefn()->SetGeomType(wkbMultiLineString);
-  } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
-    AddCoord(layer, model, obj, GetTypeObj(model, obj));
-    if (layer->GetLayerDefn()->GetGeomType() == wkbUnknown) layer->GetLayerDefn()->SetGeomType(wkbPoint);
-  } else if (EQUAL(typenam, "iom04.metamodel.NumericType") ) {
-     OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTReal);
-     layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-  } else if (EQUAL(typenam, "iom04.metamodel.EnumerationType") ) {
-     OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTInteger);
-     layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-  } else {
-    OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
-    layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-  }
-}
-
-int ILI1Reader::ReadModel(const char *pszModelFilename) {
-
-  IOM_BASKET model;
-  IOM_ITERATOR modelelei;
-  IOM_OBJECT modelele;
-
-  iom_init();
-
-  // set error listener to a iom provided one, that just
-  // dumps all errors to stderr
-  iom_seterrlistener(iom_stderrlistener);
-
-  // compile ili model
-  char *iomarr[1] = {(char *)pszModelFilename};
-  model=iom_compileIli(1, iomarr);
-  if(!model){
-    CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
-    iom_end();
-    return FALSE;
-  }
-
-  // create new layer with meta information (ILI table name and geometry column index)
-  // while reading the features from the ITF we have to know which column is the geometry column
-  metaLayer = new OGRILI1Layer("Metatable", NULL, 0, wkbUnknown, NULL);
-  OGRFieldDefn fieldDef1("layername", OFTString);
-  metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef1);
-  OGRFieldDefn fieldDef2("geomIdx", OFTInteger);
-  metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef2);
-  OGRFieldDefn fieldDef3("geomlayername", OFTString);
-  metaLayer->GetLayerDefn()->AddFieldDefn(&fieldDef3);
-
-
-  // read tables
-  int j = 0;
-  modelelei=iom_iteratorobject(model);
-  modelele=iom_nextobject(modelelei);
-  while(modelele){
-    const char *tag=iom_getobjecttag(modelele);
-
-    if (tag) {
-      if (EQUAL(tag,"iom04.metamodel.Table")) {
-
-        const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
-
-        if (!EQUAL(topic, "INTERLIS")) {
-
-          const char* layername = GetLayerName(model, modelele);
-          OGRSpatialReference *poSRSIn = NULL;
-          int bWriterIn = 0;
-          OGRwkbGeometryType eReqType = wkbUnknown;
-          OGRILI1DataSource *poDSIn = NULL;
-
-          CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
-
-          // read fields
-          IOM_OBJECT fields[255];
-          IOM_OBJECT roledefs[255];
-          memset(fields, 0, 255);
-          memset(roledefs, 0, 255);
-          int maxIdx = -1;
-          IOM_ITERATOR fieldit=iom_iteratorobject(model);
-          std::vector<IOM_OBJECT> attributes;
-
-          for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
-            const char *etag=iom_getobjecttag(fieldele);
-
-            if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
-              IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
-
-              if (table == modelele) {
-
-                IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
-                int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
-
-                if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
-                  int ili1AttrIdxOppend = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
-
-                  if (ili1AttrIdxOppend>=0) {
-                    roledefs[ili1AttrIdxOppend] = obj;
-                    if (ili1AttrIdxOppend > maxIdx) maxIdx = ili1AttrIdxOppend;
-                  }
-                } else {
-                  fields[ili1AttrIdx] = obj;
-                  if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
-                }
-              }
-            }
-            iom_releaseobject(fieldele);
-          }
-          iom_releaseiterator(fieldit);
-
-          // if multiple gets positive we have more than one geometry column (only points)
-          int multiple = -1;
-
-          for (int i=0; i<=maxIdx; i++) {
-            IOM_OBJECT obj = fields[i];
-            if (obj) {
-             attributes.push_back(obj);
-             if (EQUAL(GetTypeName(model, obj), "iom04.metamodel.CoordType")) multiple++;
-            }
-          }
-
-          for (int i=0; i<=maxIdx; i++) {
-            IOM_OBJECT obj = roledefs[i];
-            if (obj) attributes.insert(attributes.begin() + i, obj);
-          }
-
-          OGRFeature *feature = NULL;
-          char* geomlayername = '\0';
-          OGRILI1Layer* layer = NULL;
-
-          for(size_t i=0; i<attributes.size(); i++) {
-            IOM_OBJECT obj = attributes.at(i);
-            const char* typenam = GetTypeName(model, obj);
-            if (EQUAL(typenam, "iom04.metamodel.CoordType")  || EQUAL(typenam, "iom04.metamodel.AreaType")) {
-              feature = OGRFeature::CreateFeature(metaLayer->GetLayerDefn());
-              feature->SetFID(j+1);
-              feature->SetField("layername", layername);
-              feature->SetField("geomIdx", (int)i);
-
-              if(multiple > 0) {
-                geomlayername = GetPointLayerName(layername, iom_getattrvalue(obj, "name"));
-                feature->SetField("geomlayername", geomlayername);
-                layer = new OGRILI1Layer(geomlayername, poSRSIn, bWriterIn, eReqType, poDSIn);
-                AddLayer(layer);
-
-              } else {
-                feature->SetField("geomlayername", layername);
-                layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
-                AddLayer(layer);
-              }
-              metaLayer->AddFeature(feature);
-            }
-          }
-
-          if(layer == NULL) {
-            layer = new OGRILI1Layer(layername, poSRSIn, bWriterIn, eReqType, poDSIn);
-            AddLayer(layer);
-          }
-
-          OGRFieldDefn fieldDef("_TID", OFTString);
-          layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-
-          for(size_t i=0; i<attributes.size(); i++) {
-            IOM_OBJECT obj = attributes.at(i);
-            AddField(layer, model, obj);
-          }
-
-          // additional point layer added
-          if(multiple > 0) {
-            for(int i = 1; i <= multiple; i++) {
-               OGRILI1Layer* pointLayer = papoLayers[nLayers-(i+1)];
-               for (int j=0; j < layer->GetLayerDefn()->GetFieldCount(); j++) {
-                 pointLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(j));
-               }
-            if (pointLayer->GetLayerDefn()->GetGeomType() == wkbUnknown) pointLayer->GetLayerDefn()->SetGeomType(wkbPoint);
-            }
-          }
-
-          if (papoLayers[nLayers-1]->GetLayerDefn()->GetFieldCount() == 0) {
-              //Area layer added
-              OGRILI1Layer* areaLayer = papoLayers[nLayers-1];
-              for (int i=0; i < layer->GetLayerDefn()->GetFieldCount(); i++) {
-                areaLayer->CreateField(layer->GetLayerDefn()->GetFieldDefn(i));
-              }
-          }
-        }
-      } else if (EQUAL(tag,"iom04.metamodel.Ili1Format")) {
-        codeBlank = atoi(iom_getattrvalue(modelele, "blankCode"));
-        CPLDebug( "OGR_ILI", "Reading Ili1Format blankCode '%c'", codeBlank );
-        codeUndefined = atoi(iom_getattrvalue(modelele, "undefinedCode"));
-        CPLDebug( "OGR_ILI", "Reading Ili1Format undefinedCode '%c'", codeUndefined );
-        codeContinue = atoi(iom_getattrvalue(modelele, "continueCode"));
-        CPLDebug( "OGR_ILI", "Reading Ili1Format continueCode '%c'", codeContinue );
+    //CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with table '%s'", it->poTableDefn->GetName() );
+    OGRILI1Layer* layer = new OGRILI1Layer(it->poTableDefn, it->poGeomFieldInfos, poDS);
+    AddLayer(layer);
+    //Create additional layers for surface and area geometries
+    for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin(); it2 != it->poGeomFieldInfos.end(); ++it2)
+    {
+      if (it2->second.geomTable)
+      {
+        GeomFieldInfos oGeomFieldInfos;
+        //CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with geometry table '%s'", it2->second.geomTable->GetName() );
+        OGRILI1Layer* geomlayer = new OGRILI1Layer(it2->second.geomTable, oGeomFieldInfos, poDS);
+        AddLayer(geomlayer);
       }
-      iom_releaseobject(modelele);
-
-      modelele=iom_nextobject(modelelei);
-      j++;
     }
   }
 
-  iom_releaseiterator(modelelei);
-
-  iom_releasebasket(model);
-
-  iom_end();
-
+  codeBlank = poImdReader->codeBlank;
+  CPLDebug( "OGR_ILI", "Ili1Format blankCode '%c'", poImdReader->codeBlank );
+  codeUndefined = poImdReader->codeUndefined;
+  CPLDebug( "OGR_ILI", "Ili1Format undefinedCode '%c'", poImdReader->codeUndefined );
+  codeContinue = poImdReader->codeContinue;
+  CPLDebug( "OGR_ILI", "Ili1Format continueCode '%c'", poImdReader->codeContinue );
   return 0;
 }
 
@@ -448,21 +176,17 @@ int ILI1Reader::ReadFeatures() {
       }
       else if (EQUAL(firsttok, "TABL"))
       {
-        CPLDebug( "OGR_ILI", "Reading table '%s'", GetLayerNameString(topic, CSLGetField(tokens, 1)) );
         const char *layername = GetLayerNameString(topic, CSLGetField(tokens, 1));
+        CPLDebug( "OGR_ILI", "Reading table '%s'", layername );
         curLayer = GetLayerByName(layername);
 
-        int multiple = HasMultiplePointGeom(layername);
-
-        // create only a new layer if there is no curLayer AND
-        // if there are more than one point geometry columns
-        if (curLayer == NULL && multiple < 1) { //create one
-          CPLDebug( "OGR_ILI", "No model found, using default field names." );
-          OGRSpatialReference *poSRSIn = NULL;
-          int bWriterIn = 0;
-          OGRwkbGeometryType eReqType = wkbUnknown;
-          OGRILI1DataSource *poDSIn = NULL;
-          curLayer = new OGRILI1Layer(GetLayerNameString(topic, CSLGetField(tokens, 1)), poSRSIn, bWriterIn, eReqType, poDSIn);
+        if (curLayer == NULL) { //create one
+          CPLError(CE_Warning, CPLE_AppDefined,
+              "No model definition for table '%s' found, using default field names.", layername );
+          OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(GetLayerNameString(topic, CSLGetField(tokens, 1)));
+          poFeatureDefn->SetGeomType( wkbUnknown );
+          GeomFieldInfos oGeomFieldInfos;
+          curLayer = new OGRILI1Layer(poFeatureDefn, oGeomFieldInfos, NULL);
           AddLayer(curLayer);
         }
         if(curLayer != NULL) {
@@ -486,7 +210,7 @@ int ILI1Reader::ReadFeatures() {
       }
       else
       {
-        CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
+        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
@@ -529,40 +253,11 @@ int ILI1Reader::ReadTable(const char *layername) {
     int ret = TRUE;
     int warned = FALSE;
     int fIndex;
-    int geomIdx = 0;
-
-    // curLayer is NULL if we have more than one
-    // point geometry column
-    if(curLayer == NULL) {
-      OGRFeature *metaFeature = NULL;
-      metaLayer->ResetReading();
-      while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
-        if(EQUAL(layername, metaFeature->GetFieldAsString(0))) {
-          const char *geomlayername = metaFeature->GetFieldAsString(2);
-          curLayer = GetLayerByName(geomlayername);
-          delete metaFeature;
-          break;
-        }
-        delete metaFeature;
-      }
-    }
+    int geomIdx = -1;
 
     OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
     OGRFeature *feature = NULL;
 
-    // get the geometry index of the current layer
-    // only if the model is read
-    if(featureDef->GetFieldCount() != 0) {
-      OGRFeature *metaFeature = NULL;
-      metaLayer->ResetReading();
-      while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
-        if(EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
-          geomIdx = metaFeature->GetFieldAsInteger(1);
-        }
-        delete metaFeature;
-      }
-    }
-
     long fpos = VSIFTell(fpItf);
     while (ret && (tokens = ReadParseLine()))
     {
@@ -570,7 +265,7 @@ int ILI1Reader::ReadTable(const char *layername) {
       if (EQUAL(firsttok, "OBJE"))
       {
         //Check for features spread over multiple objects
-        if (featureDef->GetGeomType() == wkbPolygon)
+        if (featureDef->GetGeomType() == wkbPolygon) //FIXME: Multi-geom support
         {
           //Multiple polygon rings
           feature = curLayer->GetFeatureRef(atol(CSLGetField(tokens, 2)));
@@ -588,7 +283,8 @@ int ILI1Reader::ReadTable(const char *layername) {
         {
           if (featureDef->GetFieldCount() == 0)
           {
-            CPLDebug( "OGR_ILI", "No field definition found for table: %s", featureDef->GetName() );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                "No field definition found for table: %s", featureDef->GetName() );
             //Model not read - use heuristics
             for (fIndex=1; fIndex<CSLCount(tokens); fIndex++)
             {
@@ -620,36 +316,56 @@ int ILI1Reader::ReadTable(const char *layername) {
               }
               if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTReal
                   && fieldno > 0
-                  && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal
-                  && featureDef->GetGeomType() == wkbPoint
-
-                  /*
-                  // if there is no ili model read,
-                  // we have no chance to detect the
-                  // geometry column!!
-                  */
-
-                  && (fieldno-2) == geomIdx) {
-                //add Point geometry
-                OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-1]), atof(tokens[fIndex]));
-                feature->SetGeometryDirectly(ogrPoint);
+                  && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal) {
+                //check for Point geometry (Coord type)
+                // if there is no ili model read,
+                // we have no chance to detect the
+                // geometry column!!
+                CPLString geomfldname = featureDef->GetFieldDefn(fieldno)->GetNameRef();
+                //Check if name ends with _1
+                if (geomfldname.size() >= 2 && geomfldname[geomfldname.size()-2] == '_') {
+                  geomfldname = geomfldname.substr(0, geomfldname.size()-2);
+                  geomIdx = featureDef->GetGeomFieldIndex(geomfldname.c_str());
+                  if (geomIdx == -1)
+                  {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                        "No matching definition for field '%s' of table %s found", geomfldname.c_str(), featureDef->GetName());
+                  }
+                } else {
+                  geomIdx = -1;
+                }
+                if (geomIdx >= 0) {
+                  if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint) {
+                    //add Point geometry
+                    OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-1]), atof(tokens[fIndex]));
+                    feature->SetGeomFieldDirectly(geomIdx, ogrPoint);
+                  } else if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint25D && fieldno > 1 && featureDef->GetFieldDefn(fieldno-2)->GetType() == OFTReal) {
+                    //add 3D Point geometry
+                    OGRPoint *ogrPoint = new OGRPoint(atof(tokens[fIndex-2]), atof(tokens[fIndex-1]), atof(tokens[fIndex]));
+                    feature->SetGeomFieldDirectly(geomIdx, ogrPoint);
+                  }
+                }
               }
             }
           }
           if (!warned && featureDef->GetFieldCount() != CSLCount(tokens)-1 && !(featureDef->GetFieldCount() == CSLCount(tokens) && EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))) {
-            CPLDebug( "OGR_ILI", "Field count doesn't match. %d declared, %d found", featureDef->GetFieldCount(), CSLCount(tokens)-1);
+            CPLError(CE_Warning, CPLE_AppDefined,
+                "Field count doesn't match. %d declared, %d found", featureDef->GetFieldCount(), CSLCount(tokens)-1);
             warned = TRUE;
           }
-          if (featureDef->GetGeomType() == wkbPolygon)
-            feature->SetFID(atol(feature->GetFieldAsString(1)));
-          else if (feature->GetFieldCount() > 0)
-            feature->SetFID(atol(feature->GetFieldAsString(0)));
+          if (feature->GetFieldCount() > 0) {
+            feature->SetFID(atol(feature->GetFieldAsString(0))); //TODO: use IDENT field from model instead of TID
+          }
           curLayer->AddFeature(feature);
+          geomIdx = -1; //Reset
         }
       }
       else if (EQUAL(firsttok, "STPT"))
       {
-        ReadGeom(tokens, featureDef->GetGeomType(), feature);
+        //Find next non-Point geometry
+        do { geomIdx++; } while (geomIdx < featureDef->GetGeomFieldCount() && featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint);
+        OGRwkbGeometryType geomType = (geomIdx < featureDef->GetGeomFieldCount()) ? featureDef->GetGeomFieldDefn(geomIdx)->GetType() : wkbNone;
+        ReadGeom(tokens, geomIdx, geomType, feature);
         if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
         {
           AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos); //TODO: append multi-OBJECT geometries
@@ -662,7 +378,9 @@ int ILI1Reader::ReadTable(const char *layername) {
       else if (EQUAL(firsttok, "EDGE"))
       {
         tokens = ReadParseLine(); //STPT
-        ReadGeom(tokens, wkbMultiLineString, feature);
+        //Find next non-Point geometry
+        do { geomIdx++; } while (geomIdx < featureDef->GetGeomFieldCount() && featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint);
+        ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
         if (EQUAL(featureDef->GetFieldDefn(featureDef->GetFieldCount()-1)->GetNameRef(), "ILI_Geometry"))
         {
           AddIliGeom(feature, featureDef->GetFieldCount()-1, fpos);
@@ -673,32 +391,12 @@ int ILI1Reader::ReadTable(const char *layername) {
       }
       else if (EQUAL(firsttok, "ETAB"))
       {
-        if(HasMultiplePointGeom(layername) > 0) {
-          OGRFeature *metaFeature = NULL;
-          metaLayer->ResetReading();
-          while((metaFeature = metaLayer->GetNextFeature()) != NULL ) {
-            int pntCln = 1;
-            if(EQUAL(layername, metaFeature->GetFieldAsString(0)) && !EQUAL(curLayer->GetLayerDefn()->GetName(), metaFeature->GetFieldAsString(2))) {
-              pntCln++;
-              OGRILI1Layer *curLayerTmp = GetLayerByName(metaFeature->GetFieldAsString(2));
-              OGRFeature *tmpFeature = NULL;
-              int geomIdxTmp = metaFeature->GetFieldAsInteger(1);
-              curLayer->ResetReading();
-              while((tmpFeature = curLayer->GetNextFeature()) != NULL ) {
-                OGRPoint *ogrPoint = new OGRPoint(atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln)), atof(tmpFeature->GetFieldAsString(geomIdxTmp + pntCln + 1)));
-                tmpFeature->SetGeometryDirectly(ogrPoint);
-                curLayerTmp->AddFeature(tmpFeature);
-              }
-            }
-            delete metaFeature;
-          }
-        }
         CSLDestroy(tokens);
         return TRUE;
       }
       else
       {
-        CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
+        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
@@ -708,8 +406,7 @@ int ILI1Reader::ReadTable(const char *layername) {
     return ret;
 }
 
-void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature) {
-
+void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature) {
     char **tokens = NULL;
     const char *firsttok = NULL;
     int end = FALSE;
@@ -720,6 +417,7 @@ void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *f
     OGRPoint ogrPoint, arcPoint, endPoint; //points for arc interpolation
     OGRMultiLineString *ogrMultiLine = NULL; //current multi line
 
+    //CPLDebug( "OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d", geomIdx);
     //tokens = ["STPT", "1111", "22222"]
     ogrPoint.setX(atof(stgeom[1])); ogrPoint.setY(atof(stgeom[2]));
     ogrLine = (eType == wkbPolygon) ? new OGRLinearRing() : new OGRLineString();
@@ -729,7 +427,7 @@ void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *f
     if (eType == wkbMultiLineString)
     {
       ogrMultiLine = new OGRMultiLineString();
-      feature->SetGeometryDirectly(ogrMultiLine);
+      feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
     }
     else if (eType == wkbGeometryCollection) //AREA
     {
@@ -738,7 +436,7 @@ void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *f
       else
       {
         ogrMultiLine = new OGRMultiLineString();
-        feature->SetGeometryDirectly(ogrMultiLine);
+        feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
       }
     }
     else if (eType == wkbPolygon)
@@ -755,12 +453,12 @@ void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *f
       else
       {
         ogrPoly = new OGRPolygon();
-        feature->SetGeometryDirectly(ogrPoly);
+        feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
       }
     }
     else
     {
-      feature->SetGeometryDirectly(ogrLine);
+      feature->SetGeomFieldDirectly(geomIdx, ogrLine);
     }
 
     //Parse geometry
@@ -811,7 +509,7 @@ void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *f
       }
       else
       {
-        CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok );
+        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
@@ -834,10 +532,6 @@ void ILI1Reader::AddLayer( OGRILI1Layer * poNewLayer )
 }
 
 /************************************************************************/
-/*                              AddAreaLayer()                              */
-/************************************************************************/
-
-/************************************************************************/
 /*                              GetLayer()                              */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.h b/ogr/ogrsf_frmts/ili/ili1reader.h
index 6595a11..b4217cf 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.h
+++ b/ogr/ogrsf_frmts/ili/ili1reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1reader.h 17904 2009-10-26 19:22:46Z chaitanya $
+ * $Id: ili1reader.h 26979 2014-02-23 21:55:20Z pka $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -30,6 +30,9 @@
 #ifndef _CPL_ILI1READER_H_INCLUDED
 #define _CPL_ILI1READER_H_INCLUDED
 
+#include "imdreader.h"
+
+class OGRILI1DataSource;
 
 class CPL_DLL IILI1Reader
 {
@@ -38,10 +41,11 @@ public:
 
     virtual int  OpenFile( const char *pszFilename ) = 0;
     
-    virtual int  ReadModel( const char *pszModelFilename ) = 0;
+    virtual int  ReadModel( ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS ) = 0;
     virtual int  ReadFeatures() = 0;       
     
     virtual OGRLayer *GetLayer( int ) = 0;
+    virtual OGRLayer *GetLayerByName( const char* ) = 0;
     virtual int  GetLayerCount() = 0;
     virtual void SetArcDegrees(double newArcDegrees) = 0;
 };
diff --git a/ogr/ogrsf_frmts/ili/ili1readerp.h b/ogr/ogrsf_frmts/ili/ili1readerp.h
index 6a6e21b..fc24265 100644
--- a/ogr/ogrsf_frmts/ili/ili1readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili1readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1readerp.h 24116 2012-03-13 16:31:27Z pka $
+ * $Id: ili1readerp.h 26979 2014-02-23 21:55:20Z pka $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -32,7 +32,6 @@
 
 #include "ili1reader.h"
 #include "ogr_ili1.h"
-#include "iom/iom.h"
 
 
 class ILI1Reader;
@@ -49,7 +48,6 @@ private:
     int          nLayers;
     OGRILI1Layer **papoLayers;
     OGRILI1Layer *curLayer;
-    OGRILI1Layer *metaLayer;
     double       arcIncr;
     char         codeBlank;
     char         codeUndefined;
@@ -61,10 +59,10 @@ public:
 
     void         SetArcDegrees(double arcDegrees);
     int          OpenFile( const char *pszFilename );
-    int          ReadModel( const char *pszModelFilename );
+    int          ReadModel( ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS );
     int          ReadFeatures();
     int          ReadTable(const char *layername);
-    void         ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature);
+    void         ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature);
     char         **ReadParseLine();
 
     void         AddLayer( OGRILI1Layer * poNewLayer );
@@ -73,15 +71,7 @@ public:
     OGRILI1Layer *GetLayerByName( const char* );
     int          GetLayerCount();
 
-    int          HasMultiplePointGeom(const char* layername);
-    char*        GetPointLayerName(const char* layername, char* newlayername);
     const char*  GetLayerNameString(const char* topicname, const char* tablename);
-    const char*  GetLayerName(IOM_BASKET model, IOM_OBJECT table);
-    void         AddCoord(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT modelele, IOM_OBJECT typeobj);
-    void         AddEnumTable(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT enumeration);
-    OGRILI1Layer* AddGeomTable(const char* datalayername, const char* geomname, OGRwkbGeometryType eType);
-    void         AddField(OGRILI1Layer* layer, IOM_BASKET model, IOM_OBJECT obj);
-    unsigned int GetCoordDim(IOM_BASKET model, IOM_OBJECT typeobj);
 };
 
 
diff --git a/ogr/ogrsf_frmts/ili/ili2handler.cpp b/ogr/ogrsf_frmts/ili/ili2handler.cpp
index 4d07ae1..f30dc30 100644
--- a/ogr/ogrsf_frmts/ili/ili2handler.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2handler.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2handler.cpp 24408 2012-05-11 21:31:45Z pka $
+ * $Id: ili2handler.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Handler class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "ili2readerp.h"
 #include <xercesc/sax2/Attributes.hpp>
 
-CPL_CVSID("$Id: ili2handler.cpp 24408 2012-05-11 21:31:45Z pka $");
+CPL_CVSID("$Id: ili2handler.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // 
 // constants
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.cpp b/ogr/ogrsf_frmts/ili/ili2reader.cpp
index 5fa60f2..bf3b24c 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2reader.cpp 24408 2012-05-11 21:31:45Z pka $
+ * $Id: ili2reader.cpp 27187 2014-04-14 23:26:02Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Reader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,13 +33,15 @@
 #include "cpl_string.h"
 
 #include "ilihelper.h"
-#include "iomhelper.h"
 #include "ili2reader.h"
 #include "ili2readerp.h"
 
+//from trstring.cpp/gmlreaderp.h
+char *tr_strdup( const XMLCh * );
+
 using namespace std;
 
-CPL_CVSID("$Id: ili2reader.cpp 24408 2012-05-11 21:31:45Z pka $");
+CPL_CVSID("$Id: ili2reader.cpp 27187 2014-04-14 23:26:02Z rouault $");
 
 //
 // constants
@@ -128,10 +131,8 @@ char *getObjValue(DOMElement *elem) {
 
   if ((textElem != NULL) && (textElem->getNodeType() == DOMNode::TEXT_NODE))
   {
-    char* pszNodeValue = XMLString::transcode(textElem->getNodeValue());
-    char* pszRet = CPLStrdup(pszNodeValue);
-    XMLString::release(&pszNodeValue);
-    return pszRet;
+    char* pszNodeValue = tr_strdup(textElem->getNodeValue());
+    return pszNodeValue;
   }
 
   return NULL;
@@ -139,11 +140,9 @@ char *getObjValue(DOMElement *elem) {
 
 char *getREFValue(DOMElement *elem) {
   XMLCh* pszIli2_ref = XMLString::transcode(ILI2_REF);
-  char* pszREFValue = XMLString::transcode(elem->getAttribute(pszIli2_ref));
-  char* pszRet = CPLStrdup(pszREFValue);
+  char* pszREFValue = tr_strdup(elem->getAttribute(pszIli2_ref));
   XMLString::release(&pszIli2_ref);
-  XMLString::release(&pszREFValue);
-  return pszRet;
+  return pszREFValue;
 }
 
 OGRPoint *getPoint(DOMElement *elem) {
@@ -267,7 +266,7 @@ OGRLineString *getLineString(DOMElement *elem, int bAsLinearRing) {
       delete ptStart;
       delete ptEnd;
       delete ptOnArc;
-    } /* else { // FIXME StructureValue in Polyline not yet supported
+    } /* else { // TODO: StructureValue in Polyline not yet supported
     } */
     XMLString::release(&pszTagName);
 
@@ -374,136 +373,29 @@ OGRGeometry *ILI2Reader::getGeometry(DOMElement *elem, int type) {
   return gm;
 }
 
-const char* ILI2Reader::GetLayerName(IOM_BASKET model, IOM_OBJECT table) {
-    static char layername[512];
-    IOM_OBJECT topic = GetAttrObj(model, table, "container");
-    layername[0] = '\0';
-    strcat(layername, iom_getattrvalue(GetAttrObj(model, topic, "container"), "name"));
-    strcat(layername, ".");
-    strcat(layername, iom_getattrvalue(topic, "name"));
-    strcat(layername, ".");
-    strcat(layername, iom_getattrvalue(table, "name"));
-    return layername;
-}
-
-void ILI2Reader::AddField(OGRLayer* layer, IOM_BASKET model, IOM_OBJECT obj) {
-  const char* typenam = "Reference";
-  if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.LocalAttribute")) typenam = GetTypeName(model, obj);
-  if (EQUAL(typenam, "iom04.metamodel.SurfaceType")) {
-  } else if (EQUAL(typenam, "iom04.metamodel.AreaType")) {
-  } else if (EQUAL(typenam, "iom04.metamodel.PolylineType") ) {
-  } else if (EQUAL(typenam, "iom04.metamodel.CoordType")) {
-  } else {
-    OGRFieldDefn fieldDef(iom_getattrvalue(obj, "name"), OFTString);
-    layer->GetLayerDefn()->AddFieldDefn(&fieldDef);
-    CPLDebug( "OGR_ILI", "Field %s: %s", fieldDef.GetNameRef(), typenam);
-  }
-}
-
-int ILI2Reader::ReadModel(char **modelFilenames) {
-
-  IOM_BASKET model;
-  IOM_ITERATOR modelelei;
-  IOM_OBJECT modelele;
-
-  iom_init();
-
-  // set error listener to a iom provided one, that just
-  // dumps all errors to stderr
-  iom_seterrlistener(iom_stderrlistener);
-
-  // compile ili models
-  model=iom_compileIli(CSLCount(modelFilenames), modelFilenames);
-  if(!model){
-    CPLError( CE_Failure, CPLE_FileIO, "iom_compileIli failed." );
-    iom_end();
-    return FALSE;
-  }
-
-  // read tables
-  modelelei=iom_iteratorobject(model);
-  modelele=iom_nextobject(modelelei);
-  while(modelele){
-    const char *tag=iom_getobjecttag(modelele);
-    if (tag && EQUAL(tag,"iom04.metamodel.Table")) {
-      const char* topic = iom_getattrvalue(GetAttrObj(model, modelele, "container"), "name");
-      if (!EQUAL(topic, "INTERLIS")) {
-        const char* layername = GetLayerName(model, modelele);
-        OGRLayer* layer = new OGRILI2Layer(layername, NULL, 0, wkbUnknown, NULL);
-        m_listLayer.push_back(layer);
-        CPLDebug( "OGR_ILI", "Reading table model '%s'", layername );
-
-        // read fields
-        IOM_OBJECT fields[255];
-        IOM_OBJECT roledefs[255];
-        memset(fields, 0, 255);
-        memset(roledefs, 0, 255);
-        int maxIdx = -1;
-        IOM_ITERATOR fieldit=iom_iteratorobject(model);
-        for (IOM_OBJECT fieldele=iom_nextobject(fieldit); fieldele; fieldele=iom_nextobject(fieldit)){
-          const char *etag=iom_getobjecttag(fieldele);
-          if (etag && (EQUAL(etag,"iom04.metamodel.ViewableAttributesAndRoles"))) {
-            IOM_OBJECT table = GetAttrObj(model, fieldele, "viewable");
-            if (table == modelele) {
-              IOM_OBJECT obj = GetAttrObj(model, fieldele, "attributesAndRoles");
-              int ili1AttrIdx = GetAttrObjPos(fieldele, "attributesAndRoles")-1;
-              if (EQUAL(iom_getobjecttag(obj),"iom04.metamodel.RoleDef")) {
-                //??ili1AttrIdx = atoi(iom_getattrvalue(GetAttrObj(model, obj, "oppend"), "ili1AttrIdx"));
-                roledefs[ili1AttrIdx] = obj;
-              } else {
-                fields[ili1AttrIdx] = obj;
-              }
-              if (ili1AttrIdx > maxIdx) maxIdx = ili1AttrIdx;
-              //CPLDebug( "OGR_ILI", "Field %s Pos: %d", iom_getattrvalue(obj, "name"), ili1AttrIdx);
-            }
-          }
-          iom_releaseobject(fieldele);
-        }
-        iom_releaseiterator(fieldit);
-
-        for (int i=0; i<=maxIdx; i++) {
-          IOM_OBJECT obj = fields[i];
-          IOM_OBJECT roleobj = roledefs[i];
-          if (roleobj) AddField(layer, model, roleobj);
-          if (obj) AddField(layer, model, obj);
-        }
-      }
-    }
-    iom_releaseobject(modelele);
-
-    modelele=iom_nextobject(modelelei);
+int ILI2Reader::ReadModel(ImdReader *poImdReader, const char *modelFilename) {
+  poImdReader->ReadModel(modelFilename);
+  for (FeatureDefnInfos::const_iterator it = poImdReader->featureDefnInfos.begin(); it != poImdReader->featureDefnInfos.end(); ++it)
+  {
+    OGRLayer* layer = new OGRILI2Layer(it->poTableDefn, it->poGeomFieldInfos, NULL);
+    m_listLayer.push_back(layer);
   }
-
-  iom_releaseiterator(modelelei);
-
-  iom_releasebasket(model);
-
-  iom_end();
-
   return 0;
 }
 
+//Detect field name of value element
 char* fieldName(DOMElement* elem) {
-  string fullname;
-  int depth = 0;
-  DOMNode *node;
-  for (node = elem; node; node = node->getParentNode()) ++depth;
-  depth-=3; //ignore root elements
-
-// We cannot do this sort of dynamic stack alloc on MSVC6.
-//  DOMNode* elements[depth];
-  DOMNode* elements[1000];
-  CPLAssert( depth < (int)(sizeof(elements) / sizeof(DOMNode*)) );
-
-  int d=0;
-  for (node = elem; d<depth; node = node->getParentNode()) elements[d++] = node;
-  for (d=depth-1; d>=0; --d) {
-    if (d < depth-1) fullname += "_";
-    char* pszNodeName = XMLString::transcode(elements[d]->getNodeName());
-    fullname += pszNodeName;
-    XMLString::release(&pszNodeName);
+  DOMNode *node = elem;
+  if (getGeometryTypeOfElem(elem))
+  {
+    int depth = 0; // Depth of value elem node
+    for (node = elem; node; node = node->getParentNode()) ++depth;
+    //Field name is on level 4
+    node = elem;
+    for (int d = 0; d<depth-4; ++d) node = node->getParentNode();
   }
-  return CPLStrdup(fullname.c_str());
+  char* pszNodeName = tr_strdup(node->getNodeName());
+  return pszNodeName;
 }
 
 void ILI2Reader::setFieldDefn(OGRFeatureDefn *featureDef, DOMElement* elem) {
@@ -555,7 +447,10 @@ void ILI2Reader::SetFieldValues(OGRFeature *feature, DOMElement* elem) {
         CPLFree(fName);
       }
     } else {
-      feature->SetGeometryDirectly(getGeometry(childElem, type));
+      char *fName = fieldName(childElem);
+      int fIndex = feature->GetGeomFieldIndex(fName);
+      feature->SetGeomFieldDirectly(fIndex, getGeometry(childElem, type));
+      CPLFree(fName);
     }
   }
 }
@@ -612,11 +507,11 @@ int ILI2Reader::SetupParser() {
 
         catch (const XMLException& toCatch)
         {
-            char* msg = XMLString::transcode(toCatch.getMessage());
+            char* msg = tr_strdup(toCatch.getMessage());
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to initalize Xerces C++ based ILI2 reader. "
                       "Error message:\n%s\n", msg );
-            XMLString::release(&msg);
+            CPLFree(msg);
 
             return FALSE;
         }
@@ -692,10 +587,10 @@ int ILI2Reader::SaveClasses( const char *pszFile = NULL ) {
     }
     catch (const SAXException& toCatch)
     {
-        char* msg = XMLString::transcode(toCatch.getMessage());
+        char* msg = tr_strdup(toCatch.getMessage());
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Parsing failed: %s\n", msg );
-        XMLString::release(&msg);
+        CPLFree(msg);
 
         return FALSE;
     }
@@ -723,33 +618,35 @@ int ILI2Reader::GetLayerCount() {
   return m_listLayer.size();
 }
 
-
-int ILI2Reader::AddFeature(DOMElement *elem) {
-  bool newLayer = true;
-  OGRLayer *curLayer = 0;
-  char *pszName = XMLString::transcode(elem->getTagName());
-
-  // test if this layer exist
+OGRLayer* ILI2Reader::GetLayer(const char* pszName) {
   for (list<OGRLayer *>::reverse_iterator layerIt = m_listLayer.rbegin();
        layerIt != m_listLayer.rend();
        ++layerIt) {
     OGRFeatureDefn *fDef = (*layerIt)->GetLayerDefn();
     if (cmpStr(fDef->GetName(), pszName) == 0) {
-      newLayer = false;
-      curLayer = *layerIt;
-      break;
+      return *layerIt;
     }
   }
+  return NULL;
+}
+
+int ILI2Reader::AddFeature(DOMElement *elem) {
+  bool newLayer = true;
+  OGRLayer *curLayer = 0;
+  char *pszName = tr_strdup(elem->getTagName());
+  //CPLDebug( "OGR_ILI", "Reading layer: %s", pszName );
+
+  // test if this layer exist
+  curLayer = GetLayer(pszName);
+  newLayer = (curLayer == NULL);
 
   // add a layer
-  if (newLayer) { // FIXME in Layer: SRS Writer Type datasource
+  if (newLayer) {
     CPLDebug( "OGR_ILI", "Adding layer: %s", pszName );
-    // new layer data
-    OGRSpatialReference *poSRSIn = NULL; // FIXME fix values for initial layer
-    int bWriterIn = 0;
-    OGRwkbGeometryType eReqType = wkbUnknown;
-    OGRILI2DataSource *poDSIn = NULL;
-    curLayer = new OGRILI2Layer(pszName, poSRSIn, bWriterIn, eReqType, poDSIn);
+    OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(pszName);
+    poFeatureDefn->SetGeomType( wkbUnknown );
+    GeomFieldInfos oGeomFieldInfos;
+    curLayer = new OGRILI2Layer(poFeatureDefn, oGeomFieldInfos, NULL);
     m_listLayer.push_back(curLayer);
   }
 
@@ -770,10 +667,10 @@ int ILI2Reader::AddFeature(DOMElement *elem) {
   int fIndex = feature->GetFieldIndex(ILI2_TID);
   if (fIndex != -1) {
       XMLCh *pszIli2_tid = XMLString::transcode(ILI2_TID);
-      char *fChVal = XMLString::transcode(elem->getAttribute(pszIli2_tid));
+      char *fChVal = tr_strdup(elem->getAttribute(pszIli2_tid));
       feature->SetField(fIndex, fChVal);
-      XMLString::release (&pszIli2_tid);
-      XMLString::release (&fChVal);
+      XMLString::release(&pszIli2_tid);
+      CPLFree(fChVal);
   } else {
       CPLDebug( "OGR_ILI","'%s' not found", ILI2_TID);
   }
@@ -781,7 +678,7 @@ int ILI2Reader::AddFeature(DOMElement *elem) {
   SetFieldValues(feature, elem);
   curLayer->SetFeature(feature);
   
-  XMLString::release (&pszName);
+  CPLFree(pszName);
 
   return 0;
 }
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.h b/ogr/ogrsf_frmts/ili/ili2reader.h
index 9067e83..4b7f70d 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.h
+++ b/ogr/ogrsf_frmts/ili/ili2reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2reader.h 13906 2008-03-01 13:08:28Z rouault $
+ * $Id: ili2reader.h 27184 2014-04-14 22:21:56Z pka $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Public Declarations for Reader code.
@@ -36,6 +36,7 @@
 #define INFINITY INFINITY_XERCES
 #endif
 
+#include "imdreader.h"
 #include <list>
 
 
@@ -45,7 +46,8 @@ public:
     virtual     ~IILI2Reader();
 
     virtual void SetSourceFile( const char *pszFilename ) = 0;
-    virtual int  ReadModel( char **modelFilenames ) = 0;
+
+    virtual int  ReadModel( ImdReader *poImdReader, const char *modelFilename ) = 0;
     virtual int  SaveClasses( const char *pszFilename ) = 0;
     
     virtual std::list<OGRLayer *> GetLayers() = 0;
diff --git a/ogr/ogrsf_frmts/ili/ili2readerp.h b/ogr/ogrsf_frmts/ili/ili2readerp.h
index 05789c2..a8d7e78 100644
--- a/ogr/ogrsf_frmts/ili/ili2readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili2readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2readerp.h 17910 2009-10-27 02:07:33Z chaitanya $
+ * $Id: ili2readerp.h 27184 2014-04-14 22:21:56Z pka $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -73,7 +73,7 @@ class ILI2Reader;
 class ILI2Handler : public DefaultHandler 
 {
     ILI2Reader  *m_poReader;
-    
+
     int level;
     
     DOMDocument *dom_doc;
@@ -140,16 +140,17 @@ public:
 
     void     SetArcDegrees(double arcDegrees);
     void     SetSourceFile( const char *pszFilename );
-    int      ReadModel( char **modelFilenames );
+    int      ReadModel( ImdReader *poImdReader, const char *modelFilename );
     int      SaveClasses( const char *pszFile );
     
     std::list<OGRLayer *> GetLayers();
     int      GetLayerCount();
+    OGRLayer* GetLayer(const char* pszName);
     
     int      AddFeature(DOMElement *elem);
     void     SetFieldValues(OGRFeature *feature, DOMElement* elem);
-    const char* GetLayerName(IOM_BASKET model, IOM_OBJECT table);
-    void     AddField(OGRLayer* layer, IOM_BASKET model, IOM_OBJECT obj);
+    const char* GetLayerName(/*IOM_BASKET model, IOM_OBJECT table*/);
+    void     AddField(OGRLayer* layer/*, IOM_BASKET model, IOM_OBJECT obj*/);
     OGRLineString *getArc(DOMElement *elem);
     OGRGeometry *getGeometry(DOMElement *elem, int type);
     void     setFieldDefn(OGRFeatureDefn *featureDef, DOMElement* elem);
diff --git a/ogr/ogrsf_frmts/ili/ilihelper.cpp b/ogr/ogrsf_frmts/ili/ilihelper.cpp
index 7935086..d565213 100644
--- a/ogr/ogrsf_frmts/ili/ilihelper.cpp
+++ b/ogr/ogrsf_frmts/ili/ilihelper.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ilihelper.cpp 24609 2012-06-25 15:21:10Z pka $
+ * $Id$
  *
  * Project:  Interlis 1/2 Translator
  * Purpose:  Helper functions for Interlis reader
@@ -31,7 +31,7 @@
 #include "ilihelper.h"
 
 
-CPL_CVSID("$Id: ilihelper.cpp 24609 2012-06-25 15:21:10Z pka $");
+CPL_CVSID("$Id$");
 
 
 OGRPoint *getARCCenter(OGRPoint *ptStart, OGRPoint *ptArc, OGRPoint *ptEnd) {
diff --git a/ogr/ogrsf_frmts/ili/ilihelper.h b/ogr/ogrsf_frmts/ili/ilihelper.h
index 04e4584..cfcc26f 100644
--- a/ogr/ogrsf_frmts/ili/ilihelper.h
+++ b/ogr/ogrsf_frmts/ili/ilihelper.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ilihelper.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id$
  *
  * Project:  Interlis 1/2 Translator
  * Purpose:   Definition of classes for OGR Interlis 1 driver.
diff --git a/ogr/ogrsf_frmts/ili/imdreader.cpp b/ogr/ogrsf_frmts/ili/imdreader.cpp
new file mode 100644
index 0000000..8155ac3
--- /dev/null
+++ b/ogr/ogrsf_frmts/ili/imdreader.cpp
@@ -0,0 +1,456 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Interlis 1/2 Translator
+ * Purpose:  IlisMeta model reader.
+ * Author:   Pirmin Kalberer, Sourcepole AG
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Pirmin Kalberer, Sourcepole AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// IlisMeta model: http://www.interlis.ch/models/core/IlisMeta07-20111222.ili
+
+
+#include "imdreader.h"
+#include "cpl_minixml.h"
+#include <set>
+#include <vector>
+
+
+CPL_CVSID("$Id$");
+
+
+typedef std::map<CPLString,CPLXMLNode*> StrNodeMap;
+typedef std::vector<CPLXMLNode*> NodeVector;
+typedef std::map<CPLXMLNode*,int> NodeCountMap;
+class IliClass;
+typedef std::map<CPLXMLNode*,IliClass*> ClassesMap; /* all classes with XML node for lookup */
+
+/* Helper class for collection class infos */
+class IliClass
+{
+public:
+    CPLXMLNode* node;
+    int iliVersion;
+    OGRFeatureDefn* poTableDefn;
+    StrNodeMap& oTidLookup;
+    ClassesMap& oClasses;
+    NodeCountMap& oAxisCount;
+    GeomFieldInfos poGeomFieldInfos;
+    StructFieldInfos poStructFieldInfos;
+    NodeVector oFields;
+    bool isAssocClass;
+    bool hasDerivedClasses;
+
+    IliClass(CPLXMLNode* node_, const char* name, int iliVersion_, StrNodeMap& oTidLookup_, ClassesMap& oClasses_, NodeCountMap& oAxisCount_) :
+        node(node_), iliVersion(iliVersion_), oTidLookup(oTidLookup_), oClasses(oClasses_), oAxisCount(oAxisCount_),
+        poGeomFieldInfos(), poStructFieldInfos(), oFields(), isAssocClass(false), hasDerivedClasses(false)
+    {
+        char* layerName = LayerName(name);
+        poTableDefn = new OGRFeatureDefn(layerName);
+        CPLFree(layerName);
+    };
+    ~IliClass()
+    {
+        delete poTableDefn;
+    };
+    const char* GetName() {
+        return poTableDefn->GetName();
+    }
+    char* LayerName(const char* psClassTID) {
+        if (iliVersion == 1)
+        {
+            //Skip topic and replace . with __
+            char **papszTokens =
+                CSLTokenizeString2( psClassTID, ".", CSLT_ALLOWEMPTYTOKENS );
+
+            CPLString layername;
+            for(int i = 1; papszTokens != NULL && papszTokens[i] != NULL; i++)
+            {
+                if (i>1) layername += "__";
+                layername += papszTokens[i];
+            }
+            CSLDestroy( papszTokens );
+            return CPLStrdup(layername);
+        } else {
+            return CPLStrdup(psClassTID);
+        }
+    };
+    void AddFieldNode(CPLXMLNode* node, int iOrderPos)
+    {
+        if (iOrderPos >= (int)oFields.size())
+            oFields.resize(iOrderPos+1);
+        //CPLDebug( "OGR_ILI", "Register field with OrderPos %d to Class %s", iOrderPos, GetName());
+        oFields[iOrderPos] = node;
+    }
+    void AddRoleNode(CPLXMLNode* node, int iOrderPos)
+    {
+        isAssocClass = true;
+        AddFieldNode(node, iOrderPos);
+    }
+    bool isEmbedded()
+    {
+        if (isAssocClass)
+            for (NodeVector::const_iterator it = oFields.begin(); it != oFields.end(); ++it)
+            {
+                if (*it == NULL) continue;
+                if (CSLTestBoolean(CPLGetXMLValue( *it, "EmbeddedTransfer", "FALSE" )))
+                    return true;
+            }
+        return false;
+    }
+    // Add additional Geometry table for Interlis 1
+    void AddGeomTable(CPLString layerName, const char* psFieldName, OGRwkbGeometryType eType)
+    {
+        OGRFeatureDefn* poGeomTableDefn = new OGRFeatureDefn(layerName);
+        OGRFieldDefn fieldDef("_TID", OFTString);
+        poGeomTableDefn->AddFieldDefn(&fieldDef);
+        if (eType == wkbPolygon)
+        {
+            OGRFieldDefn fieldDefRef("_RefTID", OFTString);
+            poGeomTableDefn->AddFieldDefn(&fieldDefRef);
+        }
+        poGeomTableDefn->DeleteGeomFieldDefn(0);
+        OGRGeomFieldDefn fieldDefGeom(psFieldName, eType);
+        poGeomTableDefn->AddGeomFieldDefn(&fieldDefGeom);
+        CPLDebug( "OGR_ILI", "Adding geometry table %s for field %s", poGeomTableDefn->GetName(), psFieldName);
+        poGeomFieldInfos[psFieldName].geomTable = poGeomTableDefn;
+    }
+    void AddField(const char* psName, OGRFieldType fieldType)
+    {
+        OGRFieldDefn fieldDef(psName, fieldType);
+        poTableDefn->AddFieldDefn(&fieldDef);
+        CPLDebug( "OGR_ILI", "Adding field '%s' to Class %s", psName, GetName());
+    }
+    void AddGeomField(const char* psName, OGRwkbGeometryType geomType)
+    {
+        OGRGeomFieldDefn fieldDef(psName, geomType);
+        //oGFld.SetSpatialRef(geomlayer->GetSpatialRef());
+        poTableDefn->AddGeomFieldDefn(&fieldDef);
+        CPLDebug( "OGR_ILI", "Adding geometry field '%s' to Class %s", psName, GetName());
+    }
+    void AddCoord(const char* psName, CPLXMLNode* psTypeNode)
+    {
+        int dim = oAxisCount[psTypeNode];
+        if (dim == 0) dim = 2; //Area center points have no Axis spec
+        if (iliVersion == 1)
+        {
+            for (int i=0; i<dim; i++)
+            {
+                AddField(CPLSPrintf("%s_%d", psName, i), OFTReal);
+            }
+        }
+        OGRwkbGeometryType geomType = (dim > 2) ? wkbPoint25D : wkbPoint;
+        AddGeomField(psName, geomType);
+    }
+    OGRFieldType GetFormattedType(CPLXMLNode* node)
+    {
+        const char* psRefSuper = CPLGetXMLValue( node, "Super.REF", NULL );
+        if (psRefSuper)
+            return GetFormattedType(oTidLookup[psRefSuper]);
+        else
+            return OFTString; //TODO: Time, Date, etc. if possible
+    }
+    void InitFieldDefinitions()
+    {
+        // Delete default geometry field
+        poTableDefn->DeleteGeomFieldDefn(0);
+
+        const char* psKind = CPLGetXMLValue( node, "Kind", NULL );
+        //CPLDebug( "OGR_ILI", "InitFieldDefinitions of '%s' kind: %s", GetName(), psKind);
+        if (EQUAL(psKind, "Structure"))
+        {
+            // add foreign_key field
+            OGRFieldDefn ofieldDefn1("REF_NAME", OFTString);
+            poTableDefn->AddFieldDefn(&ofieldDefn1);
+            OGRFieldDefn ofieldDefn2("REF_ID", OFTString);
+            poTableDefn->AddFieldDefn(&ofieldDefn2);
+        } else { // Class
+            // add TID field
+            const char* psTidColName = (iliVersion == 1) ? "_TID" : "TID";
+            OGRFieldDefn ofieldDefn(psTidColName, OFTString);
+            poTableDefn->AddFieldDefn(&ofieldDefn);
+        }
+        if (CSLTestBoolean(CPLGetXMLValue( node, "Abstract", "FALSE" )))
+            hasDerivedClasses = true;
+    }
+    void AddFieldDefinitions()
+    {
+        for (NodeVector::const_iterator it = oFields.begin(); it != oFields.end(); ++it)
+        {
+            if (*it == NULL) continue;
+            const char* psName = CPLGetXMLValue( *it, "Name", NULL );
+            const char* psTypeRef = CPLGetXMLValue( *it, "Type.REF", NULL );
+            if (psTypeRef == NULL) //Assoc Role
+                AddField(psName, OFTString); //FIXME: numeric?
+            else
+            {
+                CPLXMLNode* psElementNode = oTidLookup[psTypeRef];
+                const char* typeName = psElementNode->pszValue;
+                if (EQUAL(typeName, "IlisMeta07.ModelData.TextType"))
+                { //Kind Text,MText
+                    AddField(psName, OFTString);
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.EnumType"))
+                {
+                    AddField(psName, (iliVersion == 1) ? OFTInteger : OFTString);
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.BooleanType"))
+                {
+                    AddField(psName, OFTString); //??
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.NumType"))
+                { //// Unit INTERLIS.ANYUNIT, INTERLIS.TIME, INTERLIS.h, INTERLIS.min, INTERLIS.s, INTERLIS.M, INTERLIS.d
+                    AddField(psName, OFTReal);
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.BlackboxType"))
+                {
+                    AddField(psName, OFTString);
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.FormattedType"))
+                {
+                    AddField(psName, GetFormattedType(*it));
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.MultiValue"))
+                {
+                    //min -> Multiplicity/IlisMeta07.ModelData.Multiplicity/Min
+                    //max -> Multiplicity/IlisMeta07.ModelData.Multiplicity/Max
+                    const char* psClassRef = CPLGetXMLValue( psElementNode, "BaseType.REF", NULL );
+                    if (psClassRef)
+                    {
+                        IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
+                        poStructFieldInfos[psName] = psParentClass->GetName();
+                        CPLDebug( "OGR_ILI", "Register table %s for struct field '%s'", poStructFieldInfos[psName].c_str(), psName);
+                        /* Option: Embed fields if max == 1
+                        CPLDebug( "OGR_ILI", "Adding embedded struct members of MultiValue field '%s' from Class %s", psName, psClassRef);
+                        AddFieldDefinitions(psParentClass->oFields);
+                        */
+                    }
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.CoordType"))
+                {
+                    AddCoord(psName, psElementNode);
+                }
+                else if (EQUAL(typeName, "IlisMeta07.ModelData.LineType"))
+                {
+                    const char* psKind = CPLGetXMLValue( psElementNode, "Kind", NULL );
+                    poGeomFieldInfos[psName].iliGeomType = psKind;
+                    if (iliVersion == 1)
+                    {
+                        if (EQUAL(psKind, "Area"))
+                        {
+                            CPLString areaPointGeomName = psName + CPLString("__Point");
+                            AddCoord(areaPointGeomName, psElementNode);
+
+                            CPLString lineLayerName = GetName() + CPLString("_") + psName;
+                            AddGeomTable(lineLayerName, psName, wkbMultiLineString);
+
+                            //Add geometry field for polygonized areas
+                            AddGeomField(psName, wkbPolygon);
+                        } else if (EQUAL(psKind, "Surface"))
+                        {
+                            CPLString geomLayerName = GetName() + CPLString("_") + psName;
+                            AddGeomTable(geomLayerName, psName, wkbPolygon);
+                            AddGeomField(psName, wkbPolygon);
+                        } else { // Polyline, DirectedPolyline
+                            AddGeomField(psName, wkbMultiLineString);
+                        }
+                    } else {
+                        if (EQUAL(psKind, "Area") || EQUAL(psKind, "Surface"))
+                        {
+                            AddGeomField(psName, wkbPolygon);
+                        } else { // Polyline, DirectedPolyline
+                            AddGeomField(psName, wkbMultiLineString);
+                        }
+                    }
+                }
+                else
+                {
+                    //ClassRefType
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                        "Field '%s' of class %s has unsupported type %s", psName, GetName(), typeName);
+                }
+            }
+        }
+    }
+    FeatureDefnInfo tableDefs()
+    {
+        FeatureDefnInfo poLayerInfo;
+        poLayerInfo.poTableDefn = NULL;
+        if (!hasDerivedClasses && !isEmbedded())
+        {
+            poLayerInfo.poTableDefn = poTableDefn;
+            poLayerInfo.poGeomFieldInfos = poGeomFieldInfos;
+        }
+        return poLayerInfo;
+    }
+
+};
+
+
+ImdReader::ImdReader(int iliVersionIn) : iliVersion(iliVersionIn), modelInfos() {
+  mainModelName = "OGR";
+  mainTopicName = "OGR";
+  codeBlank = '_';
+  codeUndefined = '@';
+  codeContinue = '\\';
+}
+
+ImdReader::~ImdReader() {
+}
+
+void ImdReader::ReadModel(const char *pszFilename) {
+    CPLDebug( "OGR_ILI", "Reading model '%s'", pszFilename);
+
+    CPLXMLNode* psRootNode = CPLParseXMLFile(pszFilename);
+    if( psRootNode == NULL )
+        return;
+    CPLXMLNode *psSectionNode = CPLGetXMLNode( psRootNode, "=TRANSFER.DATASECTION" );
+    if( psSectionNode == NULL )
+        return;
+
+    StrNodeMap oTidLookup; /* for fast lookup of REF relations */
+    ClassesMap oClasses;
+    NodeCountMap oAxisCount;
+    const char *modelName;
+
+    /* Fill TID lookup map and IliClasses lookup map */
+    CPLXMLNode* psModel = psSectionNode->psChild;
+    while( psModel != NULL )
+    {
+        modelName = CPLGetXMLValue( psModel, "BID", NULL );
+        //CPLDebug( "OGR_ILI", "Model: '%s'", modelName);
+
+        CPLXMLNode* psEntry = psModel->psChild;
+        while( psEntry != NULL )
+                {
+            if (psEntry->eType != CXT_Attribute) //ignore BID
+            {
+                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
+                const char* psTID = CPLGetXMLValue( psEntry, "TID", NULL );
+                if( psTID != NULL )
+                    oTidLookup[psTID] = psEntry;
+
+
+                if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Model") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    IliModelInfo modelInfo;
+                    modelInfo.name = CPLGetXMLValue( psEntry, "Name", "OGR" );
+                    modelInfo.version = CPLGetXMLValue( psEntry, "Version", "" );
+                    modelInfo.uri = CPLGetXMLValue( psEntry, "At", "" );
+                    modelInfos.push_back(modelInfo);
+                    mainModelName = modelInfo.name; //FIXME: check model inheritance
+                    //version = CPLGetXMLValue(psEntry, "iliVersion", "0"); //1 or 2.3
+
+                    CPLXMLNode *psFormatNode = CPLGetXMLNode( psEntry, "ili1Format" );
+                    if (psFormatNode != NULL)
+                    {
+                        psFormatNode = psFormatNode->psChild;
+                        codeBlank = atoi(CPLGetXMLValue(psFormatNode, "blankCode", "95"));
+                        codeUndefined = atoi(CPLGetXMLValue(psFormatNode, "undefinedCode", "64"));
+                        codeContinue = atoi(CPLGetXMLValue(psFormatNode, "continueCode", "92"));
+                    }
+                }
+                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.SubModel") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    mainBasketName = CPLGetXMLValue(psEntry, "TID", "OGR");
+                    mainTopicName = CPLGetXMLValue(psEntry, "Name", "OGR");
+                }
+                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Class") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    CPLDebug( "OGR_ILI", "Class name: '%s'", psTID);
+                    oClasses[psEntry] = new IliClass(psEntry, psTID, iliVersion, oTidLookup, oClasses, oAxisCount);
+                }
+            }
+            psEntry = psEntry->psNext;
+        }
+
+        // 2nd pass: add fields via TransferElement entries & role associations
+        psEntry = psModel->psChild;
+        while( psEntry != NULL )
+        {
+            if (psEntry->eType != CXT_Attribute) //ignore BID
+            {
+                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
+                if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.TransferElement") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    const char* psClassRef = CPLGetXMLValue( psEntry, "TransferClass.REF", NULL );
+                    const char* psElementRef = CPLGetXMLValue( psEntry, "TransferElement.REF", NULL );
+                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "TransferElement.ORDER_POS", "0" ))-1;
+                    IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
+                    CPLXMLNode* psElementNode = oTidLookup[psElementRef];
+                    psParentClass->AddFieldNode(psElementNode, iOrderPos);
+                }
+                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Role") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    const char* psRefParent = CPLGetXMLValue( psEntry, "Association.REF", NULL );
+                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Association.ORDER_POS", "0" ))-1;
+                    IliClass* psParentClass = oClasses[oTidLookup[psRefParent]];
+                    if (psParentClass)
+                        psParentClass->AddRoleNode(psEntry, iOrderPos);
+                }
+                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.AxisSpec") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                {
+                    const char* psClassRef = CPLGetXMLValue( psEntry, "CoordType.REF", NULL );
+                    //int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Axis.ORDER_POS", "0" ))-1;
+                    CPLXMLNode* psCoordTypeNode = oTidLookup[psClassRef];
+                    oAxisCount[psCoordTypeNode] += 1;
+                }
+            }
+            psEntry = psEntry->psNext;
+
+        }
+
+        psModel = psModel->psNext;
+    }
+
+    /* Analyze class inheritance & add fields to class table defn */
+    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
+    {
+        //CPLDebug( "OGR_ILI", "Class: '%s'", it->second->GetName());
+        const char* psRefSuper = CPLGetXMLValue( it->first, "Super.REF", NULL );
+        if (psRefSuper)
+            oClasses[oTidLookup[psRefSuper]]->hasDerivedClasses = true;
+        it->second->InitFieldDefinitions();
+        it->second->AddFieldDefinitions();
+    }
+
+    /* Filter relevant classes */
+    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
+    {
+        FeatureDefnInfo oClassInfo = it->second->tableDefs();
+        if (oClassInfo.poTableDefn)
+            featureDefnInfos.push_back(oClassInfo);
+    }
+
+    CPLDestroyXMLNode(psRootNode);
+}
+
+FeatureDefnInfo ImdReader::GetFeatureDefnInfo(const char *pszLayerName) {
+    FeatureDefnInfo featureDefnInfo;
+    for (FeatureDefnInfos::const_iterator it = featureDefnInfos.begin(); it != featureDefnInfos.end(); ++it)
+    {
+        OGRFeatureDefn* fdefn = it->poTableDefn;
+        if (EQUAL(fdefn->GetName(), pszLayerName)) featureDefnInfo = *it;
+    }
+    return featureDefnInfo;
+}
diff --git a/ogr/ogrsf_frmts/ili/imdreader.h b/ogr/ogrsf_frmts/ili/imdreader.h
new file mode 100644
index 0000000..d4316f2
--- /dev/null
+++ b/ogr/ogrsf_frmts/ili/imdreader.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Interlis 1/2 Translator
+ * Purpose:  IlisMeta model reader.
+ * Author:   Pirmin Kalberer, Sourcepole AG
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Pirmin Kalberer, Sourcepole AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _IMDREADER_H_INCLUDED
+#define _IMDREADER_H_INCLUDED
+
+#include "cpl_vsi.h"
+#include "cpl_error.h"
+#include "ogr_feature.h"
+#include <list>
+#include <map>
+
+
+class GeomFieldInfo
+{
+public:
+    OGRFeatureDefn* geomTable; /* separate geometry table for Ili 1 */
+    CPLString       iliGeomType;
+    GeomFieldInfo() : geomTable(0) {};
+};
+
+typedef std::map<CPLString,GeomFieldInfo> GeomFieldInfos; /* key: geom field name, value: ILI geom field info */
+typedef std::map<CPLString,CPLString> StructFieldInfos; /* key: struct field name, value: struct table */
+
+class FeatureDefnInfo
+{
+public:
+    OGRFeatureDefn* poTableDefn;
+    GeomFieldInfos  poGeomFieldInfos;
+    StructFieldInfos poStructFieldInfos;
+    FeatureDefnInfo() : poTableDefn(0) {};
+};
+typedef std::list<FeatureDefnInfo> FeatureDefnInfos;
+
+class IliModelInfo
+{
+public:
+    CPLString name;
+    CPLString version;
+    CPLString uri;
+};
+typedef std::list<IliModelInfo> IliModelInfos;
+
+class ImdReader
+{
+public:
+    int                  iliVersion; /* 1 or 2 */
+    IliModelInfos        modelInfos;
+    CPLString            mainModelName;
+    CPLString            mainBasketName;
+    CPLString            mainTopicName;
+    FeatureDefnInfos     featureDefnInfos;
+    char                 codeBlank;
+    char                 codeUndefined;
+    char                 codeContinue;
+public:
+                         ImdReader(int iliVersion);
+                        ~ImdReader();
+    void                 ReadModel(const char *pszFilename);
+    FeatureDefnInfo      GetFeatureDefnInfo(const char *pszLayerName);
+};
+
+#endif /* _IMDREADER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/iom/GNUmakefile b/ogr/ogrsf_frmts/ili/iom/GNUmakefile
deleted file mode 100644
index dd5cf8c..0000000
--- a/ogr/ogrsf_frmts/ili/iom/GNUmakefile
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-include ../../../../GDALmake.opt
-
-OBJ =	iom_attr.o iom_basket.o iom_error.o iom_file.o iom_iterator.o iom_object.o iom_utilities.o iom_value.o \
-    reader.o tags.o ustrings.o writer.o
-
-O_OBJ = $(foreach file,$(OBJ),../../o/$(file))
-
-CPPFLAGS	:=	$(XERCES_INCLUDE) $(CPPFLAGS) -I..
-
-default:	 $(O_OBJ:.o=.$(OBJ_EXT))
-
-../../o/%.$(OBJ_EXT):       %.cpp
-	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
-
-clean:
-	rm -f *.o $(O_OBJ)
-
-$(O_OBJ):	iom.h iom_p.h
diff --git a/ogr/ogrsf_frmts/ili/iom/README.src.txt b/ogr/ogrsf_frmts/ili/iom/README.src.txt
deleted file mode 100644
index bdc5c3a..0000000
--- a/ogr/ogrsf_frmts/ili/iom/README.src.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-iom - The INTERLIS Object Model
-
-Features
-- generic read and write of INTERLIS 2 transfer files
-- generic read of INTERLIS 1 and 2 model files
-- pure c API (no C++ in the public interface)
-
-How to use it?
-- include iom.h in your source
-- link with iom.lib
-- see samples and test programs for API usage
-
-License
-IOM is licensed under the MIT/X.
-ili2c.jar is licensed under the LGPL.
-IOM and ili2c include software developed by the Apache Software 
-Foundation (http://www.apache.org/).
-
-Latest Version
-The current version of iom can be found at
-http://iom.sourceforge.net/
-
-System Configuration
-Although IOM is written in C/C++, to use IOM in a application, a Java Runtime Environment is required.
-In order to compile IOM, a C/C++ compiler (on Windows MSVC 6; on Linux GCC 3.2.3) is required.
-To test IOM, python and a diff utility is required.
-To recreate the distribution zip-file, the build tool ant is required. Download it from http://ant.apache.org and install it as documented there.
-
-Installation
-In order to install IOM, extract the ZIP file into a new directory.
-
-How to compile it on Windows using Microsoft Visual C++?
-To build IOM from the source distribution (using MSVC), you will need to open the workspace containing the project. 
-The workspace containing the IOM project file and all other samples is in:
- iom\projects\win32\vc6\iom.dsw
-Once you are inside MSVC, you need to build the project marked iom.
-If you are building your application, you may want to add the IOM project inside your applications's workspace.
-You need to pick up:
- iom\projects\win32\vc6\iom\iom.dsp
-You must make sure that you are linking your application with the iom.lib library and also make sure that the associated DLL (xerces_c), the INTERLIS-Compiler (ili2c) and the JAVA virtual machine (java) is somewhere in your path.
-
-How to compile it on Linux using GCC?
-FIXME
-
-To build a distribution, use
- ant dist
-
-Dependencies
-- xerces-c (www.apache.com) 
-- ili2c (www.interlis.ch)
-- JRE (www.java.com)
-
-Comments/Suggestions
-Please send comments to ce at eisenhutinformatik.ch
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom.h b/ogr/ogrsf_frmts/ili/iom/iom.h
deleted file mode 100644
index 19f7b51..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/**********************************************************************
- * $Id: iom.h 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#ifndef IOM_IOM_H
-#define IOM_IOM_H
-
-/** @mainpage
- * IOM soll analog der XML Parser-Interfaces SAX und DOM aufgebaut werden.
- * IOM stellt kein spezifisches Interface zum Metamodell des Compilers bereit. 
- * Das Metamodell des Compilers kann mit denselben Funktionen wie die Daten 
- * abgefragt werden. Die Definitionen aus dem INTERLIS-Modell stehen als normale 
- * IOM-Objekte zur Verf�gung.
- * IOM nutzt selbst auch Informationen aus dem Compiler-Metamodell (IOM kann das Modell nicht via IOM lesen, darum ein Adapter) 
- * IOM unterst�tzt nur INTERLIS 2. (Kann aber zu einem sp�teren Zeitpunkt f�r INTERLIS 1 oder ein GML-Subset erg�nzt werden.)
- * Kein Modul von IOM ruft die Funktion "exit()" auf. Alle Funktionen geben einen entsprechenden Fehlerstatus zur�ck.
- * IOM (Interlis Object Model)
- * <UL>
- * <LI>entspricht in etwa DOM. IOM weist aber eine h�here Abstraktionsstufe auf (z.B. gib mir alle Objekte eines Basket, gib mir alle Attribute eines Objekts, gibt mir den Wert eines Attributs).</LI>
- * <LI>ist die Schnittstelle nach Aussen</LI>
- * <LI>Objektbaum durch den man mit entsprechenden Funktionen navigieren kann</LI>
- * <LI>bei grossen Datenmengen werden Objekte in eine bin�re Datei ausgelagert</LI>
- * <LI>Der Prefix f�r die tempor�ren Dateien ist konfigurierbar</LI>
- * <LI>Die XML-Datei wird nicht als Ganzes gelesen. Es wird Basket um Basket gelesen. Gelesene Baskets werden in die bin�re Datei ausgelagert. Es ist immer nur ein Basket im RAM.</LI>
- * <LI>eingebettete Beziehungsobjekte erscheinen als eigenst�ndige Objekte, so dass die Verarbeitung von Beziehung einheitlich ist</LI>
- * <LI>Ein Objekt beinhaltet alle Attributwerte inkl. direkten/indirekten Substrukturen</LI>
- * <LI>Funktion um eine XML-Datei gem. Regeln von INTERLIS zu lesen</LI>
- * <LI>Funktion um eine XML-Datei gem. Regeln von INTERLIS zu schreiben</LI>
- * <LI>Headerinformationen aus einer Transferdatei werden gem. einem zu definierenden INTERLIS-Modell als IOM-Objekte bereitgestellt</LI>
- * <LI>muss nach XML-Format Fehlern (not well-formed) wiederaufsetzen und weiterlesen. In diesem Fall stehen die Daten nicht zur Verf�gung, nur die Format-Fehlermeldungen. Dieses Feature ist keine Muss-Anforderung</LI>
- * <LI>XML-Format-Fehlermeldungen werden gem. einem zu definierenden INTERLIS-Modell als IOM-Objekte bereitgestellt</LI>
- * <LI>Sortierung: keine</LI>
- * <LI>Transformationsfunktionen (z.B. LV03->LV95): keine</LI>
- * <LI>Aggregationsfunktionen (z.B. count(), sum()): keine</LI>
- * <LI>bei fehlerhaften Daten enth�lt der Objektbaum:</LI>
- * <UL>
- *	<LI>unvollst�ndige Objekte</LI>
- *	<LI>Objekte mit Attributen die es laut Modell nicht gibt</LI>
- *	<LI>Attributwerte die es laut Modell nicht gibt </LI>
- *	<LI>mehrere Objekte mit der selben OID</LI>
- *	<LI>Referenzen auf Objekte die in den Daten nicht existieren</LI>
- *	<LI>Kardinalit�ten die nicht mit dem Modell �bereinstimmen</LI>
- * </UL>
- * <LI>Werte von Geometrieattributen werden als Strukturen/Substrukturen abgebildet</LI>
- * <LI>Von einem Basket wird soviel gelesen, wie aufgrund der Modelle bekannt ist. Erweiterungen zu denen kein Modell bekannt ist, werden ignoriert (mit Hilfe der Alias-Tabelle).</LI>
- * </UL>
- */
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-/** @file
- * Main IOM header.
- */
-
-/**
- * @defgroup types types that appear in the interfaces of iom.
- */
-
-/**
- * file handle, released by close
- * @ingroup types
- */
-typedef struct iom_file *IOM_FILE;
-
-/**
- * basket handle, requires call to release
- * @ingroup types
- */
-typedef struct iom_basket *IOM_BASKET;
-
-/**
- * object handle, requires call to release
- * @ingroup types
- */
-typedef struct iom_object *IOM_OBJECT;
-
-
-/**
- * iterator handle, requires call to release
- * @ingroup types
- */
-typedef struct iom_iterator *IOM_ITERATOR;
-
-/**
- * a tag, if returned normaly valid as associated handle
- * @ingroup types
- */
-typedef const char *IOM_TAG;
-
-/**
- * an object identifier, if returned normaly valid as associated handle
- * @ingroup types
- */
-typedef const char *IOM_OID;
-
-/**
- * pointer to function that may act as an error listener of IOM.
- * @param errobj listener should not call iom_releaseobject()
- * @ingroup types
- */
-typedef void (*IOM_ERRLISTENER)(IOM_OBJECT errobj) ;
-
-void iom_init();
-void iom_end();
-void iom_settmpdir(const char *dirname);
-char *iom_gettmpnam();
-char *iom_searchenv(const char *filename, const char *varname);
-int iom_fileexists(const char *filename);
-unsigned long iom_currentmilis();
-
-// error message handling
-void iom_stderrlistener(IOM_OBJECT errobj);
-IOM_ERRLISTENER iom_seterrlistener(IOM_ERRLISTENER newlistener);
-void iom_issueparserr(const char *message,int kind,int line,int col);
-void iom_issuesemerr(const char *message,IOM_OID bid,IOM_OID oid);
-void iom_issueerr(const char *message);
-void iom_issueanyerr(IOM_OBJECT err);
-
-// model handling
-IOM_BASKET iom_compileIli(int filec,char *filename[]);
-
-// data file handling
-IOM_FILE iom_open(const char *filename,int flags,const char *model);
-int iom_save(IOM_FILE file);
-void iom_close(IOM_FILE file);
-IOM_BASKET iom_getmodel(IOM_FILE file);
-void iom_setmodel(IOM_FILE file,IOM_BASKET model);
-
-// list all baskets in a file
-IOM_ITERATOR iom_iteratorbasket(IOM_FILE file);
-IOM_BASKET iom_nextbasket(IOM_ITERATOR iterator); 
-
-// get infos from headersection 
-const char *iom_getheadversion(IOM_FILE file);
-const char *iom_getheadversionUTF8(IOM_FILE file);
-const char *iom_getheadsender(IOM_FILE file);
-const char *iom_getheadsenderUTF8(IOM_FILE file);
-void iom_setheadsender(IOM_FILE file,const char *sender);
-void iom_setheadsenderUTF8(IOM_FILE file,const char *sender);
-const char *iom_getheadcomment(IOM_FILE file);
-const char *iom_getheadcommentUTF8(IOM_FILE file);
-void iom_setheadcomment(IOM_FILE file,const char *comment);
-void iom_setheadcommentUTF8(IOM_FILE file,const char *comment);
-
-// gets the basket with a given bid or 0
-IOM_BASKET iom_getbasket(IOM_FILE file,IOM_OID oid);
-
-
-// Basket in eine andere Datei verschieben
-int iom_relocatebasket(IOM_FILE newfile,IOM_BASKET basket);
-
-// create a new basket
-IOM_BASKET iom_newbasket(IOM_FILE file);
-// release handle
-int iom_releasebasket(IOM_BASKET basket);
-
-
-// Basket l�schen (Basket aus Datei entfernen)
-int iom_deletebasket(IOM_BASKET basket);
-
-
-// gets/sets OID of a basket
-IOM_OID iom_getbasketoid(IOM_BASKET basket);
-void iom_setbasketoid(IOM_BASKET basket,IOM_OID oid);
-
-// gets/sets the consistency of a basket
-int iom_getbasketconsistency(IOM_BASKET basket);
-void iom_setbasketconsistency(IOM_BASKET basket,int consistency);
-
-// gets/sets type of a basket
-IOM_TAG iom_getbaskettag(IOM_BASKET basket); 
-void iom_setbaskettag(IOM_BASKET basket,IOM_TAG topic); 
-
-// get xml file location of a basket
-int iom_getbasketline(IOM_BASKET basket);
-int iom_getbasketcol(IOM_BASKET basket);
-
-
-
-// get all objects of a basket
-IOM_ITERATOR iom_iteratorobject(IOM_BASKET basket);
-IOM_OBJECT iom_nextobject(IOM_ITERATOR iterator); 
-
-IOM_OBJECT iom_newobject(IOM_BASKET basket,IOM_TAG type,IOM_OID oid);
-int iom_releaseobject(IOM_OBJECT object);
-IOM_OBJECT iom_getobject(IOM_BASKET basket,IOM_OID oid);
-int iom_deleteobject(IOM_OBJECT object);
-int iom_relocateobject(IOM_BASKET basket,IOM_OBJECT object);
-
-// get xml file location of an object
-int iom_getobjectline(IOM_OBJECT obj);
-int iom_getobjectcol(IOM_OBJECT obj);
-
-// gets/sets tag of an object
-IOM_TAG iom_getobjecttag(IOM_OBJECT object); 
-void iom_setobjecttag(IOM_OBJECT object,IOM_TAG tag); 
-
-// gets/sets the oid of an object
-IOM_OID iom_getobjectoid(IOM_OBJECT object);
-void iom_setobjectoid(IOM_OBJECT object,IOM_OID oid);
-
-// gets the oid/bid of the referenced object
-IOM_OID iom_getobjectrefoid(IOM_OBJECT object);
-IOM_OID iom_getobjectrefbid(IOM_OBJECT object);
-void iom_setobjectrefoid(IOM_OBJECT object,IOM_OID refoid);
-void iom_setobjectrefbid(IOM_OBJECT object,IOM_OID refbid);
-
-// gets/sets the ORDER_POS of the referenced object
-unsigned int iom_getobjectreforderpos(IOM_OBJECT object);
-void iom_setobjectreforderpos(IOM_OBJECT object,unsigned int orderPos);
-
-// gets/sets the operation-mode of an object
-int iom_getobjectoperation(IOM_OBJECT object);
-void iom_setobjectoperation(IOM_OBJECT object,int operation);
-
-// gets/sets the consistency of an object
-int iom_getobjectconsistency(IOM_OBJECT object);
-void iom_setobjectconsistency(IOM_OBJECT object,int consistency);
-
-// get XML-elements of an object
-int iom_getxmlelecount(IOM_OBJECT object);
-IOM_TAG iom_getxmleleattrname(IOM_OBJECT object,int index);
-int iom_getxmlelevalueidx(IOM_OBJECT object,int index);
-char *iom_getxmleleprim(IOM_OBJECT object,int index);
-char *iom_getxmleleprimUTF8(IOM_OBJECT object,int index);
-IOM_OBJECT iom_getxmleleobj(IOM_OBJECT object,int index);
-
-// gets/sets attribute values of an object
-int iom_getattrcount(IOM_OBJECT object);
-IOM_TAG iom_getattrname(IOM_OBJECT object,int index);
-int iom_getattrvaluecount(IOM_OBJECT object,IOM_TAG attrName);
-char *iom_getattrvalue(IOM_OBJECT object,IOM_TAG attrName);
-char *iom_getattrvalueUTF8(IOM_OBJECT object,IOM_TAG attrName);
-void iom_setattrvalue(IOM_OBJECT object,IOM_TAG attrName,const char *value);
-void iom_setattrvalueUTF8(IOM_OBJECT object,IOM_TAG attrName,const char *value);
-void iom_setattrundefined(IOM_OBJECT object,IOM_TAG attrName);
-char *iom_getattrprim(IOM_OBJECT object,IOM_TAG attrName,int index);
-char *iom_getattrprimUTF8(IOM_OBJECT object,IOM_TAG attrName,int index);
-IOM_OBJECT iom_getattrobj(IOM_OBJECT object,IOM_TAG attrName,int index);
-IOM_OBJECT iom_changeattrobj(IOM_OBJECT object,IOM_TAG attrName,int index,IOM_TAG type);
-IOM_OBJECT iom_insertattrobj(IOM_OBJECT object,IOM_TAG attrName,int index,IOM_TAG type);
-IOM_OBJECT iom_addattrobj(IOM_OBJECT object,IOM_TAG attrName,IOM_TAG type);
-void iom_deleteattrobj(IOM_OBJECT object,IOM_TAG attrName,int index);
-
-
-// seit dem letzten Lesen/Schreiben ge�nderte Objekte
-IOM_ITERATOR iom_iteratorchgobject(IOM_BASKET basket);
-IOM_OBJECT iom_nextchgobject(IOM_ITERATOR iterator); 
-
-// seit dem letzten Lesen/Schreiben gel�schte Objekte
-IOM_ITERATOR iom_iteratordelobject(IOM_BASKET basket);
-IOM_OBJECT iom_nextdelobject(IOM_ITERATOR iterator); 
-
-/**
- * release handle
- */
-int iom_releaseiterator(IOM_ITERATOR iterator);
-
-/** @name ERR runtime errors
- * @ingroup types
- * @{
- */
-#define IOM_ERR_NOTIMPLEMENTED  -29000
-#define IOM_ERR_XMLPARSER       -29001
-#define IOM_ERR_ILLEGALARGUMENT -29002
-#define IOM_ERR_ILLEGALSTATE    -29003
-/** @} */
-
-/** @name OPENMODE possible values for  iom_open().
- * @ingroup types
- * @{
- */
-/** Create file, as necessary.
- *  If the file does not already exist and 
- * the IOM_CREATE flag is not specified, the call will fail. 
- * @see iom_open
- */
-#define IOM_CREATE 1
-/** Do not read file, if it already exists.
- * @see iom_open
- */
-#define IOM_DONTREAD 2
-
-/** @} */
-
-
-/** @name CONSISTENCY possible values for the consistency of an object or a basket.
- * @ingroup types
- * @{
- */
-#define IOM_COMPLETE     0
-#define IOM_INCOMPLETE   1
-#define IOM_INCONSISTENT 2
-#define IOM_ADAPTED      3
-/** @} */
-
-/** @name BASKETKIND possible values for the kind of a basket.
- * @ingroup types
- * @{
- */
-#define IOM_FULL     0
-#define IOM_UPDATE   1
-#define IOM_INITIAL  2
-/** @} */
-
-/** @name OPMODE possible values for the operation mode of an object.
- * @ingroup types
- * @{
- */
-#define IOM_OP_INSERT  0
-#define IOM_OP_UPDATE  1
-#define IOM_OP_DELETE  2
-/** @} */
-
-
-/** @name ERRKIND possible values for the kind of an parse error.
- * @ingroup types
- * @{
- */
-#define IOM_ERRKIND_XMLPARSER 0
-#define IOM_ERRKIND_MISSING   1
-#define IOM_ERRKIND_INVALID   2
-#define IOM_ERRKIND_OTHER     3
-/** @} */
-
-/** @page iommodel model used to represent internal objects of iom.
- * @section Errors
- * @image html Errors.jpeg
- * @section ModelDef
- * @image html ModelDef.jpeg
- * @section TopicDef
- * @image html TopicDef.jpeg
- * @section ClassDef
- * @image html ClassDef.jpeg
- * @section DomainDef
- * @image html DomainDef.jpeg
- * @section UnitDef
- * @image html UnitDef.jpeg
- * @section MetadataUseDef
- * @image html MetadataUseDef.jpeg
- * @section ConstraintDef
- * @image html ConstraintDef.jpeg
- * @section Expression
- * @image html Expression.jpeg
- * @section Factor
- * @image html Factor.jpeg
- * @section Constant
- * @image html Constant.jpeg
- * @section ObjectOrAttributePath
- * @image html ObjectOrAttributePath.jpeg
- * @section FunctionDef
- * @image html FunctionDef.jpeg
- * @section RuntimeParameterDef
- * @image html RuntimeParameterDef.jpeg
- * @section ViewDef
- * @image html ViewDef.jpeg
- * @section GraphicDef
- * @image html GraphicDef.jpeg
- * @section INTERLIS
- * @verbinclude iom04.ili
- */
-
-
-
-#if defined(__cplusplus) || defined(c_plusplus)
-}
-#endif
-
-#endif
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_attr.cpp b/ogr/ogrsf_frmts/ili/iom/iom_attr.cpp
deleted file mode 100644
index b8719e3..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_attr.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/**********************************************************************
- * $Id: iom_attr.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object attribute
- * @defgroup attribute attribute level functions
- * @{
- */
-#include <string.h>
-#include <iom/iom_p.h>
-
-/** gets the number of attributes, roles and embedded roles 
- * of an object.
- */
-extern "C" int iom_getattrcount(IOM_OBJECT object)
-{
-	return object->getAttrCount();
-}
-
-/** gets the name of an attribute, role or embedded role.
- *  returns a pointer to a static buffer.
- */
-extern "C" IOM_TAG iom_getattrname(IOM_OBJECT object,int index)
-{
-	static char *name=0;
-	int tag=object->getAttrName(index);
-	if(name){
-		XMLString::release(&name);
-	}
-	const XMLCh *const name_w=ParserHandler::getTagName(tag);
-	name=XMLString::transcode(name_w);
-	return name;
-}
-
-/** gets the number of values of an attribute.
- */
-extern "C" int iom_getattrvaluecount(IOM_OBJECT object,IOM_TAG attrName)
-{
-	int tag=ParserHandler::getTagId(attrName);
-	return object->getAttrValueCount(tag);
-}
-
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getattrvalue(IOM_OBJECT object,IOM_TAG attrName)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int nameId=ParserHandler::getTagId(attrName);
-	if(!nameId) return 0;
-	const XMLCh *ret=object->getAttrValue(nameId);
-	if(!ret)return 0;
-	value=XMLString::transcode(ret);
-	return value;
-}
-
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getattrvalueUTF8(IOM_OBJECT object,IOM_TAG attrName)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int nameId=ParserHandler::getTagId(attrName);
-	if(!nameId) return 0;
-	const XMLCh *ret=object->getAttrValue(nameId);
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** sets the value of a primitive type attribute. 
- *  If value==0, the attribute is set to undefined.
- */
-extern "C" void iom_setattrvalue(IOM_OBJECT object,IOM_TAG attrName,const char *value)
-{
-	if(value){
-		object->setAttrValue(ParserHandler::getTagId(attrName),X(value));
-	}else{
-		object->setAttrValue(ParserHandler::getTagId(attrName),0);
-	}
-}
-/** sets the value of a primitive type attribute. 
- *  If value==0, the attribute is set to undefined.
- */
-extern "C" void iom_setattrvalueUTF8(IOM_OBJECT object,IOM_TAG attrName,const char *value)
-{
-	if(value){
-		XMLCh *unicodeForm=iom_fromUTF8(value);
-		object->setAttrValue(ParserHandler::getTagId(attrName),unicodeForm);
-		XMLString::release(&unicodeForm);
-	}else{
-		object->setAttrValue(ParserHandler::getTagId(attrName),0);
-	}
-}
-
-/** sets the attribute to undefined.
- */
-extern "C" void iom_setattrundefined(IOM_OBJECT object,IOM_TAG attrName)
-{
-	object->setAttrUndefined(ParserHandler::getTagId(attrName));
-}
-
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getattrprim(IOM_OBJECT object,IOM_TAG attrName,int index)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int tag=ParserHandler::getTagId(attrName);
-	const XMLCh *ret=object->getAttrPrim(tag,index);
-	if(!ret)return 0;
-	value=XMLString::transcode(ret);
-	return value;
-}
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getattrprimUTF8(IOM_OBJECT object,IOM_TAG attrName,int index)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int tag=ParserHandler::getTagId(attrName);
-	const XMLCh *ret=object->getAttrPrim(tag,index);
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** gets the value of a object type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * It is the responsibility of the caller to release the returned object.
- */
-extern "C" IOM_OBJECT iom_getattrobj(IOM_OBJECT object,IOM_TAG attrName,int index)
-{
-	int tag=ParserHandler::getTagId(attrName);
-	IomObject ret=object->getAttrObj(tag,index);
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-/** replaces the value of an object type attribute.
- */
-extern "C" IOM_OBJECT iom_changeattrobj(IOM_OBJECT object,IOM_TAG attrName,int index,IOM_TAG type)
-{
-	IomObject ret=new iom_object();
-	ret->setTag(ParserHandler::getTagId(type));
-	object->setAttrObj(ParserHandler::getTagId(attrName),index,ret);
-	return ret->getRef();
-}
-
-/** insert a new value of an object type attribute.
- */
-extern "C" IOM_OBJECT iom_insertattrobj(IOM_OBJECT object,IOM_TAG attrName,int index,IOM_TAG type)
-{
-	IomObject ret=new iom_object();
-	ret->setTag(ParserHandler::getTagId(type));
-	object->insertAttrObj(ParserHandler::getTagId(attrName),index,ret);
-	return ret->getRef();
-}
-
-/** add a new value of an object type attribute to end of list.
- */
-extern "C" IOM_OBJECT iom_addattrobj(IOM_OBJECT object,IOM_TAG attrName,IOM_TAG type)
-{
-	IomObject ret=new iom_object();
-	ret->setTag(ParserHandler::getTagId(type));
-	object->addAttrObj(ParserHandler::getTagId(attrName),ret);
-	return ret->getRef();
-}
-
-/** remove a value of an object type attribute from the list.
- */
-extern "C" void iom_deleteattrobj(IOM_OBJECT object,IOM_TAG attrName,int index)
-{
-	object->removeAttrObj(ParserHandler::getTagId(attrName),index);
-}
-
-/** gets the number of xml-elements of an object. 
- * This function can only be called after reading a file.
- */
-extern "C" int iom_getxmlelecount(IOM_OBJECT object)
-{
-	return object->getXmleleCount();
-}
-
-/** gets the attribute name of an xml-element of an object. 
- * To get the value use iom_getattrprim(), iom_getattrobj().
- * This function can only be called after reading a file.
- */
-extern "C" IOM_TAG iom_getxmleleattrname(IOM_OBJECT object,int index)
-{
-	static char *name=0;
-	int tag=object->getXmleleAttrName(index);
-	if(name){
-		XMLString::release(&name);
-	}
-	const XMLCh *const name_w=ParserHandler::getTagName(tag);
-	name=XMLString::transcode(name_w);
-	return name;
-}
-
-/** gets the index of the value of an xml-element of an object. 
- * This function can only be called after reading a file.
- * To get the value use iom_getattrprim(), iom_getattrobj().
- */
-extern "C" int iom_getxmlelevalueidx(IOM_OBJECT object,int index)
-{
-	return object->getXmleleValueIdx(index);
-}
-
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getxmleleprim(IOM_OBJECT object,int index)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int tag=object->getXmleleAttrName(index);
-	int val_index=object->getXmleleValueIdx(index);
-	const XMLCh *ret=object->getAttrPrim(tag,val_index);
-	if(!ret)return 0;
-	value=XMLString::transcode(ret);
-	return value;
-}
-/** gets the value of a primitive type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_getxmleleprimUTF8(IOM_OBJECT object,int index)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	int tag=object->getXmleleAttrName(index);
-	int val_index=object->getXmleleValueIdx(index);
-	const XMLCh *ret=object->getAttrPrim(tag,val_index);
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** gets the value of a object type attribute. 
- * returns 0 if the attribute doesn't exist or has no value
- * It is the responsibility of the caller to release the returned object.
- */
-extern "C" IOM_OBJECT iom_getxmleleobj(IOM_OBJECT object,int index)
-{
-	int tag=object->getXmleleAttrName(index);
-	int val_index=object->getXmleleValueIdx(index);
-	return object->getAttrObj(tag,val_index)->getRef();
-}
-
-/** @}
- */
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_basket.cpp b/ogr/ogrsf_frmts/ili/iom/iom_basket.cpp
deleted file mode 100644
index 414e9b9..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_basket.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/**********************************************************************
- * $Id: iom_basket.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object basket
- * @defgroup basket basket functions
- * @{
- */
-
-#include <iom/iom_p.h>
-
-/** gets an iterator to walk threw all objects of a basket.
- * The list includes embedded link(-objects), but no structures.
- */
-extern "C" IOM_ITERATOR iom_iteratorobject(IOM_BASKET basket)
-{
-	return (dbgnew iom_iterator(basket))->getRef();
-}
-
-/** gets the next object.
- * Returns 0 if no more objects.
- */
-extern "C" IOM_OBJECT iom_nextobject(IOM_ITERATOR iterator)
-{
-	IomObject ret=iterator->next_object();
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-/** create a new object.
- */
-extern "C" IOM_OBJECT iom_newobject(IOM_BASKET basket,IOM_TAG type,IOM_OID oid)
-{
-	IomObject ret=new iom_object();
-	ret->setOid(X(oid));
-	ret->setTag(ParserHandler::getTagId(type));
-	basket->addObject(ret);
-	return ret->getRef();
-}
-
-
-/**
- * release handle
- */
-extern "C" int iom_releasebasket(IOM_BASKET basket)
-{
-	if(!basket->freeRef()){
-		delete basket;
-	}
-	return 0;
-}
-
-// Basket l�schen (Basket aus Datei entfernen)
-extern "C" int iom_deletebasket(IOM_BASKET basket);
-
-
-/** gets OID of a basket.
- *  return value is valid until iom_setbasketoid() or iom_close()
- */
-extern "C" IOM_OID iom_getbasketoid(IOM_BASKET basket)
-{
-	return basket->getOid_c();
-}
-
-/** sets OID of a basket.
- */
-extern "C" void iom_setbasketoid(IOM_BASKET basket,IOM_OID oid){
-	basket->setOid(X(oid));
-}
-
-
-/** gets the consistency of a basket.
- */
-extern "C" int iom_getbasketconsistency(IOM_BASKET basket)
-{
-	return basket->getConsistency();
-}
-
-/** sets the consistency of a basket.
- */
-extern "C" void iom_setbasketconsistency(IOM_BASKET basket,int consistency)
-{
-	basket->setConsistency(consistency);
-}
-
-/** gets xml element name of a basket.
- *  return value is valid until iom_close() or iom_setbaskettag().
- */
-extern "C" IOM_TAG iom_getbaskettag(IOM_BASKET basket)
-{
-	return basket->getTag_c();
-}
-
-/** sets xml element name of a basket.
- */
-extern "C" void iom_setbaskettag(IOM_BASKET basket,IOM_TAG topic)
-{
-	basket->setTag(ParserHandler::getTagId(topic));
-}
-
-/** get xmlfile line number of a basket.
- */
-extern "C" int iom_getbasketline(IOM_BASKET basket)
-{
-	return basket->getXMLLineNumber();
-}
-
-/** get xmlfile column number of a basket.
- */
-extern "C" int iom_getbasketcol(IOM_BASKET basket)
-{
-	return basket->getXMLColumnNumber();
-}
-
-/** gets object with a given OID or 0.
- */
-extern "C" IOM_OBJECT iom_getobject(IOM_BASKET basket,IOM_OID oid)
-{
-	IomObject ret=basket->getObject(X(oid));
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-// Objekt in einen anderen Basket verschieben
-extern "C" int iom_relocateobject(IOM_BASKET basket,IOM_OBJECT object);
-
-
-// seit dem letzten Lesen/Schreiben ge�nderte Objekte
-extern "C" IOM_ITERATOR iom_iteratorchgobject(IOM_BASKET basket);
-extern "C" IOM_OBJECT iom_nextchgobject(IOM_ITERATOR iterator); 
-
-// seit dem letzten Lesen/Schreiben gel�schte Objekte
-extern "C" IOM_ITERATOR iom_iteratordelobject(IOM_BASKET basket);
-extern "C" IOM_OBJECT iom_nextdelobject(IOM_ITERATOR iterator);
-
-
-/** @}
- */
-
-iom_basket::iom_basket() :
-	file()
-	,tag(0)
-	,tag_c(0)
-	,xmlLine(0)
-	,xmlCol(0)
-	,consistency(IOM_COMPLETE)
-	,kind(IOM_FULL)
-	,oid_w(0)
-	,oid_c(0)
-	,startstate_w(0)
-	,startstate_c(0)
-	,endstate_w(0)
-	,endstate_c(0)
-	,topics_w(0)
-	,topics_c(0)
-	,useCount(0)
-{
-}
-
-iom_basket::~iom_basket()
-{
-	if(tag_c)XMLString::release(&tag_c);
-	if(oid_c)XMLString::release(&oid_c);
-	if(oid_w)XMLString::release(&oid_w);
-	if(startstate_c)XMLString::release(&startstate_c);
-	if(startstate_w)XMLString::release(&startstate_w);
-	if(endstate_c)XMLString::release(&endstate_c);
-	if(endstate_w)XMLString::release(&endstate_w);
-	if(topics_c)XMLString::release(&topics_c);
-	if(topics_w)XMLString::release(&topics_w);
-}
-
-void iom_basket::setTag(int tag1)
-{
-	if(tag_c)tag_c=0;
-	tag=tag1;
-}
-int iom_basket::getTag()
-{
-	return tag;
-}
-const char *iom_basket::getTag_c()
-{
-	if(!tag){
-		return 0;
-	}
-	if(!tag_c){
-		const XMLCh *const tag_w=ParserHandler::getTagName(tag);
-		tag_c=XMLString::transcode(tag_w);
-	}
-	return tag_c;
-}
-
-void iom_basket::setXMLLineNumber(int line)
-{
-	xmlLine=line;
-}
-int iom_basket::getXMLLineNumber()
-{
-	return xmlLine;
-}
-
-void iom_basket::setXMLColumnNumber(int col)
-{
-	xmlCol=col;
-}
-
-int iom_basket::getXMLColumnNumber()
-{
-	return xmlCol;
-}
-
-void iom_basket::setConsistency(int cons)
-{
-	consistency=cons;
-}
-
-int iom_basket::getConsistency()
-{
-	return consistency;
-}
-
-void iom_basket::setKind(int kind1)
-{
-	kind=kind1;
-}
-
-int iom_basket::getKind()
-{
-	return kind;
-}
-
-void iom_basket::setOid(const XMLCh *oid)
-{
-	if(oid_c)XMLString::release(&oid_c);
-	if(oid_w)XMLString::release(&oid_w);
-	oid_w=XMLString::replicate(oid);
-}
-const XMLCh *iom_basket::getOid()
-{
-	return oid_w;
-}
-const char *iom_basket::getOid_c()
-{
-	if(!oid_w){
-		return 0;
-	}
-	if(!oid_c){
-		oid_c=XMLString::transcode(oid_w);
-	}
-	return oid_c;
-}
-
-void iom_basket::setStartState(const XMLCh *startstate)
-{
-	if(startstate_c)XMLString::release(&startstate_c);
-	if(startstate_w)XMLString::release(&startstate_w);
-	startstate_w=XMLString::replicate(startstate);
-}
-const XMLCh *iom_basket::getStartState()
-{
-	return startstate_w;
-}
-const char *iom_basket::getStartState_c()
-{
-	if(!startstate_w){
-		return 0;
-	}
-	if(!startstate_c){
-		startstate_c=XMLString::transcode(startstate_w);
-	}
-	return startstate_c;
-}
-
-
-void iom_basket::setEndState(const XMLCh *endstate)
-{
-	if(endstate_c)XMLString::release(&endstate_c);
-	if(endstate_w)XMLString::release(&endstate_w);
-	endstate_w=XMLString::replicate(endstate);
-}
-const XMLCh *iom_basket::getEndState()
-{
-	return endstate_w;
-}
-const char *iom_basket::getEndState_c()
-{
-	if(!endstate_w){
-		return 0;
-	}
-	if(!endstate_c){
-		endstate_c=XMLString::transcode(endstate_w);
-	}
-	return endstate_c;
-}
-
-
-void iom_basket::setTopics(const XMLCh *topics)
-{
-	if(topics_c)XMLString::release(&topics_c);
-	if(topics_w)XMLString::release(&topics_w);
-	topics_w=XMLString::replicate(topics);
-}
-const XMLCh *iom_basket::getTopics()
-{
-	return topics_w;
-}
-const char *iom_basket::getTopics_c()
-{
-	if(!topics_w){
-		return 0;
-	}
-	if(!topics_c){
-		topics_c=XMLString::transcode(topics_w);
-	}
-	return topics_c;
-}
-
-
-void iom_basket::addObject(IomObject object)
-{
-	objectv.push_back(object);
-	object->setBasket(this);
-}
-
-IomObject iom_basket::getObject(const XMLCh *oid)
-{
-	std::vector<IomObject>::iterator it;
-	for(it=objectv.begin();it!=objectv.end();it++){
-		IomObject obj=*it;
-		if(!XMLString::compareString(oid,obj->getOid())){
-			return obj;
-		}
-	}
-	return IomObject();
-}
-
-
-IomBasket::IomBasket(struct iom_basket *pointee1) 
-: pointee(pointee1 ? pointee1->getRef() : 0){
-}
-IomBasket::IomBasket(const IomBasket& src) 
-: pointee(src.pointee ? src.pointee->getRef() : 0){
-}
-IomBasket& IomBasket::operator=(const IomBasket& src){
-	if(this!=&src){
-		if(pointee && !pointee->freeRef()){
-			delete pointee;
-		}
-		pointee=src.pointee ? src.pointee->getRef() :0;
-	}
-	return *this;
-}
-IomBasket::~IomBasket(){
-	if(pointee && !pointee->freeRef()){
-		delete pointee;
-	}
-}
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_error.cpp b/ogr/ogrsf_frmts/ili/iom/iom_error.cpp
deleted file mode 100644
index b924a28..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_error.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/**********************************************************************
- * $Id: iom_error.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of error utilities
- * @defgroup error error handling functions
- * @{
- */
-
-#include <iostream>
-#include <string>
-#include <stdlib.h>
-
-#include <iom/iom_p.h>
-
-IomBasket ErrorUtility::errs;
-int ErrorUtility::errc=0;
-XMLCh ErrorUtility::itoabuf[40];
-IOM_ERRLISTENER ErrorUtility::listener=iom_stderrlistener;
-
-
-void ErrorUtility::notifyerr(IomObject obj)
-{
-	if(listener){
-		(*listener)(&(*obj)); // do not increment useCount!
-	}
-}
-
-void ErrorUtility::init()
-{
-	if(errs.isNull()){
-		errs=dbgnew iom_basket();
-	}
-}
-
-/** cleanup error module. This function is a part of iom_end().
- */
-void ErrorUtility::at_iom_end()
-{
-	if(!errs.isNull()){
-		errs=0;
-	}
-}
-
-/** issues a any object that denotes an error.
- */
-extern "C" void iom_issueanyerr(IOM_OBJECT err)
-{
-	ErrorUtility::init();
-	IomObject obj(err);
-	ErrorUtility::errs->addObject(obj);
-	ErrorUtility::notifyerr(obj);
-}
-
-
-/** issues a general IOM error.
- */
-extern "C" void iom_issueerr(const char *message)
-{
-	ErrorUtility::init();
-	IomObject obj(dbgnew iom_object());
-	XMLString::binToText( ErrorUtility::errc++,ErrorUtility::itoabuf,sizeof(ErrorUtility::itoabuf)-1,10);
-	obj->setOid(ErrorUtility::itoabuf);
-	obj->setTag(ParserHandler::getTagId(X("iomerr04.errors.Error")));
-	obj->setAttrValue(ParserHandler::getTagId("message"),X(message));
-	ErrorUtility::errs->addObject(obj);
-	ErrorUtility::notifyerr(obj);
-	
-}
-
-/** issues a post parsing error.
- */
-extern "C" void iom_issuesemerr(const char *message,IOM_OID bid,IOM_OID oid)
-{
-	ErrorUtility::init();
-	IomObject obj(dbgnew iom_object());
-	XMLString::binToText( ErrorUtility::errc++,ErrorUtility::itoabuf,sizeof(ErrorUtility::itoabuf)-1,10);
-	obj->setOid(ErrorUtility::itoabuf);
-	obj->setTag(ParserHandler::getTagId(X("iomerr04.errors.SemanticError")));
-	obj->setAttrValue(ParserHandler::getTagId("message"),X(message));
-	obj->setAttrValue(ParserHandler::getTagId("bid"),X(bid));
-	if(oid){
-		obj->setAttrValue(ParserHandler::getTagId("oid"),X(oid));
-	}
-	ErrorUtility::errs->addObject(obj);
-	ErrorUtility::notifyerr(obj);
-
-}
-
-/** issues an XML parse error or warning..
- */
-extern "C" void iom_issueparserr(const char *message,int kind,int line,int col)
-{
-	ErrorUtility::init();
-	IomObject obj(dbgnew iom_object());
-	XMLString::binToText( ErrorUtility::errc++,ErrorUtility::itoabuf,sizeof(ErrorUtility::itoabuf)-1,10);
-	obj->setOid(ErrorUtility::itoabuf);
-	obj->setTag(ParserHandler::getTagId(X("iomerr04.errors.XmlParseError")));
-	obj->setAttrValue(ParserHandler::getTagId("message"),X(message));
-	const char *kind_c;
-	switch(kind){
-	case IOM_ERRKIND_XMLPARSER:
-        kind_c="XmlParser";
-		break;
-    case IOM_ERRKIND_MISSING:
-        kind_c="Missing";
-		break;
-    case IOM_ERRKIND_INVALID:
-        kind_c="Invalid";
-		break;
-    case IOM_ERRKIND_OTHER:
-	default:
-        kind_c="Other";
-		break;
-	}
-	obj->setAttrValue(ParserHandler::getTagId("kind"),X(kind_c));
-	XMLString::binToText( line,ErrorUtility::itoabuf,sizeof(ErrorUtility::itoabuf)-1,10);
-	obj->setAttrValue(ParserHandler::getTagId("line"),ErrorUtility::itoabuf);
-	XMLString::binToText( col,ErrorUtility::itoabuf,sizeof(ErrorUtility::itoabuf)-1,10);
-	obj->setAttrValue(ParserHandler::getTagId("col"),ErrorUtility::itoabuf);
-	ErrorUtility::errs->addObject(obj);
-	ErrorUtility::notifyerr(obj);
-}
-
-/** sets a new error listener.
- * returns the old or 0.
- */
-extern "C" IOM_ERRLISTENER iom_seterrlistener(IOM_ERRLISTENER newlistener)
-{
-	IOM_ERRLISTENER old=ErrorUtility::listener;
-	ErrorUtility::listener=newlistener;
-	return old;
-}
-
-/** error listener that dumps all errors to stderr.
- *  Can be used in a iom_eterrlistener() call.
- */
-extern "C" void iom_stderrlistener(IOM_OBJECT errobj1)
-{
-	IomObject errobj(errobj1);
-	if(errobj->getTag()==ParserHandler::getTagId(X("iomerr04.errors.Error"))){
-		std::cerr << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("message")))) << std::endl;
-	}else if(errobj->getTag()==ParserHandler::getTagId(X("iomerr04.errors.XmlParseError"))){
-		std::cerr << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("kind")))) << ", ";
-		std::cerr << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("line")))) << ", ";
-		std::cerr << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("col")))) << ": ";
-		std::cerr << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("message")))) << std::endl;
-	}else if(errobj->getTag()==ParserHandler::getTagId(X("iomerr04.errors.SemanticError"))){
-		std::cerr << "basket " << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("bid"))));
-		const XMLCh *oid=errobj->getAttrValue(ParserHandler::getTagId(X("oid")));
-		if(oid){
-			std::cerr << ", object " << StrX(oid);
-		}
-		std::cerr << ": " << StrX(errobj->getAttrValue(ParserHandler::getTagId(X("message")))) << std::endl;
-	}else{
-		std::cerr << "ERROR: " << errobj->getTag_c() << std::endl;
-		errobj->dumpAttrs();
-	}
-}
-
-/** @}
- */
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_file.cpp b/ogr/ogrsf_frmts/ili/iom/iom_file.cpp
deleted file mode 100644
index cfdc609..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_file.cpp
+++ /dev/null
@@ -1,430 +0,0 @@
-/**********************************************************************
- * $Id: iom_file.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object file
- * @defgroup file file level functions
- * @{
- */
-
-#include <iostream>
-#include <string>
-
-#include <iom/iom_p.h>
-
-
-/** open an INTERLIS XML file.
- * @see IOM_CREATE IOM_DONTREAD
- */
-extern "C" IOM_FILE iom_open(const char *filename,int flags,const char *model)
-{
-	//__asm { int 3 };
-	IomFile ret(dbgnew iom_file());
-	ret->setFilename(filename);
-	if(iom_fileexists(filename)){
-		// read file?
-		if((flags & IOM_DONTREAD)==0){
-			ret->readHeader(model);
-		}
-	}else{
-		// file doesn't exist
-		// do not create file?
-		if((flags & IOM_CREATE)==0){
-			std::string msg="File '";
-			msg+=filename;
-			msg+="' doesn't exist";
-			iom_issueerr(msg.c_str());
-			return 0;
-		}
-	}
-	return ret->getRef();
-}
-
-/** saves data to an INTERLIS XML file.
- *  Requires: call to iom_setmodel().
- */
-extern "C" int iom_save(IOM_FILE file)
-{
-	//__asm { int 3 };
-	return file->save();
-}
-
-/** closes an INTERLIS XML file.
- *
- */
-extern "C" void iom_close(IOM_FILE file)
-{
-	if(!file->freeRef()){
-		delete file;
-	}
-}
-
-/** compiles an INTERLIS model file.
- *  Returns 0 if failed.
- *  Requirements: Installed JRE (Java Runtime Environment) and INTERLIS 2-Compiler. The programs 
- *  java and ili2c.jar somewhere in the PATH.
- */
-extern "C" IOM_BASKET iom_compileIli(int filec,char *filename[])
-{
-	char *ili2cout=iom_gettmpnam();
-	char *ili2c=iom_searchenv("ili2c.jar","PATH");
-	if(!ili2c){
-		iom_issueerr("ili2c.jar not found");
-		return 0;
-	}
-	// call compiler
-	std::string cmdline="java -jar ";
-	cmdline+=ili2c;
-	cmdline+=" --without-warnings -oIOM";
-        int i;
-	for(i=0;i<filec;i++){
-		cmdline+=" \"";
-		cmdline+=filename[i];
-		cmdline+="\"";
-	}
-	if(i==0){
-		iom_issueerr("no ili-file given");
-		return 0;
-	}
-	cmdline+=" >\"";
-	cmdline+=ili2cout;
-	cmdline+="\"";
-	//std::cerr << cmdline << std::endl;
-	system(cmdline.c_str());
-	// read xtf of models
-	IomFile model(dbgnew iom_file());
-	model->setFilename(ili2cout);
-	if(model->readHeader("iom04")){
-		return 0;
-	}
-	IomIterator basketi(dbgnew iom_iterator(model));
-        IomBasket nb = basketi->next_basket();
-	return nb.isNull() ? 0 : nb->getRef();
-}
-
-/** gets the INTERLIS model.
-*/
-extern "C" IOM_BASKET iom_getmodel(IOM_FILE file)
-{
-	IomBasket ret=file->getModel();
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-/** sets the INTERLIS model.
- */
-extern "C" void iom_setmodel(IOM_FILE file,IOM_BASKET model)
-{
-	file->setModel(model);
-}
-
-/** gets an iterator to list all baskets in a file.
- */
-extern "C" IOM_ITERATOR iom_iteratorbasket(IOM_FILE file)
-{
-	return (dbgnew iom_iterator(file))->getRef();
-}
-
-/** gets the next basket or 0.
- */
-extern "C" IOM_BASKET iom_nextbasket(IOM_ITERATOR iterator)
-{
-	IomBasket ret=iterator->next_basket();
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-/** gets the basket with a given bid or 0.
- */
-extern "C" IOM_BASKET iom_getbasket(IOM_FILE file,IOM_OID oid)
-{
-	IomBasket ret=file->getBasket(X(oid));
-	return ret.isNull() ? 0 : ret->getRef();
-}
-
-// Basket in eine andere Datei verschieben
-extern "C" int iom_relocatebasket(IOM_FILE file,IOM_BASKET basket);
-
-/** creates a new basket.
- */
-extern "C" IOM_BASKET iom_newbasket(IOM_FILE file)
-{
-	IomBasket basket=new iom_basket();
-	file->addBasket(basket);
-	return basket->getRef();
-}
-
-/** gets the content of the VERSION element in the headersection.
- */
-extern "C" const char *iom_getheadversion(IOM_FILE file)
-{
-	return file->getHeadSecVersion_c();
-}
-/** gets the content of the VERSION element in the headersection.
- */
-extern "C" const char *iom_getheadversionUTF8(IOM_FILE file)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	const XMLCh *ret=file->getHeadSecVersion();
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** gets the content of the SENDER element in the headersection.
- */
-extern "C" const char *iom_getheadsender(IOM_FILE file)
-{
-	return file->getHeadSecSender_c();
-}
-
-/** gets the content of the SENDER element in the headersection.
- */
-extern "C" const char *iom_getheadsenderUTF8(IOM_FILE file)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	const XMLCh *ret=file->getHeadSecSender();
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** sets the content of the SENDER element in the headersection.
- */
-extern "C" void iom_setheadsender(IOM_FILE file,const char *sender)
-{
-	file->setHeadSecSender(X(sender));
-}
-/** sets the content of the SENDER element in the headersection.
- */
-extern "C" void iom_setheadsenderUTF8(IOM_FILE file,const char *sender)
-{
-	XMLCh *unicodeForm=iom_fromUTF8(sender);
-	file->setHeadSecSender(unicodeForm);
-	XMLString::release(&unicodeForm);
-}
-
-/** gets the content of the COMMENT element in the headersection.
- */
-extern "C" const char *iom_getheadcomment(IOM_FILE file)
-{
-	return file->getHeadSecComment_c();
-}
-/** gets the content of the COMMENT element in the headersection.
- */
-extern "C" const char *iom_getheadcommentUTF8(IOM_FILE file)
-{
-	static char *value=0;
-	if(value){
-		XMLString::release(&value);
-	}
-	const XMLCh *ret=file->getHeadSecComment();
-	if(!ret)return 0;
-	value=iom_toUTF8(ret);
-	return value;
-}
-
-/** sets the content of the COMMENT element in the headersection.
- */
-extern "C" void iom_setheadcomment(IOM_FILE file,const char *comment)
-{
-	file->setHeadSecComment(X(comment));
-}
-/** sets the content of the COMMENT element in the headersection.
- */
-extern "C" void iom_setheadcommentUTF8(IOM_FILE file,const char *comment)
-{
-	XMLCh *unicodeForm=iom_fromUTF8(comment);
-	file->setHeadSecComment(unicodeForm);
-	XMLString::release(&unicodeForm);
-}
-
-/** @}
- */
-
-iom_file::iom_file()
-: parser(0)
-, handler(0)
-, filename(0)
-, useCount(0)
-, headversion_w(0)
-, headversion_c(0)
-, headsender_w(0)
-, headsender_c(0)
-, headcomment_w(0)
-, headcomment_c(0)
-
-{
-}
-iom_file::~iom_file()
-{
-	if(headversion_c)XMLString::release(&headversion_c);
-	if(headversion_w)XMLString::release(&headversion_w);
-	if(headsender_c)XMLString::release(&headsender_c);
-	if(headsender_w)XMLString::release(&headsender_w);
-	if(headcomment_c)XMLString::release(&headcomment_c);
-	if(headcomment_w)XMLString::release(&headcomment_w);
-	if(filename){
-		free((void *)filename);
-	}
-	if(parser){
-		delete parser;
-	}
-	if(handler){
-		delete handler;
-	}
-}
-
-/** sets the model.
- */
-void iom_file::setModel(IomBasket model1)
-{
-	ilibasket=model1;
-}
-
-/** gets the model.
- */
-IomBasket iom_file::getModel()
-{
-	return ilibasket;
-}
-
-void iom_file::addBasket(IomBasket basket)
-{
-	basketv.push_back(basket);
-}
-
-/** gets a basket with a given oid or null.
- */
-IomBasket iom_file::getBasket(const XMLCh *oid)
-{
-	std::vector<IomBasket>::iterator it;
-	for(it=basketv.begin();it!=basketv.end();it++){
-		IomBasket obj=*it;
-		if(!XMLString::compareString(oid,obj->getOid())){
-			return obj;
-		}
-	}
-	return IomBasket();
-}
-
-
-void iom_file::setHeadSecVersion(const XMLCh *version)
-{
-	if(headversion_c)XMLString::release(&headversion_c);
-	if(headversion_w)XMLString::release(&headversion_w);
-	headversion_w=XMLString::replicate(version);
-}
-
-const char *iom_file::getHeadSecVersion_c()
-{
-	if(!headversion_w){
-		return 0;
-	}
-	if(!headversion_c){
-		headversion_c=XMLString::transcode(headversion_w);
-	}
-	return headversion_c;
-}
-const XMLCh *iom_file::getHeadSecVersion()
-{
-	return headversion_w;
-}
-
-void iom_file::setHeadSecSender(const XMLCh *sender)
-{
-	if(headsender_c)XMLString::release(&headsender_c);
-	if(headsender_w)XMLString::release(&headsender_w);
-	headsender_w=XMLString::replicate(sender);
-}
-
-const char *iom_file::getHeadSecSender_c()
-{
-	if(!headsender_w){
-		return 0;
-	}
-	if(!headsender_c){
-		headsender_c=XMLString::transcode(headsender_w);
-	}
-	return headsender_c;
-}
-const XMLCh *iom_file::getHeadSecSender()
-{
-	return headsender_w;
-}
-
-void iom_file::setHeadSecComment(const XMLCh *comment)
-{
-	if(headcomment_c)XMLString::release(&headcomment_c);
-	if(headcomment_w)XMLString::release(&headcomment_w);
-	headcomment_w=XMLString::replicate(comment);
-}
-
-const char *iom_file::getHeadSecComment_c()
-{
-	if(!headcomment_w){
-		return 0;
-	}
-	if(!headcomment_c){
-		headcomment_c=XMLString::transcode(headcomment_w);
-	}
-	return headcomment_c;
-}
-const XMLCh *iom_file::getHeadSecComment()
-{
-	return headcomment_w;
-}
-
-
-IomFile::IomFile(struct iom_file *pointee1) 
-: pointee(pointee1 ? pointee1->getRef() : 0){
-}
-IomFile::IomFile(const IomFile& src) 
-: pointee(src.pointee ? src.pointee->getRef() : 0){
-}
-IomFile& IomFile::operator=(const IomFile& src){
-	if(this!=&src){
-		if(pointee && !pointee->freeRef()){
-			delete pointee;
-		}
-		pointee=src.pointee ? src.pointee->getRef() : 0;
-	}
-	return *this;
-}
-IomFile::~IomFile(){
-	if(pointee && !pointee->freeRef()){
-		delete pointee;
-	}
-}
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_iterator.cpp b/ogr/ogrsf_frmts/ili/iom/iom_iterator.cpp
deleted file mode 100644
index 1f3a556..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_iterator.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/**********************************************************************
- * $Id: iom_iterator.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object iterator
- * @defgroup iterator iterator functions
- * @{
- */
-
-#include <iom/iom_p.h>
-
-
-/**
- * release handle
- */
-extern "C" int iom_releaseiterator(IOM_ITERATOR iterator)
-{
-	if(!iterator->freeRef()){
-		delete iterator;
-	}
-	return 0;
-}
-
-/** @}
- */
-
-iom_iterator::iom_iterator(IomFile file1)
-: type(iom_iterator::eBASKET)
-, useCount(0)
-, basketv(file1)
-, basketi(0)
-{
-}
-
-IomBasket iom_iterator::next_basket()
-{
-	if(basketi==basketv->basketv.size()){
-		// file completly read?
-		if(!basketv->parser){
-			return IomBasket();
-		}
-		// read next basket
-		basketv->readBasket(basketv);
-	}
-	if(basketi==basketv->basketv.size()){
-		// file completly read
-		return IomBasket();
-	}
-	return basketv->basketv.at(basketi++);
-}
-
-iom_iterator::iom_iterator(IomBasket basket1)
-: type(iom_iterator::eOBJECT)
-, useCount(0)
-, objectv(basket1)
-, objecti(0)
-{
-}
-
-IomObject iom_iterator::next_object()
-{
-	if(objecti==objectv->objectv.size()){
-		// basket completly read
-		return IomObject();
-	}
-	return objectv->objectv.at(objecti++);
-}
-
-
-iom_iterator::~iom_iterator()
-{
-}
-
-
-IomIterator::IomIterator(struct iom_iterator *pointee1) 
-: pointee(pointee1 ? pointee1->getRef() : 0){
-}
-IomIterator::IomIterator(const IomIterator& src) 
-: pointee(src.pointee ? src.pointee->getRef() : 0){
-}
-IomIterator& IomIterator::operator=(const IomIterator& src){
-	if(this!=&src){
-		if(pointee && !pointee->freeRef()){
-			delete pointee;
-		}
-		pointee=src.pointee ? src.pointee->getRef() : 0;
-	}
-	return *this;
-}
-IomIterator::~IomIterator(){
-	if(pointee && !pointee->freeRef()){
-		delete pointee;
-	}
-}
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_object.cpp b/ogr/ogrsf_frmts/ili/iom/iom_object.cpp
deleted file mode 100644
index 09be08b..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_object.cpp
+++ /dev/null
@@ -1,664 +0,0 @@
-/**********************************************************************
- * $Id: iom_object.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object object
- * @defgroup object object level functions
- * @{
- */
-
-#include <assert.h>
-#include <iom/iom_p.h>
-
-/**
- * release handle
- */
-extern "C" int iom_releaseobject(IOM_OBJECT object)
-{
-	if(!object->freeRef()){
-		delete object;
-	}
-	return 0;
-}
-
-// Objekt l�schen
-extern "C" int iom_deleteobject(IOM_OBJECT object);
-
-
-/** gets the tag of this object.
- * The return value is valid until iom_close or iom_setclass.
- */
-extern "C" IOM_TAG iom_getobjecttag(IOM_OBJECT object)
-{
-	return object->getTag_c();
-}
-
-/** sets the tag of this object.
- */
-extern "C" void iom_setobjecttag(IOM_OBJECT object,IOM_TAG tag)
-{
-	object->setTag(ParserHandler::getTagId(tag));
-}
-
-/** gets the OID of this object.
- * The return value is valid until iom_close or iom_setobjectoid.
- */
-extern "C" IOM_OID iom_getobjectoid(IOM_OBJECT object){
-	return object->getOid_c();
-}
-
-/** sets the OID of this object.
- */
-extern "C" void iom_setobjectoid(IOM_OBJECT object,IOM_OID oid)
-{
-	object->setOid(X(oid));
-}
-
-/** get xmlfile line number of a object.
- */
-extern "C" int iom_getobjectline(IOM_OBJECT obj)
-{
-	return obj->getXMLLineNumber();
-}
-
-/** get xmlfile column number of a object.
- */
-extern "C" int iom_getobjectcol(IOM_OBJECT obj)
-{
-	return obj->getXMLColumnNumber();
-}
-
-/** gets the oid of the referenced object or 0 if this is not a reference.
- */
-extern "C" IOM_OID iom_getobjectrefoid(IOM_OBJECT object){
-	return object->getRefOid_c();
-}
-
-/** sets the oid of the referenced object.
- */
-extern "C" void iom_setobjectrefoid(IOM_OBJECT object,IOM_OID refoid)
-{
-	object->setRefOid(X(refoid));
-}
-
-/** get the bid of the referenced object or 0 if this is not a reference
- *  or returns 0 if the referenced object is in the same basket.
- */
-extern "C" IOM_OID iom_getobjectrefbid(IOM_OBJECT object){
-	return object->getRefBid_c();
-}
-
-/** sets the bid of the referenced object.
- */
-extern "C" void iom_setobjectrefbid(IOM_OBJECT object,IOM_OID refbid)
-{
-	object->setRefBid(X(refbid));
-}
-
-/** gets the ORDER_POS of the referenced object.
-*/
-extern "C" unsigned int iom_getobjectreforderpos(IOM_OBJECT object)
-{
-	return object->getRefOrderPos();
-}
-
-/** sets the ORDER_POS of the referenced object.
-*/
-extern "C" void iom_setobjectreforderpos(IOM_OBJECT object,unsigned int orderPos)
-{
-	object->setRefOrderPos(orderPos);
-}
-
-/** gets the operation-mode of an object.
- */
-extern "C" int iom_getobjectoperation(IOM_OBJECT object){
-	return object->getOperation();
-}
-
-/** sets the operation-mode of an object.
- */
-extern "C" void iom_setobjectoperation(IOM_OBJECT object,int operation){
-	object->setOperation(operation);
-}
-
-/** gets the consistency of an object.
- */
-extern "C" int iom_getobjectconsistency(IOM_OBJECT object){
-	return object->getConsistency();
-}
-
-/** sets the consistency of an object.
- */
-extern "C" void iom_setobjectconsistency(IOM_OBJECT object,int consistency){
-	object->setConsistency(consistency);
-}
-
-/** @}
- */
-
-iom_object::iom_object()
-	:useCount(0)
-	, basket(0)
-	,consistency(IOM_COMPLETE)
-	,operation(IOM_OP_INSERT)
-	,tag(0)
-	,tag_c(0)
-	,xmlLine(0)
-	,xmlCol(0)
-	,oid_w(0)
-	,oid_c(0)
-	,bid_w(0)
-	,bid_c(0)
-	,refOid_w(0)
-	,refOid_c(0)
-	,refBid_w(0)
-	,refBid_c(0)
-	, refOrderPos(0)
-{
-}
-iom_object::~iom_object()
-{
-	if(tag_c)XMLString::release(&tag_c);
-	if(oid_c)XMLString::release(&oid_c);
-	if(oid_w)XMLString::release(&oid_w);
-	if(bid_c)XMLString::release(&bid_c);
-	if(bid_w)XMLString::release(&bid_w);
-	if(refOid_w)XMLString::release(&refOid_w);
-	if(refOid_c)XMLString::release(&refOid_c);
-	if(refBid_w)XMLString::release(&refBid_w);
-	if(refBid_c)XMLString::release(&refBid_c);
-}
-
-void iom_object::setBasket(IomBasket basket1)
-{
-	basket=&(*basket1);
-	assert(tag!=0);
-}
-
-void iom_object::setTag(int tag1)
-{
-	if(tag_c){
-		XMLString::release(&tag_c);
-		tag_c=0;
-	}
-	tag=tag1;
-	const XMLCh *const tag_w=ParserHandler::getTagName(tag);
-	tag_c=XMLString::transcode(tag_w);
-}
-const char *iom_object::getTag_c()
-{
-	if(!tag){
-		return 0;
-	}
-	if(!tag_c){
-		const XMLCh *const tag_w=ParserHandler::getTagName(tag);
-		tag_c=XMLString::transcode(tag_w);
-	}
-	return tag_c;
-}
-int iom_object::getTag()
-{
-	return tag;
-}
-
-void iom_object::setXMLLineNumber(int line)
-{
-	xmlLine=line;
-}
-
-int iom_object::getXMLLineNumber()
-{
-	return xmlLine;
-}
-
-void iom_object::setXMLColumnNumber(int col)
-{
-	xmlCol=col;
-}
-
-int iom_object::getXMLColumnNumber()
-{
-	return xmlCol;
-}
-
-/** sets the consistency of an object.
- */
-void iom_object::setConsistency(int cons)
-{
-	consistency=cons;
-}
-
-/** gets the consistency of an object.
- */
-int iom_object::getConsistency()
-{
-	return consistency;
-}
-
-/** sets the operation-mode of an object.
- */
-void iom_object::setOperation(int op)
-{
-	operation=op;
-}
-
-/** gets the operation-mode of an object.
- */
-int iom_object::getOperation()
-{
-	return operation;
-}
-
-void iom_object::setOid(const XMLCh *oid)
-{
-	if(oid_c)XMLString::release(&oid_c);
-	if(oid_w)XMLString::release(&oid_w);
-	oid_w=XMLString::replicate(oid);
-}
-const XMLCh *iom_object::getOid()
-{
-	return oid_w;
-}
-const char *iom_object::getOid_c()
-{
-	if(!oid_w){
-		return 0;
-	}
-	if(!oid_c){
-		oid_c=XMLString::transcode(oid_w);
-	}
-	return oid_c;
-}
-
-void iom_object::setBid(const XMLCh *bid)
-{
-	if(bid_c)XMLString::release(&bid_c);
-	if(bid_w)XMLString::release(&bid_w);
-	bid_w=XMLString::replicate(bid);
-}
-const char *iom_object::getBid_c()
-{
-	if(!bid_w){
-		return 0;
-	}
-	if(!bid_c){
-		bid_c=XMLString::transcode(bid_w);
-	}
-	return bid_c;
-}
-const XMLCh* iom_object::getBid()
-{
-	return bid_w;
-}
-
-/** sets the oid of the referenced object.
- */
-void iom_object::setRefOid(const XMLCh *oid)
-{
-	if(refOid_c)XMLString::release(&refOid_c);
-	if(refOid_w)XMLString::release(&refOid_w);
-	refOid_w=XMLString::replicate(oid);
-}
-
-/** gets the oid of the referenced object.
- */
-const char *iom_object::getRefOid_c()
-{
-	if(!refOid_w){
-		return 0;
-	}
-	if(!refOid_c){
-		refOid_c=XMLString::transcode(refOid_w);
-	}
-	return refOid_c;
-}
-
-/** gets the oid of the referenced object.
- */
-const XMLCh *iom_object::getRefOid()
-{
-	return refOid_w;
-}
-
-/** sets the bid of the referenced object.
- */
-void iom_object::setRefBid(const XMLCh *bid)
-{
-	if(refBid_c)XMLString::release(&refBid_c);
-	if(refBid_w)XMLString::release(&refBid_w);
-	refBid_w=XMLString::replicate(bid);
-}
-
-
-/** gets the bid of the referenced object.
- */
-const char *iom_object::getRefBid_c()
-{
-	if(!refBid_w){
-		return 0;
-	}
-	if(!refBid_c){
-		refBid_c=XMLString::transcode(refBid_w);
-	}
-	return refBid_c;
-}
-
-/** gets the bid of the referenced object.
- */
-const XMLCh *iom_object::getRefBid()
-{
-	return refBid_w;
-}
-
-/** gets ORDER_POS value, if this is a ORDERED association end.
- */
-unsigned int iom_object::getRefOrderPos()
-{
-	return refOrderPos;
-}
-
-/** sets ORDER_POS value, if this is a ORDERED association end.
- */
-void iom_object::setRefOrderPos(unsigned int value)
-{
-	refOrderPos=value;
-}
-
-/** dumps all attributes to stderr.
- */
-void iom_object::dumpAttrs(){
-
-	attrValuev_type::iterator attr=attrValuev.begin();
-	while(attr!=attrValuev.end()){
-		std::cerr << attr->first << ", " << StrX(ParserHandler::getTagName(attr->first)) << std::endl;
-		attr++;
-	}
-}
-
-/** sets the value of a primitive type attribute.
- */
-void iom_object::parser_addAttrValue(int attrName,const XMLCh *value)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	int idx;
-	if(attr==attrValuev.end()){
-		// not found, add
-		valuev_type valuev;
-		idx=valuev.size();
-		valuev.push_back(iom_value(XMLString::replicate(value)));
-		attrValuev[attrName]=valuev;
-	}else{
-		// found, add
-		valuev_type valuev=attr->second;
-		idx=valuev.size();
-		valuev.push_back(iom_value(XMLString::replicate(value)));
-		attrValuev[attrName]=valuev;
-	}
-	xmleleidxv.push_back(xmlele_type(attrName,idx));
-}
-void iom_object::parser_addAttrValue(int attrName,IomObject value)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	int idx;
-	if(attr==attrValuev.end()){
-		// not found, add
-		valuev_type valuev;
-		idx=valuev.size();
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}else{
-		// found, add
-		valuev_type valuev=attr->second;
-		idx=valuev.size();
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}
-	xmleleidxv.push_back(xmlele_type(attrName,idx));
-}
-
-int iom_object::getXmleleCount()
-{
-	return xmleleidxv.size();
-}
-
-int iom_object::getXmleleAttrName(int index)
-{
-	return xmleleidxv.at(index).first;
-}
-
-int iom_object::getXmleleValueIdx(int index)
-{
-	return xmleleidxv.at(index).second;
-}
-
-/** sets the value of an attribute to undefined. 
- */
-void iom_object::setAttrUndefined(int attrName)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-	}else{
-		// found, remove
-		attrValuev.erase(attr); // TODO free strings
-	}
-}
-
-/** sets the value of a primitive type attribute. 
- *  If value==0, the attribute is set to undefined.
- */
-void iom_object::setAttrValue(int attrName,const XMLCh *value)
-{
-	
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found, add
-		if(value){
-			valuev_type valuev;
-			valuev.push_back(iom_value(XMLString::replicate(value)));
-			attrValuev[attrName]=valuev;
-		}
-	}else{
-		// found, replace
-		if(value){
-			valuev_type valuev=attr->second;
-			valuev.clear(); // TODO free strings
-			valuev.push_back(iom_value(XMLString::replicate(value)));
-			attrValuev[attrName]=valuev;
-		}else{
-			attrValuev.erase(attr); // TODO free strings
-		}
-	}
-}
-
-/** gets the value of a primitive type attribute.
- */
-const XMLCh *iom_object::getAttrValue(int attrName)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-		return 0;
-	}
-	// found
-	valuev_type valuev=attr->second;
-	iom_value value=valuev.at(0);
-	return value.getStr();
-}
-
-int iom_object::getAttrCount()
-{
-	return attrValuev.size();
-}
-
-int iom_object::getAttrName(int index)
-{
-	attrValuev_type::iterator attri=attrValuev.begin();
-	int i=0;
-	while(attri!=attrValuev.end() && i<=index){
-		if(i==index){
-			return attri->first;
-		}
-		attri++;
-		i++;
-	}
-	return 0;
-}
-
-int iom_object::getAttrValueCount(int attrName)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-		return 0;
-	}
-	// found
-	valuev_type valuev=attr->second;
-	return valuev.size();
-}
-
-const XMLCh *iom_object::getAttrPrim(int attrName,int index)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-		return 0;
-	}
-	// found
-	valuev_type valuev=attr->second;
-	iom_value value=valuev.at(index);
-	return value.getStr();
-}
-
-/** get value at given index.
- */
-IomObject iom_object::getAttrObj(int attrName,int index)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-		return 0;
-	}
-	// found
-	valuev_type valuev=attr->second;
-	iom_value value=valuev.at(index);
-	return value.getObj();
-}
-
-/** change value at given index
-*/
-void iom_object::setAttrObj(int attrName,int index,IomObject value)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found, add
-		valuev_type valuev;
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}else{
-		// found, replace
-		valuev_type valuev=attr->second;
-		valuev.at(index)=iom_value(value);
-		attrValuev[attrName]=valuev;
-	}
-}
-
-/** insert value a given index.
-*/
-void iom_object::insertAttrObj(int attrName,int index,IomObject value)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found, add
-		valuev_type valuev;
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}else{
-		// found, add
-		valuev_type valuev=attr->second;
-		valuev.insert(valuev.begin()+index,iom_value(value));
-		attrValuev[attrName]=valuev;
-	}
-}
-
-/** add value to end of list.
-*/
-void iom_object::addAttrObj(int attrName,IomObject value)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found, add
-		valuev_type valuev;
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}else{
-		// found, add
-		valuev_type valuev=attr->second;
-		valuev.push_back(iom_value(value));
-		attrValuev[attrName]=valuev;
-	}
-}
-
-/** remove value with given index
-*/
-void iom_object::removeAttrObj(int attrName,int index)
-{
-	attrValuev_type::iterator attr=attrValuev.find(attrName);
-	if(attr==attrValuev.end()){
-		// not found
-	}else{
-		// found, remove
-		valuev_type valuev=attr->second;
-		valuev.erase(valuev.begin()+index);
-		attrValuev[attrName]=valuev;
-	}
-}
-
-IomObject::IomObject(struct iom_object *pointee1) 
-: pointee(pointee1 ? pointee1->getRef() : 0){
-}
-IomObject::IomObject(const IomObject& src) 
-: pointee(src.pointee ? src.pointee->getRef() : 0){
-}
-IomObject& IomObject::operator=(const IomObject& src){
-	if(this!=&src){
-		if(pointee && !pointee->freeRef()){
-			delete pointee;
-		}
-		pointee=src.pointee ? src.pointee->getRef() : 0;
-	}
-	return *this;
-}
-IomObject::~IomObject(){
-	if(pointee && !pointee->freeRef()){
-		delete pointee;
-	}
-}
-
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_p.h b/ogr/ogrsf_frmts/ili/iom/iom_p.h
deleted file mode 100644
index 4ed09a2..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_p.h
+++ /dev/null
@@ -1,835 +0,0 @@
-/**********************************************************************
- * $Id: iom_p.h 17910 2009-10-27 02:07:33Z chaitanya $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#ifndef IOM_IOM_P_H
-#define IOM_IOM_P_H
-
-/** @file
- * private IOM header.
- */
-
-#ifdef _MSC_VER
-// disable warning C4786: symbol greater than 255 character,
-#pragma warning(disable: 4786)
-#endif
-
-#include <iostream>
-#include <vector>
-#include <stack>
-#include <map>
-#include <xercesc/sax/Locator.hpp>
-#include <xercesc/sax2/Attributes.hpp>
-#include <xercesc/sax2/SAX2XMLReader.hpp>
-#include <xercesc/sax2/DefaultHandler.hpp>
-#include <xercesc/framework/XMLBuffer.hpp>
-#include <xercesc/framework/XMLFormatter.hpp>
-#include <xercesc/framework/XMLPScanToken.hpp>
-#include <xercesc/framework/LocalFileFormatTarget.hpp>
-#include <xercesc/util/XMLString.hpp>
-#include <xercesc/util/StringPool.hpp>
-#include <xercesc/util/TransService.hpp>
-#include <iom/iom.h>
-#ifdef _MSC_VER
-#include <crtdbg.h>
-// signed/unsigned mismatch
-#pragma warning(default: 4018)
-#endif
-
-#ifdef _DEBUG
-   //#define dbgnew   new( _CLIENT_BLOCK, __FILE__, __LINE__)
-   #define dbgnew   new
-#else
-   #define dbgnew   new
-#endif // _DEBUG
-
-#ifdef _MSC_VER
-#define IOM_PATH_MAX _MAX_PATH
-#else
-#define IOM_PATH_MAX PATH_MAX
-#endif
-
-XERCES_CPP_NAMESPACE_USE
-
-
-class XmlWrtAttr {
-private:
-	const XMLCh *name;
-	const XMLCh *value;
-	bool  oidAttr;
-public:
-	const XMLCh *getName();
-	const XMLCh *getValue();
-	bool isOid();
-	XmlWrtAttr(const XMLCh *name,const XMLCh *value);
-	XmlWrtAttr(const XMLCh *name,const XMLCh *value,bool isOid);
-};
-
-class XmlWriter {
-private:
-	XMLFormatter *out;
-	XMLFormatTarget* destination;
-public:
-	~XmlWriter();
-	XmlWriter();
-	void open(const char *filename);
-	void startElement(int tagid,XmlWrtAttr attrv[],int attrc);
-	void endElement(int tagid);
-	void endElement();
-	void characters(const XMLCh *const chars);
-	void close();
-	void printNewLine();
-	void printIndent(int level);
-private:
-	std::stack<int> stack;
-};
-
-class IomIterator { 
-private: 
-	struct iom_iterator *pointee;
-public:
-	IomIterator(){pointee=0;}
-	IomIterator(struct iom_iterator *pointee1);
-	IomIterator(const IomIterator& src);
-	IomIterator& operator=(const IomIterator& src);
-	~IomIterator();
-	struct iom_iterator& operator*() const
-	{
-		return *pointee;
-	}
-	struct iom_iterator* operator->() const
-	{
-		return pointee;
-	}
-	bool isNull(){return pointee==0;}
-};
-
-class IomFile { 
-private: 
-	struct iom_file *pointee;
-public:
-	IomFile(){pointee=0;}
-	IomFile(struct iom_file *pointee1);
-	IomFile(const IomFile& src);
-	IomFile& operator=(const IomFile& src);
-	~IomFile();
-	struct iom_file& operator*() const
-	{
-		return *pointee;
-	}
-	struct iom_file* operator->() const
-	{
-		return pointee;
-	}
-	bool isNull(){return pointee==0;}
-};
-class IomBasket { 
-private: 
-	struct iom_basket *pointee;
-public:
-	IomBasket(){pointee=0;}
-	IomBasket(struct iom_basket *pointee1);
-	IomBasket(const IomBasket& src);
-	IomBasket& operator=(const IomBasket& src);
-	~IomBasket();
-	struct iom_basket& operator*() const
-	{
-		return *pointee;
-	}
-	struct iom_basket* operator->() const
-	{
-		return pointee;
-	}
-	bool isNull(){return pointee==0;}
-};
-
-class IomObject { 
-protected: 
-	struct iom_object *pointee;
-public:
-	IomObject(){pointee=0;}
-	IomObject(struct iom_object *pointee1);
-	IomObject(const IomObject& src);
-	IomObject& operator=(const IomObject& src);
-	~IomObject();
-	struct iom_object& operator*() const
-	{
-		return *pointee;
-	}
-	struct iom_object* operator->() const
-	{
-		return pointee;
-	}
-	bool isNull(){return pointee==0;}
-};
-
-struct iom_file {
-private:
-		XMLPScanToken token;
-		SAX2XMLReader* parser;
-		class ParserHandler* handler;
-		// table of baskets
-		std::vector<IomBasket> basketv;
-public:
-		void addBasket(IomBasket basket);
-		IomBasket getBasket(const XMLCh *oid);
-private:
-		const char *filename;
-public:
-		~iom_file();
-		iom_file();
-		int readHeader(const char *model);
-		int readBasket(IomFile file);
-		int readLoop(const char *filename);
-		void setFilename(const char *filename);
-		int save();
-private:
-		int useCount;
-public:
-		struct iom_file *getRef(){useCount++;return this;}
-		int freeRef(){useCount--;return useCount;}
-
-
-private:
-		IomBasket ilibasket;
-
-public:
-		void setModel(IomBasket model);
-		IomBasket getModel();
-
-private:
-		XMLCh *headversion_w;
-		char *headversion_c;
-public:
-		void setHeadSecVersion(const XMLCh *version);
-		const char *getHeadSecVersion_c();
-		const XMLCh *getHeadSecVersion();
-
-private:
-		XMLCh *headsender_w;
-		char *headsender_c;
-public:
-		void setHeadSecSender(const XMLCh *sender);
-		const char *getHeadSecSender_c();
-		const XMLCh *getHeadSecSender();
-
-private:
-		XMLCh *headcomment_w;
-		char *headcomment_c;
-public:
-		void setHeadSecComment(const XMLCh *comment);
-		const char *getHeadSecComment_c();
-		const XMLCh *getHeadSecComment();
-private:
-		void writePolyline(XmlWriter &out, IomObject &obj,bool hasLineAttr);
-		void writeSurface(XmlWriter &out, IomObject &obj);
-		void writeAttrs(XmlWriter &out, IomObject &obj);
-		void writeAttr(XmlWriter &out, IomObject &obj,int attr);
-private:
-		// map<int classTag,vector<pair<int pos,int attrName>>>
-		typedef std::vector< std::pair<int,int> > attrv_type;
-		typedef std::map<int,attrv_type> tagv_type;
-		tagv_type tagList;		
-		void buildTagList();
-		int getQualifiedTypeName(IomObject &aclass);
-
-private:
-public:
-		friend struct iom_iterator;
-};
-
-
-struct iom_basket {
-		struct iom_file *file; // use weak pointer to avoid a circular reference in the smart pointers
-private:
-		int tag;
-		char *tag_c;
-public:
-		void setTag(int tag);
-		const char *getTag_c();
-		int getTag();
-private:
-		int xmlLine;
-		int xmlCol;
-public:
-		void setXMLLineNumber(int line);
-		int getXMLLineNumber();
-		void setXMLColumnNumber(int col);
-		int getXMLColumnNumber();
-
-private:
-		int consistency;
-public:
-		void setConsistency(int cons);
-		int getConsistency();
-
-private:
-		int kind;
-public:
-		void setKind(int kind);
-		int getKind();
-
-private:
-		XMLCh *oid_w;
-		char *oid_c;
-public:
-		void setOid(const XMLCh *oid);
-		const char *getOid_c();
-		const XMLCh *getOid();
-private:
-		XMLCh *startstate_w;
-		char *startstate_c;
-public:
-		void setStartState(const XMLCh *startstate);
-		const char *getStartState_c();
-		const XMLCh *getStartState();
-private:
-		XMLCh *endstate_w;
-		char *endstate_c;
-public:
-		void setEndState(const XMLCh *endstate);
-		const char *getEndState_c();
-		const XMLCh *getEndState();
-private:
-		XMLCh *topics_w;
-		char *topics_c;
-public:
-		void setTopics(const XMLCh *topics);
-		const char *getTopics_c();
-		const XMLCh *getTopics();
-public:
-		iom_basket();
-		~iom_basket();
-private:
-		int useCount;
-public:
-		struct iom_basket *getRef(){useCount++;return this;}
-		int freeRef(){useCount--;return useCount;}
-private:
-		std::vector<IomObject> objectv;
-public:
-		void addObject(IomObject object);
-		IomObject getObject(const XMLCh *oid);
-
-		friend struct iom_iterator;
-};
-
-class iom_value {
-private:
-	const XMLCh *str;
-	IomObject obj;
-	iom_value(); 
-public:
-	iom_value(IomObject value); 
-	iom_value(const XMLCh *value); 
-	const XMLCh *getStr();
-	IomObject getObj();
-};
-
-struct iom_object {
-private:
-	int useCount;
-public:
-	struct iom_object *getRef(){useCount++;return this;}
-	int freeRef(){useCount--;return useCount;}
-private:
-	struct iom_basket *basket; // use weak pointer to avoid a circular reference in the smart pointers
-public:
-	void setBasket(IomBasket basket);
-public:
-		//iom_object();
-		iom_object();
-		virtual ~iom_object();
-
-private:
-		int consistency;
-public:
-		void setConsistency(int cons);
-		int getConsistency();
-
-private:
-		int operation;
-public:
-		void setOperation(int op);
-		int getOperation();
-
-private:
-		int tag;
-		char *tag_c;
-public:
-		void setTag(int tag);
-		const char *getTag_c();
-		int getTag();
-
-private:
-	int xmlLine;
-	int xmlCol;
-public:
-		void setXMLLineNumber(int line);
-		int getXMLLineNumber();
-		void setXMLColumnNumber(int col);
-		int getXMLColumnNumber();
-
-private:
-		XMLCh *oid_w;
-		char *oid_c;
-public:
-		void setOid(const XMLCh *oid);
-		const XMLCh *getOid();
-		const char *getOid_c();
-
-private:
-		XMLCh *bid_w;
-		char *bid_c;
-public:
-		void setBid(const XMLCh *bid);
-		const char *getBid_c();
-		const XMLCh* getBid();
-
-private:
-		XMLCh *refOid_w;
-		char *refOid_c;
-public:
-		void setRefOid(const XMLCh *oid);
-		const XMLCh *getRefOid();
-		const char *getRefOid_c();
-private:
-		XMLCh *refBid_w;
-		char *refBid_c;
-public:
-		void setRefBid(const XMLCh *bid);
-		const XMLCh *getRefBid();
-		const char *getRefBid_c();
-
-private:
-		unsigned int refOrderPos;
-public:
-		unsigned int getRefOrderPos();
-		void setRefOrderPos(unsigned int value);
-
-private:
-		// ArrayList<(String attrName,int index)>
-		typedef std::pair<int,int> xmlele_type;
-		typedef std::vector<xmlele_type> xmleleidxv_type;
-		xmleleidxv_type xmleleidxv;
-public:
-		int getXmleleCount();
-		int getXmleleAttrName(int index);
-		int getXmleleValueIdx(int index);
-
-
-private:
-		// HashMap<String attrName,ArrayList<String|IliObject>>
-		typedef std::vector<class iom_value> valuev_type;
-		typedef std::map<int,valuev_type> attrValuev_type;
-		attrValuev_type	attrValuev;		
-public:
-		void dumpAttrs();
-		void parser_addAttrValue(int attrName,IomObject value);
-		void parser_addAttrValue(int attrName,const XMLCh *value);
-		//void setAttrValue(int attrName,IomObject value);
-		int getAttrCount();
-		int getAttrName(int index);
-		int getAttrValueCount(int attrName);
-		void setAttrUndefined(int attrName);
-		const XMLCh *getAttrValue(int attrName);
-		void setAttrValue(int attrName,const XMLCh *value);
-		const XMLCh *getAttrPrim(int attrName,int index);
-		IomObject getAttrObj(int attrName,int index);
-		void setAttrObj(int attrName,int index,IomObject value);
-		void insertAttrObj(int attrName,int index,IomObject value);
-		void addAttrObj(int attrName,IomObject value);
-		void removeAttrObj(int attrName,int index);
-};
-
-struct iom_iterator {
-		enum { eBASKET,eOBJECT } type;
-		~iom_iterator();
-private:
-		int useCount;
-public:
-		struct iom_iterator *getRef(){useCount++;return this;}
-		int freeRef(){useCount--;return useCount;}
-private:
-		IomFile basketv;
-		std::vector<IomBasket>::size_type basketi;
-public:
-		iom_iterator(IomFile file);
-		IomBasket next_basket();
-private:
-		IomBasket objectv;
-		std::vector<IomObject>::size_type objecti;
-public:
-		iom_iterator(IomBasket basket);
-		IomObject next_object();
-};
-
-class Element {
-public:
-	IomObject object;
-	int propertyName;
-	Element(); 
-	Element(const Element& src);
-	Element& operator=(const Element& src);
-	~Element();
-
-private:
-	XMLCh *oid;
-public:
-	const XMLCh *getOid();
-	void setOid(const XMLCh *oid);
-
-private:
-	XMLCh *bid;
-public:
-	const XMLCh *getBid();
-	void setBid(const XMLCh *bid);
-
-private:
-	unsigned int orderPos;
-public:
-	unsigned int getOrderPos();
-	void setOrderPos(unsigned int value);
-};
-
-
-class ParserHandler : 
-public DefaultHandler
-{
-
-public :
-    ParserHandler(IOM_FILE file,const char* model);
-    ~ParserHandler();
-
-private:
-	// table of element and attribute names
-	static XMLStringPool *namev;
-public:
-	static void at_iom_end();
-
-public:
-	static int getTagId(const char *name);
-	static int getTagId(const XMLCh *const name);
-	static const XMLCh *const getTagName(int tagid);
-
-public:
-	// SAX handler
-#if XERCES_VERSION_MAJOR >= 3
-	void  characters (const XMLCh *const chars, const XMLSize_t length); // xerces 3
-	// void  ignorableWhitespace (const XMLCh *const chars, const XMLSize_t length); // xerces 3
-#else
-	void  characters (const XMLCh *const chars, const unsigned int length); // xerces 2
-	// void  ignorableWhitespace (const XMLCh *const chars, const unsigned int length); // xerces 2
-#endif
-	// void  startDocument ();
-	// void  endDocument ();
-	void  startElement (const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname, const Attributes &attrs);
-	void  endElement (const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname);
-	// void  processingInstruction (const XMLCh *const target, const XMLCh *const data); 
-	void  setDocumentLocator (const Locator *const locator);
-	// void  startPrefixMapping (const XMLCh *const prefix, const XMLCh *const uri);
-	// void  endPrefixMapping (const XMLCh *const prefix);
-	// void  skippedEntity (const XMLCh *const name);
-        void startEntity (const XMLCh *const name);
- 
-
-    void warning(const SAXParseException& exc);
-    void error(const SAXParseException& exc);
-    void fatalError(const SAXParseException& exc);
-
-private:
-	const Locator *locator;
-
-private:
-	struct iom_file *file;
-	char *model;
-	int skip;
-	int level;
-	int state;
-	XMLBuffer propertyValue;
-	IomBasket dataContainer; 
-	IomObject object;
-        int m_nEntityCounter;
-	std::stack<class Element> objStack;
-	std::stack<int> stateStack;
-	void pushReturnState(int returnState);
-	void popReturnState();
-	void changeReturnState(int returnState);
-
-private:
-		enum e_states {
-			BEFORE_TRANSFER=1,
-			BEFORE_DATASECTION=2,
-			BEFORE_BASKET=3,
-			BEFORE_OBJECT=4,
-			// StructValue
-			ST_BEFORE_PROPERTY=5,
-			ST_AFTER_STRUCTVALUE=6,
-			ST_BEFORE_EMBASSOC=7,
-			ST_BEFORE_CHARACTERS=8,
-			ST_AFTER_COORD=9,
-			ST_AFTER_POLYLINE=10,
-			ST_AFTER_SURFACE=11,
-			// CoordValue
-			CV_COORD=20,
-			CV_C1=21,
-			CV_AFTER_C1=22,
-			CV_C2=23,
-			CV_AFTER_C2=24,
-			CV_C3=25,
-			CV_AFTER_C3=26,
-			// PolylineValue
-			PV_POLYLINE=40,
-			PV_LINEATTR=41,
-			PV_AFTER_LINEATTRSTRUCT=42,
-			PV_AFTER_LINEATTR=43,
-			PV_CLIPPED=44,
-			PV_AFTER_CLIPPED=45,
-			// SegmentSequence
-			SS_AFTER_COORD=60,
-			// SurfaceValue
-			SV_SURFACE=80,
-			SV_CLIPPED=81,
-			SV_AFTER_CLIPPED=82,
-			// Boundaries
-			BD_BOUNDARY=100,
-			BD_AFTER_POLYLINE=101,
-			BD_AFTER_BOUNDARY=102,
-			// HeaderSection
-			START_HEADERSECTION=200
-		};
-};
-
-
-class tags {
-public:
-	static int get_COORD();
-	static int get_ARC();
-	static int get_C1();
-	static int get_C2();
-	static int get_C3();
-	static int get_A1();
-	static int get_A2();
-	static int get_iom04_metamodel_AssociationDef();
-	static int get_R();
-	static int get_lineattr();
-	static int get_TRANSFER();
-	static int get_iom04_metamodel_Table();
-	static int get_DATASECTION();
-	static int get_HEADERSECTION();
-	static int get_ALIAS();
-	static int get_COMMENT();
-	static int get_CLIPPED();
-	static int get_LINEATTR();
-	static int get_SEGMENTS();
-	static int get_segment();
-	static int get_SURFACE();
-	static int get_surface();
-	static int get_boundary();
-	static int get_BOUNDARY();
-	static int get_polyline();
-	static int get_POLYLINE();
-	static int get_sequence();
-	static int get_MULTISURFACE();
-	static int get_iom04_metamodel_ViewableAttributesAndRoles();
-	static int get_viewable();
-	static int get_attributesAndRoles();
-	static int get_container();
-	static int get_iom04_metamodel_TransferDescription();
-	static int get_name();
-	static void clear();
-private:
-	static int COORD;
-	static int ARC;
-	static int C1;
-	static int C2;
-	static int C3;
-	static int A1;
-	static int A2;
-	static int iom04_metamodel_AssociationDef;
-	static int R;
-	static int lineattr;
-	static int TRANSFER;
-	static int iom04_metamodel_Table;
-	static int DATASECTION;
-	static int HEADERSECTION;
-	static int ALIAS;
-	static int COMMENT;
-	static int CLIPPED;
-	static int LINEATTR;
-	static int SEGMENTS;
-	static int segment;
-	static int SURFACE;
-	static int surface;
-	static int boundary;
-	static int BOUNDARY;
-	static int polyline;
-	static int POLYLINE;
-	static int sequence;
-	static int MULTISURFACE;
-	static int iom04_metamodel_ViewableAttributesAndRoles;
-	static int viewable;
-	static int attributesAndRoles;
-	static int container;
-	static int iom04_metamodel_TransferDescription;
-	static int name;
-};
-class ustrings {
-public:
-	static const XMLCh*  get_xmlns();
-	static const XMLCh*  get_NS_INTERLIS22();
-	static const XMLCh*  get_BID();
-	static const XMLCh*  get_TOPICS();
-	static const XMLCh*  get_KIND();
-	static const XMLCh*  get_STARTSTATE();
-	static const XMLCh*  get_ENDSTATE();
-	static const XMLCh*  get_TID();
-	static const XMLCh*  get_OPERATION();
-	static const XMLCh*  get_INSERT();
-	static const XMLCh*  get_UPDATE();
-	static const XMLCh*  get_DELETE();
-	static const XMLCh*  get_REF();
-	static const XMLCh*  get_EXTREF();
-	static const XMLCh*  get_ORDER_POS();
-	static const XMLCh*  get_CONSISTENCY();
-	static const XMLCh*  get_COMPLETE();
-	static const XMLCh*  get_INCOMPLETE();
-	static const XMLCh*  get_INCONSISTENT();
-	static const XMLCh*  get_ADAPTED();
-	static const XMLCh*  get_SENDER();
-	static const XMLCh*  get_VERSION();
-	static const XMLCh*  get_INITIAL();
-
-};
-
-char *iom_toUTF8(const XMLCh *src);
-XMLCh *iom_fromUTF8(const char *src);
-
-// ---------------------------------------------------------------------------
-//  This is a simple class that lets us do easy (though not terribly efficient)
-//  trancoding of XMLCh data to local code page for display.
-// ---------------------------------------------------------------------------
-class StrX
-{
-public :
-    // -----------------------------------------------------------------------
-    //  Constructors and Destructor
-    // -----------------------------------------------------------------------
-    StrX(const XMLCh* const toTranscode)
-    {
-        // Call the private transcoding method
-        fLocalForm = XMLString::transcode(toTranscode);
-    }
-
-    ~StrX()
-    {
-        XMLString::release(&fLocalForm);
-    }
-
-    // -----------------------------------------------------------------------
-    //  Getter methods
-    // -----------------------------------------------------------------------
-    const char* localForm() const
-    {
-        return fLocalForm;
-    }
-
-private :
-    // -----------------------------------------------------------------------
-    //  Private data members
-    //
-    //  fLocalForm
-    //      This is the local code page form of the string.
-    // -----------------------------------------------------------------------
-    char*   fLocalForm;
-};
-
-inline std::ostream& operator<<(std::ostream& target, const StrX& toDump)
-{
-    target << toDump.localForm();
-    return target;
-}
-
-// ---------------------------------------------------------------------------
-//  This is a simple class that lets us do easy (though not terribly efficient)
-//  trancoding of char* data to XMLCh data.
-// ---------------------------------------------------------------------------
-class XStr
-{
-public :
-    // -----------------------------------------------------------------------
-    //  Constructors and Destructor
-    // -----------------------------------------------------------------------
-    XStr(const char* const toTranscode)
-    {
-        // Call the private transcoding method
-        fUnicodeForm = XMLString::transcode(toTranscode);
-    }
-
-    ~XStr()
-    {
-        XMLString::release(&fUnicodeForm);
-    }
-
-
-    // -----------------------------------------------------------------------
-    //  Getter methods
-    // -----------------------------------------------------------------------
-    const XMLCh* unicodeForm() const
-    {
-        return fUnicodeForm;
-    }
-
-private :
-    // -----------------------------------------------------------------------
-    //  Private data members
-    //
-    //  fUnicodeForm
-    //      This is the Unicode XMLCh format of the string.
-    // -----------------------------------------------------------------------
-    XMLCh*   fUnicodeForm;
-};
-
-#define X(str) XStr(str).unicodeForm()
-
-/** namespace of error handler.
-*/
-class ErrorUtility {
-public:
-	static IomBasket errs;
-	static int errc;
-	static XMLCh itoabuf[40];
-	static IOM_ERRLISTENER listener;
-	static void at_iom_end();
-	static void notifyerr(IomObject obj);
-	static void init();
-};
-
-
-#endif
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_utilities.cpp b/ogr/ogrsf_frmts/ili/iom/iom_utilities.cpp
deleted file mode 100644
index 1a05a8d..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_utilities.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/**********************************************************************
- * $Id: iom_utilities.cpp 16745 2009-04-07 20:26:08Z warmerdam $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-/** @file
- * implementation of utility functions
- * @defgroup utilities utility functions
- * @{
- */
-
-#include <cstdio>
-#include <iostream>
-#include <string>
-#include <string.h>
-
-#include <iom/iom_p.h>
-
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if defined(__MSVCRT__) || defined(_MSC_VER)
-#define stat _stat
-#else
-#include <unistd.h>
-#endif
-
-#if !defined(__MSVCRT__) && !defined(_MSC_VER)
-
-#include <stdlib.h>
-#include <string.h>
-
-#define PATHSEP ':'
-
-/*
-  _searchenv is a function provided by the MSVC library that finds
-  files which may be anywhere along a path which appears in an
-  environment variable.
-*/
-
-static void _searchenv(const char *name, const char *envname, char *hitfile)
-{
-
-	// Default failure indication
-	*hitfile = '\0';
-
-	// If the given name is absolute, then don't search the
-	//   path, but use it as is.
-	if(
-#ifdef WIN32
-		strchr(name, ':') != NULL || // Contain a drive spec? 
-		name[0] == '\\' ||		// Start with absolute ref? 
-#endif
-		name[0] == '/')			// Start with absolute ref?
-	{
-		// Copy to target
-		strcpy(hitfile, name);	
-		return;
-	}
-
-	char *cp;
-	cp = getenv(envname);
-	if(cp == NULL){
-		// Variable not defined, no search.
-		return;	
-	}
-
-	while(*cp)
-	{
-		*hitfile = '\0';
-		char *concat;
-		concat=hitfile;
-		// skip PATHSEP (and empty entries)
-		while(*cp && *cp==PATHSEP){
-			cp++;
-		}
-		// copy path
-		while(*cp && *cp!=PATHSEP){
-			*concat=*cp;
-			cp++;
-			concat++;
-		}
-		// end of variable value reached?
-		if(concat==hitfile){
-			// file not found
-			*hitfile = '\0';
-			return;
-		}
-		// does no trailing '/' exists?
-		if(*(concat-1) != '/' && *(concat-1) != '\\'){
-			// append it
-			*concat='/';
-			concat++;
-		}
-		// append file name
-		strcpy(concat, name);
-		// does file exist?
-		if(iom_fileexists(hitfile))
-		{
-			// file found
-			return;
-		}
-	}
-	// file not found
-	*hitfile = '\0';
-}
-
-#endif
-
-
-
-static char *tmpdir=0;
-static XMLTranscoder *utf8_transcoder=0;
-
-/** Perform iom library initialization.
- */
-extern "C" void iom_init()
-{
-	//__asm { int 3 };
-
-	try {
-           XMLPlatformUtils::Initialize();
-    }
-    catch (const XMLException& toCatch) {
-        char* message = XMLString::transcode(toCatch.getMessage());
-		iom_issueerr(message);
-        XMLString::release(&message);
-        return;
-    }
-    XMLTransService::Codes resCode;
-    utf8_transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
-    (
-        "UTF-8"
-        , resCode
-        , 16 * 1024
-    );
-	tags::clear();
-
-}
-
-/* Compatibility stuff due to change of Xerces-C API signature (#2616) */
-#if XERCES_VERSION_MAJOR >= 3
-#define LEN_SIZE_TYPE XMLSize_t
-#else
-#define LEN_SIZE_TYPE unsigned int
-#endif
-
-/** transcode a xerces unicode string to an utf8 encoded one.
-*/
-char *iom_toUTF8(const XMLCh *src)
-{
-	LEN_SIZE_TYPE srcLen=XMLString::stringLen(src);
-	LEN_SIZE_TYPE destLen=srcLen+10;
-	XMLByte *dest;
-	dest=dbgnew XMLByte[destLen+1];
-	LEN_SIZE_TYPE eaten;
-	LEN_SIZE_TYPE endDest;
-	endDest=utf8_transcoder->transcodeTo(src,srcLen,dest,destLen,eaten,XMLTranscoder::UnRep_RepChar);
-	while(eaten<srcLen){
-		delete[] dest;
-		destLen=destLen+srcLen-eaten+10;
-		dest=dbgnew XMLByte[destLen+1];
-		endDest=utf8_transcoder->transcodeTo(src,srcLen,dest,destLen,eaten,XMLTranscoder::UnRep_RepChar);
-	}
-	dest[endDest]=0;
-	return (char*)dest; /* should be a unsigned char* == XMLByte* instead */
-}
-
-/** transcode an utf8 encoded string to a xerces unicode one.
-*/
-XMLCh *iom_fromUTF8(const char *src)
-{
-	LEN_SIZE_TYPE srcLen=XMLString::stringLen(src);
-	LEN_SIZE_TYPE destLen=srcLen;
-	XMLCh *dest=dbgnew XMLCh[destLen+1];
-	unsigned char *charSizes=dbgnew unsigned char[destLen];
-	LEN_SIZE_TYPE eaten;
-	LEN_SIZE_TYPE endDest=utf8_transcoder->transcodeFrom((const XMLByte *)src,srcLen,dest,destLen,eaten,charSizes);
-	dest[endDest]=0;
-	delete[] charSizes;
-	return dest;
-}
-
-/** Perform iom library termination.
- */
-extern "C" void iom_end()
-{
-
-	ParserHandler::at_iom_end();
-	ErrorUtility::at_iom_end();
-	tags::clear();
-	XMLPlatformUtils::Terminate();
-}
-
-/** sets the directory where iom writes temporary files.
- */
-extern "C" void iom_settmpdir(const char *dirname)
-{
-	if(tmpdir)free(tmpdir);
-	tmpdir=strdup(dirname);
-}
-
-/** creates a temporary filename.
- * The caller should free the returned buffer.
- */
-extern "C" char *iom_gettmpnam()
-{
-#ifdef _MSC_VER
-	return _tempnam(tmpdir,"iom");
-#else
-	return tempnam(tmpdir,"iom");
-#endif
-}
-
-/** Searches for a file in
- *  a directory specified by an environment variable.
- * Returns 0 if file not found.
- * Returns a pointer to a static buffer.
- */
-extern "C" char *iom_searchenv(const char *filename, const char *varname)
-{
-	static char pathbuffer[IOM_PATH_MAX];
-	_searchenv( filename, varname, pathbuffer );
-	if( *pathbuffer != '\0' ){
-		return pathbuffer;
-	}
-	// file not found
-	return 0;
-}
-
-/** Tests if a file exists.
- * Returns !0 if file exists.
- */
-extern "C" int iom_fileexists(const char *filename)
-{
-	struct stat info;
-	// does file exist?
-	if(!stat(filename, &info))
-	{
-		// file found
-		return true;
-	}
-	return false;
-}
-
-/** Returns the current time in milliseconds.
- */
-extern "C" unsigned long iom_currentmilis()
-{
-	return XMLPlatformUtils::getCurrentMillis();
-}
-
-/**
- * @}
- */
diff --git a/ogr/ogrsf_frmts/ili/iom/iom_value.cpp b/ogr/ogrsf_frmts/ili/iom/iom_value.cpp
deleted file mode 100644
index 9b83927..0000000
--- a/ogr/ogrsf_frmts/ili/iom/iom_value.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/**********************************************************************
- * $Id: iom_value.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * implementation of object value
- * @defgroup value value related functions
- * @{
- */
-
-#include <iom/iom_p.h>
-
-iom_value::iom_value(IomObject value)
-: str(0)
-, obj(value)
-{
-}
-
-iom_value::iom_value(const XMLCh *value)
-: str(value)
-, obj(0)
-{
-}
-
-
-const XMLCh *iom_value::getStr()
-{
-	return str;
-}
-
-IomObject iom_value::getObj()
-{
-	return obj;
-}
-
-/** @}
- */
diff --git a/ogr/ogrsf_frmts/ili/iom/makefile.vc b/ogr/ogrsf_frmts/ili/iom/makefile.vc
deleted file mode 100644
index a281da6..0000000
--- a/ogr/ogrsf_frmts/ili/iom/makefile.vc
+++ /dev/null
@@ -1,18 +0,0 @@
-
-OBJ =	iom_attr.obj iom_basket.obj iom_error.obj \
-	iom_file.obj iom_iterator.obj iom_object.obj \
-	iom_utilities.obj iom_value.obj \
-	reader.obj tags.obj ustrings.obj writer.obj
-
-GDAL_ROOT	=	..\..\..\..
-
-!INCLUDE $(GDAL_ROOT)\nmake.opt
-
-EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(XERCES_INCLUDE) 
-
-default:	$(OBJ)
-
-clean:
-	-del *.lib
-	-del *.obj *.pdb
-
diff --git a/ogr/ogrsf_frmts/ili/iom/reader.cpp b/ogr/ogrsf_frmts/ili/iom/reader.cpp
deleted file mode 100644
index 82302f9..0000000
--- a/ogr/ogrsf_frmts/ili/iom/reader.cpp
+++ /dev/null
@@ -1,975 +0,0 @@
-/**********************************************************************
- * $Id: reader.cpp 17910 2009-10-27 02:07:33Z chaitanya $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * adapter to xml parser 
- * @defgroup reader xml reader functions
- * @{
- */
-
-#include <cassert>
-#include <cstring>
-
-#include <xercesc/util/XMLString.hpp>
-#include <xercesc/sax/Locator.hpp>
-#include <xercesc/sax2/XMLReaderFactory.hpp>
-#include <xercesc/sax2/Attributes.hpp>
-
-#include <iom/iom_p.h>
-
-XMLStringPool *ParserHandler::namev=0;
-
-
-/** read complete HEADERSECTION
- *  Requires: call to setFilename()
- */
-int iom_file::readHeader(const char *model)
-{
-	handler=dbgnew class ParserHandler(this,model);
-	parser=XMLReaderFactory::createXMLReader();
-	// Do not report validation errors
-    parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
-	// use scanner that performs well-formedness checking only.
-	parser->setProperty(XMLUni::fgXercesScannerName,(void *)XMLUni::fgWFXMLScanner);
-    parser->setContentHandler(handler);
-    parser->setEntityResolver(handler);
-    parser->setErrorHandler(handler);
-	return readLoop(filename);
-}
-
-
-int iom_file::readLoop(const char *filename)
-{
-	try
-    {
-		if (!parser->parseFirst(filename, token))
-		{
-			iom_issueerr("scanFirst() failed");
-			return IOM_ERR_XMLPARSER;
-		}
-		bool gotMore = true;
-		while (gotMore && !parser->getErrorCount()){
-			gotMore = parser->parseNext(token);
-		}
-		parser->parseReset(token);
-	}
-	catch (const XMLException& toCatch)
-    {
-            char* message = XMLString::transcode(toCatch.getMessage());
-			iom_issueerr(message);
-            XMLString::release(&message);
-            return IOM_ERR_XMLPARSER;
-    }
-    catch (const SAXException& toCatch)
-    {
-            char* message = XMLString::transcode(toCatch.getMessage());
-			iom_issueerr(message);
-            XMLString::release(&message);
-            return IOM_ERR_XMLPARSER;
-    }
-	return 0;
-}
-
-
-/** read one (next) basket
- */
-int iom_file::readBasket(IomFile file)
-{
-	return 1;
-}
-
-/** sets filename
- */
-void iom_file::setFilename(const char *filename1)
-{
-	if(filename)free((void *)filename);
-	filename=strdup(filename1);
-}
-
-/** @}
- */
-
-//#include <xercesc/util/XMLUniDefs.hpp>
-//#include <xercesc/util/XMLUni.hpp>
-//#include <xercesc/sax/AttributeList.hpp>
-
-Element::Element()
-	: object(0)
-	, propertyName(0)
-	, oid(0)
-	, bid(0)
-	, orderPos(0)
-{
-}
-Element::Element(const Element& src) 
-	: object(src.object)
-	, propertyName(src.propertyName)
-	, oid(XMLString::replicate(src.oid))
-	, bid(XMLString::replicate(src.bid))
-	, orderPos(src.orderPos)
-{
-}
-Element& Element::operator=(const Element& src){
-	if(this!=&src){
-		object=src.object;
-		if(bid){
-			XMLString::release(&bid);
-		}
-		if(src.bid){
-			bid=XMLString::replicate(src.bid);
-		}
-		if(oid){
-			XMLString::release(&oid);
-		}
-		if(src.oid){
-			oid=XMLString::replicate(src.oid);
-		}
-		propertyName=src.propertyName;
-		orderPos=src.orderPos;
-	}
-	return *this;
-}
-Element::~Element(){
-	if(bid)XMLString::release(&bid);
-	if(oid)XMLString::release(&oid);
-}
-
-const XMLCh *Element::getOid()
-{
-	return oid;
-}
-
-void Element::setOid(const XMLCh *oid1)
-{
-	if(oid)XMLString::release(&oid);
-	oid=XMLString::replicate(oid1);
-}
-
-const XMLCh *Element::getBid()
-{
-	return bid;
-}
-
-void Element::setBid(const XMLCh *bid1)
-{
-	if(bid)XMLString::release(&bid);
-	bid=XMLString::replicate(bid1);
-}
-
-unsigned int Element::getOrderPos()
-{
-	return orderPos;
-}
-
-void Element::setOrderPos(unsigned int value)
-{
-	orderPos=value;
-}
-
-static const XMLCh* stripX(const XMLCh* value)
-{
-	if(XMLString::startsWith(value,X("x"))){
-		return value+1;
-	}
-	return value;
-}
-
-ParserHandler::ParserHandler(struct iom_file *inputfile,const char* model1) 
-	: locator(0)
-	,file(inputfile)
-	,model(model1 ? strdup(model1) : 0)
-	,skip(0)
-	,level(0)
-	,state(BEFORE_TRANSFER)
-	,dataContainer(0)
-	,object(0)
-	,m_nEntityCounter(0)
-{
-	//  setupTag2MetaobjMapping();
-}
-
-ParserHandler::~ParserHandler()
-{
-	if(model){
-		free(model);
-		model=0;
-	}
-}
-
-bool xisClassDef(int tag)
-{
-	const XMLCh *const type=ParserHandler::getTagName(tag);
-	if(!XMLString::compareString(type,X("iom04.metamodel.Table"))){
-		return true;
-	}
-	return false;
-}
-bool xisAssociationDef(int tag)
-{
-	const XMLCh *const type=ParserHandler::getTagName(tag);
-	if(!XMLString::compareString(type,X("iom04.metamodel.AssociationDef"))){
-		return true;
-	}
-	return false;
-}
-bool xisTopicDef(int tag)
-{ 
-	const XMLCh *const type=ParserHandler::getTagName(tag);
-	if(!XMLString::compareString(type,X("iom04.metamodel.Topic"))){
-		return true;
-	}
-	return false;
-}
-
-void ParserHandler::startEntity (const XMLCh *const name)
-{
-    m_nEntityCounter ++;
-    if (m_nEntityCounter > 1000)
-    {
-        throw SAXNotSupportedException ("File probably corrupted (million laugh pattern)");
-    }
-}
-
-void  ParserHandler::startElement (const XMLCh *const uri
-									, const XMLCh *const localname
-									, const XMLCh *const qname
-									, const Attributes &attrs)
-{
-    	level++;
-        m_nEntityCounter = 0;
-    	if(skip>0){
-    		skip++;
-    		return;
-    	}
-		int tag=getTagId(localname);
-		if(state==BEFORE_TRANSFER && tag==tags::get_TRANSFER()){
-    		state=BEFORE_DATASECTION;
-    		return;
-    	}
-		if(state==BEFORE_DATASECTION && tag==tags::get_HEADERSECTION()){
-			const XMLCh* sender=0;
-			const XMLCh* version=0;
-			for(unsigned int attri=0;attri<attrs.getLength();attri++){
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_SENDER())){
-					sender=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_VERSION())){
-					version=attrs.getValue(attri);
-				}
-
-			}
-			if(!sender){
-				// SENDER is mandatory
-				iom_issueparserr("Attribute SENDER missing in file ",IOM_ERRKIND_MISSING,locator->getLineNumber(),locator->getColumnNumber());
-			}else{
-				file->setHeadSecSender(sender);
-			}
-			if(!version){
-				// VERSION is mandatory
-				iom_issueparserr("Attribute VERSION missing in file ",IOM_ERRKIND_MISSING,locator->getLineNumber(),locator->getColumnNumber());
-			}else{
-				file->setHeadSecVersion(version);
-				if (XMLString::compareString(version,X("2.2")))
-				{
-					iom_issueparserr("The VERSION attribute must be \"2.2\"",IOM_ERRKIND_INVALID,locator->getLineNumber(),locator->getColumnNumber());
-				}
-
-			}
-    		state=START_HEADERSECTION;
-    		return;
-    	}
-
-		if(state==BEFORE_DATASECTION && tag==tags::get_DATASECTION()){
-    		state=BEFORE_BASKET;
-    		return;
-    	}
-    	if(state==BEFORE_BASKET){
-			const XMLCh* bid=0;
-			const XMLCh* consistency=0;
-			for(unsigned int attri=0;attri<attrs.getLength();attri++){
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_BID())){
-					bid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_CONSISTENCY())){
-					consistency=attrs.getValue(attri);
-				}
-			}
-			dataContainer=dbgnew struct iom_basket();
-			dataContainer->setXMLLineNumber(locator->getLineNumber());
-			dataContainer->setXMLColumnNumber(locator->getColumnNumber());
-			if(!bid){
-				// BOID is mandatory
-				iom_issueparserr("Attribute BID missing in basket ",IOM_ERRKIND_MISSING,locator->getLineNumber(),locator->getColumnNumber());
-			}else{
-				dataContainer->setOid(stripX(bid));
-			}
-			if(consistency){
-				if(!XMLString::compareString(consistency,ustrings::get_COMPLETE())){
-				    dataContainer->setConsistency(IOM_COMPLETE);
-				}else if(!XMLString::compareString(consistency,ustrings::get_INCOMPLETE())){
-				    dataContainer->setConsistency(IOM_INCOMPLETE);
-				}else if(!XMLString::compareString(consistency,ustrings::get_INCONSISTENT())){
-				    dataContainer->setConsistency(IOM_INCONSISTENT);
-				}else if(!XMLString::compareString(consistency,ustrings::get_ADAPTED())){
-				    dataContainer->setConsistency(IOM_ADAPTED);
-				}else{
-					iom_issueparserr("Attribute CONSISTENCY has wrong value in basket ",IOM_ERRKIND_INVALID,locator->getLineNumber(),locator->getColumnNumber());
-				}
-			}
-			dataContainer->setTag(tag);
-			dataContainer->file=file;
-		  	state=BEFORE_OBJECT;
-			return;
-    	}
-    	// SegmentSequence
-		if(state==SS_AFTER_COORD){
-			pushReturnState(SS_AFTER_COORD);
-			if(tag==tags::get_COORD()){
-				state=CV_COORD;
-				object=dbgnew struct iom_object();
-				object->setTag(tags::get_COORD());
-			}else{
-				state=ST_BEFORE_PROPERTY;
-				object=dbgnew struct iom_object();
-				object->setTag(tag);
-			}
-			return;
-		}
-    	
-    	// PolylineValue
-		if((state==PV_POLYLINE 
-				|| state==PV_AFTER_LINEATTR) 
-				&& tag==tags::get_CLIPPED()){
-			state=PV_CLIPPED;
-			changeReturnState(PV_AFTER_CLIPPED);
-			object->setConsistency(IOM_INCOMPLETE);
-			return;
-		}
-		if(state==PV_POLYLINE && tag==tags::get_LINEATTR()){
-			state=PV_LINEATTR;
-			return;
-		}
-		if(state==PV_LINEATTR){
-			pushReturnState(PV_AFTER_LINEATTRSTRUCT);
-			state=ST_BEFORE_PROPERTY;
-			object=dbgnew struct iom_object();
-			object->setTag(tag);
-			return;
-		}
-		if(state==PV_AFTER_CLIPPED && tag==tags::get_CLIPPED()){
-			state=PV_CLIPPED;
-			pushReturnState(PV_AFTER_CLIPPED);
-			return;
-		}
-		if((state==PV_POLYLINE 
-				|| state==PV_CLIPPED 
-				|| state==PV_AFTER_LINEATTR)
-				&& tag==tags::get_COORD()){
-			pushReturnState(SS_AFTER_COORD);
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_SEGMENTS());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_segment();
-			objStack.push(ele);
-			state=CV_COORD;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_COORD());
-			return;
-		}
-		
-		// SurfaceValue
-		if(state==SV_SURFACE && tag==tags::get_CLIPPED()){
-			state=SV_CLIPPED;
-			changeReturnState(SV_AFTER_CLIPPED);
-			Element top=objStack.top();objStack.pop();
-			Element ele=objStack.top();
-			objStack.push(top);
-			ele.object->setConsistency(IOM_INCOMPLETE);
-			return;
-		}
-		if(state==SV_AFTER_CLIPPED && tag==tags::get_CLIPPED()){
-			pushReturnState(SV_AFTER_CLIPPED);
-			state=SV_CLIPPED;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_SURFACE());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_boundary();
-			objStack.push(ele);
-			return;
-		}
-		if((state==SV_SURFACE || state==SV_CLIPPED 
-				|| state==BD_AFTER_BOUNDARY)
-				&& tag==tags::get_BOUNDARY()){
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_BOUNDARY());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_polyline();
-			objStack.push(ele);
-			state=BD_BOUNDARY;
-			return;
-		}
-		if((state==BD_BOUNDARY || state==BD_AFTER_POLYLINE)
-				&& tags::get_POLYLINE()){
-			pushReturnState(BD_AFTER_POLYLINE);
-			state=PV_POLYLINE;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_POLYLINE());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_sequence();
-			objStack.push(ele);
-			return;
-		}
-    	
-    	// CoordValue
-		if(state==CV_COORD && tag==tags::get_C1()){
-			state=CV_C1;
-			// ensure we save collected characters only inside C1
-			propertyValue.reset();
-			return;
-		}
-		if(state==CV_AFTER_C1 && tag==tags::get_C2()){
-			state=CV_C2;
-			// ensure we save collected characters only inside C2
-			propertyValue.reset();
-			return;
-		}
-		if(state==CV_AFTER_C2 && tag==tags::get_C3()){
-			state=CV_C3;
-			// ensure we save collected characters only inside C3
-			propertyValue.reset();
-			return;
-		}
-		if(state==ST_BEFORE_CHARACTERS && tag==tags::get_SURFACE()){
-			pushReturnState(ST_AFTER_SURFACE);
-			state=SV_SURFACE;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_MULTISURFACE());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_surface();
-			objStack.push(ele);
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_SURFACE());
-			//ele=ceisnew Element();
-			ele.object=object;
-			ele.propertyName=tags::get_boundary();
-			objStack.push(ele);
-			return;
-		}
-		if(state==ST_BEFORE_CHARACTERS && tag==tags::get_POLYLINE()){
-			pushReturnState(ST_AFTER_POLYLINE);
-			state=PV_POLYLINE;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_POLYLINE());
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tags::get_sequence();
-			objStack.push(ele);
-			return;
-		}
-		if(state==ST_BEFORE_CHARACTERS && tag==tags::get_COORD()){
-			pushReturnState(ST_AFTER_COORD);
-			state=CV_COORD;
-			object=dbgnew struct iom_object();
-			object->setTag(tags::get_COORD());
-			return;
-		}
-
-    	if(state==BEFORE_OBJECT || state==ST_AFTER_STRUCTVALUE 
-			|| state==ST_BEFORE_CHARACTERS 
-			|| state==ST_BEFORE_EMBASSOC){
-
-		    // start StructValue
-			if(state==BEFORE_OBJECT){
-				pushReturnState(BEFORE_OBJECT);	      		
-			}else if(state==ST_AFTER_STRUCTVALUE){
-				pushReturnState(ST_AFTER_STRUCTVALUE);	      		
-			}else if(state==ST_BEFORE_CHARACTERS){
-				pushReturnState(ST_AFTER_STRUCTVALUE);	      		
-			}else if(state==ST_BEFORE_EMBASSOC){
-				pushReturnState(ST_BEFORE_EMBASSOC);	      		
-			}
-			state=ST_BEFORE_PROPERTY;
-			const XMLCh* operation=0;
-			const XMLCh* oid=0;
-			const XMLCh* objBid=0;
-			const XMLCh* consistency=0;
-			for(unsigned int attri=0;attri<attrs.getLength();attri++){
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_TID())){
-					oid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_BID())){
-					objBid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_OPERATION())){
-					operation=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_CONSISTENCY())){
-					consistency=attrs.getValue(attri);
-				}
-			}
-			object=dbgnew struct iom_object();
-		    object->setTag(tag);
-			object->setXMLLineNumber(locator->getLineNumber());
-			object->setXMLColumnNumber(locator->getColumnNumber());
-			if(oid){
-				object->setOid(stripX(oid));
-			}
-			if(objBid){
-			    object->setBid(stripX(objBid));
-			}			
-			if(operation){
-				if(!XMLString::compareString(operation,ustrings::get_INSERT())){
-				    object->setOperation(IOM_OP_INSERT);
-				}else if(!XMLString::compareString(operation,ustrings::get_UPDATE())){
-				    object->setOperation(IOM_OP_UPDATE);
-				}else if(!XMLString::compareString(operation,ustrings::get_DELETE())){
-				    object->setOperation(IOM_OP_DELETE);
-				}else{
-					iom_issueparserr("Attribute OPERATION has wrong value in object ",IOM_ERRKIND_INVALID,locator->getLineNumber(),locator->getColumnNumber());
-				}
-			}
-			if(consistency){
-				if(!XMLString::compareString(consistency,ustrings::get_COMPLETE())){
-				    object->setConsistency(IOM_COMPLETE);
-				}else if(!XMLString::compareString(consistency,ustrings::get_INCOMPLETE())){
-				    object->setConsistency(IOM_INCOMPLETE);
-				}else if(!XMLString::compareString(consistency,ustrings::get_INCONSISTENT())){
-				    object->setConsistency(IOM_INCONSISTENT);
-				}else if(!XMLString::compareString(consistency,ustrings::get_ADAPTED())){
-				    object->setConsistency(IOM_ADAPTED);
-				}else{
-					iom_issueparserr("Attribute CONSISTENCY has wrong value in object ",IOM_ERRKIND_INVALID,locator->getLineNumber(),locator->getColumnNumber());
-				}
-			}
-			return;
-    	}
-    	if(state==ST_BEFORE_PROPERTY){
-    		if(object.isNull()){
-    			//throw new IllegalStateException();
-				assert(false);
-    		}
-			// attribute ->characters 
-			// struct ->startElement
-			// ref (refattr) ->endElement
-			// ref (role) ->endElement
-			// ref (embedded assoc) ->startElement or EndElement
-			const XMLCh* oid=0;
-			const XMLCh* objBid=0;
-			unsigned int orderPos=0;
-			for(unsigned int attri=0;attri<attrs.getLength();attri++){
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_REF())){
-					oid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_BID())){
-					objBid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_EXTREF())){
-					oid=attrs.getValue(attri);
-				}
-				if(!XMLString::compareString(attrs.getLocalName(attri),ustrings::get_ORDER_POS())){
-					bool done=XMLString::textToBin(attrs.getValue(attri),orderPos);
-					if(!done || orderPos==0){
-						// illgegal value
-						iom_issueparserr("Attribute ORDER_POS has wrong value in object ",IOM_ERRKIND_INVALID,locator->getLineNumber(),locator->getColumnNumber());
-						orderPos=0;
-					}
-				}
-			}
-			// save name,oid,bid
-			// push state
-			Element ele;
-			ele.object=object;
-			ele.propertyName=tag;
-			if(oid){
-				if(objBid){
-					ele.setBid(stripX(objBid));
-				}
-				ele.setOid(stripX(oid));
-				ele.setOrderPos(orderPos);
-			}
-			objStack.push(ele);
-			object=0;
-			if(oid){
-				state=ST_BEFORE_EMBASSOC;
-			}else{
-				state=ST_BEFORE_CHARACTERS;
-			}
-			// ensure we save collected characters only inside 
-			// a property and not after a struct value
-			propertyValue.reset(); 
-			return;
-    	}
-    	skip=1;
-}
-
-void  ParserHandler::endElement (const XMLCh *const uri
-								  , const XMLCh *const localname
-								  , const XMLCh *const qname)
-{
-    	level--;
-        m_nEntityCounter = 0;
-		if(skip>0){
-			skip--;
-			return;
-		}
-		
-		// SegmentSequence
-		if(state==SS_AFTER_COORD){
-			popReturnState();
-			if(state==ST_AFTER_POLYLINE){
-				Element ele=objStack.top();objStack.pop();
-				object=ele.object; // SEGMENTS			
-				ele=objStack.top();objStack.pop();
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-				object=ele.object;	// POLYLINE		
-			}else if(state==BD_AFTER_POLYLINE){
-					Element ele=objStack.top();objStack.pop();
-					object=ele.object; // SEGMENTS			
-					ele=objStack.top();objStack.pop();
-					ele.object->parser_addAttrValue(ele.propertyName,object);
-					object=ele.object;	// POLYLINE		
-					ele=objStack.top();
-					ele.object->parser_addAttrValue(ele.propertyName,object);
-					object=0;
-			}else if(state==PV_AFTER_CLIPPED){
-				Element ele=objStack.top();objStack.pop();
-				object=ele.object;	// SEGMENTS		
-				ele=objStack.top();
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-				object=0;			
-			}else{
-				//throw new IllegalStateException();
-				assert(false);
-			}
-		}else if(state==PV_AFTER_CLIPPED){
-			Element ele=objStack.top();objStack.pop();
-			object=ele.object;	// POLYLINE		
-			state=ST_AFTER_POLYLINE;
-		}else if(state==PV_AFTER_LINEATTRSTRUCT){
-			state=PV_AFTER_LINEATTR;
-		// Boundaries
-		}else if(state==BD_AFTER_POLYLINE){
-			Element ele=objStack.top();objStack.pop();
-			object=ele.object; // BOUNDARY
-			ele=objStack.top();			
-			ele.object->parser_addAttrValue(ele.propertyName,object);
-			//Dumper dumper=new Dumper();
-			//dumper.dumpObject(System.err,ele.object);
-			object=0;
-			state=BD_AFTER_BOUNDARY;
-		// SurfaceValue
-		}else if(state==BD_AFTER_BOUNDARY){
-			popReturnState();
-			if(state==ST_AFTER_SURFACE){
-				Element ele=objStack.top();objStack.pop();
-				object=ele.object; // SURFACE
-				ele=objStack.top();
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-			}else if(state==SV_AFTER_CLIPPED){
-				Element ele=objStack.top();objStack.pop();
-				object=ele.object; // SURFACE
-				ele=objStack.top();
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-			}else{
-				//throw new IllegalStateException("state "+state);
-				assert(false);
-			}
-		}else if(state==SV_AFTER_CLIPPED){
-			state=ST_AFTER_SURFACE;
-		// CoordValue
-		}else if(state==CV_AFTER_C1 || state==CV_AFTER_C2 || state==CV_AFTER_C3){
-			popReturnState();
-			if(state==SS_AFTER_COORD){
-				// part of SEGMENTS
-				Element ele=objStack.top();
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-				//Dumper dumper=new Dumper();
-				//dumper.dumpObject(System.err,ele.object);
-				object=0;
-			}else if(state==ST_AFTER_COORD){
-			}else{
-				//throw new IllegalStateException();
-				assert(false);
-			}			
-		}else if(state==CV_C1){
-			object->parser_addAttrValue(tags::get_C1(),propertyValue.getRawBuffer());
-			propertyValue.reset();
-			state=CV_AFTER_C1;
-		}else if(state==CV_C2){
-			object->parser_addAttrValue(tags::get_C2(),propertyValue.getRawBuffer());
-			propertyValue.reset();
-			state=CV_AFTER_C2;
-		}else if(state==CV_C3){
-			object->parser_addAttrValue(tags::get_C3(),propertyValue.getRawBuffer());
-			propertyValue.reset();
-			state=CV_AFTER_C3;
-			
-		// StructValue
-		}else if(state==ST_AFTER_STRUCTVALUE 
-				|| state==ST_BEFORE_CHARACTERS){
-			// attribute
-			// struct
-			Element ele=objStack.top();objStack.pop();
-			if(state==ST_BEFORE_CHARACTERS){
-				// attribute
-				// may be: illegal whitespace, legal whitespace, not whitespace
-				ele.object->parser_addAttrValue(ele.propertyName,propertyValue.getRawBuffer());
-    		}else{
-				// bag of structvalues
-				// added to ele.object in endElement of structvalue
-    		}
-			object=ele.object;
-			propertyValue.reset();
-			state=ST_BEFORE_PROPERTY;
-    	}else if(state==ST_BEFORE_EMBASSOC){
-				// ref (refattr)
-				// ref (role)
-				// ref (embedded assoc) with or without assocattrs
-				Element ele=objStack.top();objStack.pop();
-				if(object.isNull()){
-					// ref (refattr)
-					// ref (role)
-					// ref (embedded assoc) without assocattrs
-					object=dbgnew struct iom_object();
-				}else{
-					// ref (embedded assoc) with assocattrs
-				}
-				object->setRefOid(ele.getOid());
-				object->setRefBid(ele.getBid());
-				object->setRefOrderPos(ele.getOrderPos());
-				ele.object->parser_addAttrValue(ele.propertyName,object);
-				object=ele.object;
-				propertyValue.reset();
-				state=ST_BEFORE_PROPERTY;
-		}else if(state==ST_AFTER_COORD){
-			// attr of type COORD
-			Element ele=objStack.top();objStack.pop();
-			ele.object->parser_addAttrValue(ele.propertyName,object);
-			object=ele.object;
-			state=ST_BEFORE_PROPERTY;
-			propertyValue.reset();
-		}else if(state==ST_AFTER_POLYLINE){
-			// attr of type POLYLINE
-			Element ele=objStack.top();objStack.pop();
-			ele.object->parser_addAttrValue(ele.propertyName,object);
-			object=ele.object;			
-			state=ST_BEFORE_PROPERTY;
-			propertyValue.reset();
-		}else if(state==ST_AFTER_SURFACE){
-			// attr of type SURFACE/AREA
-			Element ele=objStack.top();objStack.pop();
-			object=ele.object; // MULTISURFACE
-			ele=objStack.top();objStack.pop();
-			ele.object->parser_addAttrValue(ele.propertyName,object);
-			object=ele.object;			
-			state=ST_BEFORE_PROPERTY;
-			propertyValue.reset();
-    	}else if(state==ST_BEFORE_PROPERTY){
-			popReturnState();
-			if(state==BEFORE_OBJECT){
-				dataContainer->addObject(object);
-				object=0;
-			}else{
-				if(state==ST_AFTER_STRUCTVALUE){
-					Element ele=objStack.top();
-					ele.object->parser_addAttrValue(ele.propertyName,object);
-					object=0;
-				}else if(state==PV_AFTER_LINEATTRSTRUCT){
-					Element ele=objStack.top();
-					ele.object->parser_addAttrValue(tags::get_lineattr(),object);
-					object=0;
-				}else if(state==SS_AFTER_COORD){
-					// part of SEGMENTS
-					Element ele=objStack.top();
-					ele.object->parser_addAttrValue(ele.propertyName,object);
-					//Dumper dumper=new Dumper();
-					//dumper.dumpObject(System.err,ele.object);
-					object=0;
-				}
-			}
-    	}else if(state==BEFORE_OBJECT){
-			file->addBasket(dataContainer);
-			dataContainer=0;
-    		state=BEFORE_BASKET;
-    	}else if(state==BEFORE_BASKET){
-    		state=BEFORE_DATASECTION;
-    	}else if(state==START_HEADERSECTION){
-    		state=BEFORE_DATASECTION;
-    	}else if(state==BEFORE_DATASECTION){
-    		state=BEFORE_TRANSFER;
-    	}
-
-}
-
-
-#if XERCES_VERSION_MAJOR >= 3
-/************************************************************************/
-/*                     characters() (xerces 3 version)                  */
-/************************************************************************/
-
-void ParserHandler::characters( const XMLCh* const chars,
-                                const XMLSize_t length )
-{
-    if(   state==ST_BEFORE_CHARACTERS
-       || state==CV_C1
-       || state==CV_C2
-       || state==CV_C3 )
-    {
-        propertyValue.append(chars,length);
-    }
-}
-
-#else
-/************************************************************************/
-/*                     characters() (xerces 2 version)                  */
-/************************************************************************/
-
-void ParserHandler::characters( const XMLCh* const chars,
-                                const unsigned int length )
-{
-    if(   state==ST_BEFORE_CHARACTERS
-       || state==CV_C1
-       || state==CV_C2
-       || state==CV_C3 )
-    {
-        propertyValue.append(chars,length);
-    }
-}
-#endif
-
-void ParserHandler::error(const SAXParseException& e)
-{
-#if 0
-	std::cerr << "\nSAX Error at file " << StrX(e.getSystemId())
-		 << ", line " << e.getLineNumber()
-		 << ", char " << e.getColumnNumber()
-         << "\n  Message: " << StrX(e.getMessage()) << std::endl;
-#endif
-	iom_issueparserr(StrX(e.getMessage()).localForm(),IOM_ERRKIND_XMLPARSER,e.getLineNumber(),e.getColumnNumber());
-}
-
-void ParserHandler::fatalError(const SAXParseException& e)
-{
-#if 0
-	std::cerr << "\nSAX Error at file " << StrX(e.getSystemId())
-		 << ", line " << e.getLineNumber()
-		 << ", char " << e.getColumnNumber()
-         << "\n  Message: " << StrX(e.getMessage()) << std::endl;
-#endif
-	iom_issueparserr(StrX(e.getMessage()).localForm(),IOM_ERRKIND_XMLPARSER,e.getLineNumber(),e.getColumnNumber());
-}
-
-void ParserHandler::warning(const SAXParseException& e)
-{
-#if 0
-	std::cerr << "\nSAX Error at file " << StrX(e.getSystemId())
-		 << ", line " << e.getLineNumber()
-		 << ", char " << e.getColumnNumber()
-         << "\n  Message: " << StrX(e.getMessage()) << std::endl;
-#endif
-	iom_issueparserr(StrX(e.getMessage()).localForm(),IOM_ERRKIND_XMLPARSER,e.getLineNumber(),e.getColumnNumber());
-}
-
-void  ParserHandler::setDocumentLocator (const Locator *const locator1)
-{
-	locator=locator1;
-}
-
-
-/** pushes a return state for the parser state machine to the stack.
- *  Used before entering a sub state machine.
- */
-void ParserHandler::pushReturnState(int returnState){
-	stateStack.push(returnState);
-}
-
-/** pops a state for the parser state machine from the stack and makes it the 
- *  new current state.
- *  Used when leaving a sub state machine.
- */
-void ParserHandler::popReturnState(){
-	state=stateStack.top();
-	stateStack.pop();
-}
-
-/** changes the top state on the stack for the parser state machine.
- *  Used to change the return state of a sub state machine.
- */
-void ParserHandler::changeReturnState(int returnState){
-	stateStack.pop();
-	stateStack.push(returnState);
-}
-
-
-/** gets the id of an xml-element name
- */
-int ParserHandler::getTagId(const char *name)
-{
-	  if(!namev){
-//FIXME		  namev=dbgnew XMLStringPool();
-		  namev=new XMLStringPool();
-	  }
-	return namev->addOrFind(X(name));
-}
-
-/** gets the id of an xml-element name
- */
-int ParserHandler::getTagId(const XMLCh *const name)
-{
-	  if(!namev){
-		  namev=new XMLStringPool();
-	  }
-	return namev->addOrFind(name);
-}
-
-/** gets the id of an xml-element name
- */
-const XMLCh *const ParserHandler::getTagName(int tagid)
-{
-	  if(!namev){
-		  namev=new XMLStringPool();
-	  }
-	return namev->getValueForId(tagid);
-}
-
-/** cleanup reader module. This function is a part of iom_end().
- */
-void ParserHandler::at_iom_end()
-{
-	  if(namev){
-		  delete namev;
-		  namev=0;
-	  }
-}
diff --git a/ogr/ogrsf_frmts/ili/iom/tags.cpp b/ogr/ogrsf_frmts/ili/iom/tags.cpp
deleted file mode 100644
index d2ba93a..0000000
--- a/ogr/ogrsf_frmts/ili/iom/tags.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/**********************************************************************
- * $Id: tags.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#include <iom/iom_p.h>
-
-	int tags::COORD=0;
-	int tags::ARC=0;
-	int tags::C1=0;
-	int tags::C2=0;
-	int tags::C3=0;
-	int tags::A1=0;
-	int tags::A2=0;
-	int tags::iom04_metamodel_AssociationDef=0;
-	int tags::R=0;
-	int tags::lineattr=0;
-	int tags::TRANSFER=0;
-	int tags::iom04_metamodel_Table=0;
-	int tags::DATASECTION=0;
-	int tags::HEADERSECTION=0;
-	int tags::ALIAS=0;
-	int tags::COMMENT=0;
-	int tags::CLIPPED=0;
-	int tags::LINEATTR=0;
-	int tags::SEGMENTS=0;
-	int tags::segment=0;
-	int tags::SURFACE=0;
-	int tags::surface=0;
-	int tags::boundary=0;
-	int tags::BOUNDARY=0;
-	int tags::polyline=0;
-	int tags::POLYLINE=0;
-	int tags::sequence=0;
-	int tags::MULTISURFACE=0;
-	int tags::iom04_metamodel_ViewableAttributesAndRoles=0;
-	int tags::viewable=0;
-	int tags::attributesAndRoles=0;
-	int tags::container=0;
-	int tags::iom04_metamodel_TransferDescription=0;
-	int tags::name=0;
-
-void tags::clear()
-{
-	COORD=0;
-	ARC=0;
-	C1=0;
-	C2=0;
-	C3=0;
-	A1=0;
-	A2=0;
-	iom04_metamodel_AssociationDef=0;
-	R=0;
-	lineattr=0;
-	TRANSFER=0;
-	iom04_metamodel_Table=0;
-	DATASECTION=0;
-	HEADERSECTION=0;
-	ALIAS=0;
-	COMMENT=0;
-	CLIPPED=0;
-	LINEATTR=0;
-	SEGMENTS=0;
-	segment=0;
-	SURFACE=0;
-	surface=0;
-	boundary=0;
-	BOUNDARY=0;
-	polyline=0;
-	POLYLINE=0;
-	sequence=0;
-	MULTISURFACE=0;
-	iom04_metamodel_ViewableAttributesAndRoles=0;
-	viewable=0;
-	attributesAndRoles=0;
-	container=0;
-	iom04_metamodel_TransferDescription=0;
-	name=0;
-}
-
-int tags::get_ARC()
-{
-	if(!ARC){
-		ARC=ParserHandler::getTagId("ARC");
-	}
-	return ARC;
-}
-
-int tags::get_COORD()
-{
-	if(!COORD){
-		COORD=ParserHandler::getTagId("COORD");
-	}
-	return COORD;
-}
-
-int tags::get_C1()
-{
-	if(!C1){
-		C1=ParserHandler::getTagId("C1");
-	}
-	return C1;
-}
-
-int tags::get_C2()
-{
-	if(!C2){
-		C2=ParserHandler::getTagId("C2");
-	}
-	return C2;
-}
-
-int tags::get_C3()
-{
-	if(!C3){
-		C3=ParserHandler::getTagId("C3");
-	}
-	return C3;
-}
-
-int tags::get_A1()
-{
-	if(!A1){
-		A1=ParserHandler::getTagId("A1");
-	}
-	return A1;
-}
-
-int tags::get_A2()
-{
-	if(!A2){
-		A2=ParserHandler::getTagId("A2");
-	}
-	return A2;
-}
-
-int tags::get_iom04_metamodel_AssociationDef()
-{
-	if(!iom04_metamodel_AssociationDef){
-		iom04_metamodel_AssociationDef=ParserHandler::getTagId("iom04.metamodel.AssociationDef");
-	}
-	return iom04_metamodel_AssociationDef;
-}
-
-int tags::get_R()
-{
-	if(!R){
-		R=ParserHandler::getTagId("R");
-	}
-	return R;
-}
-
-int tags::get_lineattr()
-{
-	if(!lineattr){
-		lineattr=ParserHandler::getTagId("lineattr");
-	}
-	return lineattr;
-}
-
-int tags::get_TRANSFER()
-{
-	if(!TRANSFER){
-		TRANSFER=ParserHandler::getTagId("TRANSFER");
-	}
-	return TRANSFER;
-}
-
-int tags::get_iom04_metamodel_Table()
-{
-	if(!iom04_metamodel_Table){
-		iom04_metamodel_Table=ParserHandler::getTagId("iom04.metamodel.Table");
-	}
-	return iom04_metamodel_Table;
-}
-
-int tags::get_DATASECTION()
-{
-	if(!DATASECTION){
-		DATASECTION=ParserHandler::getTagId("DATASECTION");
-	}
-	return DATASECTION;
-}
-
-int tags::get_HEADERSECTION()
-{
-	if(!HEADERSECTION){
-		HEADERSECTION=ParserHandler::getTagId("HEADERSECTION");
-	}
-	return HEADERSECTION;
-}
-
-int tags::get_ALIAS()
-{
-	if(!ALIAS){
-		ALIAS=ParserHandler::getTagId("ALIAS");
-	}
-	return ALIAS;
-}
-
-int tags::get_COMMENT()
-{
-	if(!COMMENT){
-		COMMENT=ParserHandler::getTagId("COMMENT");
-	}
-	return COMMENT;
-}
-
-int tags::get_CLIPPED()
-{
-	if(!CLIPPED){
-		CLIPPED=ParserHandler::getTagId("CLIPPED");
-	}
-	return CLIPPED;
-}
-
-int tags::get_LINEATTR()
-{
-	if(!LINEATTR){
-		LINEATTR=ParserHandler::getTagId("LINEATTR");
-	}
-	return LINEATTR;
-}
-
-int tags::get_SEGMENTS()
-{
-	if(!SEGMENTS){
-		SEGMENTS=ParserHandler::getTagId("SEGMENTS");
-	}
-	return SEGMENTS;
-}
-
-int tags::get_segment()
-{
-	if(!segment){
-		segment=ParserHandler::getTagId("segment");
-	}
-	return segment;
-}
-
-
-int tags::get_SURFACE()
-{
-	if(!SURFACE){
-		SURFACE=ParserHandler::getTagId("SURFACE");
-	}
-	return SURFACE;
-}
-
-int tags::get_surface()
-{
-	if(!surface){
-		surface=ParserHandler::getTagId("surface");
-	}
-	return surface;
-}
-
-int tags::get_boundary()
-{
-	if(!boundary){
-		boundary=ParserHandler::getTagId("boundary");
-	}
-	return boundary;
-}
-
-int tags::get_BOUNDARY()
-{
-	if(!BOUNDARY){
-		BOUNDARY=ParserHandler::getTagId("BOUNDARY");
-	}
-	return BOUNDARY;
-}
-
-int tags::get_polyline()
-{
-	if(!polyline){
-		polyline=ParserHandler::getTagId("polyline");
-	}
-	return polyline;
-}
-
-int tags::get_POLYLINE()
-{
-	if(!POLYLINE){
-		POLYLINE=ParserHandler::getTagId("POLYLINE");
-	}
-	return POLYLINE;
-}
-
-int tags::get_sequence()
-{
-	if(!sequence){
-		sequence=ParserHandler::getTagId("sequence");
-	}
-	return sequence;
-}
-
-int tags::get_MULTISURFACE()
-{
-	if(!MULTISURFACE){
-		MULTISURFACE=ParserHandler::getTagId("MULTISURFACE");
-	}
-	return MULTISURFACE;
-}
-
-int tags::get_iom04_metamodel_ViewableAttributesAndRoles()
-{
-	if(!iom04_metamodel_ViewableAttributesAndRoles){
-		iom04_metamodel_ViewableAttributesAndRoles=ParserHandler::getTagId("iom04.metamodel.ViewableAttributesAndRoles");
-	}
-	return iom04_metamodel_ViewableAttributesAndRoles;
-}
-
-int tags::get_viewable()
-{
-	if(!viewable){
-		viewable=ParserHandler::getTagId("viewable");
-	}
-	return viewable;
-}
-int tags::get_attributesAndRoles()
-{
-	if(!attributesAndRoles){
-		attributesAndRoles=ParserHandler::getTagId("attributesAndRoles");
-	}
-	return attributesAndRoles;
-}
-int tags::get_container()
-{
-	if(!container){
-		container=ParserHandler::getTagId("container");
-	}
-	return container;
-}
-int tags::get_iom04_metamodel_TransferDescription()
-{
-	if(!iom04_metamodel_TransferDescription){
-		iom04_metamodel_TransferDescription=ParserHandler::getTagId("iom04.metamodel.TransferDescription");
-	}
-	return iom04_metamodel_TransferDescription;
-}
-int tags::get_name()
-{
-	if(!name){
-		name=ParserHandler::getTagId("name");
-	}
-	return name;
-}
diff --git a/ogr/ogrsf_frmts/ili/iom/ustrings.cpp b/ogr/ogrsf_frmts/ili/iom/ustrings.cpp
deleted file mode 100644
index 0701251..0000000
--- a/ogr/ogrsf_frmts/ili/iom/ustrings.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/**********************************************************************
- * $Id: ustrings.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#include <iom/iom_p.h>
-
-
-const XMLCh* ustrings::get_xmlns()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("xmlns");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_NS_INTERLIS22()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("http://www.interlis.ch/INTERLIS2.2");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_BID()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("BID");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_TOPICS()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("TOPICS");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_KIND()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("KIND");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_STARTSTATE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("STARTSTATE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_ENDSTATE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("ENDSTATE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_TID()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("TID");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_OPERATION()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("OPERATION");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_INSERT()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("INSERT");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_UPDATE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("UPDATE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_DELETE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("DELETE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_REF()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("REF");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_EXTREF()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("EXTREF");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_ORDER_POS()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("ORDER_POS");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_CONSISTENCY()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("CONSISTENCY");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_COMPLETE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("COMPLETE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_INCOMPLETE()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("INCOMPLETE");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_INCONSISTENT()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("INCONSISTENT");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_ADAPTED()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("ADAPTED");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_SENDER()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("SENDER");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_VERSION()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("VERSION");
-	}
-	return ret;
-}
-
-const XMLCh* ustrings::get_INITIAL()
-{
-	static XMLCh* ret=0;
-	if(!ret){
-		ret=XMLString::transcode("INITIAL");
-	}
-	return ret;
-}
diff --git a/ogr/ogrsf_frmts/ili/iom/writer.cpp b/ogr/ogrsf_frmts/ili/iom/writer.cpp
deleted file mode 100644
index b36ef05..0000000
--- a/ogr/ogrsf_frmts/ili/iom/writer.cpp
+++ /dev/null
@@ -1,877 +0,0 @@
-/**********************************************************************
- * $Id: writer.cpp 12582 2007-10-29 09:38:21Z pka $
- *
- * Project:  iom - The INTERLIS Object Model
- * Purpose:  For more information, please see <http://iom.sourceforge.net>
- * Author:   Claude Eisenhut
- *
- **********************************************************************
- * Copyright (c) 2007, Claude Eisenhut
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-/** @file
- * adapter to xml writer
- * @defgroup writer xml writer functions
- * @{
- */
-
-
-#include <string.h>
-
-//#include <xercesc/util/TransService.hpp>
-#include <xercesc/framework/XMLFormatter.hpp>
-#include <xercesc/framework/LocalFileFormatTarget.hpp>
-#include <iom/iom_p.h>
-#include <algorithm>
-#include <string>
-
-/** gets the xml representaion of a consistency value.
- */
-static const XMLCh *encodeConsistency(int consistency)
-{
-	const XMLCh *ret;
-	switch(consistency){
-	case IOM_INCOMPLETE:
-        ret=ustrings::get_INCOMPLETE();
-		break;
-    case IOM_INCONSISTENT:
-        ret=ustrings::get_INCONSISTENT();
-		break;
-    case IOM_ADAPTED:
-        ret=ustrings::get_ADAPTED();
-		break;
-    case IOM_COMPLETE:
-	default:
-        ret=0;
-		break;
-	}
-	return ret;
-}
-
-/** gets the xml representaion of a basket-kind value.
- */
-static const XMLCh *encodeBasketKind(int kind)
-{
-	const XMLCh *ret;
-	switch(kind){
-	case IOM_UPDATE:
-        ret=ustrings::get_UPDATE();
-		break;
-	case IOM_INITIAL:
-        ret=ustrings::get_INITIAL();
-		break;
-    case IOM_FULL:
-	default:
-        ret=0;
-		break;
-	}
-	return ret;
-}
-
-/** gets the xml representaion of a operation value.
- */
-static const XMLCh *encodeOperation(int ops)
-{
-	const XMLCh *ret;
-	switch(ops){
-	case IOM_OP_UPDATE:
-        ret=ustrings::get_UPDATE();
-		break;
-	case IOM_OP_DELETE:
-        ret=ustrings::get_DELETE();
-		break;
-    case IOM_OP_INSERT:
-	default:
-        ret=0;
-		break;
-	}
-	return ret;
-}
-
-/** writes a coord value or a coord segment.
- */
-static void writeCoord(XmlWriter &out, IomObject &obj)
-{
-/*
-     object: COORD
-       C1
-         102.0
-       C2
-         402.0
-	<COORD><C1>102.0</C1><C2>402.0</C2></COORD>
-*/
-	out.startElement(tags::get_COORD(),0,0);
-	out.startElement(tags::get_C1(),0,0);
-	const XMLCh *c1=obj->getAttrPrim(tags::get_C1(),0);
-	out.characters(c1);
-	out.endElement(/*C1*/);
-	const XMLCh *c2=obj->getAttrPrim(tags::get_C2(),0);
-	if(c2){
-		out.startElement(tags::get_C2(),0,0);
-		out.characters(c2);
-		out.endElement(/*C2*/);
-		const XMLCh *c3=obj->getAttrPrim(tags::get_C3(),0);
-		if(c3){
-			out.startElement(tags::get_C3(),0,0);
-			out.characters(c3);
-			out.endElement(/*C3*/);
-		}
-	}
-	out.endElement(/*COORD*/);
-
-}
-
-/** writes a arc segment value.
- */
-static void writeArc(XmlWriter &out, IomObject &obj)
-{
-/*
-     object: ARC
-       C1
-         103.0
-       C2
-         403.0
-       A1
-         104.0
-       A2
-         404.0
-	<COORD><C1>103.0</C1><C2>403.0</C2><A1>104.0</A1><A2>404.0</A2></COORD>
-*/
-	out.startElement(tags::get_ARC(),0,0);
-	out.startElement(tags::get_C1(),0,0);
-	const XMLCh *c1=obj->getAttrPrim(tags::get_C1(),0);
-	out.characters(c1);
-	out.endElement(/*C1*/);
-	const XMLCh *c2=obj->getAttrPrim(tags::get_C2(),0);
-	out.startElement(tags::get_C2(),0,0);
-	out.characters(c2);
-	out.endElement(/*C2*/);
-	const XMLCh *c3=obj->getAttrPrim(tags::get_C3(),0);
-	if(c3){
-		out.startElement(tags::get_C3(),0,0);
-		out.characters(c3);
-		out.endElement(/*C3*/);
-	}
-	const XMLCh *a1=obj->getAttrPrim(tags::get_A1(),0);
-	out.characters(a1);
-	out.endElement(/*A1*/);
-	const XMLCh *a2=obj->getAttrPrim(tags::get_A2(),0);
-	out.startElement(tags::get_A2(),0,0);
-	out.characters(a2);
-	out.endElement(/*A2*/);
-	const XMLCh *r=obj->getAttrPrim(tags::get_R(),0);
-	if(r){
-		out.startElement(tags::get_R(),0,0);
-		out.characters(r);
-		out.endElement(/*R*/);
-	}
-	out.endElement(/*ARC*/);
-}
-
-/** writes a polyline value.
- */
-void iom_file::writePolyline(XmlWriter &out, IomObject &obj,bool hasLineAttr)
-{
-/*
-     object: POLYLINE [INCOMPLETE]
-       lineattr
-         object: Model.Topic.LineAttr
-           attr00
-             11
-       sequence // if incomplete; multi sequence values
-         object: SEGMENTS
-           segment
-             object: COORD
-               C1
-                 102.0
-               C2
-                 402.0
-           segment
-             object: ARC
-               C1
-                 103.0
-               C2
-                 403.0
-               A1
-                 104.0
-               A2
-                 404.0
-           segment
-             object: Model.SplineParam
-               SegmentEndPoint
-                 object: COORD
-                   C1
-                     103.0
-                   C2
-                     403.0
-               p0
-                 1.0
-               p1
-                 2.0
-
-		<POLYLINE>
-			<LINEATTR>
-				<Model.Topic.LineAttr>
-					<attr00>11</attr00>
-				</Model.Topic.LineAttr>
-			</LINEATTR>
-			<COORD>
-				<C1>101.0</C1>
-				<C2>401.0</C2>
-			</COORD>
-			<COORD>
-				<C1>102.0</C1>
-				<C2>402.0</C2>
-			</COORD>
-			<Model.SplineParam>
-				<SegmentEndPoint>
-					<COORD>
-						<C1>103.0</C1>
-						<C2>403.0</C2>
-					</COORD>
-				</SegmentEndPoint>
-				<p0>1.0</p0>
-				<p1>2.0</p1>
-			</Model.SplineParam>
-		</POLYLINE>
-*/
-	out.startElement(tags::get_POLYLINE(),0,0);
-	if(hasLineAttr){
-		IomObject lineattr=obj->getAttrObj(tags::get_lineattr(),0);
-		if(!lineattr.isNull()){
-			out.startElement(tags::get_LINEATTR(),0,0);
-			out.startElement(lineattr->getTag(),0,0);
-			writeAttrs(out,lineattr);
-			out.endElement(/*lineattr*/);
-			out.endElement(/*LINEATTR*/);
-		}
-	}
-	bool clipped=obj->getConsistency()==IOM_INCOMPLETE;
-	for(int sequencei=0;sequencei<obj->getAttrValueCount(tags::get_sequence());sequencei++){
-		if(clipped){
-			out.startElement(tags::get_CLIPPED(),0,0);
-		}else{
-			// an unclipped polyline should have only one sequence element
-			if(sequencei>0){
-				iom_issueerr("unclipped polyline with multi 'sequence' elements");
-				break;
-			}
-		}
-		IomObject sequence=obj->getAttrObj(tags::get_sequence(),sequencei);
-		for(int segmenti=0;segmenti<sequence->getAttrValueCount(tags::get_segment());segmenti++){
-			IomObject segment=sequence->getAttrObj(tags::get_segment(),segmenti);
-			if(segment->getTag()==tags::get_COORD()){
-				// COORD
-				writeCoord(out,segment);
-			}else if(segment->getTag()==tags::get_ARC()){
-				// ARC
-				writeArc(out,segment);
-			}else{
-				// custum line form
-				out.startElement(segment->getTag(),0,0);
-				writeAttrs(out,segment);
-				out.endElement(/*segment*/);
-			}
-
-		}
-		if(clipped){
-			out.endElement(/*CLIPPED*/);
-		}
-	}
-	out.endElement(/*POLYLINE*/);
-}
-
-/** writes a surface value.
- */
-void iom_file::writeSurface(XmlWriter &out, IomObject &obj)
-{
-/*
-     object: MULTISURFACE [INCOMPLETE]
-       surface // if incomplete; multi surface values
-         object: SURFACE
-           boundary
-             object: BOUNDARY
-               polyline
-                 object: POLYLINE
-
-	
-	<SURFACE>
-		<BOUNDARY>
-			<POLYLINE .../>
-			<POLYLINE .../>
-		</BOUNDARY>
-		<BOUNDARY>
-			<POLYLINE .../>
-			<POLYLINE .../>
-		</BOUNDARY>
-	</SURFACE>
-*/
-	out.startElement(tags::get_SURFACE(),0,0);
-	bool clipped=obj->getConsistency()==IOM_INCOMPLETE;
-	for(int surfacei=0;surfacei<obj->getAttrValueCount(tags::get_surface());surfacei++){
-		if(clipped){
-			out.startElement(tags::get_CLIPPED(),0,0);
-		}else{
-			// an unclipped surface should have only one surface element
-			if(surfacei>0){
-				iom_issueerr("unclipped surface with multi 'surface' elements");
-				break;
-			}
-		}
-		IomObject surface=obj->getAttrObj(tags::get_surface(),surfacei);
-		for(int boundaryi=0;boundaryi<surface->getAttrValueCount(tags::get_boundary());boundaryi++){
-			IomObject boundary=surface->getAttrObj(tags::get_boundary(),boundaryi);
-			out.startElement(tags::get_BOUNDARY(),0,0);
-			for(int polylinei=0;polylinei<boundary->getAttrValueCount(tags::get_polyline());polylinei++){
-				IomObject polyline=boundary->getAttrObj(tags::get_polyline(),polylinei);
-				writePolyline(out,polyline,true);
-			}
-			out.endElement(/*BOUNDARY*/);
-		}
-		if(clipped){
-			out.endElement(/*CLIPPED*/);
-		}
-	}
-	out.endElement(/*SURFACE*/);
-}
-
-void iom_file::writeAttr(XmlWriter &out, IomObject &obj,int attr)
-{
-	int valueCount=obj->getAttrValueCount(attr);
-	if(valueCount>0){
-		const XMLCh *val=obj->getAttrPrim(attr,0);
-		// not a primitive?
-		if(!val){
-			IomObject child=obj->getAttrObj(attr,0);
-			// some special cases
-			if(child->getTag()==tags::get_COORD()){
-				// COORD
-				out.startElement(attr,0,0);
-				writeCoord(out,child);
-				out.endElement(/*attr*/);
-				if(valueCount>1){
-					iom_issueerr("max one COORD value allowed");
-				}
-			}else if(child->getTag()==tags::get_POLYLINE()){
-				// POLYLINE
-				out.startElement(attr,0,0);
-				writePolyline(out,child,false);
-				out.endElement(/*attr*/);
-				if(valueCount>1){
-					iom_issueerr("max one POLYLINE value allowed");
-				}
-			}else if(child->getTag()==tags::get_MULTISURFACE()){
-				// MULTISURFACE
-				out.startElement(attr,0,0);
-				writeSurface(out,child);
-				out.endElement(/*attr*/);
-				if(valueCount>1){
-					iom_issueerr("max one MULTISURFACE value allowed");
-				}
-			}else{
-				// normal case
-				const XMLCh *ref=child->getRefOid();
-				bool isRef= ref ? true : false;
-				// Reference-attribute or Role or EmbeddedLink?
-				if(isRef){
-					const XMLCh *extref=0;
-					const XMLCh *bid=0;
-					XMLCh itoabuf[40];
-					const XMLCh *orderpos=0;
-					if(ref){
-						if(child->getRefOrderPos()>0){
-							XMLString::binToText( child->getRefOrderPos(),itoabuf,sizeof(itoabuf)-1,10);
-							orderpos=itoabuf;
-						}
-					}
-					bid=child->getRefBid();
-					if(bid){
-						extref=ref;
-						ref=0;
-					}
-					XmlWrtAttr refAttr[]={
-						 XmlWrtAttr(ref      ? ustrings::get_REF()     :0, ref,true)
-						,XmlWrtAttr(extref   ? ustrings::get_EXTREF()  :0, extref,true)
-						,XmlWrtAttr(bid      ? ustrings::get_BID()     :0, bid,true)
-						,XmlWrtAttr(orderpos ? ustrings::get_ORDER_POS():0, orderpos)
-					};
-					out.startElement(attr,refAttr,sizeof(refAttr)/sizeof(refAttr[0]));
-					if(child->getAttrCount()>0){
-						out.startElement(child->getTag(),0,0);
-						writeAttrs(out,child);
-						out.endElement(/*child*/);
-					}
-					out.endElement(/*attr*/);
-					if(valueCount>1){
-						iom_issueerr("max one reference value allowed");
-					}
-				}else{
-					// struct
-					out.startElement(attr,0,0);
-					int valuei=0;
-					while(1){
-						out.startElement(child->getTag(),0,0);
-						writeAttrs(out,child);
-						out.endElement(/*child*/);
-						valuei++;
-						if(valuei>=valueCount){
-							break;
-						}
-						child=obj->getAttrObj(attr,valuei);
-					}
-					out.endElement(/*attr*/);
-				}
-			}
-
-		}else{
-			out.startElement(attr,0,0);
-			out.characters(val);
-			out.endElement(/*attr*/);
-			if(valueCount>1){
-				iom_issueerr("max one primitive-type value allowed");
-			}
-		}
-	}
-}
-
-void iom_file::writeAttrs(XmlWriter &out, IomObject &obj)
-{
-	tagv_type::iterator tag=tagList.find(obj->getTag());
-	// class not found?
-	if(tag==tagList.end()){
-		std::string msg="unknown type <";
-		msg+=+obj->getTag_c();
-		msg+=">";
-		iom_issueerr(msg.c_str());
-		// write all attributes
-		for(int attri=0;attri<obj->getAttrCount();attri++){
-			int attr=obj->getAttrName(attri);
-			writeAttr(out, obj,attr);
-		}
-	}else{
-		// class found
-		attrv_type attrv=tag->second;
-		for(attrv_type::size_type attri=0;attri<attrv.size();attri++){
-			int attr=attrv[attri].second;
-			writeAttr(out, obj,attr);
-		}
-	}
-}
-
-/** write all baskets to an xml file.
- */
-int iom_file::save()
-{
-	// build class/attribute list
-	if(ilibasket.isNull()){
-		iom_issueerr("model required to save data");
-		return IOM_ERR_ILLEGALSTATE;
-	}
-	buildTagList();
-
-	// read rest of file (before we overwrite it!)
-	IomIterator bi=new iom_iterator(this);
-	while(!bi->next_basket().isNull()){
-		; // empty
-	}
-
-	// open file for write
-	XmlWriter out;
-	int ind=0;
-	out.open(filename);out.printNewLine();
-
-	// write header
-	XmlWrtAttr trsfAttr[]={XmlWrtAttr(ustrings::get_xmlns(),ustrings::get_NS_INTERLIS22())};
-	out.printIndent(ind);
-	out.startElement(tags::get_TRANSFER(),trsfAttr,sizeof(trsfAttr)/sizeof(trsfAttr[0]));out.printNewLine();
-	{
-		ind++;
-		out.printIndent(ind);
-		XStr version("2.2");
-		XmlWrtAttr headAttr[]={
-			XmlWrtAttr(ustrings::get_VERSION(),version.unicodeForm())
-			,XmlWrtAttr(ustrings::get_SENDER(),getHeadSecSender())
-		};
-		out.startElement(tags::get_HEADERSECTION(),headAttr,sizeof(headAttr)/sizeof(headAttr[0]));out.printNewLine();
-		{
-			ind++;
-			out.printIndent(ind);
-			out.startElement(tags::get_ALIAS(),0,0);out.printNewLine();
-			{
-				ind++;
-				ind--;
-			}
-			out.printIndent(ind);
-			out.endElement(/*ALIAS*/);out.printNewLine();
-			out.printIndent(ind);
-			out.startElement(tags::get_COMMENT(),0,0);
-			out.characters(getHeadSecComment());
-			out.endElement(/*COMMENT*/);out.printNewLine();
-			ind--;
-		}
-		out.printIndent(ind);
-		out.endElement(/*HEADERSECTION*/);out.printNewLine();
-		ind--;
-	}
-
-	// write DATASECTION
-	{
-		ind++;
-		out.printIndent(ind);
-		out.startElement(tags::get_DATASECTION(),0,0);out.printNewLine();
-		{
-			ind++;
-
-			// write all baskets
-			for(std::vector<IomBasket>::size_type basketi=0;basketi<basketv.size();basketi++){
-				IomBasket basket=basketv.at(basketi);
-				const XMLCh *topics=basket->getTopics();
-				const XMLCh *kind=encodeBasketKind(basket->getKind());
-				const XMLCh *startstate=basket->getKind()!=IOM_FULL ? basket->getStartState() : 0;
-				const XMLCh *endstate=basket->getKind()!=IOM_FULL ? basket->getEndState() : 0;
-				const XMLCh *consistency=encodeConsistency(basket->getConsistency());
-				XmlWrtAttr basketAttr[]={
-					XmlWrtAttr(ustrings::get_BID(),basket->getOid(),true)
-					,XmlWrtAttr(topics ? ustrings::get_TOPICS():0,topics)
-					,XmlWrtAttr(kind ? ustrings::get_KIND():0 ,kind)
-					,XmlWrtAttr(startstate ? ustrings::get_STARTSTATE():0,startstate)
-					,XmlWrtAttr(endstate ? ustrings::get_ENDSTATE():0,endstate)
-					,XmlWrtAttr(consistency ? ustrings::get_CONSISTENCY():0,consistency)
-				};
-				out.printIndent(ind);
-				if(basket->getTag()==0){
-					iom_issueerr("basket requires a TOPIC name");
-					return IOM_ERR_ILLEGALSTATE;
-				}
-				out.startElement(basket->getTag(),basketAttr,sizeof(basketAttr)/sizeof(basketAttr[0]));out.printNewLine();
-				{
-					ind++;
-					// write all objects
-					IomIterator obji=new iom_iterator(basket);
-					IomObject obj=obji->next_object();
-					while(!obj.isNull()){
-						out.printIndent(ind);
-						const XMLCh *bid=obj->getBid();
-						const XMLCh *ops=encodeOperation(obj->getOperation());
-						const XMLCh *consistency=encodeConsistency(basket->getConsistency());
-						XmlWrtAttr objAttr[]={
-							XmlWrtAttr(ustrings::get_TID(),obj->getOid(),true)
-							,XmlWrtAttr(bid ? ustrings::get_BID():0,bid,true)
-							,XmlWrtAttr(ops ? ustrings::get_OPERATION():0 ,ops)
-							,XmlWrtAttr(consistency ? ustrings::get_CONSISTENCY():0,consistency)
-						};
-						out.startElement(obj->getTag(),objAttr,sizeof(objAttr)/sizeof(objAttr[0]));
-						writeAttrs(out,obj);
-						out.endElement(/*object*/);out.printNewLine();
-						obj=obji->next_object();
-					}
-					ind--;
-				}
-				out.printIndent(ind);
-				out.endElement(/*basket*/);out.printNewLine();
-			}
-			ind--;
-		}
-		out.printIndent(ind);
-		out.endElement(/*DATASECTION*/);out.printNewLine();
-		ind--;
-	}
-	out.printIndent(ind);
-	out.endElement(/*TRANSFER*/);out.printNewLine();
-	// close file
-	out.close();
-	return 0;
-}
-
-int iom_file::getQualifiedTypeName(IomObject &aclass)
-{
-	static const XMLCh  period[] =
-	{
-		chPeriod,  chNull
-	};
-	IomObject topic=ilibasket->getObject(aclass->getAttrObj(tags::get_container(),0)->getRefOid());
-	IomObject model=ilibasket->getObject(topic->getAttrObj(tags::get_container(),0)->getRefOid());
-	// class at model level?
-	XMLCh *qname;
-	if(model->getTag()==tags::get_iom04_metamodel_TransferDescription()){
-		const XMLCh *modelName=topic->getAttrValue(tags::get_name());
-		const XMLCh *className=aclass->getAttrValue(tags::get_name());
-		int qnLen=XMLString::stringLen(modelName)+1+XMLString::stringLen(className)+1;
-		qname=dbgnew XMLCh[qnLen];
-		XMLString::copyString(qname,modelName);
-		XMLString::catString(qname,period);
-		XMLString::catString(qname,className);
-	}else{
-		const XMLCh *modelName=model->getAttrValue(tags::get_name());
-		const XMLCh *topicName=topic->getAttrValue(tags::get_name());
-		const XMLCh *className=aclass->getAttrValue(tags::get_name());
-		int qnLen=XMLString::stringLen(modelName)+1+XMLString::stringLen(topicName)+1+XMLString::stringLen(className)+1;
-		qname=dbgnew XMLCh[qnLen];
-		XMLString::copyString(qname,modelName);
-		XMLString::catString(qname,period);
-		XMLString::catString(qname,topicName);
-		XMLString::catString(qname,period);
-		XMLString::catString(qname,className);
-	}
-	int classId=ParserHandler::getTagId(qname);
-	delete[] qname;
-	return classId;
-}
-
-void iom_file::buildTagList()
-{
-	// for all links class--(attribute|role)
-	IomIterator obji=new iom_iterator(ilibasket);
-	IomObject obj;
-	while(!(obj=obji->next_object()).isNull()){
-		if(obj->getTag()==tags::get_iom04_metamodel_Table() || obj->getTag()==tags::get_iom04_metamodel_AssociationDef()){
-			// get qualified name of class
-			int classId=getQualifiedTypeName(obj);
-			// add to tag list
-			tagv_type::iterator tag=tagList.find(classId);
-			if(tag==tagList.end()){
-				// not found, add empty attr list
-				attrv_type attrv;
-				tagList[classId]=attrv;
-			}else{
-				// found, don't change
-			}
-		}else if(obj->getTag()==tags::get_iom04_metamodel_ViewableAttributesAndRoles()){
-			// get class
-			IomObject aclass=ilibasket->getObject(obj->getAttrObj(tags::get_viewable(),0)->getRefOid());
-			// get qualified name of class
-			int classId=getQualifiedTypeName(aclass);
-			// get attribute or role
-			IomObject leafref=obj->getAttrObj(tags::get_attributesAndRoles(),0);
-			// get name
-			IomObject leafele=ilibasket->getObject(leafref->getRefOid());
-			const XMLCh *leafName=leafele->getAttrValue(tags::get_name());
-			int attrId=ParserHandler::getTagId(leafName);
-			// get element index
-			int eleIdx=leafref->getRefOrderPos()-1;
-			// add to tag list
-			tagv_type::iterator tag=tagList.find(classId);
-			if(tag==tagList.end()){
-				// not found, add
-				attrv_type attrv;
-				std::pair<int,int> ele(eleIdx,attrId);
-				attrv.push_back(ele);
-				tagList[classId]=attrv;
-			}else{
-				// found, replace
-				attrv_type attrv=tag->second;
-				std::pair<int,int> ele(eleIdx,attrId);
-				attrv.push_back(ele);
-				tagList[classId]=attrv;
-			}
-		}
-	}
-
-	// in all classes sort attrs according to pos
-	tagv_type::iterator tag=tagList.begin();
-	for(;tag!=tagList.end();tag++){
-		attrv_type attrv=tag->second;
-		std::sort(attrv.begin(),attrv.end());
-		tagList[tag->first]=attrv;		
-	}
-	
-}
-
-/** @}
- */
-
-
-//UTF-8
-static const XMLCh  gUTF8[] =
-{
-    chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, chNull
-};
-
-//</
-static const XMLCh  gEndElement[] =
-{
-    chOpenAngle, chForwardSlash, chNull
-};
-
-//<?xml version="
-static const XMLCh  gXMLDecl_VersionInfo[] =
-{
-    chOpenAngle, chQuestion, chLatin_x,     chLatin_m,  chLatin_l,  chSpace,
-    chLatin_v,   chLatin_e,  chLatin_r,     chLatin_s,  chLatin_i,  chLatin_o,
-    chLatin_n,   chEqual,    chDoubleQuote, chNull
-};
-
-static const XMLCh gXMLDecl_ver10[] =
-{
-    chDigit_1, chPeriod, chDigit_0, chNull
-};
-
-//encoding="
-static const XMLCh  gXMLDecl_EncodingDecl[] =
-{
-    chLatin_e,  chLatin_n,  chLatin_c,  chLatin_o,      chLatin_d, chLatin_i,
-    chLatin_n,  chLatin_g,  chEqual,    chDoubleQuote,  chNull
-};
-
-//"
-static const XMLCh  gXMLDecl_separator[] =
-{
-    chDoubleQuote, chSpace, chNull
-};
-
-//?>
-static const XMLCh  gXMLDecl_endtag[] =
-{
-    chQuestion, chCloseAngle,  chNull
-};
-
-
-const XMLCh *XmlWrtAttr::getName()
-{
-	return name;
-}
-
-const XMLCh *XmlWrtAttr::getValue()
-{
-	return value;
-}
-bool XmlWrtAttr::isOid()
-{
-	return oidAttr;
-}
-XmlWrtAttr::XmlWrtAttr(const XMLCh *name1,const XMLCh *value1)
-	: name(name1)
-	, value(value1)
-	,oidAttr(false)
-{
-}
-XmlWrtAttr::XmlWrtAttr(const XMLCh *name1,const XMLCh *value1,bool isOid)
-	: name(name1)
-	, value(value1)
-	,oidAttr(isOid)
-{
-}
-
-void XmlWriter::open(const char *filename)
-{
-	/*
-	out=fopen("filename","w");
-	fputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>",out);
-	newline();
-
-    XMLTransService::Codes resCode;
-    transcoder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor
-    (
-        "UTF-8"
-        , resCode
-        , 16 * 1024
-    );
-	*/
-	destination=new LocalFileFormatTarget(filename); 
-	out= new XMLFormatter(gUTF8
-                 ,gXMLDecl_ver10
-                 ,destination
-                 ,XMLFormatter::NoEscapes
-                 ,XMLFormatter::UnRep_CharRef);
-
-    out->setUnRepFlags(XMLFormatter::UnRep_CharRef);
-
-    *out << gXMLDecl_VersionInfo << gXMLDecl_ver10 << gXMLDecl_separator;
-    *out << gXMLDecl_EncodingDecl << gUTF8 << gXMLDecl_separator;
-    *out << gXMLDecl_endtag;
-}
-
-void XmlWriter::startElement(int tagid,XmlWrtAttr attrv[],int attrc)
-{
-	const XMLCh *tagName=ParserHandler::getTagName(tagid);
-
-    *out  << XMLFormatter::NoEscapes
-                 << chOpenAngle << tagName;
-
-
-	for(int i=0;i<attrc;i++){
-		if(attrv[i].getName()){
-			*out  << XMLFormatter::NoEscapes
-					 << chSpace << attrv[i].getName()
-					 << chEqual << chDoubleQuote
-					 << XMLFormatter::AttrEscapes;
-			if(attrv[i].isOid()){
-				*out << chLatin_x; 
-			}
-			*out << attrv[i].getValue()
-					 << XMLFormatter::NoEscapes
-					 << chDoubleQuote;
-		}
-	}
-
-    *out << XMLFormatter::NoEscapes << chCloseAngle;
-	stack.push(tagid);
-}
-
-void XmlWriter::endElement()
-{
-	const XMLCh *tagName=ParserHandler::getTagName(stack.top());
-	stack.pop();
-    *out  << XMLFormatter::NoEscapes
-                 << chOpenAngle 
-				 << chForwardSlash << tagName << chCloseAngle;
-}
-
-void XmlWriter::characters(const XMLCh *const chars)
-{
-    //fFormatter->setUnRepFlags(XMLFormatter::UnRep_CharRef);
-	out->formatBuf(chars, XMLString::stringLen(chars), XMLFormatter::CharEscapes);
-}
-XmlWriter::XmlWriter()
-: out(0)
-, destination(0)
-{
-}
-XmlWriter::~XmlWriter()
-{
-	close();
-}
-void XmlWriter::close()
-{
-	//fclose(out);out=0;
-	if(destination){
-		delete destination;destination=0;
-	}
-	if(out){
-		delete out;out=0;
-	}
-}
-
-void XmlWriter::printNewLine()
-{
-	static const XMLCh  gEOLSeq[] =
-	{
-		chLF, chNull
-	};
-   *out << gEOLSeq;
-}
-
-void XmlWriter::printIndent(int level)
-{
-	for(int i = 0; i < level; i++)
-		*out << chSpace << chSpace;
-}
diff --git a/ogr/ogrsf_frmts/ili/iomhelper.cpp b/ogr/ogrsf_frmts/ili/iomhelper.cpp
deleted file mode 100644
index 7c986fa..0000000
--- a/ogr/ogrsf_frmts/ili/iomhelper.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/******************************************************************************
- * $Id: iomhelper.cpp 10645 2007-01-18 02:22:39Z warmerdam $
- *
- * Project:  Interlis 1/2 Translator
- * Purpose:  Implementation of ILI1Reader class.
- * Author:   Pirmin Kalberer, Sourcepole AG
- *
- ******************************************************************************
- * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#include "iomhelper.h"
-#include "cpl_port.h"
-
-CPL_CVSID("$Id: iomhelper.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
-
-
-IOM_OBJECT GetAttrObj(IOM_BASKET model, IOM_OBJECT obj, const char* attrname) {
-    IOM_OBJECT attrobj = iom_getattrobj(obj, attrname, 0);
-    if (attrobj == NULL) return NULL;
-    const char *refoid=iom_getobjectrefoid(attrobj);
-    if (refoid == NULL) return NULL;
-    return iom_getobject(model, refoid);
-}
-
-int GetAttrObjPos(IOM_OBJECT obj, const char* attrname) {
-    IOM_OBJECT attrobj = iom_getattrobj(obj, attrname, 0);
-    if (attrobj == NULL) return -1;
-    return iom_getobjectreforderpos(attrobj);
-}
-
-const char* GetAttrObjName(IOM_BASKET model, IOM_OBJECT obj, const char* attrname) {
-    return iom_getattrvalue(GetAttrObj(model, obj, attrname), "name");
-}
-
-IOM_OBJECT GetTypeObj(IOM_BASKET model, IOM_OBJECT obj) {
-    IOM_OBJECT typeobj = GetAttrObj(model, obj, "type");
-    if (typeobj && EQUAL(iom_getobjecttag(typeobj), "iom04.metamodel.TypeAlias")) {
-        typeobj = GetTypeObj(model, GetAttrObj(model, typeobj, "aliasing"));
-    }
-    return typeobj;
-}
-
-const char* GetTypeName(IOM_BASKET model, IOM_OBJECT obj) {
-    IOM_OBJECT typeobj = GetTypeObj(model, obj);
-    if (typeobj == NULL) return "(null)";
-    return iom_getobjecttag(typeobj);
-}
-
-unsigned int GetCoordDim(IOM_BASKET model, IOM_OBJECT typeobj) {
-  unsigned int dim = 0;
-  //find attribute of this type with highest orderpos
-  IOM_ITERATOR modelelei=iom_iteratorobject(model);
-  IOM_OBJECT modelele=iom_nextobject(modelelei);
-  while(modelele){
-    const char *tag=iom_getobjecttag(modelele);
-    if (tag && EQUAL(tag,"iom04.metamodel.NumericType")) {
-      if (GetAttrObj(model, modelele, "coordType") == typeobj) {
-        unsigned int orderpos = GetAttrObjPos(modelele, "coordType");
-        if (orderpos > dim) dim = orderpos;
-      }
-    }
-    iom_releaseobject(modelele);
-    modelele=iom_nextobject(modelelei);
-  }
-  iom_releaseiterator(modelelei);
-
-  return dim;
-}
-
-const char* GetAttrObjName(IOM_BASKET model, const char* tagname) {
-  const char* result = NULL;
-  IOM_ITERATOR modelelei = iom_iteratorobject(model);
-  IOM_OBJECT modelele = iom_nextobject(modelelei);
-  while (modelele && result == NULL)
-  {
-      if(EQUAL(iom_getobjecttag(modelele), tagname)){
-          // get name of topic
-          result = iom_getattrvalue(modelele, "name");
-      }
-      iom_releaseobject(modelele);
-      modelele=iom_nextobject(modelelei);
-  }
-  iom_releaseiterator(modelelei);
-  return result;
-}
diff --git a/ogr/ogrsf_frmts/ili/iomhelper.h b/ogr/ogrsf_frmts/ili/iomhelper.h
deleted file mode 100644
index a910c28..0000000
--- a/ogr/ogrsf_frmts/ili/iomhelper.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/******************************************************************************
- * $Id: iomhelper.h 10645 2007-01-18 02:22:39Z warmerdam $
- *
- * Project:  Interlis 1/2 Translator
- * Purpose:   Definition of classes for OGR Interlis 1 driver.
- * Author:   Pirmin Kalberer, Sourcepole AG
- *
- ******************************************************************************
- * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef _IOMHELPER_H_INCLUDED
-#define _IOMHELPER_H_INCLUDED
-
-#include "iom/iom.h"
-
-IOM_OBJECT GetAttrObj(IOM_BASKET model, IOM_OBJECT obj, const char* attrname);
-int GetAttrObjPos(IOM_OBJECT obj, const char* attrname);
-const char* GetAttrObjName(IOM_BASKET model, IOM_OBJECT obj, const char* attrname);
-IOM_OBJECT GetTypeObj(IOM_BASKET model, IOM_OBJECT obj);
-const char* GetTypeName(IOM_BASKET model, IOM_OBJECT obj);
-unsigned int GetCoordDim(IOM_BASKET model, IOM_OBJECT typeobj);
-const char* GetAttrObjName(IOM_BASKET model, const char* tagname);
-
-#endif /* _IOMHELPER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/makefile.vc b/ogr/ogrsf_frmts/ili/makefile.vc
index 6e2861c..14e9a47 100644
--- a/ogr/ogrsf_frmts/ili/makefile.vc
+++ b/ogr/ogrsf_frmts/ili/makefile.vc
@@ -1,8 +1,8 @@
 
 OBJ =	ili1reader.obj ili2reader.obj ili2handler.obj \
-	iomhelper.obj ogrili1driver.obj ogrili1datasource.obj \
+	ogrili1driver.obj ogrili1datasource.obj \
 	ogrili1layer.obj ogrili2driver.obj ogrili2datasource.obj \
-	ogrili2layer.obj ilihelper.obj
+	ogrili2layer.obj ilihelper.obj imdreader.obj
 
 GDAL_ROOT	=	..\..\..
 
@@ -11,14 +11,7 @@ GDAL_ROOT	=	..\..\..
 EXTRAFLAGS =	-I. -Iiom -I.. -I..\.. $(XERCES_INCLUDE) $(GEOS_CFLAGS)
 
 default:	$(OBJ)
-	cd iom
-	$(MAKE) /f makefile.vc
-	cd ..
 
 clean:
-	-del *.lib
 	-del *.obj *.pdb
-	cd iom
-	$(MAKE) /f makefile.vc clean
-	cd ..
 
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili1.h b/ogr/ogrsf_frmts/ili/ogr_ili1.h
index d7e6a73..b39c373 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili1.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili1.h 15268 2008-08-31 19:03:09Z pka $
+ * $Id: ogr_ili1.h 26979 2014-02-23 21:55:20Z pka $
  *
  * Project:  Interlis 1 Translator
  * Purpose:   Definition of classes for OGR Interlis 1 driver.
@@ -46,10 +46,7 @@ class OGRILI1Layer : public OGRLayer
 private:
     OGRSpatialReference *poSRS;
     OGRFeatureDefn      *poFeatureDefn;
-
-    OGRILI1Layer        *poSurfacePolyLayer; //Corresponding poly layer for surfaces
-    OGRILI1Layer        *poAreaReferenceLayer; //corresponding point layer for AREA's
-    OGRILI1Layer        *poAreaLineLayer; //corresponding line layer with AREA's
+    GeomFieldInfos      oGeomFieldInfos;
 
     int                 nFeatures;
     OGRFeature          **papoFeatures;
@@ -57,14 +54,14 @@ private:
 
     int                 bWriter;
 
+    int                 bGeomsJoined;
+
     OGRILI1DataSource   *poDS;
 
   public:
-                        OGRILI1Layer( const char * pszName,
-                                     OGRSpatialReference *poSRS,
-                                     int bWriter,
-                                     OGRwkbGeometryType eType,
-                                     OGRILI1DataSource *poDS );
+                        OGRILI1Layer( OGRFeatureDefn* poFeatureDefn,
+                                      GeomFieldInfos oGeomFieldInfos,
+                                      OGRILI1DataSource *poDS );
 
                        ~OGRILI1Layer();
 
@@ -75,9 +72,6 @@ private:
     OGRFeature *        GetNextFeatureRef();
     OGRFeature *        GetFeatureRef( long nFID );
 
-    void                SetSurfacePolyLayer(OGRILI1Layer *poSurfacePolyLayer);
-    void                SetAreaLayers(OGRILI1Layer *poReferenceLayer, OGRILI1Layer *poAreaLineLayer);
-
     int                 GetFeatureCount( int bForce = TRUE );
 
     OGRErr              CreateFeature( OGRFeature *poFeature );
@@ -87,14 +81,13 @@ private:
 
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
 
-    OGRSpatialReference *GetSpatialRef();
-
     int                 TestCapability( const char * );
 
   private:
-    void                JoinSurfaceLayer();
+    void                JoinGeomLayers();
+    void                JoinSurfaceLayer( OGRILI1Layer* poSurfacePolyLayer, int nSurfaceFieldIndex );
     OGRMultiPolygon*    Polygonize( OGRGeometryCollection* poLines, bool fix_crossing_lines = false );
-    void                PolygonizeAreaLayer();
+    void                PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nAreaFieldIndex, int nPointFieldIndex );
 };
 
 /************************************************************************/
@@ -105,6 +98,7 @@ class OGRILI1DataSource : public OGRDataSource
 {
   private:
     char       *pszName;
+    ImdReader  *poImdReader;
     IILI1Reader *poReader;
     FILE       *fpTransfer;
     char       *pszTopic;
@@ -121,6 +115,7 @@ class OGRILI1DataSource : public OGRDataSource
     const char *GetName() { return pszName; }
     int         GetLayerCount() { return poReader ? poReader->GetLayerCount() : 0; }
     OGRLayer   *GetLayer( int );
+    OGRILI1Layer *GetLayerByName( const char* );
 
     FILE       *GetTransferFile() { return fpTransfer; }
 
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili2.h b/ogr/ogrsf_frmts/ili/ogr_ili2.h
index 4f8fe69..60ab5b3 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili2.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili2.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili2.h 13906 2008-03-01 13:08:28Z rouault $
+ * $Id: ogr_ili2.h 26953 2014-02-16 17:47:12Z pka $
  *
  * Project:  Interlis 2 Translator
  * Purpose:   Definition of classes for OGR Interlis 2 driver.
@@ -31,8 +31,8 @@
 #define _OGR_ILI2_H_INCLUDED
 
 #include "ogrsf_frmts.h"
+#include "imdreader.h"
 #include "ili2reader.h"
-#include "iom/iom.h"
 
 #include <string>
 #include <list>
@@ -46,21 +46,17 @@ class OGRILI2DataSource;
 class OGRILI2Layer : public OGRLayer
 {
 private:
-    OGRSpatialReference *poSRS;
     OGRFeatureDefn     *poFeatureDefn;
+    GeomFieldInfos      oGeomFieldInfos;
     std::list<OGRFeature *>    listFeature;
     std::list<OGRFeature *>::const_iterator listFeatureIt;
 
-    int                 bWriter;
-
-    OGRILI2DataSource   *poDS;
+    OGRILI2DataSource  *poDS;
 
   public:
-                        OGRILI2Layer( const char * pszName, 
-                                     OGRSpatialReference *poSRS, 
-                                     int bWriter,
-                                     OGRwkbGeometryType eType,
-                                     OGRILI2DataSource *poDS );
+                        OGRILI2Layer( OGRFeatureDefn* poFeatureDefn,
+                                      GeomFieldInfos oGeomFieldInfos,
+                                      OGRILI2DataSource *poDS );
 
                        ~OGRILI2Layer();
 
@@ -75,9 +71,9 @@ private:
     
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    CPLString           GetIliGeomType( const char* cFieldName) { return oGeomFieldInfos[cFieldName].iliGeomType; };
 
-    OGRSpatialReference *GetSpatialRef();
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
     
     int                 TestCapability( const char * );
 };
@@ -92,9 +88,9 @@ class OGRILI2DataSource : public OGRDataSource
     std::list<OGRLayer *> listLayer;
     
     char        *pszName;
+    ImdReader   *poImdReader;
     IILI2Reader *poReader;
-    IOM_FILE    fpTransfer;  //for writing
-    IOM_BASKET  basket;
+    VSILFILE    *fpOutput;
 
     int         nLayers;
     OGRILI2Layer** papoLayers;
@@ -107,7 +103,6 @@ class OGRILI2DataSource : public OGRDataSource
     int         Create( const char *pszFile, char **papszOptions );
 
     const char *GetName() { return pszName; }
-    IOM_BASKET  GetBasket() { return basket; }
     int         GetLayerCount() { return listLayer.size(); }
     OGRLayer   *GetLayer( int );
 
@@ -116,6 +111,7 @@ class OGRILI2DataSource : public OGRDataSource
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
 
+    VSILFILE *  GetOutputFP() { return fpOutput; }
     int         TestCapability( const char * );
 };
 
diff --git a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
index 77984d8..33ec4a1 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1datasource.cpp 23890 2012-02-03 16:30:23Z pka $
+ * $Id: ogrili1datasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1DataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2007-2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,12 +34,9 @@
 
 #include "ili1reader.h"
 
-#include "iomhelper.h"
-#include "iom/iom.h"
-
 #include <string>
 
-CPL_CVSID("$Id: ogrili1datasource.cpp 23890 2012-02-03 16:30:23Z pka $");
+CPL_CVSID("$Id: ogrili1datasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRILI1DataSource()                         */
@@ -48,6 +46,7 @@ OGRILI1DataSource::OGRILI1DataSource()
 
 {
     pszName = NULL;
+    poImdReader = new ImdReader(1);
     poReader = NULL;
     fpTransfer = NULL;
     pszTopic = NULL;
@@ -73,6 +72,7 @@ OGRILI1DataSource::~OGRILI1DataSource()
     CPLFree( pszName );
     CPLFree( pszTopic );
     DestroyILI1Reader( poReader );
+    delete poImdReader;
     if( fpTransfer )
     {
         VSIFPrintf( fpTransfer, "ETAB\n" );
@@ -163,7 +163,7 @@ int OGRILI1DataSource::Open( const char * pszNewName, int bTestOpen )
     pszName = CPLStrdup( osBasename.c_str() );
 
     if (osModelFilename.length() > 0 )
-        poReader->ReadModel( osModelFilename.c_str() );
+        poReader->ReadModel( poImdReader, osModelFilename.c_str(), this );
 
     if( getenv( "ARC_DEGREES" ) != NULL ) {
       //No better way to pass arguments to the reader (it could even be an -lco arg)
@@ -194,11 +194,6 @@ int OGRILI1DataSource::Create( const char *pszFilename,
 
     CSLDestroy( filenames );
 
-    if( osModelFilename.length() == 0 )
-    {
-      //TODO: create automatic model
-    }
-
 /* -------------------------------------------------------------------- */
 /*      Create the empty file.                                          */
 /* -------------------------------------------------------------------- */
@@ -217,29 +212,15 @@ int OGRILI1DataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Parse model                                                     */
 /* -------------------------------------------------------------------- */
-    iom_init();
-
-    // set error listener to a iom provided one, that just
-    // dumps all errors to stderr
-    iom_seterrlistener(iom_stderrlistener);
-
-    IOM_BASKET model = 0;
-    if( osModelFilename.length() != 0 ) {
-      // compile ili model
-      char *iliFiles[1] = {(char *)osModelFilename.c_str()};
-      model=iom_compileIli(1,iliFiles);
-      if(!model){
-        CPLError( CE_Warning, CPLE_OpenFailed,
-                  "iom_compileIli %s, %s.",
-                  pszName, VSIStrerror( errno ) );
-        iom_end();
-        return FALSE;
-      }
+    if( osModelFilename.length() == 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+            "Creating Interlis transfer file without model definition." );
+    } else {
+        poImdReader->ReadModel(osModelFilename.c_str());
     }
 
-    pszTopic = CPLStrdup(model ?
-                         GetAttrObjName(model, "iom04.metamodel.Topic") :
-                         CPLGetBasename(osBasename.c_str()));
+    pszTopic = CPLStrdup(poImdReader->mainTopicName.c_str());
 
 /* -------------------------------------------------------------------- */
 /*      Write headers                                                   */
@@ -248,9 +229,7 @@ int OGRILI1DataSource::Create( const char *pszFilename,
     VSIFPrintf( fpTransfer, "OGR/GDAL %s, INTERLIS Driver\n", GDAL_RELEASE_NAME );
     VSIFPrintf( fpTransfer, "////\n" );
     VSIFPrintf( fpTransfer, "MTID INTERLIS1\n" );
-    const char* modelname = model ?
-                            GetAttrObjName(model, "iom04.metamodel.DataModel") :
-                            CPLGetBasename(osBasename.c_str());
+    const char* modelname = poImdReader->mainModelName.c_str();
     VSIFPrintf( fpTransfer, "MODL %s\n", modelname );
 
     return TRUE;
@@ -274,6 +253,7 @@ OGRILI1DataSource::CreateLayer( const char * pszLayerName,
                                char ** papszOptions )
 
 {
+    FeatureDefnInfo featureDefnInfo = poImdReader->GetFeatureDefnInfo(pszLayerName);
     const char *table = pszLayerName;
     char * topic = ExtractTopic(pszLayerName);
     if (nLayers) VSIFPrintf( fpTransfer, "ETAB\n" );
@@ -302,7 +282,9 @@ OGRILI1DataSource::CreateLayer( const char * pszLayerName,
     }
     VSIFPrintf( fpTransfer, "TABL %s\n", table );
 
-    OGRILI1Layer *poLayer = new OGRILI1Layer(table, poSRS, TRUE, eType, this);
+    OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(table);
+    poFeatureDefn->SetGeomType( eType );
+    OGRILI1Layer *poLayer = new OGRILI1Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
 
     nLayers ++;
     papoLayers = (OGRILI1Layer**)CPLRealloc(papoLayers, sizeof(OGRILI1Layer*) * nLayers);
@@ -332,3 +314,12 @@ OGRLayer *OGRILI1DataSource::GetLayer( int iLayer )
 {
   return poReader->GetLayer( iLayer );
 }
+
+/************************************************************************/
+/*                              GetLayerByName()                              */
+/************************************************************************/
+
+OGRILI1Layer *OGRILI1DataSource::GetLayerByName( const char* pszLayerName )
+{
+  return (OGRILI1Layer*)poReader->GetLayerByName( pszLayerName );
+}
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index d064d97..084be5a 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 24611 2012-06-25 15:21:48Z pka $
+ * $Id: ogrili1layer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,37 +33,28 @@
 #include "cpl_string.h"
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrili1layer.cpp 24611 2012-06-25 15:21:48Z pka $");
+CPL_CVSID("$Id: ogrili1layer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
 /************************************************************************/
 
-OGRILI1Layer::OGRILI1Layer( const char * pszName,
-                          OGRSpatialReference *poSRSIn, int bWriterIn,
-                          OGRwkbGeometryType eReqType,
-                          OGRILI1DataSource *poDSIn )
+OGRILI1Layer::OGRILI1Layer( OGRFeatureDefn* poFeatureDefnIn,
+                            GeomFieldInfos oGeomFieldInfosIn,
+                            OGRILI1DataSource *poDSIn )
 
 {
-    if( poSRSIn == NULL )
-        poSRS = NULL;
-    else
-        poSRS = poSRSIn->Clone();
-
     poDS = poDSIn;
 
-    poFeatureDefn = new OGRFeatureDefn( pszName );
+    poFeatureDefn = poFeatureDefnIn;
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( eReqType );
+    oGeomFieldInfos = oGeomFieldInfosIn;
 
     nFeatures = 0;
     papoFeatures = NULL;
     nFeatureIdx = 0;
 
-    poSurfacePolyLayer = 0;
-    poAreaLineLayer = 0;
-
-    bWriter = bWriterIn;
+    bGeomsJoined = FALSE;
 }
 
 /************************************************************************/
@@ -81,9 +73,6 @@ OGRILI1Layer::~OGRILI1Layer()
 
     if( poFeatureDefn )
         poFeatureDefn->Release();
-
-    if( poSRS != NULL )
-        poSRS->Release();
 }
 
 
@@ -115,8 +104,7 @@ OGRFeature *OGRILI1Layer::GetNextFeature()
 {
     OGRFeature *poFeature;
 
-    if (poSurfacePolyLayer != 0) JoinSurfaceLayer();
-    if (poAreaLineLayer != 0) PolygonizeAreaLayer(); //TODO: polygonize only when polygon layer is reqested
+    if (!bGeomsJoined) JoinGeomLayers();
 
     while(nFeatureIdx < nFeatures)
     {
@@ -168,7 +156,7 @@ OGRFeature *OGRILI1Layer::GetFeatureRef( long nFID )
 int OGRILI1Layer::GetFeatureCount( int bForce )
 {
     if (m_poFilterGeom == NULL && m_poAttrQuery == NULL &&
-        poAreaLineLayer == NULL)
+        1 /*poAreaLineLayer == NULL*/)
     {
         return nFeatures;
     }
@@ -402,35 +390,48 @@ OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, int bApproxOK ) {
     return OGRERR_NONE;
 }
 
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRILI1Layer::GetSpatialRef() {
-    return poSRS;
-}
-
 
 /************************************************************************/
 /*                         Internal routines                            */
 /************************************************************************/
 
-void OGRILI1Layer::SetSurfacePolyLayer(OGRILI1Layer *poSurfacePolyLayerIn) {
-    poSurfacePolyLayer = poSurfacePolyLayerIn;
+void OGRILI1Layer::JoinGeomLayers()
+{
+    for (GeomFieldInfos::const_iterator it = oGeomFieldInfos.begin(); it != oGeomFieldInfos.end(); ++it)
+    {
+        OGRFeatureDefn* geomFeatureDefn = it->second.geomTable;
+        if (geomFeatureDefn)
+        {
+            CPLDebug( "OGR_ILI", "Join geometry table %s of field '%s'", geomFeatureDefn->GetName(), it->first.c_str() );
+            OGRILI1Layer* poGeomLayer = poDS->GetLayerByName(geomFeatureDefn->GetName());
+            int nGeomFieldIndex = GetLayerDefn()->GetGeomFieldIndex(it->first.c_str());
+            if (it->second.iliGeomType == "Surface")
+            {
+                JoinSurfaceLayer(poGeomLayer, nGeomFieldIndex);
+            }
+            else if (it->second.iliGeomType == "Area")
+            {
+                CPLString pointField = it->first + "__Point";
+                int nPointFieldIndex = GetLayerDefn()->GetGeomFieldIndex(pointField.c_str());
+                PolygonizeAreaLayer(poGeomLayer, nGeomFieldIndex, nPointFieldIndex);
+            }
+        }
+    }
+    bGeomsJoined = TRUE;
 }
 
-void OGRILI1Layer::JoinSurfaceLayer()
-{
-    if (poSurfacePolyLayer == 0) return;
 
+void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfacePolyLayer, int nSurfaceFieldIndex )
+{
     CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries", GetLayerDefn()->GetName());
-    GetLayerDefn()->SetGeomType(poSurfacePolyLayer->GetLayerDefn()->GetGeomType());
-    ResetReading();
-    while (OGRFeature *feature = GetNextFeatureRef())
-    {
-        OGRFeature *polyfeature = poSurfacePolyLayer->GetFeatureRef(feature->GetFID());
-        if (polyfeature) {
-            feature->SetGeometry(polyfeature->GetGeometryRef());
+    poSurfacePolyLayer->ResetReading();
+    while (OGRFeature *polyfeature = poSurfacePolyLayer->GetNextFeatureRef()) {
+        int reftid = polyfeature->GetFieldAsInteger(1);
+        OGRFeature *feature = GetFeatureRef(reftid);
+        if (feature) {
+            feature->SetGeomField(nSurfaceFieldIndex, polyfeature->GetGeomFieldRef(0));
+        } else {
+            CPLDebug( "OGR_ILI", "Couldn't join feature FID %d", reftid );
         }
     }
 
@@ -438,11 +439,6 @@ void OGRILI1Layer::JoinSurfaceLayer()
     poSurfacePolyLayer = 0;
 }
 
-void OGRILI1Layer::SetAreaLayers(OGRILI1Layer *poReferenceLayer, OGRILI1Layer *poAreaLineLayerIn) {
-    poAreaReferenceLayer = poReferenceLayer;
-    poAreaLineLayer = poAreaLineLayerIn;
-}
-
 OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool fix_crossing_lines )
 {
     OGRMultiPolygon *poPolygon = new OGRMultiPolygon();
@@ -458,34 +454,37 @@ OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool
 
     if (fix_crossing_lines && poLines->getNumGeometries() > 0)
     {
-#if (GEOS_VERSION_MAJOR >= 3)
         CPLDebug( "OGR_ILI", "Fixing crossing lines");
         //A union of the geometry collection with one line fixes invalid geometries
         poNoncrossingLines = (OGRGeometryCollection*)poLines->Union(poLines->getGeometryRef(0));
         CPLDebug( "OGR_ILI", "Fixed lines: %d", poNoncrossingLines->getNumGeometries()-poLines->getNumGeometries());
-#else
-        #warning Interlis 1 AREA cleanup disabled. Needs GEOS >= 3.0
-#endif
     }
+    
+    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
 
     ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*),poNoncrossingLines->getNumGeometries());
     for( i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
-          ahInGeoms[i] = poNoncrossingLines->getGeometryRef(i)->exportToGEOS();
+          ahInGeoms[i] = poNoncrossingLines->getGeometryRef(i)->exportToGEOS(hGEOSCtxt);
 
-    hResultGeom = GEOSPolygonize( ahInGeoms,
-                                  poNoncrossingLines->getNumGeometries() );
+    hResultGeom = GEOSPolygonize_r( hGEOSCtxt,
+                                    ahInGeoms,
+                                   poNoncrossingLines->getNumGeometries() );
 
     for( i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
-        GEOSGeom_destroy( ahInGeoms[i] );
+        GEOSGeom_destroy_r( hGEOSCtxt, ahInGeoms[i] );
     CPLFree( ahInGeoms );
     if (poNoncrossingLines != poLines) delete poNoncrossingLines;
 
     if( hResultGeom == NULL )
+    {
+        OGRGeometry::freeGEOSContext( hGEOSCtxt );
         return NULL;
+    }
 
-    poMP = OGRGeometryFactory::createFromGEOS( hResultGeom );
+    poMP = OGRGeometryFactory::createFromGEOS( hGEOSCtxt, hResultGeom );
 
-    GEOSGeom_destroy( hResultGeom );
+    GEOSGeom_destroy_r( hGEOSCtxt, hResultGeom );
+    OGRGeometry::freeGEOSContext( hGEOSCtxt );
 
     return (OGRMultiPolygon *) poMP;
 
@@ -495,10 +494,8 @@ OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool
 }
 
 
-void OGRILI1Layer::PolygonizeAreaLayer()
+void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nAreaFieldIndex, int nPointFieldIndex )
 {
-    if (poAreaLineLayer == 0) return;
-
     //add all lines from poAreaLineLayer to collection
     OGRGeometryCollection *gc = new OGRGeometryCollection();
     poAreaLineLayer->ResetReading();
@@ -510,9 +507,9 @@ void OGRILI1Layer::PolygonizeAreaLayer()
     poAreaLineLayer = 0;
     OGRMultiPolygon* polys = Polygonize( gc , false);
     CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
-    if (polys->getNumGeometries() != poAreaReferenceLayer->GetFeatureCount())
+    if (polys->getNumGeometries() != GetFeatureCount())
     {
-        CPLDebug( "OGR_ILI", "Feature count of layer %s: %d", poAreaReferenceLayer->GetLayerDefn()->GetName(), GetFeatureCount());
+        CPLDebug( "OGR_ILI", "Feature count of layer %s: %d", GetLayerDefn()->GetName(), GetFeatureCount());
         CPLDebug( "OGR_ILI", "Polygonizing again with crossing line fix");
         delete polys;
         polys = Polygonize( gc, true ); //try again with crossing line fix
@@ -526,29 +523,27 @@ void OGRILI1Layer::PolygonizeAreaLayer()
     GEOSGeom *ahInGeoms = NULL;
 
     CPLDebug( "OGR_ILI", "Associating layer %s with area polygons", GetLayerDefn()->GetName());
-    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*),polys->getNumGeometries());
+    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*), polys->getNumGeometries());
+    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
     for( i = 0; i < polys->getNumGeometries(); i++ )
     {
-        ahInGeoms[i] = polys->getGeometryRef(i)->exportToGEOS();
-        if (!GEOSisValid(ahInGeoms[i])) ahInGeoms[i] = NULL;
+        ahInGeoms[i] = polys->getGeometryRef(i)->exportToGEOS(hGEOSCtxt);
+        if (!GEOSisValid_r(hGEOSCtxt, ahInGeoms[i])) ahInGeoms[i] = NULL;
     }
-    poAreaReferenceLayer->ResetReading();
-    while (OGRFeature *feature = poAreaReferenceLayer->GetNextFeatureRef())
+    for ( int nFidx = 0; nFidx < nFeatures; nFidx++)
     {
-        OGRGeometry* geomRef = feature->GetGeometryRef();
+        OGRFeature *feature = papoFeatures[nFidx];
+        OGRGeometry* geomRef = feature->GetGeomFieldRef(nPointFieldIndex);
         if( !geomRef )
         {
             continue;
         }
-        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS());
+        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS(hGEOSCtxt));
         for (i = 0; i < polys->getNumGeometries(); i++ )
         {
-            if (ahInGeoms[i] && GEOSWithin(point, ahInGeoms[i]))
+            if (ahInGeoms[i] && GEOSWithin_r(hGEOSCtxt, point, ahInGeoms[i]))
             {
-                OGRFeature* areaFeature = new OGRFeature(poFeatureDefn);
-                areaFeature->SetFrom(feature);
-                areaFeature->SetGeometry( polys->getGeometryRef(i) );
-                AddFeature(areaFeature);
+                feature->SetGeomField(nAreaFieldIndex, polys->getGeometryRef(i));
                 break;
             }
         }
@@ -557,11 +552,12 @@ void OGRILI1Layer::PolygonizeAreaLayer()
             CPLDebug( "OGR_ILI", "Association between area and point failed.");
             feature->SetGeometry( &emptyPoly );
         }
-        GEOSGeom_destroy( point );
+        GEOSGeom_destroy_r( hGEOSCtxt, point );
     }
     for( i = 0; i < polys->getNumGeometries(); i++ )
-        GEOSGeom_destroy( ahInGeoms[i] );
+        GEOSGeom_destroy_r( hGEOSCtxt, ahInGeoms[i] );
     CPLFree( ahInGeoms );
+    OGRGeometry::freeGEOSContext( hGEOSCtxt );
 #endif
     poAreaLineLayer = 0;
     delete polys;
diff --git a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
index 45af58e..aae02e0 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili2datasource.cpp 24408 2012-05-11 21:31:45Z pka $
+ * $Id: ogrili2datasource.cpp 27184 2014-04-14 22:21:56Z pka $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2DataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2007-2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,12 +33,11 @@
 #include "cpl_string.h"
 
 #include "ili2reader.h"
-#include "iomhelper.h"
 
 using namespace std;
 
 
-CPL_CVSID("$Id: ogrili2datasource.cpp 24408 2012-05-11 21:31:45Z pka $");
+CPL_CVSID("$Id: ogrili2datasource.cpp 27184 2014-04-14 22:21:56Z pka $");
 
 /************************************************************************/
 /*                         OGRILI2DataSource()                         */
@@ -47,9 +47,9 @@ OGRILI2DataSource::OGRILI2DataSource()
 
 {
     pszName = NULL;
+    poImdReader = new ImdReader(2);
     poReader = NULL;
-    fpTransfer = NULL;
-    basket = NULL;
+    fpOutput = NULL;
     nLayers = 0;
     papoLayers = NULL;
 }
@@ -69,19 +69,16 @@ OGRILI2DataSource::~OGRILI2DataSource()
     }
     CPLFree( papoLayers );
 
-    if (basket) iom_releasebasket(basket);
-    if (fpTransfer)
-    {  
-      // write file
-      iom_save(fpTransfer);
-  
-      // clean up
-      iom_close(fpTransfer);
-  
-      iom_end();
-  
+    if ( fpOutput != NULL )
+    {
+        VSIFPrintfL(fpOutput, "</%s>\n", poImdReader->mainBasketName.c_str());
+        VSIFPrintfL(fpOutput, "</DATASECTION>\n");
+        VSIFPrintfL(fpOutput, "</TRANSFER>\n");
+        VSIFCloseL(fpOutput);
     }
+
     DestroyILI2Reader( poReader );
+    delete poImdReader;
     CPLFree( pszName );
 }
 
@@ -95,14 +92,11 @@ int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
     FILE        *fp;
     char        szHeader[1000];
 
-    char **modelFilenames = NULL;
     char **filenames = CSLTokenizeString2( pszNewName, ",", 0 );
+    const char *pszModelFilename = (CSLCount(filenames)>1) ? filenames[1] : NULL;
 
     pszName = CPLStrdup( filenames[0] );
 
-    if( CSLCount(filenames) > 1 )
-        modelFilenames = &filenames[1];
-
 /* -------------------------------------------------------------------- */
 /*      Open the source file.                                           */
 /* -------------------------------------------------------------------- */
@@ -110,8 +104,8 @@ int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
     if( fp == NULL )
     {
         if( !bTestOpen )
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open ILI2 file `%s'.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to open ILI2 file `%s'.",
                       pszNewName );
 
         CSLDestroy( filenames );
@@ -132,7 +126,7 @@ int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
 
         if( szHeader[0] != '<' 
             || strstr(szHeader,"interlis.ch/INTERLIS2") == NULL )
-        { // "www.interlis.ch/INTERLIS2.2"
+        { // "www.interlis.ch/INTERLIS2.3"
             VSIFClose( fp );
             CSLDestroy( filenames );
             return FALSE;
@@ -157,8 +151,8 @@ int OGRILI2DataSource::Open( const char * pszNewName, int bTestOpen )
         return FALSE;
     }
 
-    if (modelFilenames)
-        poReader->ReadModel( modelFilenames );
+    if (pszModelFilename)
+        poReader->ReadModel( poImdReader, pszModelFilename );
 
     if( getenv( "ARC_DEGREES" ) != NULL ) {
       //No better way to pass arguments to the reader (it could even be an -lco arg)
@@ -191,73 +185,72 @@ int OGRILI2DataSource::Create( const char *pszFilename,
 {
     char **filenames = CSLTokenizeString2( pszFilename, ",", 0 );
     pszName = CPLStrdup(filenames[0]);
-    const char  *pszModelFilename = (CSLCount(filenames)>1) ? filenames[1] : NULL;
+    const char *pszModelFilename = (CSLCount(filenames)>1) ? filenames[1] : NULL;
 
     if( pszModelFilename == NULL )
     {
-        CPLError( CE_Warning, CPLE_OpenFailed, 
-                  "Model file '%s' (%s) not found : %s.", 
+        CPLError( CE_Warning, CPLE_OpenFailed,
+                  "Model file '%s' (%s) not found : %s.",
                   pszModelFilename, pszFilename, VSIStrerror( errno ) );
         CSLDestroy(filenames);
         return FALSE;
     }
 
-    iom_init();
-
-    // set error listener to a iom provided one, that just 
-    // dumps all errors to stderr
-    iom_seterrlistener(iom_stderrlistener);
+/* -------------------------------------------------------------------- */
+/*      Create the output file.                                         */
+/* -------------------------------------------------------------------- */
 
-    // compile ili model
-    char *iliFiles[1] = {(char *)pszModelFilename};
-    IOM_BASKET model=iom_compileIli(1,iliFiles);
-    if(!model){
-        CPLError( CE_Warning, CPLE_OpenFailed, 
-                    "iom_compileIli %s, %s.", 
-                    pszName, VSIStrerror( errno ) );
-                iom_end();
-        CSLDestroy(filenames);
-        return FALSE;
+    if( strcmp(pszName,"/vsistdout/") == 0 ||
+        strncmp(pszName,"/vsigzip/", 9) == 0 )
+    {
+        fpOutput = VSIFOpenL(pszName, "wb");
     }
+    else if ( strncmp(pszName,"/vsizip/", 8) == 0)
+    {
+        if (EQUAL(CPLGetExtension(pszName), "zip"))
+        {
+            CPLFree(pszName);
+            pszName = CPLStrdup(CPLFormFilename(pszName, "out.xtf", NULL));
+        }
 
-    // open new file
-    fpTransfer=iom_open(pszName,IOM_CREATE | IOM_DONTREAD,0);
-    if(!fpTransfer){
-        CPLError( CE_Warning, CPLE_OpenFailed, 
-                    "Failed to open %s.", 
-                    pszName );
+        fpOutput = VSIFOpenL(pszName, "wb");
+    }
+    else
+        fpOutput = VSIFOpenL( pszName, "wb+" );
+    if( fpOutput == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create XTF file %s.",
+                  pszName );
         CSLDestroy(filenames);
         return FALSE;
     }
 
-    // set model of new file
-    iom_setmodel(fpTransfer,model);
 
-    iom_setheadsender(fpTransfer, pszModelFilename);
-
-    iom_setheadcomment(fpTransfer,"Created by OGR");
+/* -------------------------------------------------------------------- */
+/*      Parse model                                                     */
+/* -------------------------------------------------------------------- */
+    poImdReader->ReadModel(pszModelFilename);
 
-    // create new basket
-    static char basketname[512];
-    basketname[0] = '\0';
-    const char* val = GetAttrObjName(model, "iom04.metamodel.DataModel");
-    if (val)
-    {
-      strcat(basketname, val);
-      strcat(basketname, ".");
-      val = GetAttrObjName(model, "iom04.metamodel.Topic");
-      if (val) strcat(basketname, val);
-    }
-    else
+/* -------------------------------------------------------------------- */
+/*      Write headers                                                   */
+/* -------------------------------------------------------------------- */
+    VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+    VSIFPrintfL(fpOutput, "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
+    VSIFPrintfL(fpOutput, "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n", GDAL_RELEASE_NAME);
+    VSIFPrintfL(fpOutput, "<MODELS>\n");
+    for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin(); it != poImdReader->modelInfos.end(); ++it)
     {
-      strcat(basketname, "Basket");
+        VSIFPrintfL(fpOutput, "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
+            it->name.c_str(), it->uri.c_str(), it->version.c_str());
     }
+    VSIFPrintfL(fpOutput, "</MODELS>\n");
+    VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
+    VSIFPrintfL(fpOutput, "<DATASECTION>\n");
+    const char* basketName = poImdReader->mainBasketName.c_str();
+    VSIFPrintfL(fpOutput, "<%s BID=\"%s\">\n", basketName, basketName);
 
-    CSLDestroy(filenames);
-
-    basket=iom_newbasket(fpTransfer);
-    iom_setbaskettag(basket, basketname);
-    iom_setbasketoid(basket, "0");
+    CSLDestroy( filenames );
     return TRUE;
 }
 
@@ -272,9 +265,21 @@ OGRILI2DataSource::CreateLayer( const char * pszLayerName,
                                char ** papszOptions )
 
 {
-    OGRILI2Layer *poLayer = new OGRILI2Layer(pszLayerName, poSRS, TRUE, eType, this);
+    if (fpOutput == NULL)
+        return NULL;
+
+    FeatureDefnInfo featureDefnInfo = poImdReader->GetFeatureDefnInfo(pszLayerName);
+    OGRFeatureDefn* poFeatureDefn = featureDefnInfo.poTableDefn;
+    if (poFeatureDefn == NULL)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Layer '%s' not found in model definition. Creating adhoc layer", pszLayerName);
+        poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+        poFeatureDefn->SetGeomType( eType );
+    }
+    OGRILI2Layer *poLayer = new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
 
-    nLayers ++;
+    nLayers++;
     papoLayers = (OGRILI2Layer**)CPLRealloc(papoLayers, sizeof(OGRILI2Layer*) * nLayers);
     papoLayers[nLayers-1] = poLayer;
 
diff --git a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
index 0f4f7b8..a214b97 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili2layer.cpp 23895 2012-02-04 11:21:18Z rouault $
+ * $Id: ogrili2layer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2Layer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,30 +32,21 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrili2layer.cpp 23895 2012-02-04 11:21:18Z rouault $");
+CPL_CVSID("$Id: ogrili2layer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI2Layer()                              */
 /************************************************************************/
 
-OGRILI2Layer::OGRILI2Layer( const char * pszName,
-                          OGRSpatialReference *poSRSIn, int bWriterIn,
-                          OGRwkbGeometryType eReqType,
-                          OGRILI2DataSource *poDSIn )
-
+OGRILI2Layer::OGRILI2Layer( OGRFeatureDefn* poFeatureDefnIn,
+                            GeomFieldInfos oGeomFieldInfosIn,
+                            OGRILI2DataSource *poDSIn )
 {
-    if( poSRSIn == NULL )
-        poSRS = NULL;
-    else
-        poSRS = poSRSIn->Clone();
-
-    poDS = poDSIn;
-
-    poFeatureDefn = new OGRFeatureDefn( pszName );
+    poFeatureDefn = poFeatureDefnIn;
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( eReqType );
+    oGeomFieldInfos = oGeomFieldInfosIn;
 
-    bWriter = bWriterIn;
+    poDS = poDSIn;
 
     listFeatureIt = listFeature.begin();
 }
@@ -64,14 +56,10 @@ OGRILI2Layer::OGRILI2Layer( const char * pszName,
 /************************************************************************/
 
 OGRILI2Layer::~OGRILI2Layer()
-
 {
     if( poFeatureDefn )
         poFeatureDefn->Release();
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     listFeatureIt = listFeature.begin();
     while(listFeatureIt != listFeature.end())
     {
@@ -85,7 +73,8 @@ OGRILI2Layer::~OGRILI2Layer()
 /*                             SetFeature()                             */
 /************************************************************************/
 
-OGRErr OGRILI2Layer::SetFeature (OGRFeature *poFeature) {
+OGRErr OGRILI2Layer::SetFeature (OGRFeature *poFeature)
+{
     listFeature.push_back(poFeature);
     return OGRERR_NONE;
 }
@@ -94,7 +83,8 @@ OGRErr OGRILI2Layer::SetFeature (OGRFeature *poFeature) {
 /*                            ResetReading()                            */
 /************************************************************************/
 
-void OGRILI2Layer::ResetReading(){
+void OGRILI2Layer::ResetReading()
+{
     listFeatureIt = listFeature.begin();
 }
 
@@ -102,7 +92,8 @@ void OGRILI2Layer::ResetReading(){
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
-OGRFeature *OGRILI2Layer::GetNextFeature() {
+OGRFeature *OGRILI2Layer::GetNextFeature()
+{
     OGRFeature *poFeature = NULL;
     while (listFeatureIt != listFeature.end())
     {
@@ -147,87 +138,75 @@ static char* d2str(double val)
     return strbuf;
 }
 
-static void AppendCoordinateList( OGRLineString *poLine, IOM_OBJECT sequence)
+static void AppendCoordinateList( OGRLineString *poLine, VSILFILE* fp )
 {
-	IOM_OBJECT coordValue;
     int         b3D = (poLine->getGeometryType() & wkb25DBit);
 
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
-        coordValue=iom_addattrobj(sequence,"segment","COORD");
-        iom_setattrvalue(coordValue,"C1", d2str(poLine->getX(iPoint)));
-        iom_setattrvalue(coordValue,"C2", d2str(poLine->getY(iPoint)));
-        if (b3D) iom_setattrvalue(coordValue,"C3", d2str(poLine->getZ(iPoint)));
-        iom_releaseobject(coordValue);
+        VSIFPrintfL(fp, "<COORD>");
+        VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poLine->getX(iPoint)));
+        VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poLine->getY(iPoint)));
+        if (b3D) VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poLine->getZ(iPoint)));
+        VSIFPrintfL(fp, "</COORD>\n");
     }
 }
 
-static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, IOM_OBJECT obj, const char *attrname )
+static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const char *attrname, CPLString iliGeomType )
 {
-    IOM_OBJECT polylineValue;
-    IOM_OBJECT sequence;
-    IOM_OBJECT coordValue;
-    IOM_OBJECT multisurface;
-    IOM_OBJECT surface;
-    IOM_OBJECT boundary;
-
-/* -------------------------------------------------------------------- */
-/*      2D Point                                                        */
-/* -------------------------------------------------------------------- */
-    if( poGeometry->getGeometryType() == wkbPoint )
-    {
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
-
-        coordValue=iom_changeattrobj(obj,attrname,0,"COORD");
-        iom_setattrvalue(coordValue,"C1", d2str(poPoint->getX()));
-        iom_setattrvalue(coordValue,"C2", d2str(poPoint->getY()));
-        iom_releaseobject(coordValue);
-    }
+    //CPLDebug( "OGR_ILI", "OGR2ILIGeometryAppend getGeometryType %s iliGeomType %s", poGeometry->getGeometryName(), iliGeomType.c_str());
 /* -------------------------------------------------------------------- */
-/*      3D Point                                                        */
+/*      2D/3D Point                                                     */
 /* -------------------------------------------------------------------- */
-    else if( poGeometry->getGeometryType() == wkbPoint25D )
+    if( poGeometry->getGeometryType() == wkbPoint || poGeometry->getGeometryType() == wkbPoint25D )
     {
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
-        coordValue=iom_changeattrobj(obj,attrname,0,"COORD");
-        iom_setattrvalue(coordValue,"C1", d2str(poPoint->getX()));
-        iom_setattrvalue(coordValue,"C2", d2str(poPoint->getY()));
-        iom_setattrvalue(coordValue,"C3", d2str(poPoint->getZ()));
-        iom_releaseobject(coordValue);
+        VSIFPrintfL(fp, "<%s>\n", attrname);
+        VSIFPrintfL(fp, "<COORD>");
+        VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poPoint->getX()));
+        VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poPoint->getY()));
+        if( poGeometry->getGeometryType() == wkbPoint25D )
+            VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poPoint->getZ()));
+        VSIFPrintfL(fp, "</COORD>\n");
+        VSIFPrintfL(fp, "</%s>\n", attrname);
     }
 
 /* -------------------------------------------------------------------- */
 /*      LineString and LinearRing                                       */
 /* -------------------------------------------------------------------- */
-    else if( poGeometry->getGeometryType() == wkbLineString 
+    else if( poGeometry->getGeometryType() == wkbLineString
              || poGeometry->getGeometryType() == wkbLineString25D )
     {
-        //int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
-        if (attrname) polylineValue=iom_changeattrobj(obj,attrname,0,"POLYLINE");
-        else polylineValue=iom_addattrobj(obj,"polyline","POLYLINE");
+        if (attrname) VSIFPrintfL(fp, "<%s>\n", attrname);
+        VSIFPrintfL(fp, "<POLYLINE>\n");
         // unclipped polyline, add one sequence
-        sequence=iom_changeattrobj(polylineValue,"sequence",0,"SEGMENTS");
-        AppendCoordinateList( (OGRLineString *) poGeometry, sequence );
-        iom_releaseobject(sequence);
-        iom_releaseobject(polylineValue);
+        // VSIFPrintfL(fp, "<SEGMENTS>\n");
+        AppendCoordinateList( (OGRLineString *) poGeometry, fp );
+        // VSIFPrintfL(fp, "</SEGMENTS>\n");
+        VSIFPrintfL(fp, "</POLYLINE>\n");
+        if (attrname) VSIFPrintfL(fp, "</%s>\n", attrname);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Polygon                                                         */
 /* -------------------------------------------------------------------- */
-    else if( poGeometry->getGeometryType() == wkbPolygon 
+    else if( poGeometry->getGeometryType() == wkbPolygon
              || poGeometry->getGeometryType() == wkbPolygon25D )
     {
         OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
 
-        multisurface=iom_changeattrobj(obj,attrname,0,"MULTISURFACE");
-        surface=iom_changeattrobj(multisurface,"surface",0,"SURFACE");
-        boundary=iom_changeattrobj(surface,"boundary",0,"BOUNDARY");
+        if (attrname) VSIFPrintfL(fp, "<%s>\n", attrname);
+        if( iliGeomType == "Surface" || iliGeomType == "Area" )
+        {
+            //VSIFPrintfL(fp, "<MULTISURFACE>\n");
+            VSIFPrintfL(fp, "<SURFACE>\n");
+            VSIFPrintfL(fp, "<BOUNDARY>\n");
+        }
 
         if( poPolygon->getExteriorRing() != NULL )
         {
-            if( !OGR2ILIGeometryAppend( poPolygon->getExteriorRing(), boundary, NULL  ) )
+            if( !OGR2ILIGeometryAppend( poPolygon->getExteriorRing(), fp, NULL, "" ) )
                 return FALSE;
         }
 
@@ -235,18 +214,22 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, IOM_OBJECT obj, const
         {
             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
 
-            if( !OGR2ILIGeometryAppend( poRing, boundary, NULL ) )
+            if( !OGR2ILIGeometryAppend( poRing, fp, NULL, "" ) )
                 return FALSE;
         }
-        iom_releaseobject(boundary);
-        iom_releaseobject(surface);
-        iom_releaseobject(multisurface);
+        if( iliGeomType == "Surface" || iliGeomType == "Area" )
+        {
+            VSIFPrintfL(fp, "</BOUNDARY>\n");
+            VSIFPrintfL(fp, "</SURFACE>\n");
+            //VSIFPrintfL(fp, "</MULTISURFACE>\n");
+        }
+        if (attrname) VSIFPrintfL(fp, "</%s>\n", attrname);
     }
 
 /* -------------------------------------------------------------------- */
 /*      MultiPolygon                                                    */
 /* -------------------------------------------------------------------- */
-    else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon 
+    else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon
              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
@@ -271,7 +254,7 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, IOM_OBJECT obj, const
         {
             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
 
-            if( !OGR2ILIGeometryAppend( poMember, obj, NULL ) )
+            if( !OGR2ILIGeometryAppend( poMember, fp, NULL, "" ) )
                 return FALSE;
         }
 
@@ -301,15 +284,25 @@ OGRErr OGRILI2Layer::CreateFeature( OGRFeature *poFeature ) {
         sprintf( szTempBuffer, "%ld", poFeature->GetFID() );
         tid = szTempBuffer;
     }
-    // create new object
-    IOM_OBJECT obj;
-    obj=iom_newobject(poDS->GetBasket(), poFeatureDefn->GetName(), tid);
 
-    // Write out Geometry
-    if( poFeature->GetGeometryRef() != NULL )
+    VSILFILE* fp = poDS->GetOutputFP();
+    if (fp == NULL)
+        return CE_Failure;
+
+    VSIFPrintfL(fp, "<%s TID=\"%s\">\n", poFeatureDefn->GetName(), tid);
+
+    // Write out Geometries
+    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
     {
-        OGR2ILIGeometryAppend(poFeature->GetGeometryRef(), obj, "Geometry");
+        OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField);
+        if( poGeom != NULL )
+        {
+            CPLString iliGeomType = GetIliGeomType(poFieldDefn->GetNameRef());
+            OGR2ILIGeometryAppend(poGeom, fp, poFieldDefn->GetNameRef(), iliGeomType);
+        }
     }
+
     // Write all "set" fields. 
     for( ; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
@@ -319,18 +312,12 @@ OGRErr OGRILI2Layer::CreateFeature( OGRFeature *poFeature ) {
         if( poFeature->IsFieldSet( iField ) )
         {
             const char *pszRaw = poFeature->GetFieldAsString( iField );
-
-            //while( *pszRaw == ' ' )
-            //    pszRaw++;
-
-            //char *pszEscaped = CPLEscapeString( pszRaw, -1, CPLES_XML );
-
-            iom_setattrvalue(obj, poField->GetNameRef(), pszRaw);
-            //CPLFree( pszEscaped );
+            VSIFPrintfL(fp, "<%s>%s</%s>\n", poField->GetNameRef(), pszRaw, poField->GetNameRef());
         }
     }
 
-    iom_releaseobject(obj);
+    VSIFPrintfL(fp, "</%s>\n", poFeatureDefn->GetName());
+
     return OGRERR_NONE;
 }
 
@@ -350,11 +337,3 @@ OGRErr OGRILI2Layer::CreateField( OGRFieldDefn *poField, int bApproxOK ) {
     poFeatureDefn->AddFieldDefn( poField );
     return OGRERR_NONE;
 }
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRILI2Layer::GetSpatialRef() {
-    return poSRS;
-}
diff --git a/ogr/ogrsf_frmts/ingres/drv_ingres.html b/ogr/ogrsf_frmts/ingres/drv_ingres.html
index 5817296..15f0ff4 100644
--- a/ogr/ogrsf_frmts/ingres/drv_ingres.html
+++ b/ogr/ogrsf_frmts/ingres/drv_ingres.html
@@ -7,29 +7,31 @@
 
 <h1>INGRES</h1>
 
-This driver implements read and write access for spatial data in 
-<a href="http://www.ingres.com/">INGRES</a> database tables.  This 
-functionality was introduced in GDAL/OGR 1.6.0.  <p>
+<p>This driver implements read and write access for spatial data in
+<a href="http://www.actian.com/products/ingres/geospatial/">INGRES</a> database tables. This
+functionality was introduced in GDAL/OGR 1.6.0. </p>
 
-When opening a database, it's name should be specified in the form
+<p>When opening a database, it's name should be specified in the form
 "@driver=ingres,[host=<i>host</i>, instance=<i>instance</i>],dbname=<i>[vnode::]dbname</i>
-[,options]". where the options can 
+[,options]". where the options can
 include comma seperated
-items like "host=*ip_address*","instance=*instance*", "username=*userid*", "password=*password*", 
+items like "host=*ip_address*","instance=*instance*", "username=*userid*", "password=*password*",
 "effuser=*database_user*", "dbpwd=*database_passwd*", "timeout=*timeout*",
-"tables=table1/table2".  The driver and dbname values are required, while
-the rest are optional.  If username and password are not provided an attempt
-is made to authenticate as the current OS user.<p>
-
-If the host and instance options are both specified,
-the username and password *must* be supplied as to componsit the 
-<a href=http://docs.actian.com/ingres/10.0/command-reference-guide/1207-dynamic-vnode-specificationconnect-to-remote-node>dynamic vnode</a>.
-The default protocal is Tcp/IP. If any other protocal is expected to be used, a pre-build vnode is preferable.
+"tables=table1/table2".</p>
+
+<p><b>The driver and dbname values are required, while
+the rest are optional.</b> If username and password are not provided an attempt
+is made to authenticate as the current OS user.</p>
+
+<p>If the host and instance options are both specified,
+the username and password *must* be supplied as it creates a temporary
+<a href=http://docs.actian.com/ingres/10.0/command-reference-guide/1207-dynamic-vnode-specificationconnect-to-remote-node>dynamic vnode connection</a>.
+The default protocal is TCP/IP. If any other protocal is expected to be used, a pre-built vnode is preferable.
 If vnode and these two options are passed at the same time, an error will occur.
-<p>
+</p>
 
-The option effuser and dbpwd are mapped to the real user name and password needs to be authorized in dbms, compared to the
-username and password which are used for OS level authorization.<p>
+<p>The option effuser and dbpwd are mapped to the real user name and password needs to be authorized in dbms, compared to the
+username and password which are used for OS level authorization.</p>
 
 Examples:
 <pre>
@@ -48,39 +50,34 @@ Examples:
   @driver=ingres,dbname=mapping
 </pre>
 
-If the tables list is not provided, an attempt is made to enumerate all 
+<p>
+If the tables list is not provided, an attempt is made to enumerate all
 non-system tables as layers, otherwise only the listed tables are represented
-as layers.  This option is primarily useful when a database has a lot of 
-tables, and scanning all their schemas would take a significant amount of 
-time. <p>
+as layers. This option is primarily useful when a database has a lot of
+tables, and scanning all their schemas would take a significant amount of
+time.</p>
 
-If an integer field exists in a table that is named "ogr_fid" it will be
-used as the FID, otherwise FIDs will be assigned sequentially.  This can
+<p>If an integer field exists in a table that is named "ogr_fid" it will be
+used as the FID, otherwise FIDs will be assigned sequentially. This can
 result in different FIDs being assigned to a given record/feature depending
-on the spatial and attribute query filters in effect at a given time.<p>
+on the spatial and attribute query filters in effect at a given time.</p>
 
-<p>By default, SQL statements are passed directly to the INGRES database 
-engine.  It's also possible to request the driver to handle SQL commands 
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, 
-by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() 
+<p>By default, SQL statements are passed directly to the INGRES database
+engine. It's also possible to request the driver to handle SQL commands
+with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine,
+by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
 
-Currently the INGRES driver supports only "old style" INGRES spatial data
-types such as POLYGON, POINT, LINE, LONG POLYGON, LONG LINE, etc.  It is
-anticipated in the future a newer OGC compliant set of spatial types will
-also be supported.<p>
+<p>
+The INGRES driver supports OGC SFSQL 1.1 compliant spatial types and functions,
+including types: POINT, LINESTRING, POLYGON, MULTI* versions, and GEOMETRYCOLLECTION.
+</p>
  
 <h2>Caveats</h2>
 <ul>
-<li> The spatial types CIRCLE and ICIRCLE are not currently supported for 
-reading. <p>
-
 <li> No fast spatial index is used when reading, so spatial filters are
 implemented by reading and parsing all records, and then discarding those
 that do not satisfy the spatial filter.<p>
-
-<li> There is currently no support for coordinate systems.<p>
-
 </ul>
 
 <h2>Creation Issues</h2>
@@ -91,48 +88,35 @@ existing database instance.<P>
 
 <ul>
 
-<li>    
+<li>
 The INGRES driver makes no allowances for character encodings at this time.<p>
 
 <li>
 The INGRES driver is not transactional at this time.<p>
-    
-<li> The spatial types BOX and IBOX are not supported for creating, and when
-read are represented as polygons.<p>
-
-<li> The non-LONG types (such as LINE, ILINE, and POLYGON) only support a 
-limited number of vertices.  Attempts to create objects with more than the 
-maximum possible vertices for these types will fail.  <p>
-
-<li> The old ingres spatial types are very particular about geometry 
-validation, and attempts to insert (create) features with invalid geometries
-will fail.  Reasons for invalidity include self-intersection of linestrings,
-and self-intersections for polygons. <p>
-
 </ul>
 
 <h3>Layer Creation Options</h3>
 
 <ul>
     <li>
-        <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the 
+        <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
         desired name to be destroyed before creating the requested layer.
     </li>
     <li>
-        <b>LAUNDER</b>: This may be "YES" to force new fields created on this 
-        layer to have their field names "laundered" into a form more 
-        compatible with MySQL.  This converts to lower case and converts 
-        some special characters like "-" and "#" to "_".  If "NO" exact names 
-        are preserved.  The default value is "YES".
+        <b>LAUNDER</b>: This may be "YES" to force new fields created on this
+        layer to have their field names "laundered" into a form more
+        compatible with MySQL. This converts to lower case and converts
+        some special characters like "-" and "#" to "_". If "NO" exact names
+        are preserved. The default value is "YES".
     </li>
     <li>
-        <b>PRECISION</b>: This may be "TRUE" to attempt to preserve field 
+        <b>PRECISION</b>: This may be "TRUE" to attempt to preserve field
         widths and precisions for the creation and reading of MySQL layers.
         The default value is "TRUE".
     </li>
     <li>
-        <b>GEOMETRY_NAME</b>: This option specifies the name of the 
-        geometry column.  The default value is "SHAPE".
+        <b>GEOMETRY_NAME</b>: This option specifies the name of the
+        geometry column. The default value is "SHAPE".
     </li>
     <li>
         <b>INGRES_FID</b>: This option specifies the name of the FID column.
@@ -140,11 +124,21 @@ and self-intersections for polygons. <p>
     </li>
     <li>
         <b>GEOMETRY_TYPE</b>: Specifies the object type for the geometry
-        column.  It may be one of POINT, LSEG, LINE, LONG LINE, POLYGON, or 
-        LONG POLYGON.  By default POINT, LONG LINE or LONG POLYGON are used
-        depending on the layer type. 
+        column. It may be one of POINT, LSEG, LINE, LONG LINE, POLYGON, or
+        LONG POLYGON. By default POINT, LONG LINE or LONG POLYGON are used
+        depending on the layer type.
     </li>
 </ul>
 
+<h2>Older Versions</h2>
+<p>The INGRES GDAL driver also includes support for old INGRES spatial types,
+  but these are not enabled by default. It enable these, the input <i>configure</i>
+  script needs to include pointers to libraries used by the older version:
+  <pre>INGRES_LIB="-L$II_SYSTEM/ingres/lib \
+         $II_SYSTEM/ingres/lib/iiclsadt.o \
+         $II_SYSTEM/ingres/lib/iiuseradt.o \
+         -liiapi.1 -lcompat.1 -lq.1 -lframe.1"
+</pre>
+</p>
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
index 2d552cb..bafcf3c 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringresdatasource.cpp 24341 2012-04-29 03:11:16Z warmerdam $
+ * $Id: ogringresdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresDataSource class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogringresdatasource.cpp 24341 2012-04-29 03:11:16Z warmerdam $");
+CPL_CVSID("$Id: ogringresdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $");
 
 /************************************************************************/
 /*                            SetConnParam()                            */
@@ -736,9 +736,9 @@ OGRLayer * OGRIngresDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic implementation for OGRSQL dialect.                  */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
index ee423ac..8af14e8 100644
--- a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringrestablelayer.cpp 23803 2012-01-26 07:49:25Z warmerdam $
+ * $Id: ogringrestablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresTableLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_ingres.h"
 
-CPL_CVSID("$Id: ogringrestablelayer.cpp 23803 2012-01-26 07:49:25Z warmerdam $");
+CPL_CVSID("$Id: ogringrestablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $");
 
 /************************************************************************/
 /*                         OGRIngresTableLayer()                         */
@@ -416,6 +416,9 @@ char *OGRIngresTableLayer::BuildFields()
 OGRErr OGRIngresTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     osQuery = "";
 
     if( pszQuery != NULL )
diff --git a/ogr/ogrsf_frmts/kml/kml.cpp b/ogr/ogrsf_frmts/kml/kml.cpp
index e2f021d..a7fe63e 100644
--- a/ogr/ogrsf_frmts/kml/kml.cpp
+++ b/ogr/ogrsf_frmts/kml/kml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.cpp 25440 2013-01-03 20:20:32Z rouault $
+ * $Id: kml.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/kml.h b/ogr/ogrsf_frmts/kml/kml.h
index 4e874d1..ef0ef00 100644
--- a/ogr/ogrsf_frmts/kml/kml.h
+++ b/ogr/ogrsf_frmts/kml/kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.h 23978 2012-02-14 20:42:34Z rouault $
+ * $Id: kml.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.cpp b/ogr/ogrsf_frmts/kml/kmlnode.cpp
index 1b58b36..166098e 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.cpp 25309 2012-12-15 12:14:44Z rouault $
+ * $Id: kmlnode.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.h b/ogr/ogrsf_frmts/kml/kmlnode.h
index 6fca599..d9d6419 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.h
+++ b/ogr/ogrsf_frmts/kml/kmlnode.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.h 24175 2012-03-30 20:41:29Z rouault $
+ * $Id: kmlnode.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/kmlutility.h b/ogr/ogrsf_frmts/kml/kmlutility.h
index 81eff79..cdc9768 100644
--- a/ogr/ogrsf_frmts/kml/kmlutility.h
+++ b/ogr/ogrsf_frmts/kml/kmlutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlutility.h 16908 2009-05-02 14:53:26Z rouault $
+ * $Id: kmlutility.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  KML driver utilities
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/kmlvector.cpp b/ogr/ogrsf_frmts/kml/kmlvector.cpp
index fe6b13f..92f5b44 100644
--- a/ogr/ogrsf_frmts/kml/kmlvector.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlvector.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlvector.cpp 23978 2012-02-14 20:42:34Z rouault $
+ * $Id: kmlvector.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Specialization of the kml class, only for vectors in kml files.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Jens Oberender
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
index c67098e..fb25c61 100644
--- a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2kmlgeometry.cpp 21019 2010-10-30 11:37:54Z rouault $
+ * $Id: ogr2kmlgeometry.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGR -> KML geometries writer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Christopher Condit
+ * Copyright (c) 2007-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/kml/ogr_kml.h b/ogr/ogrsf_frmts/kml/ogr_kml.h
index eee8ada..d0a1c26 100644
--- a/ogr/ogrsf_frmts/kml/ogr_kml.h
+++ b/ogr/ogrsf_frmts/kml/ogr_kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_kml.h 25979 2013-05-03 19:10:30Z rouault $
+ * $Id: ogr_kml.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Declarations for OGR wrapper classes for KML, and OGR->KML
@@ -10,6 +10,7 @@
  ******************************************************************************
  * Copyright (c) 2006, Christopher Condit
  *               2007, Jens Oberender
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -59,7 +60,6 @@ public:
     // OGRLayer Interface
     //
     OGRFeatureDefn* GetLayerDefn();
-    OGRSpatialReference* GetSpatialRef();
     OGRErr CreateFeature( OGRFeature* poFeature );
     OGRErr CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE );
     void ResetReading();
@@ -74,9 +74,11 @@ public:
 
     void SetClosedForWriting() { bClosedForWriting = TRUE; }
     
-    void WriteSchema();
+    CPLString WriteSchema();
 
 private:
+    friend class OGRKMLDataSource;
+
     OGRKMLDataSource* poDS_;
     OGRSpatialReference* poSRS_;
 	OGRCoordinateTransformation *poCT_;
@@ -88,6 +90,7 @@ private:
     int bWriter_;
     int nLayerNumber_;
     int nWroteFeatureCount_;
+    int bSchemaWritten_;
     int bClosedForWriting;
     char* pszName_;
 
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
index df9a357..f0cc250 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmldatasource.cpp 25979 2013-05-03 19:10:30Z rouault $
+ * $Id: ogrkmldatasource.cpp 27051 2014-03-19 12:27:33Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDataSource class.
@@ -9,6 +9,7 @@
  ******************************************************************************
  * Copyright (c) 2006, Christopher Condit
  *               2007, Jens Oberender
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -66,10 +67,24 @@ OGRKMLDataSource::~OGRKMLDataSource()
 {
     if( fpOutput_ != NULL )
     {
-        VSIFPrintfL( fpOutput_, "%s", "</Folder>\n");
-        for( int i = 0; i < nLayers_; i++ )
+        if( nLayers_ > 0 )
         {
-            papoLayers_[i]->WriteSchema();
+            if( nLayers_ == 1 && papoLayers_[0]->nWroteFeatureCount_ == 0 )
+            {
+                VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", papoLayers_[0]->GetName() );
+            }
+
+            VSIFPrintfL( fpOutput_, "%s", "</Folder>\n");
+
+            for( int i = 0; i < nLayers_; i++ )
+            {
+                if( !(papoLayers_[i]->bSchemaWritten_) && papoLayers_[i]->nWroteFeatureCount_ != 0 )
+                {
+                    CPLString osRet = papoLayers_[i]->WriteSchema();
+                    if( osRet.size() )
+                        VSIFPrintfL( fpOutput_, "%s", osRet.c_str() );
+                }
+            }
         }
         VSIFPrintfL( fpOutput_, "%s", "</Document></kml>\n" );
 
@@ -298,7 +313,7 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 
     if (strcmp(pszName, "/dev/stdout") == 0)
         pszName = "/vsistdout/";
-
+    
     pszName_ = CPLStrdup( pszName );
 
     fpOutput_ = VSIFOpenL( pszName, "wb" );
@@ -314,7 +329,7 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /* -------------------------------------------------------------------- */
     VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );	
     
-    VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>" );
+    VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document id=\"root_doc\">\n" );
 
     return TRUE;
 }
@@ -349,6 +364,11 @@ OGRKMLDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     if (GetLayerCount() > 0)
     {
+        if( nLayers_ == 1 && papoLayers_[0]->nWroteFeatureCount_ == 0 )
+        {
+            VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", papoLayers_[0]->GetName() );
+        }
+
         VSIFPrintfL( fpOutput_, "</Folder>\n");
         ((OGRKMLLayer*)GetLayer(GetLayerCount()-1))->SetClosedForWriting();
     }
@@ -365,7 +385,11 @@ OGRKMLDataSource::CreateLayer( const char * pszLayerName,
                   "Layer name '%s' adjusted to '%s' for XML validity.",
                   pszLayerName, pszCleanLayerName );
     }
-    VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
+    
+    if (GetLayerCount() > 0)
+    {
+        VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
+    }
     
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
diff --git a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
index 9ff0833..348152b 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmllayer.cpp 26347 2013-08-20 18:22:32Z rouault $
+ * $Id: ogrkmllayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLLayer class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Christopher Condit
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -93,6 +94,8 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
     poFeatureDefn_ = new OGRFeatureDefn( pszName );
     poFeatureDefn_->Reference();
     poFeatureDefn_->SetGeomType( eReqType );
+    if( poFeatureDefn_->GetGeomFieldCount() != 0 )
+        poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRS_);
 
     OGRFieldDefn oFieldName( "Name", OFTString );
     poFeatureDefn_->AddFieldDefn( &oFieldName );
@@ -103,6 +106,7 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
     bWriter_ = bWriterIn;
     nWroteFeatureCount_ = 0;
     bClosedForWriting = (bWriterIn == FALSE);
+    bSchemaWritten_ = FALSE;
 
     pszName_ = CPLStrdup(pszName);
 }
@@ -236,12 +240,11 @@ int OGRKMLLayer::GetFeatureCount( int bForce )
 /*                           WriteSchema()                              */
 /************************************************************************/
 
-void OGRKMLLayer::WriteSchema()
+CPLString OGRKMLLayer::WriteSchema()
 {
-    if (0 != nWroteFeatureCount_)
+    CPLString osRet;
+    if ( !(bSchemaWritten_) )
     {
-        VSILFILE *fp = poDS_->GetOutputFP();
-        int nFieldsWritten = 0;
         OGRFeatureDefn *featureDefinition = GetLayerDefn();
         for (int j=0; j < featureDefinition->GetFieldCount(); j++)
         {
@@ -255,11 +258,10 @@ void OGRKMLLayer::WriteSchema()
                 EQUAL(fieldDefinition->GetNameRef(), poDS_->GetDescriptionField()) )
                 continue;
 
-            if( nFieldsWritten == 0 )
+            if( osRet.size() == 0 )
             {
-                VSIFPrintfL( fp, "<Schema name=\"%s\" id=\"%s\">\n", pszName_, pszName_ );
+                osRet += CPLSPrintf( "<Schema name=\"%s\" id=\"%s\">\n", pszName_, pszName_ );
             }
-            nFieldsWritten ++;
 
             const char* pszKMLType = NULL;
             const char* pszKMLEltName = NULL;
@@ -290,10 +292,6 @@ void OGRKMLLayer::WriteSchema()
                 pszKMLType = "string";
                 pszKMLEltName = "SimpleArrayField";
                 break;
-              case OFTBinary:
-                pszKMLType = "bool";
-                pszKMLEltName = "SimpleField";
-                break;
                 //TODO: KML doesn't handle these data types yet...
               case OFTDate:                
               case OFTTime:                
@@ -307,12 +305,13 @@ void OGRKMLLayer::WriteSchema()
                 pszKMLEltName = "SimpleField";
                 break;
             }
-            VSIFPrintfL( fp, "\t<%s name=\"%s\" type=\"%s\"></%s>\n", 
+            osRet += CPLSPrintf( "\t<%s name=\"%s\" type=\"%s\"></%s>\n", 
                         pszKMLEltName, fieldDefinition->GetNameRef() ,pszKMLType, pszKMLEltName );
         }
-        if( nFieldsWritten > 0 )
-            VSIFPrintfL( fp, "</Schema>\n" );
+        if( osRet.size() )
+            osRet += CPLSPrintf( "%s", "</Schema>\n" );
     }
+    return osRet;
 }
 
 /************************************************************************/
@@ -337,6 +336,16 @@ OGRErr OGRKMLLayer::CreateFeature( OGRFeature* poFeature )
     VSILFILE *fp = poDS_->GetOutputFP();
     CPLAssert( NULL != fp );
 
+    if( poDS_->GetLayerCount() == 1 && nWroteFeatureCount_ == 0 )
+    {
+        CPLString osRet = WriteSchema();
+        if( osRet.size() )
+            VSIFPrintfL( fp, "%s", osRet.c_str() );
+        bSchemaWritten_ = TRUE;
+
+        VSIFPrintfL( fp, "<Folder><name>%s</name>\n", pszName_);
+    }
+
     VSIFPrintfL( fp, "  <Placemark>\n" );
 
     if( poFeature->GetFID() == OGRNullFID )
@@ -602,15 +611,6 @@ OGRErr OGRKMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRKMLLayer::GetSpatialRef()
-{
-    return poSRS_;
-}
-
-/************************************************************************/
 /*                           SetLayerNumber()                           */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/libkml/drv_libkml.html b/ogr/ogrsf_frmts/libkml/drv_libkml.html
index b1c2e2a..f472b57 100644
--- a/ogr/ogrsf_frmts/libkml/drv_libkml.html
+++ b/ogr/ogrsf_frmts/libkml/drv_libkml.html
@@ -12,7 +12,7 @@
     
   <p>
     The LIBKML driver is a client of
-    <a href="http://code.google.com/p/libkml/">Libkml</a> from Google, a
+    <a href="https://github.com/google/libkml">Libkml</a> from Google, a
     reference implementation of
     <a href="http://www.opengeospatial.org/standards/kml/">KML</a>
     reading and writing, in the form of a cross platform C++ library.
@@ -30,7 +30,7 @@
   <p>
     Libkml from Google provides reading services for any valid KML file.
     However, please be advised that some KML facilities do not map into the
-    Simple Features specification ogr uses as its internal structure.
+    Simple Features specification OGR uses as its internal structure.
     Therefore, a best effort will be made by the driver to understand the
     content of a KML file read by libkml into ogr, but your mileage may vary.
     Please try a few KML files as samples to get a sense of what is understood.
@@ -49,8 +49,8 @@
   
   <p>
     By default on directory and kmz datasources, an index file of all the
-    layers will be read from or written to doc.kml. It conatains a
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#networklink">
+    layers will be read from or written to doc.kml. It contains a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#networklink">
     <NetworkLink></a> to each layer file in the datasource. This feature
     can be turned off by setting the enviroment variable LIBKML_USE_DOC.KML to
     "no"
@@ -60,33 +60,133 @@
   
   <p>
     Datasource style tables are written to the
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#document">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a> in a .kml, style/style.kml
     in a kmz file, or style.kml in a directory, as one or more
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#style">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#style">
     <Style></a> elements. Not all of
     <a href="http://www.gdal.org/ogr/ogr_feature_style.html">OGR Feature Style</a>
     can translate into KML.
   </p>
   
+  <h3>Datasource creation options</h3>
+
+  <p>
+    Starting with OGR 1.11, the following datasource creation options can be used to generate a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#atomauthor">
+    <atom:Author></a> element at the top Document level.
+    <ul>
+        <li><b>AUTHOR_NAME</b></li>
+        <li><b>AUTHOR_URI</b></li>
+        <li><b>AUTHOR_EMAIL</b></li>
+    </ul>
+  </p>
+  <p>
+    The href of an <a href="https://developers.google.com/kml/documentation/kmlreference#atomlink">
+    <atom:link></a> element at the top Document level can be specified with the <b>LINK</b> creation option.
+  </p>
+  <p>
+    The <a href="https://developers.google.com/kml/documentation/kmlreference#phonenumber">
+    <phoneNumber></a> element at the top Document level can be specified with the <b>PHONENUMBER</b> creation option.
+    The value must follow the syntax of <a href="http://tools.ietf.org/html/rfc3966">IETF RFC 3966</a>.
+  </p>
+
+
+    <h4>Container properties</h4>
+
+    <p>The following dataset creation options can be used to set container options :
+    <ul>
+        <li><b>NAME</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#name"><name></a> element</li>
+        <li><b>VISIBILITY</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#visibility"><visibility></a> element</li>
+        <li><b>OPEN</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#open"><open></a> element</li>
+        <li><b>SNIPPET</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#snippet"><snippet></a> element</li>
+        <li><b>DESCRIPTION</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#description"><description></a> element</li>
+    </ul>
+    </p>
+
+    <h4>List style</h4>
+
+    <p>
+    The following dataset creation options can be used to control how the main folder
+    (folder of layers) appear in the Places panel of the Earth browser, trough a
+     <a href="https://developers.google.com/kml/documentation/kmlreference#liststyle"><ListStyle></a> element:
+    <ul>
+        <li><b>LISTSTYLE_TYPE</b>: can be one of "check", "radioFolder", "checkOffOnly" or "checkHideChildren". Sets the
+            <a href="https://developers.google.com/kml/documentation/kmlreference#listItemType"><listItemType></a> element.</li>
+        <li><b>LISTSTYLE_ICON_HREF</b>: URL of the icon to display for the main folder. Sets the href element of the
+            <a href="https://developers.google.com/kml/documentation/kmlreference#itemicon"><ItemIcon></a> element.</li>
+    </ul>
+    </p>
+
+    <h4>Balloon style</h4>
+
+    <p>If a style <i>foo</i> is defined, it is possible to add a
+        <a href="https://developers.google.com/kml/documentation/kmlreference#balloonstyle"><BalloonStyle></a> element to it,
+       by specifying the <b>foo_BALLOONSTYLE_BGCOLOR</b> and/or <b>foo_BALLOONSTYLE_TEXT</b> elements.
+    </p>
+
+    <h4>NetworkLinkControl</h4>
+
+    <p>
+    A  <a href="https://developers.google.com/kml/documentation/kmlreference#networklinkcontrol">
+    <NetworkLinkControl></a> element can be defined if at least one of the following dataset creation option
+    is specified:
+    <ul>
+        <li><b>NLC_MINREFRESHPERIOD</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#minrefreshperiod">
+    <minRefreshPeriod></a> element</li>
+        <li><b>NLC_MAXSESSIONLENGTH</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#maxsessionlength">
+    <maxSessionLength></a> element</li>
+        <li><b>NLC_COOKIE</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#cookie">
+    <cookie></a> element</li>
+        <li><b>NLC_MESSAGE</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#message">
+    <message></a> element</li>
+        <li><b>NLC_LINKNAME</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#linkname">
+    <linkName></a> element</li>
+        <li><b>NLC_LINKDESCRIPTION</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#linkdescription">
+    <linkDescription></a> element</li>
+        <li><b>NLC_LINKSNIPPET</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#linksnippet">
+    <linkSnippet></a> element</li>
+        <li><b>NLC_EXPIRES</b> : to set the <a href="https://developers.google.com/kml/documentation/kmlreference#expires">
+    <expires></a> element</li>
+    </ul>
+    </p>
+
+    <h4>Update documents</h4>
+
+    <p>
+    When defining the dataset creation option <b>UPDATE_TARGETHREF</b>, a NetworkLinkControl KML
+    file with an <a href="https://developers.google.com/kml/documentation/kmlreference#update">
+    <Update></a> element will be generated.
+    See the <a href="https://developers.google.com/kml/documentation/updates">tutorial about update</a>.<p>
+
+    The CreateFeature() operation on a layer will be translated as a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#create"><Create></a> element.<p>
+
+    The SetFeature() operation on a layer will be translated as a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#change"><Change></a> element.<p>
+
+    The DeleteFeature() operation on a layer will be translated as a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#delete"><Delete></a> element.<p>
+    </p>
+ 
   <h2>Layer</h2>
   
   <p>
     <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_layer">
     Layers</a> are mapped to kml files as a
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#document">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a>
     or
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#folder">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
     <Folder></a>, and in kmz files or directorys as a seperate kml file.
   </p>
   
   <h3>Style</h3>
   <p>
     Layer style tables can not be read from or written to a kml layer that is a 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#folder">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
     <Folder></a>, otherwise they are in the
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#document">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a> that is the layer.
   </p>
   
@@ -94,23 +194,145 @@
   
   <p>
     Read and write of
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#schema">
-    <Schema></a> is supported for .kml files , .kmz files, and
-    directorys.
+    <a href="https://developers.google.com/kml/documentation/kmlreference#schema">
+    <Schema></a> is supported for .kml files, .kmz files, and
+    directories.
   </p>
- 
+
+  <h3>Layer creation options</h3>
+
+  <p>
+    Starting with OGR 1.11, the following layer creation options can be used to generate a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#lookat">
+    <LookAt></a> element at the layer level.
+    <ul>
+        <li><b>LOOKAT_LONGITUDE</b> (required)</li>
+        <li><b>LOOKAT_LATITUDE</b> (required)</li>
+        <li><b>LOOKAT_RANGE</b> (required)</li>
+        <li><b>LOOKAT_HEADING</b></li>
+        <li><b>LOOKAT_TILT</b></li>
+        <li><b>LOOKAT_ALTITUDE</b></li>
+        <li><b>LOOKAT_ALTITUDEMODE</b></li>
+    </ul>
+  </p>
+
+  <p>Alternatively, a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
+    <Camera></a> element can be generated.
+    <ul>
+        <li><b>CAMERA_LONGITUDE</b> (required)</li>
+        <li><b>CAMERA_LATITUDE</b> (required)</li>
+        <li><b>CAMERA_ALTITUDE</b> (required)</li>
+        <li><b>CAMERA_ALTITUDEMODE</b> (required)</li>
+        <li><b>CAMERA_HEADING</b></li>
+        <li><b>CAMERA_TILT</b></li>
+        <li><b>CAMERA_ROLL</b></li>
+    </ul>
+  </p>
+
+  <p>A <a href="https://developers.google.com/kml/documentation/kmlreference#region">
+    <Region></a> element can be generated to control when objects of the layer are visible or not.
+    If REGION_XMIN, REGION_YMIN, REGION_XMAX and REGION_YMAX, the region coordinates are determined from
+    the spatial extent of the features being written in the layer.
+    <ul>
+        <li><b>ADD_REGION=YES/NO</b> : defaults to NO</li>
+        <li><b>REGION_XMIN</b> (optional) : defines the west coordinate of the region.</li>
+        <li><b>REGION_YMIN</b> (optional) : defines the south coordinate of the region.</li>
+        <li><b>REGION_XMAX</b> (optional) : defines the east coordinate of the region.</li>
+        <li><b>REGION_YMAX</b> (optional) : defines the north coordinate of the region.</li>
+        <li><b>REGION_MIN_LOD_PIXELS</b> (optional) : minimum size in pixels of the region so that it is displayed. Defaults to 256.</li>
+        <li><b>REGION_MAX_LOD_PIXELS</b> (optional) : maximum size in pixels of the region so that it is displayed. Defaults to -1 (infinite).</li>
+        <li><b>REGION_MIN_FADE_EXTENT</b> (optional) : distance over which the geometry fades, from fully opaque to fully transparent. Defaults to 0.</li>
+        <li><b>REGION_MAX_FADE_EXTENT</b> (optional) : distance over which the geometry fades, from fully transparent to fully opaque. Defaults to 0.</li>
+    </ul>
+  </p>
+
+  <p>A <a href="https://developers.google.com/kml/documentation/kmlreference#screenoverlay">
+    <ScreenOverlay></a> element can be added to display a logo, a legend, etc...
+    <ul>
+        <li><b>SO_HREF</b> (required) : URL of the image to display.</li>
+        <li><b>SO_NAME</b> (optional)</li>
+        <li><b>SO_DESCRIPTION</b> (optional)</li>
+        <li><b>SO_OVERLAY_X</b> (optional)</li>
+        <li><b>SO_OVERLAY_Y</b> (optional)</li>
+        <li><b>SO_OVERLAY_XUNITS</b> (optional)</li>
+        <li><b>SO_OVERLAY_YUNITS</b> (optional)</li>
+        <li><b>SO_SCREEN_X</b> (optional). Defaults to 0.05</li>
+        <li><b>SO_SCREEN_Y</b> (optional). Defaults to 0.05</li>
+        <li><b>SO_SCREEN_XUNITS</b> (optional). Defaults to Fraction</li>
+        <li><b>SO_SCREEN_YUNITS</b> (optional). Defaults to Fraction</li>
+        <li><b>SO_SIZE_X</b> (optional)</li>
+        <li><b>SO_SIZE_Y</b> (optional)</li>
+        <li><b>SO_SIZE_XUNITS</b> (optional)</li>
+        <li><b>SO_SIZE_YUNITS</b> (optional)</li>
+    </ul>
+  </p>
+
+    <p>By default, layers are written as
+    <a href="https://developers.google.com/kml/documentation/kmlreference#document">
+    <Document></a> elements. By settings the <b>FOLDER</b> layer creation option
+    to No, it is also possible to write them as <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
+    <Folder></a> elements (only in .kml files). 
+    </p>
+
+    <p>The following layer creation options can be used to set container options :
+    <ul>
+        <li><b>NAME</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#name"><name></a> element</li>
+        <li><b>VISIBILITY</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#visibility"><visibility></a> element</li>
+        <li><b>OPEN</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#open"><open></a> element</li>
+        <li><b>SNIPPET</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#snippet"><snippet></a> element</li>
+        <li><b>DESCRIPTION</b>: <a href="https://developers.google.com/kml/documentation/kmlreference#description"><description></a> element</li>
+    </ul>
+    </p>
+
+    <p>
+    The following layer creation options can be used to control how the folder
+    of a layer appear in the Places panel of the Earth browser, trough a
+     <a href="https://developers.google.com/kml/documentation/kmlreference#liststyle"><ListStyle></a> element:
+    <ul>
+        <li><b>LISTSTYLE_TYPE</b>: can be one of "check", "radioFolder", "checkOffOnly" or "checkHideChildren". Sets the
+            <a href="https://developers.google.com/kml/documentation/kmlreference#listItemType"><listItemType></a> element.</li>
+        <li><b>LISTSTYLE_ICON_HREF</b>: URL of the icon to display for the layer folder. Sets the href element of the
+            <a href="https://developers.google.com/kml/documentation/kmlreference#itemicon"><ItemIcon></a> element.</li>
+    </ul>
+    </p>
+
   <h2>Feature</h2>
   
   <p>
     An OGR <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_feature">feature</a>
-    translates to kml as a
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#placemark">
+    generally translates to kml as a
+    <a href="https://developers.google.com/kml/documentation/kmlreference#placemark">
     <Placemark></a>, and vice-versa.
   </p>
 
+  <p>If the model field is defined, a <a href="https://developers.google.com/kml/documentation/kmlreference#model">
+    <Model></a> object within the Placemark will be generated.
+  </p>
+
+  <p>If the networklink field is defined, a <a href="https://developers.google.com/kml/documentation/kmlreference#networklink">
+    <NetworkLink></a> will be generated. Other networklink_ fields are optional.
+  </p>
+
+  <p>If the photooverlay field is defined, a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+    <PhotoOverlay></a> will be generated (provided that the camera_longitude,
+    camera_latitude, camera_altitude, camera_altitudemode, head and/or tilt and/or roll,
+    leftfov, rightfov, bottomfov, topfov, near fields are also set. The shape field is optional.
+  </p>
+  <p>In case the PhotoOverlay is a big image, it is highly recommanded to tile it and
+     generate overview levels, as explained in the <a href="https://developers.google.com/kml/documentation/photos">
+     PhotoOverlay tutorial</a>. In which case, the URL should contain the "$[level]", "$[x]" and "$[y]"
+     sub-strings in the photooverlay field, and the imagepyramid_tilesize,
+     imagepyramid_maxwidth, imagepyramid_maxheight and imagepyramid_gridorigin fields should be set.
+  </p>
+
+  <p>Placemark, Model, NetworkLink and PhotoOverlay objects can have an associated camera
+     if the camera_longitude, camera_latitude, camera_altitude, camera_altitudemode, head and/or tilt and/or roll
+     fields are defined.
+  </p>
+
   <p>
     Starting with OGR 1.10, KML 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#groundoverlay">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#groundoverlay">
     <GroundOverlay></a> elements are supported for reading (unless the 
     LIBKML_READ_GROUND_OVERLAY configuration option is set to FALSE). For such elements, there
     are icon and drawOrder fields.
@@ -120,11 +342,11 @@
   
   <p>
     Style Strings at the feature level are Mapped to KML as either a 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#style">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#style">
     <Style></a> or
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#styleurl">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#styleurl">
     <StyleUrl></a> in each
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#placemark">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#placemark">
     <Placemark></a>.
   </p>
   <p>
@@ -148,23 +370,35 @@
      wish to use the highlighted styles set the enviroment variable
      LIBKML_STYLEMAP_KEY to "highlight"
   </p>
-    
+
+  <p>
+     When writing a kml, if there exist 2 styles of the form "astylename_normal"
+     and "astylename_highlight" (where astylename is any string), then a StyleMap
+     object will be creating from both styles and called "astylename".
+  </p>
+
   <h2>Fields</h2>
   
-  <p> OGR fields (feature atributes) are mapped to kml with
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#schema">
-    <Schema&gt</a>; and
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#simpledata">
+  <p> OGR fields (feature attributes) are mapped to kml with
+    <a href="https://developers.google.com/kml/documentation/kmlreference#schema">
+    <Schema></a>; and
+    <a href="https://developers.google.com/kml/documentation/kmlreference#simpledata">
     <SimpleData></a>, except for some special fields as noted below.
   </p>
-  
+
+  <p>Note: it is also possible to export fields as
+    <a href="https://developers.google.com/kml/documentation/kmlreference#data">
+    <Data></a> elements if the LIBKML_USE_SCHEMADATA configuration option is
+    set to NO.
+  </p>
+
   <p>
     A rich set of environment variables are available to define how fields in
     input and output, map to a KML 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#placemark">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#placemark">
     <Placemark></a>. For example, if you want a field called 'Cities'
     to map to the
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#name">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#name">
     <name></a>; tag in KML, you can set an
     environment variable. 
   </p>
@@ -173,72 +407,315 @@
     <dt>Name</dt>
     <dd>
       This String field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#name">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#name">
       <name></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_NAME_FIELD .
     </dd>
     <dt>description</dt>
     <dd>This String field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#description">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#description">
       <description></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_DESCRIPTION_FIELD .
     </dd>
     <dt>timestamp</dt>
     <dd>This string or datetime or date and/or time field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#timestamp">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#timestamp">
       <timestamp></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_TIMESTAMP_FIELD .
     </dd>
     <dt>begin</dt>
     <dd>This string or datetime or date and/or time field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#begin">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#begin">
       <begin></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_BEGIN_FIELD .
     </dd>
     <dt>end</dt>
     <dd>This string or datetime or date and/or time field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#end">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#end">
       <end></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_END_FIELD .
     </dd>
     <dt>altitudeMode</dt>
     <dd>This string field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#altitudemode">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#altitudemode">
       <altitudeMode></a> or
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#gxaltitudemode">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#gxaltitudemode">
       <gx:altitudeMode></a>. The name of the ogr field can be changed
       with the enviroment variable LIBKML_ALTITUDEMODE_FIELD .
     </dd>
     <dt>tessellate</dt>
     <dd>This integer field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#tessellate">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#tessellate">
       <tessellate></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_TESSELLATE_FIELD .
     </dd>
     <dt>extrude</dt>
     <dd>This integer field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#extrude">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#extrude">
       <extrude></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_EXTRUDE_FIELD .
     </dd>
     <dt>visibility</dt>
     <dd>This integer field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#visibility">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#visibility">
       <visibility></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_VISIBILITY_FIELD .
     </dd>
     <dt>icon</dt>
     <dd>This string field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#icon">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#icon">
       <icon></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_ICON_FIELD .
     </dd>
     <dt>drawOrder</dt>
     <dd>This integer field maps to the kml tag 
-      <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#draworder">
+      <a href="https://developers.google.com/kml/documentation/kmlreference#draworder">
       <drawOrder></a>. The name of the ogr field can be changed with the
       enviroment variable LIBKML_DRAWORDER_FIELD .
     </dd>
+    <dt>snippet</dt>
+    <dd>This integer field maps to the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#snippet">
+      <snippet></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_SNIPPET_FIELD .
+    </dd>
+    <dt>heading</dt>
+    <dd>This real field maps to the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#heading">
+      <heading></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_HEADING_FIELD. When reading, this field is present only if a Placemark has
+      a Camera with a heading element.
+    </dd>
+    <dt>tilt</dt>
+    <dd>This real field maps to the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#tilt">
+      <tilt></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_TILT_FIELD. When reading, this field is present only if a Placemark has
+      a Camera with a tilt element.
+    </dd>
+    <dt>roll</dt>
+    <dd>This real field maps to the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#roll">
+      <roll></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_ROLL_FIELD. When reading, this field is present only if a Placemark has
+      a Camera with a roll element.
+    </dd>
+
+    <dt>model</dt>
+    <dd>This string field can be used to define the URL of a 3D
+      <a href="https://developers.google.com/kml/documentation/kmlreference#model">
+      <model></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_MODEL_FIELD.
+    </dd>
+    <dt>scale_x</dt>
+    <dd>This real field maps to the x element of the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
+      <scale></a> for a 3D model. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_SCALE_X_FIELD.
+    </dd>
+    <dt>scale_y</dt>
+    <dd>This real field maps to the y element of the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
+      <scale></a>for a 3D model. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_SCALE_Y_FIELD.
+    </dd>
+    <dt>scale_z</dt>
+    <dd>This real field maps to the z element of the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
+      <scale></a>for a 3D model. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_SCALE_Z_FIELD.
+    </dd>
+
+    <dt>networklink</dt>
+    <dd>This string field maps to the href element of the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#href">
+      <href></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_FIELD.
+    </dd>
+
+    <dt>networklink_refreshvisibility</dt>
+    <dd>This integer field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#refreshvisibility">
+      <refreshVisibility></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD.
+    </dd>
+
+    <dt>networklink_flytoview</dt>
+    <dd>This integer field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#flytoview">
+      <flyToView></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_FLYTOVIEW_FIELD.
+    </dd>
+
+    <dt>networklink_refreshmode</dt>
+    <dd>This string field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#refreshmode">
+      <refreshMode></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_REFRESHMODE_FIELD.
+    </dd>
+
+    <dt>networklink_refreshinterval</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#refreshinterval">
+      <refreshInterval></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD.
+    </dd>
+
+    <dt>networklink_viewrefreshmode</dt>
+    <dd>This string field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#viewrefreshmode">
+      <viewRefreshMode></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD.
+    </dd>
+
+    <dt>networklink_viewrefreshtime</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#viewrefreshtime">
+      <viewRefreshTime></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD.
+    </dd>
+
+    <dt>networklink_viewboundscale</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#viewboundscale">
+      <viewBoundScale></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD.
+    </dd>
+
+    <dt>networklink_viewformat</dt>
+    <dd>This string field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#viewformat">
+      <viewFormat></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_VIEWFORMAT_FIELD.
+    </dd>
+
+    <dt>networklink_httpquery</dt>
+    <dd>This string field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#httpquery">
+      <httpQuery></a> of a NetworkLink. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NETWORKLINK_HTTPQUERY_FIELD.
+    </dd>
+
+    <dt>camera_longitude</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#longitude">
+      <longitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
+      <Camera></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_CACameraMERA_LONGITUDE_FIELD.
+    </dd>
+
+    <dt>camera_latitude</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#latitude">
+      <latitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
+      <Camera></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_CAMERA_LATITUDE_FIELD.
+    </dd>
+
+    <dt>camera_altitude</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#altitude">
+      <altitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
+      <Camera></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_CAMERA_ALTITUDE_FIELD.
+    </dd>
+
+    <dt>camera_altitudemode</dt>
+    <dd>This real field maps to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#altitudemode">
+      <altitudeMode></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
+      <Camera></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_CAMERA_ALTITUDEMODE_FIELD.
+    </dd>
+
+    <dt>photooverlay</dt>
+    <dd>This string field maps to the href element of the kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#href">
+      <href></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_PHOTOOVERLAY_FIELD.
+    </dd>
+
+    <dt>leftfov</dt>
+    <dd>This real field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#leftfov">
+      <LeftFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_LEFTFOV_FIELD.
+    </dd>
+
+    <dt>rightfov</dt>
+    <dd>This real field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#rightfov">
+      <RightFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_RightFOV_FIELD.
+    </dd>
+
+    <dt>bottomfov</dt>
+    <dd>This real field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#bottomfov">
+      <BottomFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_BOTTOMTFOV_FIELD.
+    </dd>
+
+    <dt>topfov</dt>
+    <dd>This real field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#topfov">
+      <TopFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_TOPFOV_FIELD.
+    </dd>
+
+    <dt>near</dt>
+    <dd>This real field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#leftfov">
+      <Near></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_NEAR_FIELD.
+    </dd>
+
+    <dt>shape</dt>
+    <dd>This string field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#shape">
+      <shape></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
+      <PhotoOverlay></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_SHAPE_FIELD.
+    </dd>
+
+    <dt>imagepyramid_tilesize</dt>
+    <dd>This integer field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#tilesize">
+      <tileSize></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
+      <ImagePyramid></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_IMAGEPYRAMID_TILESIZE.
+    </dd>
+
+    <dt>imagepyramid_maxwidth</dt>
+    <dd>This integer field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#maxwidth">
+      <maxWidth></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
+      <ImagePyramid></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_IMAGEPYRAMID_MAXWIDTH.
+    </dd>
+
+    <dt>imagepyramid_maxheight</dt>
+    <dd>This integer field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#maxheight">
+      <maxHeight></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
+      <ImagePyramid></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_IMAGEPYRAMID_MAXHEIGHT.
+    </dd>
+
+    <dt>imagepyramid_gridorigin</dt>
+    <dd>This string field maps to to kml tag 
+      <a href="https://developers.google.com/kml/documentation/kmlreference#maxheight">
+      <gridOrigin></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
+      <ImagePyramid></a>. The name of the ogr field can be changed with the
+      enviroment variable LIBKML_IMAGEPYRAMID_GRIDORIGIN.
+    </dd>
+
     <dt>OGR_STYLE</dt>
     <dd>This string field maps to a features style string, OGR reads this field
       if there is no style string set on the feature.
@@ -252,22 +729,23 @@
     <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_geometry">
     Geometry</a> to KML Geometry is pretty strait forwards with only a couple
     of exceptions. Point to 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#point">
-    <Point></a>, LineString to
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#linestring">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#point">
+    <Point></a> (unless heading and/or tilt and/or roll field names are found, in
+    which case a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">Camera</a> object will be generated), LineString to
+    <a href="https://developers.google.com/kml/documentation/kmlreference#linestring">
     <LineString></a>, LinearRing to
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#linearring">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#linearring">
     <LinearRing></a>, and Polygon to
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#polygon">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#polygon">
     <Polygon></a>. In OGR a polygon contains an array of LinearRings,
     the first one being the outer ring. KML has the tags
-     <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#outerboundaryis">
+     <a href="https://developers.google.com/kml/documentation/kmlreference#outerboundaryis">
     <outerBoundaryIs></a> and  
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#innerboundaryis">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#innerboundaryis">
     <innerBoundaryIs></a> to differentiate between the two. OGR has
     several Multi types of geometry : GeometryCollection, MultiPolygon,
     MultiPoint, and MultiLineString. When possible, OGR will try to map 
-    <a href="http://code.google.com/apis/kml/documentation/kmlreference.html#multigeometry">
+    <a href="https://developers.google.com/kml/documentation/kmlreference#multigeometry">
     <MultiGeometry></a> to the more precise OGR geometry type (MultiPoint, MultiLineString or MultiPolygon),
     and default to GeometryCollection in case of mixed content.
   </p>
@@ -304,6 +782,7 @@ Writing to /dev/stdout or /vsistdout/ is also supported.<p>
  
 #!/bin/bash
 # Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/libkml/ogr_libkml.h b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
index 413f5ab..92fa90d 100644
--- a/ogr/ogrsf_frmts/libkml/ogr_libkml.h
+++ b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,6 +42,7 @@ using kmldom::DocumentPtr;
 using kmldom::ContainerPtr;
 using kmldom::ElementPtr;
 using kmldom::SchemaPtr;
+using kmldom::UpdatePtr;
 using kmlengine::KmzFile;
 using kmlengine::KmzFilePtr;
 
@@ -49,6 +51,8 @@ using kmlengine::KmlFilePtr;
 
 class OGRLIBKMLDataSource;
 
+CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName);
+
 /******************************************************************************
   layer class
 ******************************************************************************/
@@ -65,7 +69,7 @@ class OGRLIBKMLLayer:public OGRLayer
 
     ContainerPtr              m_poKmlLayer;
     ElementPtr                m_poKmlLayerRoot;
-    //KmlFile                  *m_poKmlKmlfile;
+    UpdatePtr                 m_poKmlUpdate;
 
     DocumentPtr               m_poKmlDocument;
     //OGRStyleTable            *m_poStyleTable;
@@ -75,6 +79,23 @@ class OGRLIBKMLLayer:public OGRLayer
     OGRSpatialReference      *m_poOgrSRS;
 
     int                       m_bReadGroundOverlay;
+    int                       m_bUseSimpleField;
+
+    int                       m_bWriteRegion;
+    int                       m_bRegionBoundsAuto;
+    double                    m_dfRegionMinLodPixels;
+    double                    m_dfRegionMaxLodPixels;
+    double                    m_dfRegionMinFadeExtent;
+    double                    m_dfRegionMaxFadeExtent;
+    double                    m_dfRegionMinX;
+    double                    m_dfRegionMinY;
+    double                    m_dfRegionMaxX;
+    double                    m_dfRegionMaxY;
+
+    CPLString                 osListStyleType;
+    CPLString                 osListStyleIconHref;
+    
+    int                       m_bUpdateIsFolder;
 
   public:
     OGRLIBKMLLayer            ( const char *pszLayerName,
@@ -83,6 +104,7 @@ class OGRLIBKMLLayer:public OGRLayer
                                 OGRLIBKMLDataSource *poOgrDS,
                                 ElementPtr poKmlRoot,
                                 ContainerPtr poKmlContainer,
+                                UpdatePtr poKmlUpdate,
                                 const char *pszFileName,
                                 int bNew,
                                 int bUpdate);
@@ -94,8 +116,8 @@ class OGRLIBKMLLayer:public OGRLayer
     OGRFeatureDefn           *GetLayerDefn (  ) { return m_poOgrFeatureDefn; };
     //OGRErr                    SetAttributeFilter (const char * );
     OGRErr                    CreateFeature ( OGRFeature * poOgrFeat );
-
-    OGRSpatialReference      *GetSpatialRef (  ) { return m_poOgrSRS; };
+    OGRErr                    SetFeature ( OGRFeature * poOgrFeat );
+    OGRErr                    DeleteFeature( long nFID );
 
     int                       GetFeatureCount ( int bForce = TRUE );
     OGRErr                    GetExtent ( OGREnvelope * psExtent,
@@ -119,9 +141,51 @@ class OGRLIBKMLLayer:public OGRLayer
     SchemaPtr                 GetKmlSchema () { return m_poKmlSchema; };
     const char               *GetFileName (  ) { return m_pszFileName; };
 
+    void                      SetLookAt(const char* pszLookatLongitude,
+                                        const char* pszLookatLatitude,
+                                        const char* pszLookatAltitude,
+                                        const char* pszLookatHeading,
+                                        const char* pszLookatTilt,
+                                        const char* pszLookatRange,
+                                        const char* pszLookatAltitudeMode);
+    void                      SetCamera(const char* pszCameraLongitude,
+                                        const char* pszCameraLatitude,
+                                        const char* pszCameraAltitude,
+                                        const char* pszCameraHeading,
+                                        const char* pszCameraTilt,
+                                        const char* pszCameraRoll,
+                                        const char* pszCameraAltitudeMode);
 
     static CPLString          LaunderFieldNames(CPLString osName);
-
+    
+    void                      SetWriteRegion(double dfMinLodPixels,
+                                             double dfMaxLodPixels,
+                                             double dfMinFadeExtent,
+                                             double dfMaxFadeExtent);
+    void                      SetRegionBounds(double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY);
+
+    void                      SetScreenOverlay(const char* pszSOHref,
+                                               const char* pszSOName,
+                                               const char* pszSODescription,
+                                               const char* pszSOOverlayX,
+                                               const char* pszSOOverlayY,
+                                               const char* pszSOOverlayXUnits,
+                                               const char* pszSOOverlayYUnits,
+                                               const char* pszSOScreenX,
+                                               const char* pszSOScreenY,
+                                               const char* pszSOScreenXUnits,
+                                               const char* pszSOScreenYUnits,
+                                               const char* pszSOSizeX,
+                                               const char* pszSOSizeY,
+                                               const char* pszSOSizeXUnits,
+                                               const char* pszSOSizeYUnits);
+
+    void                      SetListStyle(const char* pszListStyleType,
+                                           const char* pszListStyleIconHref);
+
+    void                      Finalize(DocumentPtr poKmlDocument);
+    void                      SetUpdateIsFolder(int bUpdateIsFolder) { m_bUpdateIsFolder = bUpdateIsFolder; }
 };
 
 /******************************************************************************
@@ -141,11 +205,15 @@ class OGRLIBKMLDataSource:public OGRDataSource
 
     int                       bUpdate;
     int                       bUpdated;
+    CPLString                 osUpdateTargetHref;
+
+    char                    **m_papszOptions;
 
     /***** for kml files *****/
     int                       m_isKml;
     KmlPtr                    m_poKmlDSKml;
     ContainerPtr              m_poKmlDSContainer;
+    UpdatePtr                 m_poKmlUpdate;
 
     /***** for kmz files *****/
 
@@ -165,7 +233,11 @@ class OGRLIBKMLDataSource:public OGRDataSource
     
     /***** style table pointer *****/
     
-    //OGRStyleTable            *m_poStyleTable;
+    void                      SetCommonOptions(ContainerPtr poKmlContainer,
+                                               char** papszOptions);
+
+    void                      ParseDocumentOptions(KmlPtr poKml,
+                                                   DocumentPtr poKmlDocument);
 
   public:
     OGRLIBKMLDataSource       ( KmlFactory *poKmlFactory );
@@ -242,11 +314,11 @@ class OGRLIBKMLDataSource:public OGRDataSource
 
     /***** methods to create layers on various datasource types *****/
     
-    OGRLayer                 *CreateLayerKml ( const char *pszLayerName,
+    OGRLIBKMLLayer           *CreateLayerKml ( const char *pszLayerName,
                                                OGRSpatialReference * poOgrSRS,
                                                OGRwkbGeometryType eGType,
                                                char **papszOptions );
-    OGRLayer                 *CreateLayerKmz ( const char *pszLayerName,
+    OGRLIBKMLLayer           *CreateLayerKmz ( const char *pszLayerName,
                                                OGRSpatialReference * poOgrSRS,
                                                OGRwkbGeometryType eGType,
                                                char **papszOptions );
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
index 3f5493f..641b8a5 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,11 +43,16 @@ using kmldom::NetworkLinkPtr;
 using kmldom::StyleSelectorPtr;
 using kmldom::LinkPtr;
 using kmldom::SchemaPtr;
+using kmldom::NetworkLinkControlPtr;
+using kmldom::LinkSnippetPtr;
 using kmlbase::File;
 using kmldom::KmlPtr;
+using kmldom::SnippetPtr;
+using kmlbase::Attributes;
 
 #include "ogr_libkml.h"
 #include "ogrlibkmlstyle.h"
+#include "ogr_p.h"
 
 /***** this was shamelessly swiped from the kml driver *****/
 
@@ -76,12 +82,14 @@ OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
     papoLayers = NULL;
     nLayers = 0;
     nAlloced = 0;
+    m_papszOptions = NULL;
 
     bUpdated = FALSE;
 
     m_isKml = FALSE;
     m_poKmlDSKml = NULL;
     m_poKmlDSContainer = NULL;
+    m_poKmlUpdate = NULL;
 
     m_isKmz = FALSE;
     m_poKmlDocKml = NULL;
@@ -95,6 +103,103 @@ OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
 
 }
 
+/************************************************************************/
+/*                       OGRLIBKMLPreProcessInput()                     */
+/************************************************************************/
+
+/* Substitute <snippet> by deprecated <Snippet> since libkml currently */
+/* only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet */
+static void OGRLIBKMLPreProcessInput(std::string& oKml)
+{
+    size_t nPos = 0;
+    while( TRUE )
+    {
+        nPos = oKml.find("<snippet>", nPos);
+        if( nPos == std::string::npos )
+        {
+            break;
+        }
+        oKml[nPos+1] = 'S';
+        nPos = oKml.find("</snippet>", nPos);
+        if( nPos == std::string::npos )
+        {
+            break;
+        }
+        oKml[nPos+2] = 'S';
+    }
+}
+
+/************************************************************************/
+/*                       OGRLIBKMLRemoveSpaces()                        */
+/************************************************************************/
+
+static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle)
+{
+    size_t nPos = 0;
+    while( TRUE )
+    {
+        nPos = oKml.find("<" + osNeedle, nPos);
+        if( nPos == std::string::npos )
+        {
+            break;
+        }
+        size_t nPosOri = nPos;
+        nPos = oKml.find(">", nPos);
+        if( nPos == std::string::npos || oKml[nPos+1] != '\n' )
+        {
+            break;
+        }
+        oKml = oKml.substr(0, nPos) + ">" + oKml.substr(nPos + strlen(">\n"));
+        CPLString osSpaces;
+        for(size_t nPosTmp = nPosOri - 1; oKml[nPosTmp] == ' '; nPosTmp -- )
+        {
+            osSpaces += ' ';
+        }
+        nPos = oKml.find(osSpaces + "</" + osNeedle +">", nPos);
+        if( nPos != std::string::npos )
+            oKml = oKml.substr(0, nPos) + "</" + osNeedle +">" + oKml.substr(nPos + osSpaces.size() + strlen("</>") + osNeedle.size());
+        else
+            break;
+    }
+}
+
+/************************************************************************/
+/*                      OGRLIBKMLPostProcessOutput()                    */
+/************************************************************************/
+
+/* Substitute deprecated <Snippet> by <snippet> since libkml currently */
+/* only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet */
+static void OGRLIBKMLPostProcessOutput(std::string& oKml)
+{
+    size_t nPos = 0;
+
+    /* Manually add <?xml> node since libkml does not produce it currently */
+    /* and this is usefull in some circumstances (#5407) */
+    if( !(oKml[0] == '<' && oKml[1] == '?') )
+        oKml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + oKml;
+
+    while( TRUE )
+    {
+        nPos = oKml.find("<Snippet>", nPos);
+        if( nPos == std::string::npos )
+        {
+            break;
+        }
+        oKml[nPos+1] = 's';
+        nPos = oKml.find("</Snippet>", nPos);
+        if( nPos == std::string::npos )
+        {
+            break;
+        }
+        oKml[nPos+2] = 's';
+    }
+
+    /* Fix indentation problems */
+    OGRLIBKMLRemoveSpaces(oKml, "snippet");
+    OGRLIBKMLRemoveSpaces(oKml, "linkSnippet");
+    OGRLIBKMLRemoveSpaces(oKml, "SimpleData");
+}
+
 /******************************************************************************
  method to write a single file ds .kml at ds destroy
 
@@ -114,6 +219,8 @@ void OGRLIBKMLDataSource::WriteKml (
         DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
         int iLayer;
 
+        ParseDocumentOptions(m_poKmlDSKml, poKmlDocument);
+
         for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
             SchemaPtr poKmlSchema;
             SchemaPtr poKmlSchema2;
@@ -132,16 +239,18 @@ void OGRLIBKMLDataSource::WriteKml (
                 if ( poKmlSchema2 != poKmlSchema )
                     poKmlDocument->add_schema ( poKmlSchema );
             }
+
+            papoLayers[iLayer]->Finalize(poKmlDocument);
         }
     }
+    else
+    {
+        ParseDocumentOptions(m_poKmlDSKml, NULL);
+    }
 
     std::string oKmlOut;
-    if ( m_poKmlDSKml ) {
-        oKmlOut = kmldom::SerializePretty ( m_poKmlDSKml );
-    }
-    else if ( m_poKmlDSContainer ) {
-        oKmlOut = kmldom::SerializePretty ( m_poKmlDSContainer );
-    }
+    oKmlOut = kmldom::SerializePretty ( m_poKmlDSKml );
+    OGRLIBKMLPostProcessOutput(oKmlOut);
 
     if (oKmlOut.size() != 0)
     {
@@ -160,6 +269,37 @@ void OGRLIBKMLDataSource::WriteKml (
     return;
 }
 
+/******************************************************************************/
+/*                      OGRLIBKMLCreateOGCKml22()                             */
+/******************************************************************************/
+
+static KmlPtr OGRLIBKMLCreateOGCKml22(KmlFactory* poFactory,
+                                      char** papszOptions = NULL)
+{
+    const char* pszAuthorName = CSLFetchNameValue(papszOptions, "AUTHOR_NAME");
+    const char* pszAuthorURI = CSLFetchNameValue(papszOptions, "AUTHOR_URI");
+    const char* pszAuthorEmail = CSLFetchNameValue(papszOptions, "AUTHOR_EMAIL");
+    const char* pszLink = CSLFetchNameValue(papszOptions, "LINK");
+    int bWithAtom = pszAuthorName != NULL ||
+                    pszAuthorURI != NULL ||
+                    pszAuthorEmail != NULL ||
+                    pszLink != NULL;
+
+    KmlPtr kml = poFactory->CreateKml (  );
+    if( bWithAtom )
+    {
+        const char* kAttrs[] = { "xmlns", "http://www.opengis.net/kml/2.2",
+                                 "xmlns:atom", "http://www.w3.org/2005/Atom", NULL };
+        kml->AddUnknownAttributes(Attributes::Create(kAttrs));
+    }
+    else
+    {
+        const char* kAttrs[] = { "xmlns", "http://www.opengis.net/kml/2.2", NULL };
+        kml->AddUnknownAttributes(Attributes::Create(kAttrs));
+    }
+    return kml;
+}
+
 /******************************************************************************
  method to write a ds .kmz at ds destroy
 
@@ -186,19 +326,24 @@ void OGRLIBKMLDataSource::WriteKmz (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
+    if ( CSLTestBoolean ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
 
         /***** if we dont have the doc.kml root *****/
         /***** make it and add the container    *****/
         
         if ( !m_poKmlDocKmlRoot ) {
-            m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
+            m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
 
-            AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
+            if( m_poKmlDocKml != NULL )
+            {
+                AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
+            }
+
+            ParseDocumentOptions(AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
         }
-        
-        std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
 
+        std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
         if ( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
@@ -212,12 +357,12 @@ void OGRLIBKMLDataSource::WriteKmz (
 
     int iLayer;
 
-    for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
-        ContainerPtr poKlmContainer = papoLayers[iLayer]->GetKmlLayer (  );
+    for ( iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ ) {
+        ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
 
-        if ( poKlmContainer->IsA ( kmldom::Type_Document ) ) {
+        if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
 
-            DocumentPtr poKmlDocument = AsDocument ( poKlmContainer );
+            DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
             SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
 
             if ( !poKmlDocument->get_schema_array_size (  ) &&
@@ -225,6 +370,8 @@ void OGRLIBKMLDataSource::WriteKmz (
                  poKmlSchema->get_simplefield_array_size (  ) ) {
                 poKmlDocument->add_schema ( poKmlSchema );
             }
+
+            papoLayers[iLayer]->Finalize(poKmlDocument);
         }
 
         /***** if we dont have the layers root *****/
@@ -234,14 +381,24 @@ void OGRLIBKMLDataSource::WriteKmz (
 
         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
 
-            poKmlKml = m_poKmlFactory->CreateKml (  );
+            poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
-            poKmlKml->set_feature ( poKlmContainer );
+            poKmlKml->set_feature ( poKmlContainer );
         }
 
         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if ( CPLCreateFileInZip( hZIP, papoLayers[iLayer]->GetFileName (  ), NULL ) != CE_None ||
+        if( iLayer == 0 && CSLTestBoolean ( pszUseDocKml ) )
+            CPLCreateFileInZip( hZIP, "layers/", NULL );
+        
+        const char* pszLayerFileName;
+        if( CSLTestBoolean ( pszUseDocKml ) )
+            pszLayerFileName = CPLSPrintf("layers/%s", papoLayers[iLayer]->GetFileName (  ));
+        else
+            pszLayerFileName = papoLayers[iLayer]->GetFileName (  );
+
+        if ( CPLCreateFileInZip( hZIP, pszLayerFileName , NULL ) != CE_None ||
              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
             CPLError ( CE_Failure, CPLE_FileIO,
                        "ERROR adding %s to %s", papoLayers[iLayer]->GetFileName (  ), pszName );
@@ -253,12 +410,14 @@ void OGRLIBKMLDataSource::WriteKmz (
 
     if ( m_poKmlStyleKml ) {
 
-        KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
+        KmlPtr poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
         poKmlKml->set_feature ( m_poKmlStyleKml );
         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if ( CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
+        if ( CPLCreateFileInZip( hZIP, "style/", NULL ) != CE_None ||
+             CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
             CPLError ( CE_Failure, CPLE_FileIO,
                        "ERROR adding %s to %s", "style/style.kml", pszName );
@@ -288,18 +447,21 @@ void OGRLIBKMLDataSource::WriteDir (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
+    if ( CSLTestBoolean ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
 
         /***** if we dont have the doc.kml root *****/
         /***** make it and add the container    *****/
         
         if ( !m_poKmlDocKmlRoot ) {
-            m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
+            m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
+            if( m_poKmlDocKml != NULL )
+                AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
 
-            AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
+            ParseDocumentOptions(AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
         }
         
         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
         const char *pszOutfile = CPLFormFilename ( pszName, "doc.kml", NULL );
 
@@ -319,7 +481,7 @@ void OGRLIBKMLDataSource::WriteDir (
 
     int iLayer;
 
-    for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
+    for ( iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ ) {
         ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
 
         if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
@@ -331,7 +493,9 @@ void OGRLIBKMLDataSource::WriteDir (
                  poKmlSchema &&
                  poKmlSchema->get_simplefield_array_size (  ) ) {
                 poKmlDocument->add_schema ( poKmlSchema );
-            };
+            }
+
+            papoLayers[iLayer]->Finalize(poKmlDocument);
         }
 
         /***** if we dont have the layers root *****/
@@ -341,12 +505,13 @@ void OGRLIBKMLDataSource::WriteDir (
 
         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
 
-            poKmlKml = m_poKmlFactory->CreateKml (  );
+            poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
             poKmlKml->set_feature ( poKmlContainer );
         }
 
         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
         const char *pszOutfile = CPLFormFilename ( pszName,
                                                    papoLayers[iLayer]->
@@ -370,10 +535,11 @@ void OGRLIBKMLDataSource::WriteDir (
 
     if ( m_poKmlStyleKml ) {
 
-        KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
+        KmlPtr poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
         poKmlKml->set_feature ( m_poKmlStyleKml );
         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        OGRLIBKMLPostProcessOutput(oKmlOut);
 
         const char *pszOutfile = CPLFormFilename ( pszName,
                                                    "style.kml",
@@ -456,6 +622,8 @@ OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
         delete papoLayers[i];
 
     CPLFree ( papoLayers );
+    
+    CSLDestroy( m_papszOptions );
 
     //delete m_poStyleTable;
 
@@ -612,6 +780,7 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
                                                       poOgrDS,
                                                       poKmlRoot,
                                                       poKmlContainer,
+                                                      m_poKmlUpdate,
                                                       pszFileName,
                                                       bNew,
                                                       bUpdate );
@@ -821,6 +990,7 @@ int OGRLIBKMLDataSource::OpenKml (
             return FALSE;
         }
     }
+    OGRLIBKMLPreProcessInput(oKmlKml);
     VSIFCloseL(fp);
 
     CPLLocaleC  oLocaleForcer;
@@ -1330,6 +1500,231 @@ int OGRLIBKMLDataSource::Open (
     }
 }
 
+/************************************************************************/
+/*                         IsValidPhoneNumber()                         */
+/************************************************************************/
+
+/* Very approximative validation of http://tools.ietf.org/html/rfc3966#page-6 */
+static int IsValidPhoneNumber(const char* pszPhoneNumber)
+{
+    if( strncmp(pszPhoneNumber, "tel:", strlen("tel:")) == 0 )
+        pszPhoneNumber += strlen("tel:");
+    char ch;
+    int bDigitFound = FALSE;
+    if( *pszPhoneNumber == '+' )
+        pszPhoneNumber ++;
+    while( (ch = *pszPhoneNumber) != '\0' )
+    {
+        if( ch >= '0' && ch <= '9' )
+            bDigitFound = TRUE;
+        else if( ch == ';' )
+            break;
+        else if( !(ch == '-' || ch == '.' || ch == '(' || ch == ')') )
+            return FALSE;
+        pszPhoneNumber ++;
+    }
+    return bDigitFound;
+}
+
+/************************************************************************/
+/*                           SetCommonOptions()                         */
+/************************************************************************/
+
+void OGRLIBKMLDataSource::SetCommonOptions(ContainerPtr poKmlContainer,
+                                           char** papszOptions)
+{
+    const char* pszName = CSLFetchNameValue(papszOptions, "NAME");
+    if( pszName != NULL )
+        poKmlContainer->set_name(pszName);
+
+    const char* pszVisibilility = CSLFetchNameValue(papszOptions, "VISIBILITY");
+    if( pszVisibilility != NULL )
+        poKmlContainer->set_visibility(CSLTestBoolean(pszVisibilility));
+
+    const char* pszOpen = CSLFetchNameValue(papszOptions, "OPEN");
+    if( pszOpen != NULL )
+        poKmlContainer->set_open(CSLTestBoolean(pszOpen));
+
+    const char* pszSnippet = CSLFetchNameValue(papszOptions, "SNIPPET");
+    if( pszSnippet != NULL )
+    {
+        SnippetPtr poKmlSnippet = m_poKmlFactory->CreateSnippet();
+        poKmlSnippet->set_text(pszSnippet);
+        poKmlContainer->set_snippet(poKmlSnippet);
+    }
+
+    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+    if( pszDescription != NULL )
+        poKmlContainer->set_description(pszDescription);
+}
+
+/************************************************************************/
+/*                        ParseDocumentOptions()                        */
+/************************************************************************/
+
+void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
+                                               DocumentPtr poKmlDocument)
+{
+    if( poKmlDocument != NULL )
+    {
+        poKmlDocument->set_id("root_doc");
+
+        const char* pszAuthorName = CSLFetchNameValue(m_papszOptions, "AUTHOR_NAME");
+        const char* pszAuthorURI = CSLFetchNameValue(m_papszOptions, "AUTHOR_URI");
+        const char* pszAuthorEmail = CSLFetchNameValue(m_papszOptions, "AUTHOR_EMAIL");
+        const char* pszLink = CSLFetchNameValue(m_papszOptions, "LINK");
+
+        if( pszAuthorName != NULL || pszAuthorURI != NULL || pszAuthorEmail != NULL )
+        {
+            kmldom::AtomAuthorPtr author = m_poKmlFactory->CreateAtomAuthor();
+            if( pszAuthorName != NULL )
+                author->set_name(pszAuthorName);
+            if( pszAuthorURI != NULL )
+            {
+                /* Ad-hoc validation. The ABNF is horribly complicated : http://tools.ietf.org/search/rfc3987#page-7 */
+                if( strncmp(pszAuthorURI, "http://", strlen("http://")) == 0 ||
+                    strncmp(pszAuthorURI, "https://", strlen("https://")) == 0 )
+                {
+                    author->set_uri(pszAuthorURI);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined, "Invalid IRI for AUTHOR_URI");
+                }
+            }
+            if( pszAuthorEmail != NULL )
+            {
+                const char* pszArobase = strchr(pszAuthorEmail, '@');
+                if( pszArobase != NULL && strchr(pszArobase + 1, '.') != NULL )
+                {
+                    author->set_email(pszAuthorEmail);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined, "Invalid email for AUTHOR_EMAIL");
+                }
+            }
+            poKmlDocument->set_atomauthor(author);
+        }
+
+        if( pszLink != NULL )
+        {
+            kmldom::AtomLinkPtr link = m_poKmlFactory->CreateAtomLink();
+            link->set_href(pszLink);
+            link->set_rel("related");
+            poKmlDocument->set_atomlink(link);
+        }
+
+        const char* pszPhoneNumber = CSLFetchNameValue(m_papszOptions, "PHONENUMBER");
+        if( pszPhoneNumber != NULL )
+        {
+            if( IsValidPhoneNumber(pszPhoneNumber) )
+            {
+                if( strncmp(pszPhoneNumber, "tel:", strlen("tel:")) != 0 )
+                    poKmlDocument->set_phonenumber(CPLSPrintf("tel:%s", pszPhoneNumber));
+                else
+                    poKmlDocument->set_phonenumber(pszPhoneNumber);
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "Invalid phone number");
+            }
+        }
+
+        SetCommonOptions(poKmlDocument, m_papszOptions);
+
+        CPLString osListStyleType = CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_TYPE", "");
+        CPLString osListStyleIconHref = CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_ICON_HREF", "");
+        createkmlliststyle (m_poKmlFactory,
+                            "root_doc",
+                            poKmlDocument,
+                            poKmlDocument,
+                            osListStyleType,
+                            osListStyleIconHref);
+    }
+
+    if( poKml != NULL )
+    {
+        if( m_poKmlUpdate != NULL )
+        {
+            NetworkLinkControlPtr nlc = m_poKmlFactory->CreateNetworkLinkControl();
+            poKml->set_networklinkcontrol ( nlc );
+            if( m_poKmlUpdate->get_updateoperation_array_size() != 0 )
+            {
+                nlc->set_update(m_poKmlUpdate);
+            }
+        }
+
+        const char* pszNLCMinRefreshPeriod = CSLFetchNameValue(m_papszOptions, "NLC_MINREFRESHPERIOD");
+        const char* pszNLCMaxSessionLength = CSLFetchNameValue(m_papszOptions, "NLC_MAXSESSIONLENGTH");
+        const char* pszNLCCookie = CSLFetchNameValue(m_papszOptions, "NLC_COOKIE");
+        const char* pszNLCMessage = CSLFetchNameValue(m_papszOptions, "NLC_MESSAGE");
+        const char* pszNLCLinkName = CSLFetchNameValue(m_papszOptions, "NLC_LINKNAME");
+        const char* pszNLCLinkDescription = CSLFetchNameValue(m_papszOptions, "NLC_LINKDESCRIPTION");
+        const char* pszNLCLinkSnippet = CSLFetchNameValue(m_papszOptions, "NLC_LINKSNIPPET");
+        const char* pszNLCExpires = CSLFetchNameValue(m_papszOptions, "NLC_EXPIRES");
+        if( pszNLCMinRefreshPeriod != NULL || pszNLCMaxSessionLength != NULL ||
+            pszNLCCookie != NULL || pszNLCMessage != NULL || pszNLCLinkName != NULL ||
+            pszNLCLinkDescription != NULL || pszNLCLinkSnippet != NULL ||
+            pszNLCExpires != NULL )
+        {
+            NetworkLinkControlPtr nlc;
+            if( poKml->has_networklinkcontrol() )
+                nlc = poKml->get_networklinkcontrol();
+            else
+            {
+                nlc = m_poKmlFactory->CreateNetworkLinkControl();
+                poKml->set_networklinkcontrol ( nlc );
+            }
+            if( pszNLCMinRefreshPeriod != NULL )
+            {
+                double dfVal = CPLAtof(pszNLCMinRefreshPeriod);
+                if( dfVal >= 0 )
+                    nlc->set_minrefreshperiod(dfVal);
+            }
+            if( pszNLCMaxSessionLength != NULL )
+            {
+                double dfVal = CPLAtof(pszNLCMaxSessionLength);
+                nlc->set_maxsessionlength(dfVal);
+            }
+            if( pszNLCCookie != NULL )
+            {
+                nlc->set_cookie(pszNLCCookie);
+            }
+            if( pszNLCMessage != NULL )
+            {
+                nlc->set_message(pszNLCMessage);
+            }
+            if( pszNLCLinkName != NULL )
+            {
+                nlc->set_linkname(pszNLCLinkName);
+            }
+            if( pszNLCLinkDescription != NULL )
+            {
+                nlc->set_linkdescription(pszNLCLinkDescription);
+            }
+            if( pszNLCLinkSnippet != NULL )
+            {
+                LinkSnippetPtr linksnippet = m_poKmlFactory->CreateLinkSnippet();
+                linksnippet->set_text(pszNLCLinkSnippet);
+                nlc->set_linksnippet(linksnippet);
+            }
+            if( pszNLCExpires != NULL )
+            {
+                int year, month, day, hour, minute, tz;
+                float fSecond;
+                if( OGRParseXMLDateTime( pszNLCExpires, &year, &month, &day,
+                                        &hour, &minute, &fSecond, &tz) )
+                {
+                    char* pszXMLDate = OGRGetXMLDateTime(year, month, day, hour, minute, (int)fSecond, tz);
+                    nlc->set_expires(pszXMLDate);
+                    CPLFree(pszXMLDate);
+                }
+            }
+        }
+    }
+}
+
 /******************************************************************************
  method to create a single file .kml ds
  
@@ -1344,12 +1739,14 @@ int OGRLIBKMLDataSource::CreateKml (
     const char *pszFilename,
     char **papszOptions )
 {
+    m_poKmlDSKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, papszOptions);
+    if( osUpdateTargetHref.size() == 0 )
+    {
+        DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
+        m_poKmlDSKml->set_feature ( poKmlDocument );
+        m_poKmlDSContainer = poKmlDocument;
+    }
 
-    m_poKmlDSKml = m_poKmlFactory->CreateKml (  );
-    DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
-
-    m_poKmlDSKml->set_feature ( poKmlDocument );
-    m_poKmlDSContainer = poKmlDocument;
     m_isKml = TRUE;
     bUpdated = TRUE;
 
@@ -1373,11 +1770,14 @@ int OGRLIBKMLDataSource::CreateKmz (
 
 
     /***** create the doc.kml  *****/
+    if( osUpdateTargetHref.size() == 0 )
+    {
+        const char *pszUseDocKml =
+            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( !strcmp ( namefield, "yes" ) ) {
-        m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        if ( CSLTestBoolean( pszUseDocKml ) ) {
+            m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        }
     }
 
     pszStylePath = CPLStrdup((char *) "style/style.kml");
@@ -1412,11 +1812,14 @@ int OGRLIBKMLDataSource::CreateDir (
     m_isDir = TRUE;
     bUpdated = TRUE;
 
+    if( osUpdateTargetHref.size() == 0 )
+    {
+        const char *pszUseDocKml =
+            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( !strcmp ( namefield, "yes" ) ) {
-        m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        if ( CSLTestBoolean( pszUseDocKml ) ) {
+            m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        }
     }
 
     pszStylePath = CPLStrdup((char *) "style.kml");
@@ -1451,6 +1854,15 @@ int OGRLIBKMLDataSource::Create (
     pszName = CPLStrdup ( pszFilename );
     bUpdate = TRUE;
 
+    osUpdateTargetHref = CSLFetchNameValueDef(papszOptions, "UPDATE_TARGETHREF", "");
+    if( osUpdateTargetHref.size() )
+    {
+        m_poKmlUpdate = m_poKmlFactory->CreateUpdate();
+        m_poKmlUpdate->set_targethref(osUpdateTargetHref.c_str());
+    }
+
+    m_papszOptions = CSLDuplicate(papszOptions);
+
     /***** kml *****/
 
     if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
@@ -1564,7 +1976,7 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
+    if ( CSLTestBoolean ( pszUseDocKml ) && m_poKmlDocKml ) {
 
         /***** loop over the features *****/
 
@@ -1679,7 +2091,7 @@ OGRErr OGRLIBKMLDataSource::DeleteLayer (
 
 ******************************************************************************/
 
-OGRLayer *OGRLIBKMLDataSource::CreateLayerKml (
+OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml (
     const char *pszLayerName,
     OGRSpatialReference * poOgrSRS,
     OGRwkbGeometryType eGType,
@@ -1687,21 +2099,33 @@ OGRLayer *OGRLIBKMLDataSource::CreateLayerKml (
 {
 
     OGRLIBKMLLayer *poOgrLayer = NULL;
+    ContainerPtr poKmlLayerContainer = NULL;
+    
+    if( m_poKmlDSContainer != NULL )
+    {
+        if( CSLFetchBoolean( papszOptions, "FOLDER", FALSE ) )
+            poKmlLayerContainer = m_poKmlFactory->CreateFolder (  );
+        else
+            poKmlLayerContainer = m_poKmlFactory->CreateDocument (  );
+        poKmlLayerContainer->set_id(OGRLIBKMLGetSanitizedNCName(pszLayerName).c_str());
 
-    DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
-
-    m_poKmlDSContainer->add_feature ( poKmlDocument );
+        m_poKmlDSContainer->add_feature ( poKmlLayerContainer );
+    }
 
     /***** create the layer *****/
 
     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
-                            NULL, poKmlDocument, "", TRUE, bUpdate, 1 );
+                            NULL, poKmlLayerContainer, "", TRUE, bUpdate, 1 );
 
     /***** add the layer name as a <Name> *****/
+    if( poKmlLayerContainer != NULL )
+        poKmlLayerContainer->set_name ( pszLayerName );
+    else if(  CSLFetchBoolean( papszOptions, "FOLDER", FALSE ) )
+    {
+        poOgrLayer->SetUpdateIsFolder(TRUE);
+    }
 
-    poKmlDocument->set_name ( pszLayerName );
-
-    return ( OGRLayer * ) poOgrLayer;
+    return poOgrLayer;
 }
 
 /******************************************************************************
@@ -1716,40 +2140,46 @@ OGRLayer *OGRLIBKMLDataSource::CreateLayerKml (
 
 ******************************************************************************/
 
-OGRLayer *OGRLIBKMLDataSource::CreateLayerKmz (
+OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKmz (
     const char *pszLayerName,
     OGRSpatialReference * poOgrSRS,
     OGRwkbGeometryType eGType,
     char **papszOptions )
 {
+    OGRLIBKMLLayer *poOgrLayer = NULL;
+    DocumentPtr poKmlDocument = NULL;
+    
+    if( m_poKmlUpdate == NULL )
+    {
+        /***** add a network link to doc.kml *****/
 
-    /***** add a network link to doc.kml *****/
-
-    const char *pszUseDocKml =
-        CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
+        const char *pszUseDocKml =
+            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-        DocumentPtr poKmlDocument = AsDocument ( m_poKmlDocKml );
+        if ( CSLTestBoolean ( pszUseDocKml ) && m_poKmlDocKml ) {
 
-        NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
-        LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
+            DocumentPtr poKmlDocument = AsDocument ( m_poKmlDocKml );
 
-        std::string oHref;
-        oHref.append ( pszLayerName );
-        oHref.append ( ".kml" );
-        poKmlLink->set_href ( oHref );
+            NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
+            LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
 
-        poKmlNetLink->set_link ( poKmlLink );
-        poKmlDocument->add_feature ( poKmlNetLink );
+            std::string oHref;
+            if( IsKmz() )
+                oHref.append ( "layers/" );
+            oHref.append ( pszLayerName );
+            oHref.append ( ".kml" );
+            poKmlLink->set_href ( oHref );
 
-    }
+            poKmlNetLink->set_link ( poKmlLink );
+            poKmlDocument->add_feature ( poKmlNetLink );
 
-    /***** create the layer *****/
+        }
 
-    OGRLIBKMLLayer *poOgrLayer = NULL;
+        /***** create the layer *****/
 
-    DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
+        poKmlDocument = m_poKmlFactory->CreateDocument (  );
+        poKmlDocument->set_id(OGRLIBKMLGetSanitizedNCName(pszLayerName).c_str());
+    }
 
     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
                             NULL, poKmlDocument,
@@ -1757,10 +2187,12 @@ OGRLayer *OGRLIBKMLDataSource::CreateLayerKmz (
                             TRUE, bUpdate, 1 );
 
     /***** add the layer name as a <Name> *****/
+    if( m_poKmlUpdate == NULL )
+    {
+        poKmlDocument->set_name ( pszLayerName );
+    }
 
-    poKmlDocument->set_name ( pszLayerName );
-
-    return ( OGRLayer * ) poOgrLayer;
+    return poOgrLayer;
 }
 
 /******************************************************************************
@@ -1792,7 +2224,7 @@ OGRLayer *OGRLIBKMLDataSource::CreateLayer (
         return NULL;
     }
 
-    OGRLayer *poOgrLayer = NULL;
+    OGRLIBKMLLayer *poOgrLayer = NULL;
 
     /***** kml DS *****/
 
@@ -1808,8 +2240,122 @@ OGRLayer *OGRLIBKMLDataSource::CreateLayer (
 
     }
 
+    const char* pszLookatLongitude = CSLFetchNameValue(papszOptions, "LOOKAT_LONGITUDE");
+    const char* pszLookatLatitude = CSLFetchNameValue(papszOptions, "LOOKAT_LATITUDE");
+    const char* pszLookatAltitude = CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDE");
+    const char* pszLookatHeading = CSLFetchNameValue(papszOptions, "LOOKAT_HEADING");
+    const char* pszLookatTilt = CSLFetchNameValue(papszOptions, "LOOKAT_TILT");
+    const char* pszLookatRange = CSLFetchNameValue(papszOptions, "LOOKAT_RANGE");
+    const char* pszLookatAltitudeMode = CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDEMODE");
+    if( poOgrLayer != NULL && pszLookatLongitude != NULL && pszLookatLatitude != NULL &&
+        pszLookatRange != NULL )
+    {
+        poOgrLayer->SetLookAt(pszLookatLongitude,
+                              pszLookatLatitude,
+                              pszLookatAltitude,
+                              pszLookatHeading,
+                              pszLookatTilt,
+                              pszLookatRange,
+                              pszLookatAltitudeMode);
+    }
+    else
+    {
+        const char* pszCameraLongitude = CSLFetchNameValue(papszOptions, "CAMERA_LONGITUDE");
+        const char* pszCameraLatitude = CSLFetchNameValue(papszOptions, "CAMERA_LATITUDE");
+        const char* pszCameraAltitude = CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDE");
+        const char* pszCameraHeading = CSLFetchNameValue(papszOptions, "CAMERA_HEADING");
+        const char* pszCameraTilt = CSLFetchNameValue(papszOptions, "CAMERA_TILT");
+        const char* pszCameraRoll = CSLFetchNameValue(papszOptions, "CAMERA_ROLL");
+        const char* pszCameraAltitudeMode = CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDEMODE");
+        if( poOgrLayer != NULL && pszCameraLongitude != NULL && pszCameraLatitude != NULL &&
+            pszCameraAltitude != NULL && pszCameraAltitudeMode != NULL )
+        {
+            poOgrLayer->SetCamera(pszCameraLongitude,
+                                pszCameraLatitude,
+                                pszCameraAltitude,
+                                pszCameraHeading,
+                                pszCameraTilt,
+                                pszCameraRoll,
+                                pszCameraAltitudeMode);
+        }
+    }
+    
+    const char* pszRegionAdd = CSLFetchNameValueDef(papszOptions, "ADD_REGION", "FALSE");
+    const char* pszRegionXMin = CSLFetchNameValue(papszOptions, "REGION_XMIN");
+    const char* pszRegionYMin = CSLFetchNameValue(papszOptions, "REGION_YMIN");
+    const char* pszRegionXMax = CSLFetchNameValue(papszOptions, "REGION_XMAX");
+    const char* pszRegionYMax = CSLFetchNameValue(papszOptions, "REGION_YMAX");
+    const char* pszRegionMinLodPixels =
+        CSLFetchNameValueDef(papszOptions, "REGION_MIN_LOD_PIXELS", "256");
+    const char* pszRegionMaxLodPixels =
+        CSLFetchNameValueDef(papszOptions, "REGION_MAX_LOD_PIXELS", "-1");
+    const char* pszRegionMinFadeExtent =
+        CSLFetchNameValueDef(papszOptions, "REGION_MIN_FADE_EXTENT", "0");
+    const char* pszRegionMaxFadeExtent =
+        CSLFetchNameValueDef(papszOptions, "REGION_MAX_FADE_EXTENT", "0");
+    if( poOgrLayer != NULL && CSLTestBoolean(pszRegionAdd) )
+    {
+        poOgrLayer->SetWriteRegion(CPLAtof(pszRegionMinLodPixels),
+                                   CPLAtof(pszRegionMaxLodPixels),
+                                   CPLAtof(pszRegionMinFadeExtent),
+                                   CPLAtof(pszRegionMaxFadeExtent));
+        if( pszRegionXMin != NULL && pszRegionYMin != NULL &&
+            pszRegionXMax != NULL && pszRegionYMax != NULL )
+        {
+            double xmin = CPLAtof(pszRegionXMin);
+            double ymin = CPLAtof(pszRegionYMin);
+            double xmax = CPLAtof(pszRegionXMax);
+            double ymax = CPLAtof(pszRegionYMax);
+            if( xmin < xmax && ymin < ymax )
+                poOgrLayer->SetRegionBounds(xmin, ymin, xmax, ymax);
+        }
+    }
+    
+    const char* pszSOHref = CSLFetchNameValue(papszOptions, "SO_HREF");
+    const char* pszSOName = CSLFetchNameValue(papszOptions, "SO_NAME");
+    const char* pszSODescription = CSLFetchNameValue(papszOptions, "SO_DESCRIPTION");
+    const char* pszSOOverlayX = CSLFetchNameValue(papszOptions, "SO_OVERLAY_X");
+    const char* pszSOOverlayY = CSLFetchNameValue(papszOptions, "SO_OVERLAY_Y");
+    const char* pszSOOverlayXUnits = CSLFetchNameValue(papszOptions, "SO_OVERLAY_XUNITS");
+    const char* pszSOOverlayYUnits = CSLFetchNameValue(papszOptions, "SO_OVERLAY_YUNITS");
+    const char* pszSOScreenX = CSLFetchNameValue(papszOptions, "SO_SCREEN_X");
+    const char* pszSOScreenY = CSLFetchNameValue(papszOptions, "SO_SCREEN_Y");
+    const char* pszSOScreenXUnits = CSLFetchNameValue(papszOptions, "SO_SCREEN_XUNITS");
+    const char* pszSOScreenYUnits = CSLFetchNameValue(papszOptions, "SO_SCREEN_YUNITS");
+    const char* pszSOSizeX = CSLFetchNameValue(papszOptions, "SO_SIZE_X");
+    const char* pszSOSizeY = CSLFetchNameValue(papszOptions, "SO_SIZE_Y");
+    const char* pszSOSizeXUnits = CSLFetchNameValue(papszOptions, "SO_SIZE_XUNITS");
+    const char* pszSOSizeYUnits = CSLFetchNameValue(papszOptions, "SO_SIZE_YUNITS");
+    if( poOgrLayer != NULL && pszSOHref != NULL )
+    {
+        poOgrLayer->SetScreenOverlay(pszSOHref,
+                                     pszSOName,
+                                     pszSODescription,
+                                     pszSOOverlayX,
+                                     pszSOOverlayY,
+                                     pszSOOverlayXUnits,
+                                     pszSOOverlayYUnits,
+                                     pszSOScreenX,
+                                     pszSOScreenY,
+                                     pszSOScreenXUnits,
+                                     pszSOScreenYUnits,
+                                     pszSOSizeX,
+                                     pszSOSizeY,
+                                     pszSOSizeXUnits,
+                                     pszSOSizeYUnits);
+    }
+    
+    const char* pszListStyleType = CSLFetchNameValue(papszOptions, "LISTSTYLE_TYPE");
+    const char* pszListStyleIconHref = CSLFetchNameValue(papszOptions, "LISTSTYLE_ICON_HREF");
+    if( poOgrLayer != NULL )
+    {
+        poOgrLayer->SetListStyle(pszListStyleType, pszListStyleIconHref);
+    }
 
-
+    if( poOgrLayer != NULL && poOgrLayer->GetKmlLayer() != NULL )
+    {
+        SetCommonOptions(poOgrLayer->GetKmlLayer(), papszOptions);
+    }
 
     /***** mark the dataset as updated *****/
 
@@ -1848,6 +2394,8 @@ OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
 void OGRLIBKMLDataSource::SetStyleTable2Kml (
     OGRStyleTable * poStyleTable )
 {
+    if( m_poKmlDSContainer == NULL )
+        return;
 
     /***** delete all the styles *****/
 
@@ -1862,7 +2410,7 @@ void OGRLIBKMLDataSource::SetStyleTable2Kml (
     /***** add the new style table to the document *****/
 
     styletable2kml ( poStyleTable, m_poKmlFactory,
-                     AsContainer ( poKmlDocument ) );
+                     AsContainer ( poKmlDocument ), m_papszOptions );
 
     return;
 }
@@ -1879,12 +2427,15 @@ void OGRLIBKMLDataSource::SetStyleTable2Kml (
 void OGRLIBKMLDataSource::SetStyleTable2Kmz (
     OGRStyleTable * poStyleTable )
 {
+    if( m_poKmlStyleKml != NULL || poStyleTable != NULL )
+    {
+        /***** replace the style document with a new one *****/
 
-    /***** replace the style document with a new one *****/
-
-    m_poKmlStyleKml = m_poKmlFactory->CreateDocument (  );
+        m_poKmlStyleKml = m_poKmlFactory->CreateDocument (  );
+        m_poKmlStyleKml->set_id ( "styleId" );
 
-    styletable2kml ( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
+        styletable2kml ( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
+    }
 
     return;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
index d9d2620..20b3e01 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,6 +29,7 @@
 
 #include <ogrsf_frmts.h>
 #include <ogr_geometry.h>
+#include "gdal.h"
 
 #include <kml/dom.h>
 
@@ -37,6 +39,19 @@ using kmldom::ElementPtr;
 using kmldom::GeometryPtr;
 using kmldom::Geometry;
 using kmldom::GroundOverlayPtr;
+using kmldom::CameraPtr;
+using kmldom::ModelPtr;
+using kmldom::LinkPtr;
+using kmldom::LocationPtr;
+using kmldom::OrientationPtr;
+using kmldom::ScalePtr;
+using kmldom::ResourceMapPtr;
+using kmldom::AliasPtr;
+using kmldom::NetworkLinkPtr;
+using kmldom::PhotoOverlayPtr;
+using kmldom::IconPtr;
+using kmldom::ViewVolumePtr;
+using kmldom::ImagePyramidPtr;
 
 #include "ogr_libkml.h"
 
@@ -44,35 +59,649 @@ using kmldom::GroundOverlayPtr;
 #include "ogrlibkmlfield.h"
 #include "ogrlibkmlfeaturestyle.h"
 
-PlacemarkPtr feat2kml (
+static CameraPtr feat2kmlcamera( const struct fieldconfig& oFC,
+                                 int iHeading,
+                                 int iTilt,
+                                 int iRoll,
+                                 OGRFeature * poOgrFeat,
+                                 KmlFactory * poKmlFactory )
+{
+    int iCameraLongitudeField = poOgrFeat->GetFieldIndex(oFC.camera_longitude_field);
+    int iCameraLatitudeField = poOgrFeat->GetFieldIndex(oFC.camera_latitude_field);
+    int iCameraAltitudeField = poOgrFeat->GetFieldIndex(oFC.camera_altitude_field);
+    int iCameraAltitudeModeField = poOgrFeat->GetFieldIndex(oFC.camera_altitudemode_field);
+    if( iCameraLongitudeField >= 0 && poOgrFeat->IsFieldSet(iCameraLongitudeField) &&
+        iCameraLatitudeField >= 0  && poOgrFeat->IsFieldSet(iCameraLatitudeField) &&
+        ((iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
+        (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
+        (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll))) )
+    {
+        CameraPtr camera = poKmlFactory->CreateCamera();
+        camera->set_latitude(poOgrFeat->GetFieldAsDouble(iCameraLatitudeField));
+        camera->set_longitude(poOgrFeat->GetFieldAsDouble(iCameraLongitudeField));
+        int isGX = FALSE;
+        int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+        if( iCameraAltitudeModeField >= 0 && poOgrFeat->IsFieldSet(iCameraAltitudeModeField) )
+        {
+            nAltitudeMode = kmlAltitudeModeFromString(
+                poOgrFeat->GetFieldAsString(iCameraAltitudeModeField), isGX);
+            camera->set_altitudemode(nAltitudeMode);
+        }
+        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
+        if( iCameraAltitudeField >= 0 && poOgrFeat->IsFieldSet(iCameraAltitudeField))
+            camera->set_altitude(poOgrFeat->GetFieldAsDouble(iCameraAltitudeField));
+        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
+            camera->set_altitude(0.0);
+        }
+        if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
+            camera->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
+        if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
+            camera->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
+        if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
+            camera->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
+        return camera;
+    }
+    else
+        return NULL;
+}
+
+
+/************************************************************************/
+/*                 OGRLIBKMLReplaceXYLevelInURL()                       */
+/************************************************************************/
+
+static CPLString OGRLIBKMLReplaceLevelXYInURL(const char* pszURL,
+                                              int level, int x, int y)
+{
+    CPLString osRet(pszURL);
+    int nPos = osRet.find("$[level]");
+    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", level) + osRet.substr(nPos + strlen("$[level]"));
+    nPos = osRet.find("$[x]");
+    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", x) + osRet.substr(nPos + strlen("$[x]"));
+    nPos = osRet.find("$[y]");
+    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", y) + osRet.substr(nPos + strlen("$[y]"));
+    return osRet;
+}
+
+
+/************************************************************************/
+/*                        IsPowerOf2                                    */
+/************************************************************************/
+
+static int IsPowerOf2(int nVal)
+{
+    unsigned int nTmp = (unsigned int) nVal;
+    while( (nTmp & 1) == 0 )
+    {
+        nTmp >>= 1;
+    }
+    return( nTmp == 1 );
+}
+
+/************************************************************************/
+/*                    OGRLIBKMLGetMaxDimensions()                       */
+/************************************************************************/
+
+static void OGRLIBKMLGetMaxDimensions(const char* pszURL, 
+                                      int nTileSize,
+                                      int* panMaxWidth,
+                                      int* panMaxHeight)
+{
+    VSIStatBufL sStat;
+    int nMaxLevel = 0;
+    *panMaxWidth = 0;
+    *panMaxHeight = 0;
+    while( TRUE )
+    {
+        CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, 0, 0);
+        if( strstr(osURL, ".kmz/") )
+            osURL = "/vsizip/" + osURL;
+        if( VSIStatL(osURL, &sStat) == 0 )
+            nMaxLevel ++;
+        else
+        {
+            if( nMaxLevel == 0 )
+                return;
+            break;
+        }
+    }
+    nMaxLevel --;
+
+    int i;
+    for(i = 0; ; i++ )
+    {
+        CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, i + 1, 0);
+        if( strstr(osURL, ".kmz/") )
+            osURL = "/vsizip/" + osURL;
+        if( VSIStatL(osURL, &sStat) != 0 )
+            break;
+    }
+    *panMaxWidth = (i + 1) * nTileSize;
+    for(i = 0; ; i++ )
+    {
+        CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, 0, i + 1);
+        if( strstr(osURL, ".kmz/") )
+            osURL = "/vsizip/" + osURL;
+        if( VSIStatL(osURL, &sStat) != 0 )
+            break;
+    }
+    *panMaxHeight = (i + 1) * nTileSize;
+}
+
+/************************************************************************/
+/*                           feat2kml()                                 */
+/************************************************************************/
+
+FeaturePtr feat2kml (
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat,
-    KmlFactory * poKmlFactory )
+    KmlFactory * poKmlFactory,
+    int bUseSimpleField )
 {
+    FeaturePtr poKmlFeature = NULL;
 
-    PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
-
-    /***** style *****/
-
-    featurestyle2kml ( poOgrDS, poOgrLayer, poOgrFeat, poKmlFactory,
-                       poKmlPlacemark );
+    struct fieldconfig oFC;
+    get_fieldconfig( &oFC );
 
     /***** geometry *****/
 
     OGRGeometry *poOgrGeom = poOgrFeat->GetGeometryRef (  );
-    ElementPtr poKmlElement = geom2kml ( poOgrGeom, -1, 0, poKmlFactory );
+    int iHeading = poOgrFeat->GetFieldIndex(oFC.headingfield),
+        iTilt = poOgrFeat->GetFieldIndex(oFC.tiltfield),
+        iRoll = poOgrFeat->GetFieldIndex(oFC.rollfield),
+        iModel = poOgrFeat->GetFieldIndex(oFC.modelfield);
+    int iNetworkLink = poOgrFeat->GetFieldIndex(oFC.networklinkfield);
+    int iPhotoOverlay = poOgrFeat->GetFieldIndex(oFC.photooverlayfield);
+    CameraPtr camera = NULL;
+
+    /* PhotoOverlay */
+    if( iPhotoOverlay >= 0 && poOgrFeat->IsFieldSet(iPhotoOverlay) &&
+        poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
+        wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint &&
+        (camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll, poOgrFeat, poKmlFactory)) != NULL)
+    {
+        int iLeftFovField = poOgrFeat->GetFieldIndex(oFC.leftfovfield);
+        int iRightFovField = poOgrFeat->GetFieldIndex(oFC.rightfovfield);
+        int iBottomFovField = poOgrFeat->GetFieldIndex(oFC.bottomfovfield);
+        int iTopFovField = poOgrFeat->GetFieldIndex(oFC.topfovfield);
+        int iNearField = poOgrFeat->GetFieldIndex(oFC.nearfield);
+        double dfNear;
+
+        const char* pszURL = poOgrFeat->GetFieldAsString(iPhotoOverlay);
+        int iImagePyramidTileSize = poOgrFeat->GetFieldIndex(oFC.imagepyramid_tilesize_field);
+        int iImagePyramidMaxWidth = poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxwidth_field);
+        int iImagePyramidMaxHeight = poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxheight_field);
+        int iImagePyramidGridOrigin = poOgrFeat->GetFieldIndex(oFC.imagepyramid_gridorigin_field);
+        int nTileSize = 0, nMaxWidth = 0, nMaxHeight = 0;
+        int bIsTiledPhotoOverlay = FALSE;
+        int bGridOriginIsUpperLeft = TRUE;
+        /* ATC 52 and 62 */
+        if( strstr(pszURL, "$[x]") && strstr(pszURL, "$[y]") && strstr(pszURL, "$[level]") )
+        {
+            bIsTiledPhotoOverlay = TRUE;
+            int bErrorEmitted = FALSE;
+            if( iImagePyramidTileSize < 0 || !poOgrFeat->IsFieldSet(iImagePyramidTileSize) )
+            {
+                CPLDebug("LIBKML", "Missing ImagePyramid tileSize. Computing it");
+                CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, 0, 0, 0);
+                if( strstr(osURL, ".kmz/") )
+                    osURL = "/vsizip/" + osURL;
+                GDALDatasetH hDS = GDALOpen( osURL, GA_ReadOnly );
+                if( hDS != NULL )
+                {
+                    nTileSize = GDALGetRasterXSize(hDS);
+                    if( nTileSize != GDALGetRasterYSize(hDS) )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Non square tile : %dx%d",
+                                 GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
+                        nTileSize = 0;
+                        bErrorEmitted = TRUE;
+                    }
+                    GDALClose(hDS);
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", osURL.c_str());
+                    bErrorEmitted = TRUE;
+                }
+            }
+            else
+            {
+                nTileSize = poOgrFeat->GetFieldAsInteger(iImagePyramidTileSize);
+            }
+            if( !bErrorEmitted && (nTileSize <= 1 || !IsPowerOf2(nTileSize)) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Tile size is not a power of two: %d", nTileSize);
+                nTileSize = 0;
+            }
+
+            if( nTileSize > 0 )
+            {
+                if( iImagePyramidMaxWidth < 0 || !poOgrFeat->IsFieldSet(iImagePyramidMaxWidth) ||
+                    iImagePyramidMaxHeight < 0 || !poOgrFeat->IsFieldSet(iImagePyramidMaxHeight) )
+                {
+                    CPLDebug("LIBKML", "Missing ImagePyramid maxWidth and/or maxHeight. Computing it");
+                    OGRLIBKMLGetMaxDimensions(pszURL, nTileSize, &nMaxWidth, &nMaxHeight);
+                }
+                else
+                {
+                    nMaxWidth = poOgrFeat->GetFieldAsInteger(iImagePyramidMaxWidth);
+                    nMaxHeight = poOgrFeat->GetFieldAsInteger(iImagePyramidMaxHeight);
+                }
+
+                if( nTileSize <= 0 || nMaxWidth <= 0 || nMaxHeight <= 0)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Cannot generate PhotoOverlay object since there are "
+                            "missing information to generate ImagePyramid element");
+                }
+            }
+
+            if( iImagePyramidGridOrigin >= 0 && poOgrFeat->IsFieldSet(iImagePyramidGridOrigin) )
+            {
+                const char* pszGridOrigin = poOgrFeat->GetFieldAsString(iImagePyramidGridOrigin);
+                if( EQUAL(pszGridOrigin, "UpperLeft") )
+                    bGridOriginIsUpperLeft = TRUE;
+                else if( EQUAL(pszGridOrigin, "BottomLeft") )
+                    bGridOriginIsUpperLeft = FALSE;
+                else
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Unhandled value for imagepyramid_gridorigin : %s. Assuming UpperLeft",
+                             pszGridOrigin);
+                }
+            }
+        }
+        else
+        {
+            if( (iImagePyramidTileSize >= 0 && poOgrFeat->IsFieldSet(iImagePyramidTileSize)) ||
+                (iImagePyramidMaxWidth >= 0 && poOgrFeat->IsFieldSet(iImagePyramidMaxWidth)) ||
+                (iImagePyramidMaxHeight >= 0 && poOgrFeat->IsFieldSet(iImagePyramidMaxHeight)) ||
+                (iImagePyramidGridOrigin >= 0 && poOgrFeat->IsFieldSet(iImagePyramidGridOrigin)) )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Ignoring any ImagePyramid information since the URL does "
+                         "not include $[x] and/or $[y] and/or $[level]");
+            }
+        }
+
+        /* ATC 19 & 35 */
+        if( (!bIsTiledPhotoOverlay || (nTileSize > 0 && nMaxWidth > 0 && nMaxHeight > 0)) &&
+            iLeftFovField >= 0 && poOgrFeat->IsFieldSet(iLeftFovField) &&
+            iRightFovField >= 0 && poOgrFeat->IsFieldSet(iRightFovField) &&
+            iBottomFovField >= 0 && poOgrFeat->IsFieldSet(iBottomFovField) &&
+            iTopFovField >= 0 && poOgrFeat->IsFieldSet(iTopFovField) &&
+            iNearField >= 0 && (dfNear = poOgrFeat->GetFieldAsDouble(iNearField)) > 0 )
+        {
+            PhotoOverlayPtr poKmlPhotoOverlay = poKmlFactory->CreatePhotoOverlay (  );
+            poKmlFeature = poKmlPhotoOverlay;
+
+            IconPtr poKmlIcon = poKmlFactory->CreateIcon (  );
+            poKmlPhotoOverlay->set_icon(poKmlIcon);
+            poKmlIcon->set_href( pszURL );
+
+            ViewVolumePtr poKmlViewVolume = poKmlFactory->CreateViewVolume( );
+            poKmlPhotoOverlay->set_viewvolume(poKmlViewVolume);
+
+            double dfLeftFov = poOgrFeat->GetFieldAsDouble(iLeftFovField);
+            double dfRightFov = poOgrFeat->GetFieldAsDouble(iRightFovField);
+            double dfBottomFov = poOgrFeat->GetFieldAsDouble(iBottomFovField);
+            double dfTopFov = poOgrFeat->GetFieldAsDouble(iTopFovField);
+
+            poKmlViewVolume->set_leftfov(dfLeftFov);
+            poKmlViewVolume->set_rightfov(dfRightFov);
+            poKmlViewVolume->set_bottomfov(dfBottomFov);
+            poKmlViewVolume->set_topfov(dfTopFov);
+            poKmlViewVolume->set_near(dfNear);
+            
+            if( bIsTiledPhotoOverlay )
+            {
+                ImagePyramidPtr poKmlImagePyramid = poKmlFactory->CreateImagePyramid( );
+                poKmlPhotoOverlay->set_imagepyramid(poKmlImagePyramid);
+
+                poKmlImagePyramid->set_tilesize(nTileSize);
+                poKmlImagePyramid->set_maxwidth(nMaxWidth);
+                poKmlImagePyramid->set_maxheight(nMaxHeight);
+                poKmlImagePyramid->set_gridorigin( (bGridOriginIsUpperLeft) ?
+                    kmldom::GRIDORIGIN_UPPERLEFT : kmldom::GRIDORIGIN_LOWERLEFT );
+            }
+
+            int iPhotoOverlayShapeField = poOgrFeat->GetFieldIndex(oFC.photooverlay_shape_field);
+            if( iPhotoOverlayShapeField >= 0 && poOgrFeat->IsFieldSet(iPhotoOverlayShapeField) )
+            {
+                const char* pszShape = poOgrFeat->GetFieldAsString(iPhotoOverlayShapeField);
+                if( EQUAL(pszShape, "rectangle") )
+                    poKmlPhotoOverlay->set_shape(kmldom::SHAPE_RECTANGLE);
+                else if( EQUAL(pszShape, "cylinder") )
+                    poKmlPhotoOverlay->set_shape(kmldom::SHAPE_CYLINDER);
+                else if( EQUAL(pszShape, "sphere") )
+                    poKmlPhotoOverlay->set_shape(kmldom::SHAPE_SPHERE);
+            }
+
+            ElementPtr poKmlElement = geom2kml ( poOgrGeom, -1, 0, poKmlFactory );
+
+            poKmlPhotoOverlay->set_point ( AsPoint ( poKmlElement ) );
+        }
+    }
 
-    poKmlPlacemark->set_geometry ( AsGeometry ( poKmlElement ) );
+    /* NetworkLink */
+    if( poKmlFeature == NULL && iNetworkLink >= 0 && poOgrFeat->IsFieldSet(iNetworkLink) )
+    {
+        NetworkLinkPtr poKmlNetworkLink = poKmlFactory->CreateNetworkLink (  );
+        poKmlFeature = poKmlNetworkLink;
+
+        int iRefreshVisibility = poOgrFeat->GetFieldIndex(oFC.networklink_refreshvisibility_field);
+        int iFlyToView = poOgrFeat->GetFieldIndex(oFC.networklink_flytoview_field);
+
+        if( iRefreshVisibility >= 0 && poOgrFeat->IsFieldSet(iRefreshVisibility) )
+            poKmlNetworkLink->set_refreshvisibility(poOgrFeat->GetFieldAsInteger(iRefreshVisibility));
+
+        if( iFlyToView >= 0 && poOgrFeat->IsFieldSet(iFlyToView) )
+            poKmlNetworkLink->set_flytoview(poOgrFeat->GetFieldAsInteger(iFlyToView));
+
+        LinkPtr poKmlLink = poKmlFactory->CreateLink (  );
+        poKmlLink->set_href( poOgrFeat->GetFieldAsString( iNetworkLink ) );
+        poKmlNetworkLink->set_link(poKmlLink);
+
+        int iRefreshMode = poOgrFeat->GetFieldIndex(oFC.networklink_refreshMode_field);
+        int iRefreshInterval = poOgrFeat->GetFieldIndex(oFC.networklink_refreshInterval_field);
+        int iViewRefreshMode = poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshMode_field);
+        int iViewRefreshTime = poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshTime_field);
+        int iViewBoundScale = poOgrFeat->GetFieldIndex(oFC.networklink_viewBoundScale_field);
+        int iViewFormat = poOgrFeat->GetFieldIndex(oFC.networklink_viewFormat_field);
+        int iHttpQuery = poOgrFeat->GetFieldIndex(oFC.networklink_httpQuery_field);
+
+        double dfRefreshInterval = 0.0;
+        if( iRefreshInterval >= 0 && poOgrFeat->IsFieldSet(iRefreshInterval) )
+        {
+            dfRefreshInterval = poOgrFeat->GetFieldAsDouble(iRefreshInterval);
+            if( dfRefreshInterval < 0 )
+                dfRefreshInterval = 0.0;
+        }
+
+        double dfViewRefreshTime = 0.0;
+        if( iViewRefreshTime >= 0 && poOgrFeat->IsFieldSet(iViewRefreshTime) )
+        {
+            dfViewRefreshTime = poOgrFeat->GetFieldAsDouble(iViewRefreshTime);
+            if( dfViewRefreshTime < 0 )
+                dfViewRefreshTime = 0.0;
+        }
+
+        if( dfRefreshInterval > 0 ) /* ATC 51 */
+            poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONINTERVAL);
+        else if( iRefreshMode >= 0 && poOgrFeat->IsFieldSet(iRefreshMode) )
+        {
+            const char* pszRefreshMode = poOgrFeat->GetFieldAsString(iRefreshMode);
+            if( EQUAL(pszRefreshMode, "onChange") )
+                poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONCHANGE);
+            else if( EQUAL(pszRefreshMode, "onInterval") )
+                poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONINTERVAL);
+            else if( EQUAL(pszRefreshMode, "onExpire") )
+                poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONEXPIRE);
+        }
+
+        if( dfRefreshInterval > 0 ) /* ATC 9 */
+            poKmlLink->set_refreshinterval(dfRefreshInterval);
+
+        if( dfViewRefreshTime > 0 ) /* ATC  51 */
+            poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONSTOP);
+        else if( iViewRefreshMode >= 0 && poOgrFeat->IsFieldSet(iViewRefreshMode) )
+        {
+            const char* pszViewRefreshMode = poOgrFeat->GetFieldAsString(iViewRefreshMode);
+            if( EQUAL(pszViewRefreshMode, "never") )
+                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_NEVER);
+            else if( EQUAL(pszViewRefreshMode, "onRequest") )
+                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONREQUEST);
+            else if( EQUAL(pszViewRefreshMode, "onStop") )
+                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONSTOP);
+            else if( EQUAL(pszViewRefreshMode, "onRegion") )
+                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONREGION);
+        }
+
+        if( dfViewRefreshTime > 0 ) /* ATC 9 */
+            poKmlLink->set_viewrefreshtime(dfViewRefreshTime);
+
+        if( iViewBoundScale >= 0 && poOgrFeat->IsFieldSet(iViewBoundScale) )
+        {
+            double dfViewBoundScale = poOgrFeat->GetFieldAsDouble(iViewBoundScale);
+            if( dfViewBoundScale > 0 ) /* ATC 9 */
+                poKmlLink->set_viewboundscale(dfViewBoundScale);
+        }
+
+        if( iViewFormat >= 0 && poOgrFeat->IsFieldSet(iViewFormat) )
+        {
+            const char* pszViewFormat = poOgrFeat->GetFieldAsString(iViewFormat);
+            if( pszViewFormat[0] != '\0' ) /* ATC 46 */
+                poKmlLink->set_viewformat(pszViewFormat);
+        }
+
+        if( iHttpQuery >= 0 && poOgrFeat->IsFieldSet(iHttpQuery) )
+        {
+            const char* pszHttpQuery = poOgrFeat->GetFieldAsString(iHttpQuery);
+            if( strstr(pszHttpQuery, "[clientVersion]") != NULL ||
+                strstr(pszHttpQuery, "[kmlVersion]") != NULL ||
+                strstr(pszHttpQuery, "[clientName]") != NULL || 
+                strstr(pszHttpQuery, "[language]") != NULL ) /* ATC 47 */
+            {
+                poKmlLink->set_httpquery(pszHttpQuery);
+            }
+        }
+    }
 
-    /***** fields *****/
+    /* Model */
+    else if( poKmlFeature == NULL && iModel>= 0 && poOgrFeat->IsFieldSet(iModel) &&
+        poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
+        wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint )
+    {
+        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        poKmlFeature = poKmlPlacemark;
+
+        OGRPoint* poOgrPoint = (OGRPoint*) poOgrGeom;
+        ModelPtr model = poKmlFactory->CreateModel();
+
+        LocationPtr location = poKmlFactory->CreateLocation();
+        model->set_location(location);
+        location->set_latitude(poOgrPoint->getY());
+        location->set_longitude(poOgrPoint->getX());
+        if( poOgrPoint->getCoordinateDimension() == 3 )
+            location->set_altitude(poOgrPoint->getZ());
+
+        int isGX = FALSE;
+        int iAltitudeMode = poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
+        int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSet(iAltitudeMode) )
+        {
+            nAltitudeMode = kmlAltitudeModeFromString(
+                poOgrFeat->GetFieldAsString(iAltitudeMode), isGX);
+            model->set_altitudemode(nAltitudeMode);
+
+            /* ATC 55 */
+            if( nAltitudeMode != kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
+                poOgrPoint->getCoordinateDimension() != 3 )
+            {
+                if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                    CPLError(CE_Warning, CPLE_AppDefined, "Altitude should be defined");
+            }
+        }
+
+        if( (iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
+            (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
+            (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll)) )
+        {
+            OrientationPtr orientation = poKmlFactory->CreateOrientation();
+            model->set_orientation(orientation);
+            if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
+                orientation->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
+            else
+                orientation->set_heading(0);
+            if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
+                orientation->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
+            else
+                orientation->set_tilt(0);
+            if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
+                orientation->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
+            else
+                orientation->set_roll(0);
+        }
+        int iScaleX = poOgrFeat->GetFieldIndex(oFC.scalexfield);
+        int iScaleY = poOgrFeat->GetFieldIndex(oFC.scaleyfield);
+        int iScaleZ = poOgrFeat->GetFieldIndex(oFC.scalezfield);
+        
+        ScalePtr scale = poKmlFactory->CreateScale();
+        model->set_scale(scale);
+        if( iScaleX >= 0 && poOgrFeat->IsFieldSet(iScaleX) )
+            scale->set_x(poOgrFeat->GetFieldAsDouble(iScaleX));
+        else
+            scale->set_x(1.0);
+        if( iScaleY >= 0 && poOgrFeat->IsFieldSet(iScaleY) )
+            scale->set_y(poOgrFeat->GetFieldAsDouble(iScaleY));
+        else
+            scale->set_y(1.0);
+        if( iScaleZ >= 0 && poOgrFeat->IsFieldSet(iScaleZ) )
+            scale->set_z(poOgrFeat->GetFieldAsDouble(iScaleZ));
+        else
+            scale->set_z(1.0);
+
+        LinkPtr link = poKmlFactory->CreateLink();
+        model->set_link(link);
+        const char* pszURL = poOgrFeat->GetFieldAsString(oFC.modelfield);
+        link->set_href( pszURL );
+
+        /* Collada 3D file ? */
+        if( EQUAL(CPLGetExtension(pszURL), "dae") &&
+            CSLTestBoolean(CPLGetConfigOption("LIBKML_ADD_RESOURCE_MAP", "TRUE")) )
+        {
+            VSILFILE* fp;
+            int bIsURL = FALSE;
+            if( EQUALN(pszURL, "http://", strlen("http://")) ||
+                EQUALN(pszURL, "https://", strlen("https://")) )
+            {
+                bIsURL = TRUE;
+                fp = VSIFOpenL(CPLSPrintf("/vsicurl/%s", pszURL), "rb");
+            }
+            else if( strstr(pszURL, ".kmz/") != NULL )
+            {
+                fp = VSIFOpenL(CPLSPrintf("/vsizip/%s", pszURL), "rb");
+            }
+            else
+            {
+                fp = VSIFOpenL(pszURL, "rb");
+            }
+            if( fp != NULL )
+            {
+                ResourceMapPtr resourceMap = NULL;
+                const char* pszLine;
+                while( (pszLine = CPLReadLineL(fp)) != NULL )
+                {
+                    const char* pszInitFrom = strstr(pszLine, "<init_from>");
+                    if( pszInitFrom )
+                    {
+                        pszInitFrom += strlen("<init_from>");
+                        const char* pszInitFromEnd = strstr(pszInitFrom, "</init_from>");
+                        if( pszInitFromEnd )
+                        {
+                            CPLString osImage(pszInitFrom);
+                            osImage.resize(pszInitFromEnd - pszInitFrom);
+                            const char* pszExtension = CPLGetExtension(osImage);
+                            if( EQUAL(pszExtension, "jpg") ||
+                                EQUAL(pszExtension, "jpeg") ||
+                                EQUAL(pszExtension, "png") ||
+                                EQUAL(pszExtension, "gif") )
+                            {
+                                if( resourceMap == NULL )
+                                    resourceMap = poKmlFactory->CreateResourceMap();
+                                AliasPtr alias = poKmlFactory->CreateAlias();
+                                if( bIsURL && CPLIsFilenameRelative(osImage) )
+                                    alias->set_targethref(CPLFormFilename(CPLGetPath(pszURL), osImage, NULL));
+                                else
+                                    alias->set_targethref(osImage);
+                                alias->set_sourcehref(osImage);
+                                resourceMap->add_alias(alias);
+                            }
+                        }
+                    }
+                }
+                if( resourceMap != NULL )
+                    model->set_resourcemap(resourceMap);
+                VSIFCloseL(fp);
+            }
+        }
+
+        poKmlPlacemark->set_geometry ( AsGeometry ( model ) );
+    }
 
-    field2kml ( poOgrFeat, ( OGRLIBKMLLayer * ) poOgrLayer, poKmlFactory,
-                poKmlPlacemark );
+    /* Camera */
+    else if( poKmlFeature == NULL && poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
+        wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint &&
+        poOgrFeat->GetFieldIndex(oFC.camera_longitude_field) < 0 &&
+        ((iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
+         (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
+         (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll))) )
+    {
+        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        poKmlFeature = poKmlPlacemark;
+
+        OGRPoint* poOgrPoint = (OGRPoint*) poOgrGeom;
+        CameraPtr camera = poKmlFactory->CreateCamera();
+        camera->set_latitude(poOgrPoint->getY());
+        camera->set_longitude(poOgrPoint->getX());
+        int isGX = FALSE;
+        int iAltitudeMode = poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
+        int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSet(iAltitudeMode) )
+        {
+            nAltitudeMode = kmlAltitudeModeFromString(
+                poOgrFeat->GetFieldAsString(iAltitudeMode), isGX);
+            camera->set_altitudemode(nAltitudeMode);
+        }
+        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
+        if( poOgrPoint->getCoordinateDimension() == 3 )
+            camera->set_altitude(poOgrPoint->getZ());
+        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
+            camera->set_altitude(0.0);
+        }
+        if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
+            camera->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
+        if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
+            camera->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
+        if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
+            camera->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
+        poKmlPlacemark->set_abstractview(camera);
+    }
+
+    else if( poKmlFeature == NULL )
+    {
+        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        poKmlFeature = poKmlPlacemark;
 
+        ElementPtr poKmlElement = geom2kml ( poOgrGeom, -1, 0, poKmlFactory );
 
+        poKmlPlacemark->set_geometry ( AsGeometry ( poKmlElement ) );
+    }
+
+    if( camera == NULL )
+        camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll, poOgrFeat, poKmlFactory);
+    if( camera != NULL )
+        poKmlFeature->set_abstractview(camera);
+
+    /***** style *****/
+
+    featurestyle2kml ( poOgrDS, poOgrLayer, poOgrFeat, poKmlFactory,
+                       poKmlFeature );
 
-    return poKmlPlacemark;
+    /***** fields *****/
+
+    field2kml ( poOgrFeat, ( OGRLIBKMLLayer * ) poOgrLayer, poKmlFactory,
+                poKmlFeature, bUseSimpleField );
+
+    return poKmlFeature;
 }
 
 OGRFeature *kml2feat (
@@ -97,6 +726,18 @@ OGRFeature *kml2feat (
         poOgrFeat->SetGeometryDirectly ( poOgrGeom );
 
     }
+    else if ( poKmlPlacemark->has_abstractview (  ) &&
+              poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) ) {
+        const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
+        if( camera->has_longitude() && camera->has_latitude() )
+        {
+            if( camera->has_altitude() )
+                poOgrFeat->SetGeometryDirectly( new OGRPoint( camera->get_longitude(), camera->get_latitude(), camera->get_altitude() ) );
+            else
+                poOgrFeat->SetGeometryDirectly( new OGRPoint( camera->get_longitude(), camera->get_latitude() ) );
+            poOgrFeat->GetGeometryRef()->assignSpatialReference( poOgrSRS );
+        }
+    }
 
     /***** fields *****/
 
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
index 4283d57..e7c3f3b 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
@@ -29,6 +29,7 @@
 #include <kml/dom.h>
 
 using kmldom::KmlFactory;
+using kmldom::FeaturePtr;
 using kmldom::PlacemarkPtr;
 
 #include "ogr_libkml.h"
@@ -38,11 +39,12 @@ using kmldom::PlacemarkPtr;
  function to output a ogr feature to a kml placemark
 ******************************************************************************/
 
-PlacemarkPtr feat2kml (
+FeaturePtr feat2kml (
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poKOgrLayer,
     OGRFeature * poOgrFeat,
-    KmlFactory * poKmlFactory );
+    KmlFactory * poKmlFactory,
+    int bUseSimpleField );
 
 /******************************************************************************
  function to read a kml placemark into a ogr feature
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
index 6d57322..1c32222 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -55,7 +56,7 @@ args:
             poOgrLayer      the layer the feature is in
             poOgrFeat       the feature
             poKmlFactory    the kml dom factory
-            poKmlPlacemark  the placemark to add it to
+            poKmlFeature  the placemark to add it to
 
 returns:
             nothing
@@ -66,7 +67,7 @@ void featurestyle2kml (
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark )
+    FeaturePtr poKmlFeature )
 {
 
     /***** get the style table *****/
@@ -77,26 +78,28 @@ void featurestyle2kml (
 
     /***** does the feature have style? *****/
 
-    if ( pszStyleString ) {
+    if ( pszStyleString && pszStyleString[0] != '\0' ) {
 
         /***** does it ref a style table? *****/
 
         if ( *pszStyleString == '@' ) {
 
+            const char* pszStyleName = pszStyleString + 1;
+
             /***** is the name in the layer style table *****/
 
             OGRStyleTable *hSTBLLayer;
             const char *pszTest = NULL;
 
             if ( ( hSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
-                pszTest = hSTBLLayer->Find ( pszStyleString );
+                pszTest = hSTBLLayer->Find ( pszStyleName );
 
             if ( pszTest ) {
                 string oTmp = "#";
 
-                oTmp.append ( pszStyleString + 1 );
+                oTmp.append ( pszStyleName );
 
-                poKmlPlacemark->set_styleurl ( oTmp );
+                poKmlFeature->set_styleurl ( oTmp );
             }
 
 
@@ -108,25 +111,23 @@ void featurestyle2kml (
                 if ( poOgrDS->GetStylePath (  ) )
                     oTmp.append ( poOgrDS->GetStylePath (  ) );
                 oTmp.append ( "#" );
-                oTmp.append ( pszStyleString + 1 );
+                oTmp.append ( pszStyleName );
 
-                poKmlPlacemark->set_styleurl ( oTmp );
+                poKmlFeature->set_styleurl ( oTmp );
             }
         }
 
         /***** no style table ref *****/
 
         else {
-            StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
-
             /***** parse the style string *****/
 
-            addstylestring2kml ( pszStyleString, poKmlStyle, poKmlFactory,
-                                 poKmlPlacemark, poOgrFeat );
+            StylePtr poKmlStyle = addstylestring2kml ( pszStyleString, NULL, poKmlFactory,
+                                 poKmlFeature );
 
             /***** add the style to the placemark *****/
-
-            poKmlPlacemark->set_styleselector ( poKmlStyle );
+            if( poKmlStyle != NULL )
+                poKmlFeature->set_styleselector ( poKmlStyle );
 
         }
     }
@@ -136,7 +137,7 @@ void featurestyle2kml (
     else if ( ( poOgrSTBL = poOgrFeat->GetStyleTable (  ) ) ) {
 
 
-        StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
+        StylePtr poKmlStyle = NULL;
 
         /***** parse the style table *****/
 
@@ -147,20 +148,22 @@ void featurestyle2kml (
 
             if ( *pszStyleString == '@' ) {
 
+                const char* pszStyleName = pszStyleString + 1;
+
                 /***** is the name in the layer style table *****/
 
                 OGRStyleTable *poOgrSTBLLayer;
                 const char *pszTest = NULL;
 
                 if ( ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
-                    poOgrSTBLLayer->Find ( pszStyleString );
+                    poOgrSTBLLayer->Find ( pszStyleName );
 
                 if ( pszTest ) {
                     string oTmp = "#";
 
-                    oTmp.append ( pszStyleString + 1 );
+                    oTmp.append ( pszStyleName );
 
-                    poKmlPlacemark->set_styleurl ( oTmp );
+                    poKmlFeature->set_styleurl ( oTmp );
                 }
 
                 /***** assume its a dataset style,      *****/
@@ -172,9 +175,9 @@ void featurestyle2kml (
                     if ( poOgrDS->GetStylePath (  ) )
                         oTmp.append ( poOgrDS->GetStylePath (  ) );
                     oTmp.append ( "#" );
-                    oTmp.append ( pszStyleString + 1 );
+                    oTmp.append ( pszStyleName );
 
-                    poKmlPlacemark->set_styleurl ( oTmp );
+                    poKmlFeature->set_styleurl ( oTmp );
                 }
             }
 
@@ -182,12 +185,14 @@ void featurestyle2kml (
 
                 /***** parse the style string *****/
 
-                addstylestring2kml ( pszStyleString, poKmlStyle,
-                                     poKmlFactory, poKmlPlacemark, poOgrFeat );
-
-                /***** add the style to the placemark *****/
+                poKmlStyle = addstylestring2kml ( pszStyleString, poKmlStyle,
+                                     poKmlFactory, poKmlFeature );
+                if( poKmlStyle != NULL )
+                {
+                    /***** add the style to the placemark *****/
 
-                poKmlPlacemark->set_styleselector ( poKmlStyle );
+                    poKmlFeature->set_styleselector ( poKmlStyle );
+                }
 
             }
         }
@@ -200,7 +205,7 @@ void featurestyle2kml (
 ******************************************************************************/
 
 void kml2featurestyle (
-    PlacemarkPtr poKmlPlacemark,
+    FeaturePtr poKmlFeature,
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat )
@@ -208,9 +213,9 @@ void kml2featurestyle (
 
     /***** does the placemark have a style url? *****/
 
-    if (    poKmlPlacemark->has_styleurl (  ) ) {
+    if (    poKmlFeature->has_styleurl (  ) ) {
 
-        const string poKmlStyleUrl = poKmlPlacemark->get_styleurl (  );
+        const string poKmlStyleUrl = poKmlFeature->get_styleurl (  );
 
         /***** is the name in the layer style table *****/
 
@@ -233,7 +238,7 @@ void kml2featurestyle (
 
             const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
-            if (EQUAL(pszResolve, "yes")) {
+            if (CSLTestBoolean(pszResolve)) {
 
                 poOgrFeat->SetStyleString ( pszTest );
             }
@@ -262,7 +267,7 @@ void kml2featurestyle (
 
                 const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
-                if (    EQUAL(pszResolve, "yes")
+                if (    CSLTestBoolean(pszResolve)
                      && ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) )
                      && ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) )
                    )
@@ -285,7 +290,7 @@ void kml2featurestyle (
 
                 const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
 
-                if ( EQUAL(pszFetch, "yes") ) {
+                if ( CSLTestBoolean(pszFetch) ) {
 
                     /***** load up the style table *****/
 
@@ -334,7 +339,7 @@ void kml2featurestyle (
 
                         if ( poOgrDS->ParseIntoStyleTable (&oStyle, pszUrlTmp)) {
 
-                            kml2featurestyle (poKmlPlacemark,
+                            kml2featurestyle (poKmlFeature,
                                               poOgrDS,
                                               poOgrLayer,
                                               poOgrFeat );
@@ -363,10 +368,10 @@ void kml2featurestyle (
 
     /***** does the placemark have a style selector *****/
 
-   if ( poKmlPlacemark->has_styleselector (  ) ) {
+   if ( poKmlFeature->has_styleselector (  ) ) {
 
         StyleSelectorPtr poKmlStyleSelector =
-            poKmlPlacemark->get_styleselector (  );
+            poKmlFeature->get_styleselector (  );
 
         /***** is the style a style? *****/
 
@@ -379,7 +384,7 @@ void kml2featurestyle (
             /***** might already have styling to add too *****/
             
             const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
-            if (EQUAL(pszResolve, "yes")) {
+            if (CSLTestBoolean(pszResolve)) {
                  poOgrSM->InitFromFeature ( poOgrFeat );
             }
             else {
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
index 3e03aca..8424362 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
@@ -28,21 +28,21 @@
 
 #include "ogr_libkml.h"
 
-using kmldom::PlacemarkPtr;
+using kmldom::FeaturePtr;
 
 void featurestyle2kml (
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poKOgrLayer,
     OGRFeature * poOgrFeat,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark );
+    FeaturePtr poKmlFeature );
 
 /******************************************************************************
  function to read a kml style into ogr's featurestyle
 ******************************************************************************/
 
 void kml2featurestyle (
-    PlacemarkPtr poKmlPlacemark,
+    FeaturePtr poKmlFeature,
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature *poOgrFeat);
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
index e8c0379..7ae78ab 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,6 +43,7 @@ using kmldom::DataPtr;
 using kmldom::TimeStampPtr;
 using kmldom::TimeSpanPtr;
 using kmldom::TimePrimitivePtr;
+using kmldom::SnippetPtr;
 
 using kmldom::PointPtr;
 using kmldom::LineStringPtr;
@@ -52,6 +54,9 @@ using kmldom::GeometryPtr;
 using kmldom::FeaturePtr;
 using kmldom::GroundOverlayPtr;
 using kmldom::IconPtr;
+using kmldom::CameraPtr;
+
+using kmldom::GxTrackPtr;
 
 #include "ogr_libkml.h"
 
@@ -282,23 +287,29 @@ void field2kml (
     OGRFeature * poOgrFeat,
     OGRLIBKMLLayer * poOgrLayer,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark )
+    FeaturePtr poKmlFeature,
+    int bUseSimpleField)
 {
     int i;
 
-    SchemaDataPtr poKmlSchemaData = poKmlFactory->CreateSchemaData (  );
-    SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema (  );
+    ExtendedDataPtr poKmlExtendedData = NULL;
+    SchemaDataPtr poKmlSchemaData = NULL;
+    if( bUseSimpleField )
+    {
+        poKmlSchemaData = poKmlFactory->CreateSchemaData (  );
+        SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema (  );
 
-    /***** set the url to the schema *****/
+        /***** set the url to the schema *****/
 
-    if ( poKmlSchema && poKmlSchema->has_id (  ) ) {
-        std::string oKmlSchemaID = poKmlSchema->get_id (  );
+        if ( poKmlSchema && poKmlSchema->has_id (  ) ) {
+            std::string oKmlSchemaID = poKmlSchema->get_id (  );
 
 
-        std::string oKmlSchemaURL = "#";
-        oKmlSchemaURL.append ( oKmlSchemaID );
+            std::string oKmlSchemaURL = "#";
+            oKmlSchemaURL.append ( oKmlSchemaID );
 
-        poKmlSchemaData->set_schemaurl ( oKmlSchemaURL );
+            poKmlSchemaData->set_schemaurl ( oKmlSchemaURL );
+        }
     }
 
     /***** get the field config *****/
@@ -311,6 +322,8 @@ void field2kml (
     int nFields = poOgrFeat->GetFieldCount (  );
     int iSkip1 = -1;
     int iSkip2 = -1;
+    int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+    int isGX = FALSE;
 
     for ( i = 0; i < nFields; i++ ) {
 
@@ -329,6 +342,7 @@ void field2kml (
         const char *name = poOgrFieldDef->GetNameRef (  );
 
         SimpleDataPtr poKmlSimpleData = NULL;
+        DataPtr poKmlData = NULL;
         int year,
             month,
             day,
@@ -343,10 +357,16 @@ void field2kml (
             {
                 char* pszUTF8String = OGRLIBKMLSanitizeUTF8String(
                                         poOgrFeat->GetFieldAsString ( i ));
+                if( pszUTF8String[0] == '\0' )
+                {
+                    CPLFree( pszUTF8String );
+                    continue;
+                }
+
                 /***** name *****/
 
                 if ( EQUAL ( name, oFC.namefield ) ) {
-                    poKmlPlacemark->set_name ( pszUTF8String );
+                    poKmlFeature->set_name ( pszUTF8String );
                     CPLFree( pszUTF8String );
                     continue;
                 }
@@ -354,7 +374,7 @@ void field2kml (
                 /***** description *****/
 
                 else if ( EQUAL ( name, oFC.descfield ) ) {
-                    poKmlPlacemark->set_description ( pszUTF8String );
+                    poKmlFeature->set_description ( pszUTF8String );
                     CPLFree( pszUTF8String );
                     continue;
                 }
@@ -364,38 +384,18 @@ void field2kml (
                 else if ( EQUAL ( name, oFC.altitudeModefield ) ) {
                     const char *pszAltitudeMode = pszUTF8String ;
 
-                    int isGX = FALSE;
-                    int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-
-                    if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
-                        iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-
-                    else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
-                        iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND;
-
-                    else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
-                        iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE;
-
-                    else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
-                        iAltitudeMode =
-                            kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR;
-                        isGX = TRUE;
-                    }
-
-                    else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
-                        iAltitudeMode =
-                            kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR;
-                        isGX = TRUE;
-                    }
-
+                    iAltitudeMode = kmlAltitudeModeFromString(pszAltitudeMode, isGX);
 
-                    if ( poKmlPlacemark->has_geometry (  ) ) {
-                        GeometryPtr poKmlGeometry =
-                            poKmlPlacemark->get_geometry (  );
+                    if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
+                        PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
+                        if ( poKmlPlacemark->has_geometry (  ) ) {
+                            GeometryPtr poKmlGeometry =
+                                poKmlPlacemark->get_geometry (  );
 
-                        ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
-                                               isGX );
+                            ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
+                                                isGX );
 
+                        }
                     }
 
                     CPLFree( pszUTF8String );
@@ -410,7 +410,7 @@ void field2kml (
                     TimeStampPtr poKmlTimeStamp =
                         poKmlFactory->CreateTimeStamp (  );
                     poKmlTimeStamp->set_when ( pszUTF8String  );
-                    poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
+                    poKmlFeature->set_timeprimitive ( poKmlTimeStamp );
 
                     CPLFree( pszUTF8String );
 
@@ -423,7 +423,7 @@ void field2kml (
 
                     if ( !poKmlTimeSpan ) {
                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
+                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
                     }
 
                     poKmlTimeSpan->set_begin ( pszUTF8String );
@@ -440,7 +440,7 @@ void field2kml (
 
                     if ( !poKmlTimeSpan ) {
                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
+                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
                     }
 
                     poKmlTimeSpan->set_end ( pszUTF8String );
@@ -450,23 +450,62 @@ void field2kml (
                     continue;
                 }
 
-                /***** icon *****/
+                /***** snippet *****/
+
+                else if  ( EQUAL ( name, oFC.snippetfield ) ) {
+
+                    SnippetPtr snippet = poKmlFactory->CreateSnippet (  );
+                    snippet->set_text(pszUTF8String);
+                    poKmlFeature->set_snippet ( snippet );
+
+                    CPLFree( pszUTF8String );
 
-                else if ( EQUAL ( name, oFC.iconfield ) ) {
                     continue;
+
                 }
-                
+
+                /***** other special fields *****/
+
+                else if (  EQUAL ( name, oFC.iconfield ) ||
+                           EQUAL ( name, oFC.modelfield ) ||
+                           EQUAL ( name, oFC.networklinkfield ) ||
+                           EQUAL ( name, oFC.networklink_refreshMode_field ) ||
+                           EQUAL ( name, oFC.networklink_viewRefreshMode_field ) ||
+                           EQUAL ( name, oFC.networklink_viewFormat_field ) ||
+                           EQUAL ( name, oFC.networklink_httpQuery_field ) ||
+                           EQUAL ( name, oFC.camera_altitudemode_field ) ||
+                           EQUAL ( name, oFC.photooverlayfield ) ||
+                           EQUAL ( name, oFC.photooverlay_shape_field ) ||
+                           EQUAL ( name, oFC.imagepyramid_gridorigin_field ) ) {
+
+                    CPLFree( pszUTF8String );
+
+                    continue;
+                }
+
                 /***** other *****/
 
-                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( pszUTF8String );
+                if( bUseSimpleField )
+                {
+                    poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
+                    poKmlSimpleData->set_name ( name );
+                    poKmlSimpleData->set_text ( pszUTF8String );
+                }
+                else
+                {
+                    poKmlData = poKmlFactory->CreateData (  );
+                    poKmlData->set_name ( name );
+                    poKmlData->set_value ( pszUTF8String );
+                }
 
                 CPLFree( pszUTF8String );
 
                 break;
             }
 
+        /* This code checks if there's a OFTTime field with the same name */
+        /* that could be used to compose a DateTime. Not sure this is really */
+        /* supported in OGR data model to have 2 fields with same name... */
         case OFTDate:          //   Date
             {
                 poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
@@ -516,7 +555,9 @@ void field2kml (
 
             }
 
-
+        /* This code checks if there's a OFTTime field with the same name */
+        /* that could be used to compose a DateTime. Not sure this is really */
+        /* supported in OGR data model to have 2 fields with same name... */
         case OFTTime:          //   Time
             {
                 poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
@@ -533,7 +574,7 @@ void field2kml (
                     OGRFieldType type2 = poOgrFieldDef2->GetType (  );
                     const char *name2 = poOgrFieldDef2->GetNameRef (  );
 
-                    if ( EQUAL ( name2, name ) && type2 == OFTTime &&
+                    if ( EQUAL ( name2, name ) && type2 == OFTDate &&
                          ( EQUAL ( name, oFC.tsfield ) ||
                            EQUAL ( name, oFC.beginfield ) ||
                            EQUAL ( name, oFC.endfield ) ) ) {
@@ -581,7 +622,7 @@ void field2kml (
                     TimeStampPtr poKmlTimeStamp =
                         poKmlFactory->CreateTimeStamp (  );
                     poKmlTimeStamp->set_when ( timebuf );
-                    poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
+                    poKmlFeature->set_timeprimitive ( poKmlTimeStamp );
                     CPLFree( timebuf );
 
                     continue;
@@ -596,7 +637,7 @@ void field2kml (
 
                     if ( !poKmlTimeSpan ) {
                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
+                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
                     }
 
                     poKmlTimeSpan->set_begin ( timebuf );
@@ -616,7 +657,7 @@ void field2kml (
 
                     if ( !poKmlTimeSpan ) {
                         poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
+                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
                     }
 
                     poKmlTimeSpan->set_end ( timebuf );
@@ -627,10 +668,20 @@ void field2kml (
 
                 /***** other *****/
 
-                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( poOgrFeat->
-                                            GetFieldAsString ( i ) );
+                if( bUseSimpleField )
+                {
+                    poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
+                    poKmlSimpleData->set_name ( name );
+                    poKmlSimpleData->set_text ( poOgrFeat->
+                                                GetFieldAsString ( i ) );
+                }
+                else
+                {
+                    poKmlData = poKmlFactory->CreateData (  );
+                    poKmlData->set_name ( name );
+                    poKmlData->set_value ( poOgrFeat->
+                                                GetFieldAsString ( i ) );
+                }
 
                 break;
             }
@@ -641,12 +692,26 @@ void field2kml (
 
             if ( EQUAL ( name, oFC.extrudefield ) ) {
 
-                if ( poKmlPlacemark->has_geometry (  )
-                     && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
-                    GeometryPtr poKmlGeometry =
-                        poKmlPlacemark->get_geometry (  );
-                    ogr2extrude_rec ( poOgrFeat->GetFieldAsInteger ( i ),
-                                      poKmlGeometry );
+                if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
+                    if ( poKmlPlacemark->has_geometry (  )
+                        && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
+                        int iExtrude = poOgrFeat->GetFieldAsInteger ( i );
+                        if( iExtrude &&
+                            isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
+                            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                        {
+                            CPLError(CE_Warning, CPLE_NotSupported,
+                                "altitudeMode=clampToGround unsupported with extrude=1");
+                        }
+                        else
+                        {
+                            GeometryPtr poKmlGeometry =
+                                poKmlPlacemark->get_geometry (  );
+                            ogr2extrude_rec ( iExtrude,
+                                            poKmlGeometry );
+                        }
+                    }
                 }
                 continue;
             }
@@ -656,12 +721,30 @@ void field2kml (
 
             if ( EQUAL ( name, oFC.tessellatefield ) ) {
 
-                if ( poKmlPlacemark->has_geometry (  )
-                     && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
-                    GeometryPtr poKmlGeometry =
-                        poKmlPlacemark->get_geometry (  );
-                    ogr2tessellate_rec ( poOgrFeat->GetFieldAsInteger ( i ),
-                                         poKmlGeometry );
+                if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
+                    if ( poKmlPlacemark->has_geometry (  )
+                        && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
+                        int iTesselate = poOgrFeat->GetFieldAsInteger ( i );
+                        if( iTesselate &&
+                            !(isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND) &&
+                            !(isGX == TRUE && iAltitudeMode == kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR) &&
+                            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                        {
+                            CPLError(CE_Warning, CPLE_NotSupported,
+                                "altitudeMode!=clampToGround && altitudeMode!=clampToSeaFloor unsupported with tesselate=1");
+                        }
+                        else
+                        {
+                            GeometryPtr poKmlGeometry =
+                                poKmlPlacemark->get_geometry (  );
+                            ogr2tessellate_rec ( iTesselate,
+                                                poKmlGeometry );
+                            if( isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND )
+                                ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
+                                                    isGX );
+                        }
+                    }
                 }
 
                 continue;
@@ -672,37 +755,89 @@ void field2kml (
 
             if ( EQUAL ( name, oFC.visibilityfield ) ) {
                 if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) )
-                    poKmlPlacemark->set_visibility ( poOgrFeat->
+                    poKmlFeature->set_visibility ( poOgrFeat->
                                                      GetFieldAsInteger ( i ) );
 
                 continue;
             }
 
-            /***** icon *****/
 
-            else if ( EQUAL ( name, oFC.drawOrderfield ) ) {
+            /***** other special fields *****/
+
+            else if (  EQUAL ( name, oFC.drawOrderfield ) ||
+                        EQUAL ( name, oFC.networklink_refreshvisibility_field ) ||
+                        EQUAL ( name, oFC.networklink_flytoview_field ) ||
+                        EQUAL ( name, oFC.networklink_refreshInterval_field ) ||
+                        EQUAL ( name, oFC.networklink_viewRefreshMode_field ) ||
+                        EQUAL ( name, oFC.networklink_viewRefreshTime_field ) ||
+                        EQUAL ( name, oFC.imagepyramid_tilesize_field ) ||
+                        EQUAL ( name, oFC.imagepyramid_maxwidth_field ) ||
+                        EQUAL ( name, oFC.imagepyramid_maxheight_field ) ) {
+
                 continue;
             }
-                
+
             /***** other *****/
 
-            poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-            poKmlSimpleData->set_name ( name );
-            poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+            if( bUseSimpleField )
+            {
+                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
+                poKmlSimpleData->set_name ( name );
+                poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+            }
+            else
+            {
+                poKmlData = poKmlFactory->CreateData (  );
+                poKmlData->set_name ( name );
+                poKmlData->set_value ( poOgrFeat->GetFieldAsString ( i ) );
+            }
 
             break;
 
         case OFTReal:          //   Double Precision floating point
         {
-            poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-            poKmlSimpleData->set_name ( name );
+            if( EQUAL(name, oFC.headingfield) ||
+                EQUAL(name, oFC.tiltfield) ||
+                EQUAL(name, oFC.rollfield) ||
+                EQUAL(name, oFC.scalexfield) ||
+                EQUAL(name, oFC.scaleyfield) ||
+                EQUAL(name, oFC.scalezfield) ||
+                EQUAL(name, oFC.networklink_refreshInterval_field ) ||
+                EQUAL(name, oFC.networklink_viewRefreshMode_field) ||
+                EQUAL(name, oFC.networklink_viewRefreshTime_field) ||
+                EQUAL(name, oFC.networklink_viewBoundScale_field) ||
+                EQUAL(name, oFC.camera_longitude_field) ||
+                EQUAL(name, oFC.camera_latitude_field) ||
+                EQUAL(name, oFC.camera_altitude_field) ||
+                EQUAL(name, oFC.leftfovfield) ||
+                EQUAL(name, oFC.rightfovfield) ||
+                EQUAL(name, oFC.bottomfovfield) ||
+                EQUAL(name, oFC.topfovfield) ||
+                EQUAL(name, oFC.nearfield) ||
+                EQUAL(name, oFC.camera_altitude_field) )
+            {
+                continue;
+            }
 
             char* pszStr = CPLStrdup( poOgrFeat->GetFieldAsString ( i ) );
             /* Use point as decimal separator */
             char* pszComma = strchr(pszStr, ',');
             if (pszComma)
                 *pszComma = '.';
-            poKmlSimpleData->set_text ( pszStr );
+
+            if( bUseSimpleField )
+            {
+                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
+                poKmlSimpleData->set_name ( name );
+                poKmlSimpleData->set_text ( pszStr );
+            }
+            else
+            {
+                poKmlData = poKmlFactory->CreateData (  );
+                poKmlData->set_name ( name );
+                poKmlData->set_value ( pszStr );
+            }
+
             CPLFree(pszStr);
 
             break;
@@ -717,22 +852,43 @@ void field2kml (
 
         /***** other *****/
 
-            poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-            poKmlSimpleData->set_name ( name );
-            poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+            if( bUseSimpleField )
+            {
+                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
+                poKmlSimpleData->set_name ( name );
+                poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+            }
+            else
+            {
+                poKmlData = poKmlFactory->CreateData (  );
+                poKmlData->set_name ( name );
+                poKmlData->set_value ( poOgrFeat->GetFieldAsString ( i ) );
+            }
 
             break;
         }
-        poKmlSchemaData->add_simpledata ( poKmlSimpleData );
+        
+        if( poKmlSimpleData )
+        {
+            poKmlSchemaData->add_simpledata ( poKmlSimpleData );
+        }
+        else if( poKmlData )
+        {
+            if( poKmlExtendedData == NULL )
+                poKmlExtendedData = poKmlFactory->CreateExtendedData (  );
+            poKmlExtendedData->add_data ( poKmlData );
+        }
     }
 
     /***** dont add it to the placemark unless there is data *****/
 
-    if ( poKmlSchemaData->get_simpledata_array_size (  ) > 0 ) {
-        ExtendedDataPtr poKmlExtendedData =
-            poKmlFactory->CreateExtendedData (  );
+    if ( bUseSimpleField && poKmlSchemaData->get_simpledata_array_size (  ) > 0 ) {
+        poKmlExtendedData = poKmlFactory->CreateExtendedData (  );
         poKmlExtendedData->add_schemadata ( poKmlSchemaData );
-        poKmlPlacemark->set_extendeddata ( poKmlExtendedData );
+    }
+    if( poKmlExtendedData != NULL )
+    {
+        poKmlFeature->set_extendeddata ( poKmlExtendedData );
     }
 
     return;
@@ -963,6 +1119,96 @@ int kml2tessellate_rec (
     return FALSE;
 }
 
+/************************************************************************/
+/*                     ogrkmlSetAltitudeMode()                          */
+/************************************************************************/
+
+static void ogrkmlSetAltitudeMode(OGRFeature* poOgrFeat, int iField,
+                                  int nAltitudeMode, int bIsGX)
+{
+    if ( !bIsGX ) {
+        switch ( nAltitudeMode ) {
+        case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
+            poOgrFeat->SetField ( iField, "clampToGround" );
+            break;
+
+        case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
+            poOgrFeat->SetField ( iField, "relativeToGround" );
+            break;
+
+        case kmldom::ALTITUDEMODE_ABSOLUTE:
+            poOgrFeat->SetField ( iField, "absolute" );
+            break;
+
+        }
+    }
+
+    else {
+        switch ( nAltitudeMode ) {
+        case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
+            poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
+            break;
+
+        case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
+            poOgrFeat->SetField ( iField, "clampToSeaFloor" );
+            break;
+        }
+    }
+}
+
+/************************************************************************/
+/*                            TrimSpaces()                              */
+/************************************************************************/
+
+static const char* TrimSpaces(string& oText)
+{
+
+    /* SerializePretty() adds a new line before the data */
+    /* ands trailing spaces. I believe this is wrong */
+    /* as it breaks round-tripping */
+
+    /* Trim trailing spaces */
+    while (oText.size() != 0 && oText[oText.size()-1] == ' ')
+        oText.resize(oText.size()-1);
+
+    /* Skip leading newline and spaces */
+    const char* pszText = oText.c_str (  );
+    if (pszText[0] == '\n')
+        pszText ++;
+    while (pszText[0] == ' ')
+        pszText ++;
+
+    return pszText;
+}
+
+/************************************************************************/
+/*                            kmldatetime2ogr()                         */
+/************************************************************************/
+
+static void kmldatetime2ogr( OGRFeature* poOgrFeat,
+                             const char* pszOGRField,
+                             const std::string& osKmlDateTime )
+{
+    int iField = poOgrFeat->GetFieldIndex ( pszOGRField );
+
+    if ( iField > -1 ) {
+        int nYear,
+            nMonth,
+            nDay,
+            nHour,
+            nMinute,
+            nTZ;
+        float fSecond;
+
+        if ( OGRParseXMLDateTime
+                ( osKmlDateTime.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
+                &nMinute, &fSecond, &nTZ ) )
+            poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
+                                    nHour, nMinute, ( int )fSecond,
+                                    nTZ );
+    }
+}
+
 /******************************************************************************
  function to read kml into ogr fields
 ******************************************************************************/
@@ -1008,26 +1254,7 @@ void kml2field (
 
             if ( poKmlTimeStamp->has_when (  ) ) {
                 const std::string oKmlWhen = poKmlTimeStamp->get_when (  );
-
-
-                int iField = poOgrFeat->GetFieldIndex ( oFC.tsfield );
-
-                if ( iField > -1 ) {
-                    int nYear,
-                        nMonth,
-                        nDay,
-                        nHour,
-                        nMinute,
-                        nTZ;
-                    float fSecond;
-
-                    if ( OGRParseXMLDateTime
-                         ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
-                           &nMinute, &fSecond, &nTZ ) )
-                        poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
-                                              nHour, nMinute, ( int )fSecond,
-                                              nTZ );
-                }
+                kmldatetime2ogr(poOgrFeat, oFC.tsfield, oKmlWhen );
             }
         }
 
@@ -1040,57 +1267,18 @@ void kml2field (
 
             if ( poKmlTimeSpan->has_begin (  ) ) {
                 const std::string oKmlWhen = poKmlTimeSpan->get_begin (  );
-
-
-                int iField = poOgrFeat->GetFieldIndex ( oFC.beginfield );
-
-                if ( iField > -1 ) {
-                    int nYear,
-                        nMonth,
-                        nDay,
-                        nHour,
-                        nMinute,
-                        nTZ;
-                    float fSecond;
-
-                    if ( OGRParseXMLDateTime
-                         ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
-                           &nMinute, &fSecond, &nTZ ) )
-                        poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
-                                              nHour, nMinute, ( int )fSecond,
-                                              nTZ );
-                }
+                kmldatetime2ogr(poOgrFeat, oFC.beginfield, oKmlWhen );
             }
 
             /***** end *****/
 
             if ( poKmlTimeSpan->has_end (  ) ) {
                 const std::string oKmlWhen = poKmlTimeSpan->get_end (  );
-
-
-                int iField = poOgrFeat->GetFieldIndex ( oFC.endfield );
-
-                if ( iField > -1 ) {
-                    int nYear,
-                        nMonth,
-                        nDay,
-                        nHour,
-                        nMinute,
-                        nTZ;
-                    float fSecond;
-
-                    if ( OGRParseXMLDateTime
-                         ( oKmlWhen.c_str (  ), &nYear, &nMonth, &nDay, &nHour,
-                           &nMinute, &fSecond, &nTZ ) )
-                        poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
-                                              nHour, nMinute, ( int )fSecond,
-                                              nTZ );
-                }
+                kmldatetime2ogr(poOgrFeat, oFC.endfield, oKmlWhen );
             }
         }
     }
 
-
     /***** placemark *****/
     
     PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
@@ -1110,37 +1298,7 @@ void kml2field (
 
             if ( kml2altitudemode_rec ( poKmlGeometry,
                                         &nAltitudeMode, &bIsGX ) ) {
-
-                if ( !bIsGX ) {
-
-                    switch ( nAltitudeMode ) {
-                    case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
-                        poOgrFeat->SetField ( iField, "clampToGround" );
-                        break;
-
-                    case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
-                        poOgrFeat->SetField ( iField, "relativeToGround" );
-                        break;
-
-                    case kmldom::ALTITUDEMODE_ABSOLUTE:
-                        poOgrFeat->SetField ( iField, "absolute" );
-                        break;
-
-                    }
-                }
-
-                else {
-                    switch ( nAltitudeMode ) {
-                    case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
-                        poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
-                        break;
-
-                    case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
-                        poOgrFeat->SetField ( iField, "clampToSeaFloor" );
-                        break;
-                    }
-
-                }
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, bIsGX);
             }
 
         }
@@ -1165,6 +1323,66 @@ void kml2field (
         if ( iField > -1 )
             poOgrFeat->SetField ( iField, nExtrude );
 
+        /***** special case for gx:Track ******/
+        /* we set the first timestamp as begin and the last one as end */
+        if ( poKmlGeometry->Type (  )  == kmldom::Type_GxTrack && 
+             !poKmlFeature->has_timeprimitive (  ) ) {
+            GxTrackPtr poKmlGxTrack = AsGxTrack ( poKmlGeometry );
+            size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
+            if( nCoords > 0 )
+            {
+                kmldatetime2ogr(poOgrFeat, oFC.beginfield,
+                            poKmlGxTrack->get_when_array_at ( 0 ).c_str() );
+                kmldatetime2ogr(poOgrFeat, oFC.endfield,
+                            poKmlGxTrack->get_when_array_at ( nCoords - 1 ).c_str() );
+            }
+        }
+    }
+    
+    /***** camera *****/
+    
+    else if ( poKmlPlacemark &&
+              poKmlPlacemark->has_abstractview (  ) &&
+              poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) ) {
+
+        const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
+
+        if( camera->has_heading() )
+        {
+            int iField = poOgrFeat->GetFieldIndex ( oFC.headingfield );
+            if ( iField > -1 )
+                poOgrFeat->SetField ( iField, camera->get_heading() );
+        }
+
+        if( camera->has_tilt() )
+        {
+            int iField = poOgrFeat->GetFieldIndex ( oFC.tiltfield );
+            if ( iField > -1 )
+                poOgrFeat->SetField ( iField, camera->get_tilt() );
+        }
+
+        if( camera->has_roll() )
+        {
+            int iField = poOgrFeat->GetFieldIndex ( oFC.rollfield );
+            if ( iField > -1 )
+                poOgrFeat->SetField ( iField, camera->get_roll() );
+        }
+
+        int nAltitudeMode = -1;
+
+        int iField = poOgrFeat->GetFieldIndex ( oFC.altitudeModefield );
+
+        if ( iField > -1 ) {
+
+            if ( camera->has_altitudemode (  ) ) {
+                nAltitudeMode = camera->get_altitudemode (  );
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, FALSE);
+            }
+            else if ( camera->has_gx_altitudemode (  ) ) {
+                nAltitudeMode = camera->get_gx_altitudemode (  );
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, TRUE);
+            }
+        }
     }
 
     /***** ground overlay *****/
@@ -1243,6 +1461,19 @@ void kml2field (
     if ( iField > -1 )
         poOgrFeat->SetField ( iField, nVisibility );
 
+    /***** snippet *****/
+
+    if ( poKmlFeature->has_snippet (  ) )
+    {
+        string oText = poKmlFeature->get_snippet (  )->get_text();
+
+        iField = poOgrFeat->GetFieldIndex ( oFC.snippetfield );
+
+        if ( iField > -1 )
+            poOgrFeat->SetField ( iField, TrimSpaces(oText) );
+    }
+
+    /***** extended schema *****/
     ExtendedDataPtr poKmlExtendedData = NULL;
 
     if ( poKmlFeature->has_extendeddata (  ) ) {
@@ -1285,22 +1516,7 @@ void kml2field (
                 if ( iField > -1 && poKmlSimpleData->has_text (  ) ) {
                     string oText = poKmlSimpleData->get_text (  );
 
-                    /* SerializePretty() adds a new line before the data */
-                    /* ands trailing spaces. I believe this is wrong */
-                    /* as it breaks round-tripping */
-
-                    /* Trim trailing spaces */
-                    while (oText.size() != 0 && oText[oText.size()-1] == ' ')
-                        oText.resize(oText.size()-1);
-
-                    /* Skip leading newline and spaces */
-                    const char* pszText = oText.c_str (  );
-                    if (pszText[0] == '\n')
-                        pszText ++;
-                    while (pszText[0] == ' ')
-                        pszText ++;
-
-                    poOgrFeat->SetField ( iField, pszText );
+                    poOgrFeat->SetField ( iField, TrimSpaces(oText) );
                 }
             }
         }
@@ -1338,28 +1554,70 @@ SimpleFieldPtr FieldDef2kml (
     OGRFieldDefn * poOgrFieldDef,
     KmlFactory * poKmlFactory )
 {
+    /***** get the field config *****/
+
+    struct fieldconfig oFC;
+    get_fieldconfig( &oFC );
 
-    SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField (  );
     const char *pszFieldName = poOgrFieldDef->GetNameRef (  );
 
+    if ( EQUAL ( pszFieldName, oFC.namefield ) ||
+         EQUAL ( pszFieldName, oFC.descfield ) ||
+         EQUAL ( pszFieldName, oFC.tsfield ) ||
+         EQUAL ( pszFieldName, oFC.beginfield ) ||
+         EQUAL ( pszFieldName, oFC.endfield ) ||
+         EQUAL ( pszFieldName, oFC.altitudeModefield ) ||
+         EQUAL ( pszFieldName, oFC.tessellatefield ) ||
+         EQUAL ( pszFieldName, oFC.extrudefield ) ||
+         EQUAL ( pszFieldName, oFC.visibilityfield ) ||
+         EQUAL ( pszFieldName, oFC.drawOrderfield ) ||
+         EQUAL ( pszFieldName, oFC.iconfield ) ||
+         EQUAL ( pszFieldName, oFC.headingfield ) ||
+         EQUAL ( pszFieldName, oFC.tiltfield ) ||
+         EQUAL ( pszFieldName, oFC.rollfield ) ||
+         EQUAL ( pszFieldName, oFC.snippetfield ) ||
+         EQUAL ( pszFieldName, oFC.modelfield ) ||
+         EQUAL ( pszFieldName, oFC.scalexfield ) ||
+         EQUAL ( pszFieldName, oFC.scaleyfield ) ||
+         EQUAL ( pszFieldName, oFC.scalezfield ) ||
+         EQUAL ( pszFieldName, oFC.networklinkfield ) ||
+         EQUAL ( pszFieldName, oFC.networklink_refreshvisibility_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_flytoview_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_refreshMode_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_refreshInterval_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_viewRefreshMode_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_viewRefreshTime_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_viewBoundScale_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_viewFormat_field ) ||
+         EQUAL ( pszFieldName, oFC.networklink_httpQuery_field ) ||
+         EQUAL ( pszFieldName, oFC.camera_longitude_field ) ||
+         EQUAL ( pszFieldName, oFC.camera_latitude_field ) ||
+         EQUAL ( pszFieldName, oFC.camera_altitude_field ) ||
+         EQUAL ( pszFieldName, oFC.camera_altitudemode_field ) ||
+         EQUAL ( pszFieldName, oFC.photooverlayfield ) ||
+         EQUAL ( pszFieldName, oFC.leftfovfield ) ||
+         EQUAL ( pszFieldName, oFC.rightfovfield ) ||
+         EQUAL ( pszFieldName, oFC.bottomfovfield ) ||
+         EQUAL ( pszFieldName, oFC.topfovfield ) ||
+         EQUAL ( pszFieldName, oFC.nearfield ) ||
+         EQUAL ( pszFieldName, oFC.photooverlay_shape_field ) ||
+         EQUAL ( pszFieldName, oFC.imagepyramid_tilesize_field) ||
+         EQUAL ( pszFieldName, oFC.imagepyramid_maxwidth_field) ||
+         EQUAL ( pszFieldName, oFC.imagepyramid_maxheight_field) ||
+         EQUAL ( pszFieldName, oFC.imagepyramid_gridorigin_field) )
+    {
+        return NULL;
+    }
+
+    SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField (  );
     poKmlSimpleField->set_name ( pszFieldName );
 
-	/***** get the field config *****/
-	
-	struct fieldconfig oFC;
-	get_fieldconfig( &oFC );
 
     SimpleDataPtr poKmlSimpleData = NULL;
 
     switch ( poOgrFieldDef->GetType (  ) ) {
-
     case OFTInteger:
     case OFTIntegerList:
-        if ( EQUAL ( pszFieldName, oFC.tessellatefield ) ||
-             EQUAL ( pszFieldName, oFC.extrudefield ) ||
-             EQUAL ( pszFieldName, oFC.visibilityfield ) ||
-             EQUAL ( pszFieldName, oFC.drawOrderfield ) )
-            break;
         poKmlSimpleField->set_type ( "int" );
         return poKmlSimpleField;
 			
@@ -1367,18 +1625,9 @@ SimpleFieldPtr FieldDef2kml (
     case OFTRealList:
         poKmlSimpleField->set_type ( "float" );
         return poKmlSimpleField;
-			
-    case OFTBinary:
-        poKmlSimpleField->set_type ( "bool" );
-        return poKmlSimpleField;
 	
     case OFTString:
     case OFTStringList:
-        if ( EQUAL ( pszFieldName, oFC.namefield ) ||
-             EQUAL ( pszFieldName, oFC.descfield ) ||
-             EQUAL ( pszFieldName, oFC.altitudeModefield ) ||
-             EQUAL ( pszFieldName, oFC.iconfield ) )
-            break;
         poKmlSimpleField->set_type ( "string" );
         return poKmlSimpleField;
 
@@ -1387,11 +1636,8 @@ SimpleFieldPtr FieldDef2kml (
     case OFTDate:
     case OFTTime:
     case OFTDateTime:
-        if ( EQUAL ( pszFieldName, oFC.tsfield )
-             || EQUAL ( pszFieldName, oFC.beginfield )
-             || EQUAL ( pszFieldName, oFC.endfield ) )
-            break;
-    
+        break;
+
     default:
         poKmlSimpleField->set_type ( "string" );
         return poKmlSimpleField;
@@ -1417,12 +1663,13 @@ void kml2FeatureDef (
             poKmlSchema->get_simplefield_array_at ( iSimpleField );
 
         const char *pszType = "string";
-    string osName = "Unknown";
+        string osName = "Unknown";
+        string osType;
 
         if ( poKmlSimpleField->has_type (  ) ) {
-            const string oType = poKmlSimpleField->get_type (  );
+            osType = poKmlSimpleField->get_type (  );
 
-            pszType = oType.c_str (  );
+            pszType = osType.c_str (  );
         }
 
         /* FIXME? We cannot set displayname as the field name because in kml2field() we make the */
@@ -1439,7 +1686,7 @@ void kml2FeatureDef (
             osName = poKmlSimpleField->get_name (  );
         }
 
-        if ( EQUAL ( pszType, "bool" ) ||
+        if ( EQUAL ( pszType, "boolean" ) ||
              EQUAL ( pszType, "int" ) ||
              EQUAL ( pszType, "short" ) ||
              EQUAL ( pszType, "ushort" ) ) {
@@ -1493,4 +1740,77 @@ void get_fieldconfig( struct fieldconfig *oFC) {
                                                        "drawOrder" );
     oFC->iconfield = CPLGetConfigOption ( "LIBKML_ICON_FIELD",
                                                   "icon" );
+    oFC->headingfield = CPLGetConfigOption( "LIBKML_HEADING_FIELD", "heading");
+    oFC->tiltfield = CPLGetConfigOption( "LIBKML_TILT_FIELD", "tilt");
+    oFC->rollfield = CPLGetConfigOption( "LIBKML_ROLL_FIELD", "roll");
+    oFC->snippetfield = CPLGetConfigOption( "LIBKML_SNIPPET_FIELD", "snippet");
+    oFC->modelfield = CPLGetConfigOption( "LIBKML_MODEL_FIELD", "model");
+    oFC->scalexfield = CPLGetConfigOption( "LIBKML_SCALE_X_FIELD", "scale_x");
+    oFC->scaleyfield = CPLGetConfigOption( "LIBKML_SCALE_Y_FIELD", "scale_y");
+    oFC->scalezfield = CPLGetConfigOption( "LIBKML_SCALE_Z_FIELD", "scale_z");
+    oFC->networklinkfield = CPLGetConfigOption( "LIBKML_NETWORKLINK_FIELD", "networklink");
+    oFC->networklink_refreshvisibility_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD", "networklink_refreshvisibility");
+    oFC->networklink_flytoview_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_FLYTOVIEW_FIELD", "networklink_flytoview");
+    oFC->networklink_refreshMode_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHMODE_FIELD", "networklink_refreshmode");
+    oFC->networklink_refreshInterval_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD", "networklink_refreshinterval");
+    oFC->networklink_viewRefreshMode_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD", "networklink_viewrefreshmode");
+    oFC->networklink_viewRefreshTime_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD", "networklink_viewrefreshtime");
+    oFC->networklink_viewBoundScale_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD", "networklink_viewboundscale");
+    oFC->networklink_viewFormat_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWFORMAT_FIELD", "networklink_viewformat");
+    oFC->networklink_httpQuery_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_HTTPQUERY_FIELD", "networklink_httpquery");
+    oFC->camera_longitude_field = CPLGetConfigOption( "LIBKML_CAMERA_LONGITUDE_FIELD", "camera_longitude");
+    oFC->camera_latitude_field = CPLGetConfigOption( "LIBKML_CAMERA_LATITUDE_FIELD", "camera_latitude");
+    oFC->camera_altitude_field = CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDE_FIELD", "camera_altitude");
+    oFC->camera_altitudemode_field = CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDEMODE_FIELD", "camera_altitudemode");
+    oFC->photooverlayfield = CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_FIELD", "photooverlay");
+    oFC->leftfovfield = CPLGetConfigOption( "LIBKML_LEFTFOV_FIELD", "leftfov");
+    oFC->rightfovfield = CPLGetConfigOption( "LIBKML_RIGHTFOV_FIELD", "rightfov");
+    oFC->bottomfovfield = CPLGetConfigOption( "LIBKML_BOTTOMFOV_FIELD", "bottomfov");
+    oFC->topfovfield = CPLGetConfigOption( "LIBKML_TOPFOV_FIELD", "topfov");
+    oFC->nearfield = CPLGetConfigOption( "LIBKML_NEARFOV_FIELD", "near");
+    oFC->photooverlay_shape_field = CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_SHAPE_FIELD", "photooverlay_shape");
+    oFC->imagepyramid_tilesize_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_TILESIZE", "imagepyramid_tilesize");
+    oFC->imagepyramid_maxwidth_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXWIDTH", "imagepyramid_maxwidth");
+    oFC->imagepyramid_maxheight_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXHEIGHT", "imagepyramid_maxheight");
+    oFC->imagepyramid_gridorigin_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_GRIDORIGIN", "imagepyramid_gridorigin");
+}
+
+/************************************************************************/
+/*                 kmlAltitudeModeFromString()                          */
+/************************************************************************/
+
+int kmlAltitudeModeFromString(const char* pszAltitudeMode,
+                              int& isGX)
+{
+    isGX = FALSE;
+    int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+
+    if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
+        iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+
+    else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
+        iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND;
+
+    else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
+        iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE;
+
+    else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
+        iAltitudeMode =
+            kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR;
+        isGX = TRUE;
+    }
+
+    else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
+        iAltitudeMode =
+            kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR;
+        isGX = TRUE;
+    }
+    else
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "Unrecognized value for altitudeMode: %s",
+                 pszAltitudeMode);
+    }
+
+    return iAltitudeMode;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
index ae94b40..1fa885a 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -58,7 +59,8 @@ void field2kml (
     OGRFeature * poOgrFeat,
     OGRLIBKMLLayer * poOgrLayer,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark );
+    FeaturePtr poKmlPlacemark,
+    int bUseSimpleField );
 
 /******************************************************************************
  function to read kml into ogr fields
@@ -101,7 +103,42 @@ struct fieldconfig {
     const char *visibilityfield;
     const char *drawOrderfield;
     const char *iconfield;
+    const char *headingfield;
+    const char *tiltfield;
+    const char *rollfield;
+    const char *snippetfield;
+    const char *modelfield;
+    const char *scalexfield;
+    const char *scaleyfield;
+    const char *scalezfield;
+    const char *networklinkfield;
+    const char *networklink_refreshvisibility_field;
+    const char *networklink_flytoview_field;
+    const char *networklink_refreshMode_field;
+    const char *networklink_refreshInterval_field;
+    const char *networklink_viewRefreshMode_field;
+    const char *networklink_viewRefreshTime_field;
+    const char *networklink_viewBoundScale_field;
+    const char *networklink_viewFormat_field;
+    const char *networklink_httpQuery_field;
+    const char *camera_longitude_field;
+    const char *camera_latitude_field;
+    const char *camera_altitude_field;
+    const char *camera_altitudemode_field;
+    const char *photooverlayfield;
+    const char *leftfovfield;
+    const char *rightfovfield;
+    const char *bottomfovfield;
+    const char *topfovfield;
+    const char *nearfield;
+    const char *photooverlay_shape_field;
+    const char *imagepyramid_tilesize_field;
+    const char *imagepyramid_maxwidth_field;
+    const char *imagepyramid_maxheight_field;
+    const char *imagepyramid_gridorigin_field;
 };
 
 void get_fieldconfig( struct fieldconfig *oFC );
 
+int kmlAltitudeModeFromString(const char* pszAltitudeMode,
+                              int& isGX);
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
index b666a16..0e61f0b 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -44,6 +45,7 @@ using kmldom::GeometryPtr;
 using kmldom::ElementPtr;
 using kmldom::GeometryPtr;
 using kmldom::GxLatLonQuadPtr;
+using kmldom::GxTrackPtr;
 
 using kmlbase::Vec3;
 
@@ -104,7 +106,7 @@ ElementPtr geom2kml (
 
     int numpoints = 0;
     int nGeom;
-    int type = poOgrGeom->getGeometryType (  );
+    OGRwkbGeometryType type = poOgrGeom->getGeometryType (  );
 
     wkb25D = type & wkb25DBit;
 
@@ -153,9 +155,33 @@ ElementPtr geom2kml (
     case wkbLineString:
         poOgrLineString = ( OGRLineString * ) poOgrGeom;
 
-        coordinates = poKmlFactory->CreateCoordinates (  );
+        if( extra >= 0 )
+        {
+            ((OGRLinearRing*)poOgrGeom)->closeRings();
+        }
 
         numpoints = poOgrLineString->getNumPoints (  );
+        if( extra >= 0 )
+        {
+            if( numpoints < 4 && 
+                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
+                return NULL;
+            }
+        }
+        else
+        {
+            if( numpoints < 2 && 
+                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
+                return NULL;
+            }
+        }
+
+        coordinates = poKmlFactory->CreateCoordinates (  );
+
         poOgrPoint = new OGRPoint (  );
 
         for ( i = 0; i < numpoints; i++ ) {
@@ -204,9 +230,34 @@ ElementPtr geom2kml (
 
         poOgrLineString = ( OGRLineString * ) poOgrGeom;
 
+        if( extra >= 0 )
+        {
+            ((OGRLinearRing*)poOgrGeom)->closeRings();
+        }
+
+        numpoints = poOgrLineString->getNumPoints (  );
+        if( extra >= 0 )
+        {
+            if( numpoints < 4 && 
+                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
+                return NULL;
+            }
+        }
+        else
+        {
+            if( numpoints < 2 && 
+                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
+                return NULL;
+            }
+        }
+
         coordinates = poKmlFactory->CreateCoordinates (  );
         poOgrPoint = new OGRPoint (  );
-        numpoints = poOgrLineString->getNumPoints (  );
+
         for ( i = 0; i < numpoints; i++ ) {
             poOgrLineString->getPoint ( i, poOgrPoint );
 
@@ -253,6 +304,14 @@ ElementPtr geom2kml (
 
     case wkbPolygon:
 
+        CPLErrorReset();
+        if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+            OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
+             CPLGetLastErrorType() != CE_None) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Invalid polygon");
+            return NULL;
+        }
         poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
 
         poKmlGeometry = poKmlPolygon = poKmlFactory->CreatePolygon (  );
@@ -274,6 +333,14 @@ ElementPtr geom2kml (
 
     case wkbPolygon25D:
 
+        CPLErrorReset();
+        if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+            OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
+             CPLGetLastErrorType() != CE_None) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Invalid polygon");
+            return NULL;
+        }
         poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
 
         poKmlGeometry = poKmlPolygon = poKmlFactory->CreatePolygon (  );
@@ -304,15 +371,30 @@ ElementPtr geom2kml (
 
         poOgrMultiGeom = ( OGRGeometryCollection * ) poOgrGeom;
 
-        poKmlGeometry = poKmlMultiGeometry =
-            poKmlFactory->CreateMultiGeometry (  );
-
         nGeom = poOgrMultiGeom->getNumGeometries (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            poKmlTmpGeometry = geom2kml ( poOgrMultiGeom->getGeometryRef ( i ),
-                                          -1, wkb25D, poKmlFactory );
-            poKmlMultiGeometry->
-                add_geometry ( AsGeometry ( poKmlTmpGeometry ) );
+
+        if( nGeom == 1 && 
+            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        {
+            CPLDebug("LIBKML", "Turning multiple geometry into single geometry");
+            poKmlGeometry = geom2kml( poOgrMultiGeom->getGeometryRef ( 0 ),
+                                      -1, wkb25D, poKmlFactory );
+        }
+        else
+        {
+            if( nGeom == 0 && 
+                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "Empty multi geometry are not recommended");
+            }
+            poKmlGeometry = poKmlMultiGeometry =
+                poKmlFactory->CreateMultiGeometry (  );
+            for ( i = 0; i < nGeom; i++ ) {
+                poKmlTmpGeometry = geom2kml ( poOgrMultiGeom->getGeometryRef ( i ),
+                                            -1, wkb25D, poKmlFactory );
+                poKmlMultiGeometry->
+                    add_geometry ( AsGeometry ( poKmlTmpGeometry ) );
+            }
         }
 
         break;
@@ -366,6 +448,7 @@ OGRGeometry *kml2geom_rec (
     InnerBoundaryIsPtr poKmlInnerRing;
     PolygonPtr poKmlPolygon;
     MultiGeometryPtr poKmlMultiGeometry;
+    GxTrackPtr poKmlGxTrack;
     GeometryPtr poKmlTmpGeometry;
 
     Vec3 oKmlVec;
@@ -521,6 +604,26 @@ OGRGeometry *kml2geom_rec (
         poOgrGeometry = poOgrMultiGeometry;
         break;
     }
+    
+    case kmldom::Type_GxTrack:
+        poKmlGxTrack = AsGxTrack ( poKmlGeometry );
+        nCoords = poKmlGxTrack->get_gx_coord_array_size();
+        poOgrLineString = new OGRLineString (  );
+        for ( i = 0; i < nCoords; i++ ) {
+            oKmlVec = poKmlGxTrack->get_gx_coord_array_at ( i );
+            if ( oKmlVec.has_altitude (  ) )
+                poOgrLineString->
+                    addPoint ( oKmlVec.get_longitude (  ),
+                                oKmlVec.get_latitude (  ),
+                                oKmlVec.get_altitude (  ) );
+            else
+                poOgrLineString->
+                    addPoint ( oKmlVec.get_longitude (  ),
+                                oKmlVec.get_latitude (  ) );
+        }
+        poOgrGeometry = poOgrLineString;
+        break;
+
     default:
         break;
     }
@@ -539,7 +642,6 @@ OGRGeometry *kml2geom_latlonbox_int (
 {
     OGRPolygon *poOgrPolygon;
     double north, south, east, west;
-    poOgrPolygon = new OGRPolygon (  );
     if ( !poKmlLatLonBox->has_north (  ) ||
          !poKmlLatLonBox->has_south (  ) ||
          !poKmlLatLonBox->has_east (  ) ||
@@ -547,6 +649,7 @@ OGRGeometry *kml2geom_latlonbox_int (
 
         return NULL;
     }
+    poOgrPolygon = new OGRPolygon (  );
     north = poKmlLatLonBox->get_north (  );
     south = poKmlLatLonBox->get_south (  );
     east = poKmlLatLonBox->get_east (  );
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
index a8aac5a..bc46414 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -48,11 +49,50 @@ using kmlengine::Bbox;
 using kmldom::ExtendedDataPtr;
 using kmldom::SchemaDataPtr;
 using kmldom::DataPtr;
+using kmldom::CameraPtr;
+using kmldom::LookAtPtr;
+using kmldom::RegionPtr;
+using kmldom::LatLonAltBoxPtr;
+using kmldom::LodPtr;
+using kmldom::ScreenOverlayPtr;
+using kmldom::IconPtr;
+using kmldom::CreatePtr;
+using kmldom::ChangePtr;
+using kmldom::DeletePtr;
 
 #include "ogrlibkmlfeature.h"
 #include "ogrlibkmlfield.h"
 #include "ogrlibkmlstyle.h"
 
+/************************************************************************/
+/*                    OGRLIBKMLGetSanitizedNCName()                     */
+/************************************************************************/
+
+CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName)
+{
+    CPLString osName(pszName);
+    /* (Approximate) validation rules for a valic NCName */
+    for(size_t i = 0; i < osName.size(); i++)
+    {
+        char ch = osName[i];
+        if( (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= 'a' && ch <= 'z') )
+        {
+            /* ok */
+        }
+        else if ( i > 0 && (ch == '-' || ch == '.' || (ch >= '0' && ch <= '9')) )
+        {
+            /* ok */
+        }
+        else if ( ch > 127 )
+        {
+            /* ok : this is an approximation */
+        }
+        else
+            osName[i] = '_';
+    }
+    return osName;
+}
+
 /******************************************************************************
  OGRLIBKMLLayer constructor
 
@@ -61,6 +101,7 @@ using kmldom::DataPtr;
                 eGType          the layers geometry type
                 poOgrDS         pointer to the datasource the layer is in
                 poKmlRoot       pointer to the root kml element of the layer
+                poKmlContainer  pointer to the kml container of the layer
                 pszFileName     the filename of the layer
                 bNew            true if its a new layer
                 bUpdate         true if the layer is writeable
@@ -75,6 +116,7 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
                                  OGRLIBKMLDataSource * poOgrDS,
                                  ElementPtr poKmlRoot,
                                  ContainerPtr poKmlContainer,
+                                 UpdatePtr poKmlUpdate,
                                  const char *pszFileName,
                                  int bNew,
                                  int bUpdate )
@@ -86,6 +128,7 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     nFID = 1;
 
     this->bUpdate = bUpdate;
+    bUpdated = FALSE;
     m_pszName = CPLStrdup ( pszLayerName );
     m_pszFileName = CPLStrdup ( pszFileName );
     m_poOgrDS = poOgrDS;
@@ -96,6 +139,8 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     m_poOgrFeatureDefn = new OGRFeatureDefn ( pszLayerName );
     m_poOgrFeatureDefn->Reference (  );
     m_poOgrFeatureDefn->SetGeomType ( eGType );
+    if( m_poOgrFeatureDefn->GetGeomFieldCount() != 0 )
+        m_poOgrFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poOgrSRS);
 
     /***** store the root element pointer *****/
 
@@ -104,10 +149,32 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     /***** store the layers container *****/
 
     m_poKmlLayer = poKmlContainer;
+    
+    /* update container */
+    m_poKmlUpdate = poKmlUpdate;
+
+    m_poKmlSchema = NULL;
+
+    /***** related to Region *****/
+
+    m_bWriteRegion = FALSE;
+    m_bRegionBoundsAuto = FALSE;
+    m_dfRegionMinLodPixels = 0;
+    m_dfRegionMaxLodPixels = -1;
+    m_dfRegionMinFadeExtent = 0;
+    m_dfRegionMaxFadeExtent = 0;
+    m_dfRegionMinX = 200;
+    m_dfRegionMinY = 200;
+    m_dfRegionMaxX = -200;
+    m_dfRegionMaxY = -200;
 
-    /***** was the layer created from a DS::Open *****/
 
     m_bReadGroundOverlay = CSLTestBoolean(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
+    m_bUseSimpleField = CSLTestBoolean(CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"));
+    
+    m_bUpdateIsFolder = FALSE;
+
+    /***** was the layer created from a DS::Open *****/
 
     if ( !bNew ) {
 
@@ -182,8 +249,6 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
 
         /***** get the schema if the layer is a Document *****/
 
-        m_poKmlSchema = NULL;
-
         if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) ) {
             DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
 
@@ -199,6 +264,8 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
 
             /***** try to find the correct schema *****/
 
+            int bHasHeading = FALSE, bHasTilt = FALSE, bHasRoll = FALSE;
+            int bHasSnippet = FALSE;
             FeaturePtr poKmlFeature;
 
             /***** find the first placemark *****/
@@ -210,6 +277,40 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
                 poKmlFeature =
                     m_poKmlLayer->get_feature_array_at ( iFeature++ );
 
+                if( poKmlFeature->Type() == kmldom::Type_Placemark )
+                {
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
+                    if( !poKmlPlacemark->has_geometry (  ) &&
+                        poKmlPlacemark->has_abstractview (  ) &&
+                        poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) )
+                    {
+                        const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
+                        if( camera->has_heading() && !bHasHeading )
+                        {
+                            bHasHeading = TRUE;
+                            OGRFieldDefn oOgrField ( oFC.headingfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                        }
+                        if( camera->has_tilt() && !bHasTilt )
+                        {
+                            bHasTilt = TRUE;
+                            OGRFieldDefn oOgrField ( oFC.tiltfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                        }
+                        if( camera->has_roll() && !bHasRoll )
+                        {
+                            bHasRoll = TRUE;
+                            OGRFieldDefn oOgrField ( oFC.rollfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                        }
+                    }
+                }
+                if( !bHasSnippet && poKmlFeature->has_snippet() )
+                {
+                    bHasSnippet = TRUE;
+                    OGRFieldDefn oOgrField ( oFC.snippetfield, OFTString );
+                    m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                }
             } while ( poKmlFeature->Type (  ) != kmldom::Type_Placemark );
 
             if ( iFeature <= nFeatures && poKmlFeature &&
@@ -277,23 +378,8 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
         /***** mark the layer as updated *****/
 
         bUpdated = TRUE;
-
-        /***** create a new schema *****/
-
-        KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
-
-        m_poKmlSchema = poKmlFactory->CreateSchema (  );
-
-        /***** set the id on the new schema *****/
-
-        std::string oKmlSchemaID = m_pszName;
-        oKmlSchemaID.append ( ".schema" );
-        m_poKmlSchema->set_id ( oKmlSchemaID );
     }
 
-
-
-
 }
 
 /******************************************************************************
@@ -363,6 +449,9 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
 {
     FeaturePtr poKmlFeature;
     OGRFeature *poOgrFeature = NULL;
+    
+    if( m_poKmlLayer == NULL )
+        return NULL;
 
     /***** loop over the kml features to find the next placemark *****/
 
@@ -426,15 +515,143 @@ OGRErr OGRLIBKMLLayer::CreateFeature (
     if ( !bUpdate )
         return OGRERR_UNSUPPORTED_OPERATION;
 
-    PlacemarkPtr poKmlPlacemark =
-        feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory (  ) );
+    if( m_bRegionBoundsAuto && poOgrFeat->GetGeometryRef() != NULL &&
+        !(poOgrFeat->GetGeometryRef()->IsEmpty()) )
+    {
+        OGREnvelope sEnvelope;
+        poOgrFeat->GetGeometryRef()->getEnvelope(&sEnvelope);
+        m_dfRegionMinX = MIN(m_dfRegionMinX, sEnvelope.MinX);
+        m_dfRegionMinY = MIN(m_dfRegionMinY, sEnvelope.MinY);
+        m_dfRegionMaxX = MAX(m_dfRegionMaxX, sEnvelope.MaxX);
+        m_dfRegionMaxY = MAX(m_dfRegionMaxY, sEnvelope.MaxY);
+    }
+
+    FeaturePtr poKmlFeature =
+        feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory (  ),
+                   m_bUseSimpleField );
 
-    m_poKmlLayer->add_feature ( poKmlPlacemark );
+    if( m_poKmlLayer != NULL )
+        m_poKmlLayer->add_feature ( poKmlFeature );
+    else
+    {
+        CPLAssert( m_poKmlUpdate != NULL );
+        KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+        CreatePtr poCreate = poKmlFactory->CreateCreate();
+        ContainerPtr poContainer;
+        if( m_bUpdateIsFolder )
+            poContainer = poKmlFactory->CreateFolder();
+        else
+            poContainer = poKmlFactory->CreateDocument();
+        poContainer->set_targetid(OGRLIBKMLGetSanitizedNCName(GetName()));
+        poContainer->add_feature ( poKmlFeature );
+        poCreate->add_container(poContainer);
+        m_poKmlUpdate->add_updateoperation(poCreate);
+    }
 
     /***** update the layer class count of features  *****/
 
-    nFeatures++;
+    if( m_poKmlLayer != NULL )
+    {
+        nFeatures++;
+        
+        const char* pszId = CPLSPrintf("%s.%d",
+                        OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFeatures);
+        poOgrFeat->SetFID(nFeatures);
+        poKmlFeature->set_id(pszId);
+    }
+    else
+    {
+        if( poOgrFeat->GetFID() < 0 )
+        {
+            static int bAlreadyWarned = FALSE;
+            if( !bAlreadyWarned )
+            {
+                bAlreadyWarned = TRUE;
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "It is recommanded to define a FID when calling CreateFeature() in a update document");
+            }
+        }
+        else
+        {
+            const char* pszId = CPLSPrintf("%s.%ld",
+                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), poOgrFeat->GetFID());
+            poOgrFeat->SetFID(nFeatures);
+            poKmlFeature->set_id(pszId);
+        }
+    }
+
+    /***** mark the layer as updated *****/
+
+    bUpdated = TRUE;
+    m_poOgrDS->Updated (  );
+
+    return OGRERR_NONE;
+}
+
+
+/******************************************************************************
+ method to update a feature to a layer. Only work on a NetworkLinkControl/Update
+
+ Args:          poOgrFeat   pointer to the feature to update
+ 
+ Returns:       OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
+                not writeable
+
+******************************************************************************/
+
+OGRErr OGRLIBKMLLayer::SetFeature ( OGRFeature * poOgrFeat )
+{
+    if( !bUpdate || m_poKmlUpdate == NULL )
+        return OGRERR_UNSUPPORTED_OPERATION;
+    if( poOgrFeat->GetFID() == OGRNullFID )
+        return OGRERR_FAILURE;
+
+    FeaturePtr poKmlFeature =
+        feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory (  ),
+                   m_bUseSimpleField );
+
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    ChangePtr poChange = poKmlFactory->CreateChange();
+    poChange->add_object(poKmlFeature);
+    m_poKmlUpdate->add_updateoperation(poChange);
+    
+    const char* pszId = CPLSPrintf("%s.%ld",
+                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), poOgrFeat->GetFID());
+    poKmlFeature->set_targetid(pszId);
+
+    /***** mark the layer as updated *****/
+
+    bUpdated = TRUE;
+    m_poOgrDS->Updated (  );
+
+    return OGRERR_NONE;
+}
+
+/******************************************************************************
+ method to delete a feature to a layer. Only work on a NetworkLinkControl/Update
+
+ Args:          nFID   id of the feature to delete
+ 
+ Returns:       OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
+                not writeable
+
+******************************************************************************/
+
+OGRErr OGRLIBKMLLayer::DeleteFeature( long nFID )
+{
+    if( !bUpdate || m_poKmlUpdate == NULL )
+        return OGRERR_UNSUPPORTED_OPERATION;
+
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    DeletePtr poDelete = poKmlFactory->CreateDelete();
+    m_poKmlUpdate->add_updateoperation(poDelete);
+    PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
+    poDelete->add_feature(poKmlPlacemark);
     
+    const char* pszId = CPLSPrintf("%s.%ld",
+                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFID);
+    poKmlPlacemark->set_targetid(pszId);
+
     /***** mark the layer as updated *****/
 
     bUpdated = TRUE;
@@ -465,7 +682,7 @@ int OGRLIBKMLLayer::GetFeatureCount (
         i = OGRLayer::GetFeatureCount( bForce );
     }
 
-    else {
+    else if( m_poKmlLayer != NULL ) {
         size_t iKmlFeature; 
         size_t nKmlFeatures = m_poKmlLayer->get_feature_array_size (  );
         FeaturePtr poKmlFeature;
@@ -514,7 +731,8 @@ OGRErr OGRLIBKMLLayer::GetExtent (
 {
     Bbox oKmlBbox;
 
-    if ( kmlengine::
+    if ( m_poKmlLayer != NULL &&
+        kmlengine::
          GetFeatureBounds ( AsFeature ( m_poKmlLayer ), &oKmlBbox ) ) {
         psExtent->MinX = oKmlBbox.get_west (  );
         psExtent->MinY = oKmlBbox.get_south (  );
@@ -549,11 +767,31 @@ OGRErr OGRLIBKMLLayer::CreateField (
     if ( !bUpdate )
         return OGRERR_UNSUPPORTED_OPERATION;
 
-    SimpleFieldPtr poKmlSimpleField = NULL;
+    if( m_bUseSimpleField )
+    {
+        SimpleFieldPtr poKmlSimpleField = NULL;
+
+        if ( (poKmlSimpleField =
+            FieldDef2kml ( poField, m_poOgrDS->GetKmlFactory (  ) )) != NULL )
+        {
+            if( m_poKmlSchema == NULL )
+            {
+                /***** create a new schema *****/
+
+                KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+
+                m_poKmlSchema = poKmlFactory->CreateSchema (  );
+
+                /***** set the id on the new schema *****/
+
+                std::string oKmlSchemaID = OGRLIBKMLGetSanitizedNCName(m_pszName);
+                oKmlSchemaID.append ( ".schema" );
+                m_poKmlSchema->set_id ( oKmlSchemaID );
+            }
 
-    if ( (poKmlSimpleField =
-         FieldDef2kml ( poField, m_poOgrDS->GetKmlFactory (  ) )) != NULL )
-        m_poKmlSchema->add_simplefield ( poKmlSimpleField );
+            m_poKmlSchema->add_simplefield ( poKmlSimpleField );
+        }
+    }
 
     m_poOgrFeatureDefn->AddFieldDefn ( poField );
 
@@ -613,7 +851,7 @@ void OGRLIBKMLLayer::SetStyleTableDirectly (
     OGRStyleTable * poStyleTable )
 {
 
-    if ( !bUpdate )
+    if ( !bUpdate || m_poKmlLayer == NULL )
         return;
 
     KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
@@ -665,7 +903,7 @@ void OGRLIBKMLLayer::SetStyleTable (
     OGRStyleTable * poStyleTable )
 {
 
-    if ( !bUpdate )
+    if ( !bUpdate || m_poKmlLayer == NULL )
         return;
 
     if ( poStyleTable )
@@ -729,3 +967,287 @@ CPLString OGRLIBKMLLayer::LaunderFieldNames(CPLString osName)
     }
     return osLaunderedName;
 }
+
+/************************************************************************/
+/*                            SetLookAt()                               */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetLookAt( const char* pszLookatLongitude,
+                                const char* pszLookatLatitude,
+                                const char* pszLookatAltitude,
+                                const char* pszLookatHeading,
+                                const char* pszLookatTilt,
+                                const char* pszLookatRange,
+                                const char* pszLookatAltitudeMode )
+{
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    LookAtPtr lookAt = poKmlFactory->CreateLookAt();
+    lookAt->set_latitude(CPLAtof(pszLookatLatitude));
+    lookAt->set_longitude(CPLAtof(pszLookatLongitude));
+    if( pszLookatAltitude != NULL )
+        lookAt->set_altitude(CPLAtof(pszLookatAltitude));
+    if( pszLookatHeading != NULL )
+        lookAt->set_heading(CPLAtof(pszLookatHeading));
+    if( pszLookatTilt != NULL )
+    {
+        double dfTilt = CPLAtof(pszLookatTilt);
+        if( dfTilt >= 0 && dfTilt <= 90 )
+            lookAt->set_tilt(dfTilt);
+        else
+            CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for tilt: %s",
+                     pszLookatTilt);
+    }
+    lookAt->set_range(CPLAtof(pszLookatRange));
+    if( pszLookatAltitudeMode != NULL )
+    {
+        int isGX = FALSE;
+        int iAltitudeMode = kmlAltitudeModeFromString(pszLookatAltitudeMode, isGX);
+        if( iAltitudeMode != kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
+            pszLookatAltitude == NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "Lookat altitude should be present for altitudeMode = %s",
+                     pszLookatAltitudeMode);
+        }
+        else if( isGX )
+            lookAt->set_gx_altitudemode(iAltitudeMode);
+        else
+            lookAt->set_altitudemode(iAltitudeMode);
+    }
+
+    m_poKmlLayer->set_abstractview(lookAt);
+}
+
+/************************************************************************/
+/*                            SetCamera()                               */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetCamera( const char* pszCameraLongitude,
+                                const char* pszCameraLatitude,
+                                const char* pszCameraAltitude,
+                                const char* pszCameraHeading,
+                                const char* pszCameraTilt,
+                                const char* pszCameraRoll,
+                                const char* pszCameraAltitudeMode )
+{
+    int isGX = FALSE;
+    int iAltitudeMode = kmlAltitudeModeFromString(pszCameraAltitudeMode, isGX);
+    if( isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "Camera altitudeMode should be different from %s",
+                    pszCameraAltitudeMode);
+        return;
+    }
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    CameraPtr camera = poKmlFactory->CreateCamera();
+    camera->set_latitude(CPLAtof(pszCameraLatitude));
+    camera->set_longitude(CPLAtof(pszCameraLongitude));
+    camera->set_altitude(CPLAtof(pszCameraAltitude));
+    if( pszCameraHeading != NULL )
+        camera->set_heading(CPLAtof(pszCameraHeading));
+    if( pszCameraTilt != NULL )
+    {
+        double dfTilt = CPLAtof(pszCameraTilt);
+        if( dfTilt >= 0 && dfTilt <= 90 )
+            camera->set_tilt(dfTilt);
+        else
+            CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for tilt: %s",
+                     pszCameraTilt);
+    }
+    if( pszCameraRoll != NULL )
+        camera->set_roll(CPLAtof(pszCameraRoll));
+    if( isGX )
+        camera->set_gx_altitudemode(iAltitudeMode);
+    else
+        camera->set_altitudemode(iAltitudeMode);
+
+    m_poKmlLayer->set_abstractview(camera);
+}
+
+/************************************************************************/
+/*                         SetWriteRegion()                             */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetWriteRegion(double dfMinLodPixels,
+                                    double dfMaxLodPixels,
+                                    double dfMinFadeExtent,
+                                    double dfMaxFadeExtent)
+{
+    m_bWriteRegion = TRUE;
+    m_bRegionBoundsAuto = TRUE;
+    m_dfRegionMinLodPixels = dfMinLodPixels;
+    m_dfRegionMaxLodPixels = dfMaxLodPixels;
+    m_dfRegionMinFadeExtent = dfMinFadeExtent;
+    m_dfRegionMaxFadeExtent = dfMaxFadeExtent;
+}
+
+/************************************************************************/
+/*                          SetRegionBounds()                           */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetRegionBounds(double dfMinX, double dfMinY,
+                                     double dfMaxX, double dfMaxY)
+{
+    m_bRegionBoundsAuto = FALSE;
+    m_dfRegionMinX = dfMinX;
+    m_dfRegionMinY = dfMinY;
+    m_dfRegionMaxX = dfMaxX;
+    m_dfRegionMaxY = dfMaxY;
+}
+
+/************************************************************************/
+/*                            Finalize()                                */
+/************************************************************************/
+
+void OGRLIBKMLLayer::Finalize(DocumentPtr poKmlDocument)
+{
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+
+    if( m_bWriteRegion && m_dfRegionMinX < m_dfRegionMaxX )
+    {
+        RegionPtr region = poKmlFactory->CreateRegion();
+
+        LatLonAltBoxPtr box = poKmlFactory->CreateLatLonAltBox();
+        box->set_west(m_dfRegionMinX);
+        box->set_east(m_dfRegionMaxX);
+        box->set_south(m_dfRegionMinY);
+        box->set_north(m_dfRegionMaxY);
+        region->set_latlonaltbox(box);
+
+        LodPtr lod = poKmlFactory->CreateLod();
+        lod->set_minlodpixels(m_dfRegionMinLodPixels);
+        lod->set_maxlodpixels(m_dfRegionMaxLodPixels);
+        if( (m_dfRegionMinFadeExtent != 0 || m_dfRegionMaxFadeExtent != 0) &&
+            m_dfRegionMinFadeExtent + m_dfRegionMaxFadeExtent <
+                m_dfRegionMaxLodPixels - m_dfRegionMinLodPixels )
+        {
+            lod->set_minfadeextent(m_dfRegionMinFadeExtent);
+            lod->set_maxfadeextent(m_dfRegionMaxFadeExtent);
+        }
+
+        region->set_lod(lod);
+        m_poKmlLayer->set_region(region);
+    }
+
+    createkmlliststyle (poKmlFactory,
+                        GetName(),
+                        m_poKmlLayer,
+                        poKmlDocument,
+                        osListStyleType,
+                        osListStyleIconHref);
+}
+
+/************************************************************************/
+/*                             LIBKMLGetUnits()                         */
+/************************************************************************/
+
+static int LIBKMLGetUnits(const char* pszUnits)
+{
+    if( EQUAL(pszUnits, "fraction") )
+        return kmldom::UNITS_FRACTION;
+    if( EQUAL(pszUnits, "pixels") )
+        return  kmldom::UNITS_PIXELS;
+    if( EQUAL(pszUnits, "insetPixels") )
+        return  kmldom::UNITS_INSETPIXELS;
+    return  kmldom::UNITS_FRACTION;
+}
+
+/************************************************************************/
+/*                         LIBKMLSetVec2()                              */
+/************************************************************************/
+
+static void LIBKMLSetVec2(kmldom::Vec2Ptr vec2, const char* pszX, const char* pszY,
+                    const char* pszXUnits, const char* pszYUnits)
+{
+    double dfX = CPLAtof(pszX); 
+    double dfY = CPLAtof(pszY);
+    vec2->set_x(dfX);
+    vec2->set_y(dfY);
+    if( dfX <= 1 && dfY <= 1 )
+    {
+        if( pszXUnits == NULL ) pszXUnits = "fraction";
+        if( pszYUnits == NULL ) pszYUnits = "fraction";
+    }
+    else
+    {
+        if( pszXUnits == NULL ) pszXUnits = "pixels";
+        if( pszYUnits == NULL ) pszYUnits = "pixels";
+    }
+    vec2->set_xunits(LIBKMLGetUnits(pszXUnits));
+    vec2->set_yunits(LIBKMLGetUnits(pszYUnits));
+}
+
+/************************************************************************/
+/*                         SetScreenOverlay()                           */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetScreenOverlay(const char* pszSOHref,
+                                      const char* pszSOName,
+                                      const char* pszSODescription,
+                                      const char* pszSOOverlayX,
+                                      const char* pszSOOverlayY,
+                                      const char* pszSOOverlayXUnits,
+                                      const char* pszSOOverlayYUnits,
+                                      const char* pszSOScreenX,
+                                      const char* pszSOScreenY,
+                                      const char* pszSOScreenXUnits,
+                                      const char* pszSOScreenYUnits,
+                                      const char* pszSOSizeX,
+                                      const char* pszSOSizeY,
+                                      const char* pszSOSizeXUnits,
+                                      const char* pszSOSizeYUnits)
+{
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    ScreenOverlayPtr so = poKmlFactory->CreateScreenOverlay();
+
+    if( pszSOName != NULL )
+        so->set_name(pszSOName);
+    if( pszSODescription != NULL )
+        so->set_description(pszSODescription);
+
+    IconPtr icon = poKmlFactory->CreateIcon();
+    icon->set_href(pszSOHref);
+    so->set_icon(icon);
+
+    if( pszSOOverlayX != NULL && pszSOOverlayY != NULL )
+    {
+        kmldom::OverlayXYPtr overlayxy = poKmlFactory->CreateOverlayXY();
+        LIBKMLSetVec2(overlayxy, pszSOOverlayX, pszSOOverlayY,
+                      pszSOOverlayXUnits, pszSOOverlayYUnits);
+        so->set_overlayxy(overlayxy);
+    }
+
+    if( pszSOScreenX != NULL && pszSOScreenY != NULL )
+    {
+        kmldom::ScreenXYPtr screenxy = poKmlFactory->CreateScreenXY();
+        LIBKMLSetVec2(screenxy, pszSOScreenX, pszSOScreenY,
+                      pszSOScreenXUnits, pszSOScreenYUnits);
+        so->set_screenxy(screenxy);
+    }
+    else
+    {
+        kmldom::ScreenXYPtr screenxy = poKmlFactory->CreateScreenXY();
+        LIBKMLSetVec2(screenxy, "0.05", "0.05", NULL, NULL);
+        so->set_screenxy(screenxy);
+    }
+
+    if( pszSOSizeX != NULL && pszSOSizeY != NULL )
+    {
+        kmldom::SizePtr sizexy = poKmlFactory->CreateSize();
+        LIBKMLSetVec2(sizexy, pszSOSizeX, pszSOSizeY,
+                      pszSOSizeXUnits, pszSOSizeYUnits);
+        so->set_size(sizexy);
+    }
+
+    m_poKmlLayer->add_feature(so);
+}
+
+/************************************************************************/
+/*                           SetListStyle()                              */
+/************************************************************************/
+
+void OGRLIBKMLLayer::SetListStyle(const char* pszListStyleType,
+                                  const char* pszListStyleIconHref)
+{
+    osListStyleType = (pszListStyleType) ? pszListStyleType : "";
+    osListStyleIconHref = (pszListStyleIconHref) ? pszListStyleIconHref : "";
+}
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
index f60d167..b3658c0 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
@@ -6,6 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Brian Case
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,6 +29,8 @@
 
 #include <ogr_featurestyle.h>
 
+#include <set>
+
 #include <kml/dom.h>
 #include <kml/engine.h>
 #include <kml/base/color32.h>
@@ -46,32 +49,35 @@ using kmldom::PolyStylePtr;
 using kmldom::IconStylePtr;
 using kmldom::IconStyleIconPtr;
 using kmldom::LabelStylePtr;
+using kmldom::BalloonStylePtr;
 using kmldom::HotSpotPtr;
 using kmlbase::Color32;
 using kmldom::PairPtr;
 using kmldom::KmlPtr;
+using kmldom::ListStylePtr;
+using kmldom::ItemIconPtr;
 
 #include "ogrlibkmlstyle.h"
+#include "ogr_libkml.h"
 
 /******************************************************************************
  generic function to parse a stylestring and add to a kml style
 
 args:
             pszStyleString  the stylestring to parse
-            poKmlStyle      the kml style to add to
+            poKmlStyle      the kml style to add to (or NULL)
             poKmlFactory    the kml dom factory
 
 returns:
-            nothing
+            the kml style
 
 ******************************************************************************/
 
-void addstylestring2kml (
+StylePtr addstylestring2kml (
     const char *pszStyleString,
     StylePtr poKmlStyle,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark,
-    OGRFeature * poOgrFeat )
+    FeaturePtr poKmlFeature )
 {
 
     LineStylePtr poKmlLineStyle = NULL;
@@ -82,7 +88,7 @@ void addstylestring2kml (
     /***** just bail now if stylestring is empty *****/
 
     if ( !pszStyleString || !*pszStyleString ) {
-        return;
+        return poKmlStyle;
     }
 
     /***** create and init a style mamager with the style string *****/
@@ -124,6 +130,7 @@ void addstylestring2kml (
                      && poStylePen->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
                     poKmlLineStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
                 }
+                poStylePen->SetUnit(OGRSTUPixel);
                 double dfWidth = poStylePen->Width ( nullcheck );
 
                 if ( nullcheck )
@@ -137,8 +144,6 @@ void addstylestring2kml (
             {
                 GBool nullcheck;
 
-                poKmlPolyStyle = poKmlFactory->CreatePolyStyle (  );
-
                 OGRStyleBrush *poStyleBrush = ( OGRStyleBrush * ) poOgrST;
 
                 /***** brush color *****/
@@ -152,6 +157,7 @@ void addstylestring2kml (
 
                 if ( !nullcheck
                      && poStyleBrush->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
+                    poKmlPolyStyle = poKmlFactory->CreatePolyStyle (  );
                     poKmlPolyStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
                 }
                 
@@ -257,8 +263,6 @@ void addstylestring2kml (
                 GBool nullcheck;
                 GBool nullcheck2;
                 
-                poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
-
                 OGRStyleLabel *poStyleLabel = ( OGRStyleLabel * ) poOgrST;
 
                 /***** color *****/
@@ -272,6 +276,8 @@ void addstylestring2kml (
 
                 if ( !nullcheck
                      && poStyleLabel->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
+                    if( poKmlLabelStyle == NULL )
+                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
                     poKmlLabelStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
                 }
 
@@ -281,6 +287,8 @@ void addstylestring2kml (
 
                 if ( !nullcheck ) {
                     dfScale /= 100.0;
+                    if( poKmlLabelStyle == NULL )
+                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
                     poKmlLabelStyle->set_scale ( dfScale );
                 }
                 
@@ -323,9 +331,9 @@ void addstylestring2kml (
                 const char *pszText = poStyleLabel->TextString ( nullcheck );
 
                 if ( !nullcheck ) {
-                    if ( poKmlPlacemark ) {
+                    if ( poKmlFeature ) {
 
-                        poKmlPlacemark->set_name( pszText );
+                        poKmlFeature->set_name( pszText );
                     }
                 }
                     
@@ -339,19 +347,27 @@ void addstylestring2kml (
         delete poOgrST;
     }
 
-    if ( poKmlLineStyle )
-        poKmlStyle->set_linestyle ( poKmlLineStyle );
+    if ( poKmlLineStyle || poKmlPolyStyle || poKmlIconStyle || poKmlLabelStyle )
+    {
+        if( poKmlStyle == NULL )
+            poKmlStyle = poKmlFactory->CreateStyle (  );
 
-    if ( poKmlPolyStyle )
-        poKmlStyle->set_polystyle ( poKmlPolyStyle );
+        if ( poKmlLineStyle )
+            poKmlStyle->set_linestyle ( poKmlLineStyle );
 
-    if ( poKmlIconStyle )
-        poKmlStyle->set_iconstyle ( poKmlIconStyle );
+        if ( poKmlPolyStyle )
+            poKmlStyle->set_polystyle ( poKmlPolyStyle );
+
+        if ( poKmlIconStyle )
+            poKmlStyle->set_iconstyle ( poKmlIconStyle );
+
+        if ( poKmlLabelStyle )
+            poKmlStyle->set_labelstyle ( poKmlLabelStyle );
+    }
 
-    if ( poKmlLabelStyle )
-        poKmlStyle->set_labelstyle ( poKmlLabelStyle );
-    
     delete poOgrSM;
+    
+    return poKmlStyle;
 }
 
 /******************************************************************************
@@ -732,7 +748,7 @@ void kml2styletable (
         const std::string oName = poKmlStyle->get_id (  );
 
 
-        poOgrSM->AddStyle ( CPLString (  ).Printf ( "@%s",
+        poOgrSM->AddStyle ( CPLString (  ).Printf ( "%s",
                                                     oName.c_str (  ) ), NULL );
 
         /***** cleanup the style manager *****/
@@ -849,7 +865,7 @@ StyleSelectorPtr StyleFromStyleURL(
     else if ( strchr(pszUrl, '#') ) {
 
         const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
-        if ( EQUAL(pszFetch, "yes") ) {
+        if ( CSLTestBoolean(pszFetch) ) {
 
             /***** Lets go out and fetch the style from the external URL *****/
 
@@ -1079,7 +1095,8 @@ void ParseStyles (
 void styletable2kml (
     OGRStyleTable * poOgrStyleTable,
     KmlFactory * poKmlFactory,
-    ContainerPtr poKmlContainer )
+    ContainerPtr poKmlContainer,
+    char** papszOptions )
 {
 
     /***** just return if the styletable is null *****/
@@ -1087,33 +1104,160 @@ void styletable2kml (
     if ( !poOgrStyleTable )
         return;
 
-    /***** parse the style table *****/
-
+    std::set<CPLString> aoSetNormalStyles;
+    std::set<CPLString> aoSetHighlightStyles;
     poOgrStyleTable->ResetStyleStringReading (  );
     const char *pszStyleString;
 
+    /* Collect styles that end with _normal or _highlight */
+    while ( poOgrStyleTable->GetNextStyle (  ) != NULL ) {
+        const char *pszStyleName = poOgrStyleTable->GetLastStyleName (  );
+
+        if( strlen(pszStyleName) > strlen("_normal") &&
+            EQUAL(pszStyleName + strlen(pszStyleName) - strlen("_normal"), "_normal") )
+        {
+            CPLString osName(pszStyleName);
+            osName.resize(strlen(pszStyleName) - strlen("_normal"));
+            aoSetNormalStyles.insert(osName);
+        }
+        else if( strlen(pszStyleName) > strlen("_highlight") &&
+                  EQUAL(pszStyleName + strlen(pszStyleName) - strlen("_highlight"), "_highlight") )
+        {
+            CPLString osName(pszStyleName);
+            osName.resize(strlen(pszStyleName) - strlen("_highlight"));
+            aoSetHighlightStyles.insert(osName);
+        }
+    }
+
+    /***** parse the style table *****/
+
+    poOgrStyleTable->ResetStyleStringReading (  );
+    
     while ( ( pszStyleString = poOgrStyleTable->GetNextStyle (  ) ) ) {
         const char *pszStyleName = poOgrStyleTable->GetLastStyleName (  );
 
+        if( aoSetNormalStyles.find(pszStyleName) != aoSetNormalStyles.end() &&
+            aoSetHighlightStyles.find(pszStyleName) != aoSetHighlightStyles.end() )
+        {
+            continue;
+        }
+
         /***** add the style header to the kml *****/
 
         StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
 
-        poKmlStyle->set_id ( pszStyleName + 1 );
+        poKmlStyle->set_id ( pszStyleName );
 
         /***** parse the style string *****/
 
-        addstylestring2kml ( pszStyleString, poKmlStyle, poKmlFactory, NULL, NULL );
+        addstylestring2kml ( pszStyleString, poKmlStyle, poKmlFactory, NULL );
+
+        /***** add balloon style *****/
+        const char* pszBalloonStyleBgColor = CSLFetchNameValue(papszOptions, CPLSPrintf("%s_balloonstyle_bgcolor", pszStyleName));
+        const char* pszBalloonStyleText = CSLFetchNameValue(papszOptions, CPLSPrintf("%s_balloonstyle_text", pszStyleName));
+        int nR, nG, nB, nA;
+        OGRStylePen oStyleTool;
+        if( (pszBalloonStyleBgColor != NULL &&
+             oStyleTool.GetRGBFromString ( pszBalloonStyleBgColor, nR, nG, nB, nA )  ) ||
+            pszBalloonStyleText != NULL )
+        {
+            BalloonStylePtr poKmlBalloonStyle = poKmlFactory->CreateBalloonStyle();
+            if( pszBalloonStyleBgColor != NULL &&
+                oStyleTool.GetRGBFromString ( pszBalloonStyleBgColor, nR, nG, nB, nA ) )
+                poKmlBalloonStyle->set_bgcolor ( Color32 ( nA, nB, nG, nR ) );
+            if( pszBalloonStyleText != NULL )
+                poKmlBalloonStyle->set_text(pszBalloonStyleText);
+            poKmlStyle->set_balloonstyle ( poKmlBalloonStyle );
+        }
 
         /***** add the style to the container *****/
 
         DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
-
-        //ObjectPtr pokmlObject = boost::static_pointer_cast <kmldom::Object> () ;
-        //poKmlContainer->add_feature ( AsFeature( poKmlStyle) );
         poKmlDocument->add_styleselector ( poKmlStyle );
 
     }
 
+    /* Find style name that end with _normal and _highlight to create */
+    /* a StyleMap from both */
+    std::set<CPLString>::iterator aoSetNormalStylesIter =
+        aoSetNormalStyles.begin();
+    for( ; aoSetNormalStylesIter != aoSetNormalStyles.end(); ++aoSetNormalStylesIter )
+    {
+        CPLString osStyleName(*aoSetNormalStylesIter);
+        if( aoSetHighlightStyles.find(osStyleName) !=
+                aoSetHighlightStyles.end() )
+        {
+            StyleMapPtr poKmlStyleMap = poKmlFactory->CreateStyleMap (  );
+            poKmlStyleMap->set_id ( osStyleName );
+
+            PairPtr poKmlPairNormal = poKmlFactory->CreatePair (  );
+            poKmlPairNormal->set_key(STYLESTATE_NORMAL);
+            poKmlPairNormal->set_styleurl(CPLSPrintf("#%s_normal", osStyleName.c_str()));
+            poKmlStyleMap->add_pair(poKmlPairNormal);
+
+            PairPtr poKmlPairHightlight = poKmlFactory->CreatePair (  );
+            poKmlPairHightlight->set_key(STYLESTATE_HIGHLIGHT);
+            poKmlPairHightlight->set_styleurl(CPLSPrintf("#%s_highlight", osStyleName.c_str()));
+            poKmlStyleMap->add_pair(poKmlPairHightlight);
+
+            /***** add the style to the container *****/
+            DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
+            poKmlDocument->add_styleselector ( poKmlStyleMap );
+        }
+    }
+
     return;
 }
+
+
+/******************************************************************************
+ function to add a ListStyle and select it to a container
+******************************************************************************/
+
+void createkmlliststyle (
+    KmlFactory * poKmlFactory,
+    const char* pszBaseName,
+    ContainerPtr poKmlLayerContainer,
+    DocumentPtr poKmlDocument,
+    const CPLString& osListStyleType,
+    const CPLString& osListStyleIconHref)
+{
+    if( osListStyleType.size() || osListStyleIconHref.size() )
+    {
+        StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
+
+        const char* pszStyleName = CPLSPrintf("%s_liststyle", OGRLIBKMLGetSanitizedNCName(pszBaseName).c_str());
+        poKmlStyle->set_id ( pszStyleName );
+
+        ListStylePtr poKmlListStyle = poKmlFactory->CreateListStyle (  );
+        poKmlStyle->set_liststyle ( poKmlListStyle );
+        if( osListStyleType.size() )
+        {
+            if( EQUAL(osListStyleType, "check") )
+                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECK );
+            else if( EQUAL(osListStyleType, "radioFolder") )
+                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_RADIOFOLDER );
+            else if( EQUAL(osListStyleType, "checkOffOnly") )
+                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECKOFFONLY );
+            else if( EQUAL(osListStyleType, "checkHideChildren") )
+                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECKHIDECHILDREN );
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Invalid value for list style type: %s. Defaulting to Check",
+                         osListStyleType.c_str());
+                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECK );
+            }
+        }
+
+        if( osListStyleIconHref.size() )
+        {
+            ItemIconPtr poItemIcon = poKmlFactory->CreateItemIcon (  );
+            poItemIcon->set_href( osListStyleIconHref.c_str() );
+            poKmlListStyle->add_itemicon(poItemIcon);
+        }
+
+        poKmlDocument->add_styleselector ( poKmlStyle );
+        poKmlLayerContainer->set_styleurl( CPLSPrintf("#%s", pszStyleName) );
+    }
+}
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
index f0bd1d0..01dca66 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
@@ -32,14 +32,13 @@ using kmldom::StylePtr;
 using kmldom::StyleMapPtr;
 using kmldom::DocumentPtr;
 using kmldom::ContainerPtr;
-using kmldom::PlacemarkPtr;
+using kmldom::FeaturePtr;
 
-void addstylestring2kml (
+StylePtr addstylestring2kml (
     const char *stylestring,
     StylePtr poKmlStyle,
     KmlFactory * poKmlFactory,
-    PlacemarkPtr poKmlPlacemark,
-    OGRFeature * poOgrFeat );
+    FeaturePtr poKmlFeature );
 
 
 
@@ -84,5 +83,17 @@ void ParseStyles (
 void styletable2kml (
     OGRStyleTable * poOgrStyleTable,
     KmlFactory * poKmlFactory,
-    ContainerPtr poKmlContainer  );
+    ContainerPtr poKmlContainer,
+    char** papszOptions = NULL  );
 
+/******************************************************************************
+ function to add a ListStyle and select it to a container
+******************************************************************************/
+
+void createkmlliststyle (
+    KmlFactory * poKmlFactory,
+    const char* pszBaseName,
+    ContainerPtr poKmlLayerContainer,
+    DocumentPtr poKmlDocument,
+    const CPLString& osListStyleType,
+    const CPLString& osListStyleIconHref);
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 9ff475b..510115b 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -4,18 +4,20 @@ DIRLIST		=	generic geojson shape ntf sdts tiger s57 dgn mitab gml \
 			avc rec mem vrt csv gmt bna kml gpx \
 			geoconcept xplane georss gtm dxf pgdump gpsbabel \
 			sua openair pds htf aeronavfaa edigeo svg idrisi arcgen \
-			segukooa segy pdf \
+			segukooa segy pdf sxf openfilegdb wasp \
 			$(ARCOBJECTS_DIR) \
 			$(OGDIDIR) $(FMEDIR) $(OCIDIR) $(PG_DIR) $(DWGDIR) \
 			$(ODBCDIR) $(SQLITE_DIR) $(MYSQL_DIR) $(ILI_DIR) \
 			$(SDE_DIR) $(IDB_DIR) $(NAS_DIR) $(DODSDIR) \
 			$(PCIDSK_DIR) $(LIBKMLDIR) $(WFSDIR) $(SOSIDIR) $(GFTDIR) \
 			$(COUCHDBDIR) $(FGDB_DIR) $(XLSDIR) $(ODSDIR) $(XLSXDIR) \
-			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR)
+			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODBDIR) \
+			$(GMEDIR)
 
 PLUGINDIRLIST	=	$(PLUGIN_ARCOBJECTS_DIR) \
 			$(PLUGIN_DWG_DIR) \
 			$(PLUGIN_PG_DIR) \
+			$(PLUGIN_SOSI_DIR) \
 			$(PLUGIN_FGDB_DIR) \
 			$(PLUGIN_OCIDIR) \
 			$(PLUGIN_SDE_DIR) \
@@ -39,13 +41,13 @@ OGDIOBJ =	ogdi\*.obj
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDIR	=	odbc pgeo mssqlspatial geomedia
-ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj
+ODBCDIR	=	odbc pgeo mssqlspatial geomedia walk
+ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj walk\*.obj
 !ENDIF
 
 !IFDEF SQLITE_LIB
-SQLITE_DIR	=	sqlite
-SQLITE_OBJ =	sqlite\*.obj
+SQLITE_DIR	=	sqlite gpkg
+SQLITE_OBJ =	sqlite\*.obj gpkg\*.obj
 !ENDIF
 
 !IFDEF OCI_LIB
@@ -157,9 +159,13 @@ WFSDIR = wfs
 WFS_OBJ = wfs\*.obj
 !ENDIF
 
-!IFDEF SOSI_ENABLED
+!IFDEF SOSI_INC_DIR
+!IF "$(SOSI_PLUGIN)" != "YES"
 SOSIDIR = sosi
 SOSI_OBJ = sosi\*.obj
+!ELSE
+PLUGIN_SOSI_DIR = sosi
+!ENDIF
 !ENDIF
 
 !IFDEF CURL_LIB
@@ -199,6 +205,16 @@ VFKDIR	=	vfk
 VFK_OBJ =	vfk\*.obj
 !ENDIF
 
+!IFDEF CURL_LIB
+CARTODBDIR = cartodb
+CARTODB_OBJ = cartodb\*.obj
+!ENDIF
+
+!IFDEF CURL_LIB
+GMEDIR = gme
+GME_OBJ = gme\*.obj
+!ENDIF
+
 default:
 	for %d in ( $(DIRLIST) ) do \
 		cd %d \
@@ -211,18 +227,19 @@ default:
 				 mitab\*.obj dgn\*.obj avc\*.obj mem\*.obj \
 				 vrt\*.obj csv\*.obj rec\*.obj kml\*.obj \
 				 gmt\*.obj bna\*.obj geoconcept\*.obj \
-				 geojson\*.obj geojson\jsonc\*.obj \
+				 geojson\*.obj geojson\libjson\*.obj \
 				 gpx\*.obj xplane\*.obj georss\*.obj gtm\*.obj \
 				 dxf\*.obj pgdump\*.obj gpsbabel\*.obj \
 				 sua\*.obj openair\*.obj pds\*.obj htf\*.obj \
 				 aeronavfaa\*.obj edigeo\*.obj svg\*.obj idrisi\*.obj \
-				 arcgen\*.obj segukooa\*.obj segy\*.obj pdf\*.obj \
+				 arcgen\*.obj segukooa\*.obj segy\*.obj pdf\*.obj sxf\*.obj \
+				 openfilegdb\*.obj wasp\*.obj \
 				$(OGDIOBJ) $(ODBCOBJ) $(SQLITE_OBJ) \
 				$(FMEOBJ) $(OCIOBJ) $(PG_OBJ) $(MYSQL_OBJ) \
 				$(ILI_OBJ) $(DWG_OBJ) $(SDE_OBJ) $(FGDB_OBJ) $(ARCDRIVER_OBJ) $(IDB_OBJ) \
 				$(DODS_OBJ) $(NAS_OBJ) $(PCIDSKOBJ) $(LIBKMLOBJ) $(WFS_OBJ) \
 				$(SOSI_OBJ) $(GFT_OBJ) $(COUCHDB_OBJ) $(XLS_OBJ) $(ODS_OBJ) $(XLSX_OBJ)  \
-				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ)
+				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTODB_OBJ) $(GME_OBJ)
 	lib /out:ogrsf_frmts_sup.lib \
 				 ..\..\frmts\iso8211\*.obj \
 				 ..\..\frmts\sdts\sdtsattrreader.obj \
diff --git a/ogr/ogrsf_frmts/mdb/ogr_mdb.h b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
index 5ac3a90..220f0c8 100644
--- a/ogr/ogrsf_frmts/mdb/ogr_mdb.h
+++ b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_mdb.h 21557 2011-01-22 23:42:14Z rouault $
+ * $Id: ogr_mdb.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for MDB driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -277,12 +277,9 @@ class OGRMDBLayer : public OGRLayer
     
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual int         TestCapability( const char * );
 
     virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
 
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
 };
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
index e0654f4..d67ddba 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z rouault $
+ * $Id: ogrmdbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include <vector>
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z rouault $");
+CPL_CVSID("$Id: ogrmdbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRMDBDataSource()                          */
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
index 9fdf148..11080a2 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrmdbdriver.cpp 21560 2011-01-23 12:11:33Z rouault $
+ * $Id: ogrmdbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_mdb.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrmdbdriver.cpp 21560 2011-01-23 12:11:33Z rouault $");
+CPL_CVSID("$Id: ogrmdbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/mdb/*.cpp -shared -o ogr_MDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mdb -L. -lgdal -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux  -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server -ljvm
 
@@ -65,6 +65,15 @@ OGRDataSource *OGRMDBDriver::Open( const char * pszFilename,
 {
     OGRMDBDataSource     *poDS;
 
+    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+        return NULL;
+
     if( !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
 
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
index a72b6d4..5908944 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z rouault $
+ * $Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBJavaEnv class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_mdb.h"
 
-CPL_CVSID("$Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z rouault $");
+CPL_CVSID("$Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static JavaVM *jvm_static = NULL;
 static JNIEnv *env_static = NULL;
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
index 5d42a16..335e21c 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z rouault $
+ * $Id: ogrmdblayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBLayer class
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogrpgeogeometry.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z rouault $");
+CPL_CVSID("$Id: ogrmdblayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRMDBLayer()                            */
@@ -174,6 +174,13 @@ CPLErr OGRMDBLayer::BuildFeatureDefn()
         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
     }
 
+    if( poFeatureDefn->GetGeomFieldCount() > 0 )
+    {
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        if( pszGeomColumn != NULL )
+            poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
+    }
+
     return CE_None;
 }
 
@@ -284,6 +291,10 @@ OGRFeature *OGRMDBLayer::GetNextRawFeature()
         CPLFree(pszValue);
     }
 
+    if( !(m_poAttrQuery == NULL
+          || m_poAttrQuery->Evaluate( poFeature )) )
+        return poFeature;
+
 /* -------------------------------------------------------------------- */
 /*      Try to extract a geometry.                                      */
 /* -------------------------------------------------------------------- */
@@ -373,16 +384,6 @@ int OGRMDBLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRMDBLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                           LookupSRID()                               */
 /************************************************************************/
 
@@ -478,20 +479,6 @@ const char *OGRMDBLayer::GetFIDColumn()
 }
 
 /************************************************************************/
-/*                         GetGeometryColumn()                          */
-/************************************************************************/
-
-const char *OGRMDBLayer::GetGeometryColumn()
-
-{
-    if( pszGeomColumn != NULL )
-        return pszGeomColumn;
-    else
-        return "";
-}
-
-
-/************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/mem/ogr_mem.h b/ogr/ogrsf_frmts/mem/ogr_mem.h
index bdbacd8..4264463 100644
--- a/ogr/ogrsf_frmts/mem/ogr_mem.h
+++ b/ogr/ogrsf_frmts/mem/ogr_mem.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mem.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_mem.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the OGR Memory driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -38,7 +39,6 @@
 
 class OGRMemLayer : public OGRLayer
 {
-    OGRSpatialReference *poSRS;
     OGRFeatureDefn     *poFeatureDefn;
     
     int                 nFeatureCount;
@@ -77,9 +77,9 @@ class OGRMemLayer : public OGRLayer
     virtual OGRErr      DeleteField( int iField );
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     int                 TestCapability( const char * );
 
     void                SetUpdatable(int bUpdatableIn) { bUpdatable = bUpdatableIn; }
diff --git a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
index 6d46964..5c83d55 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemdatasource.cpp 13027 2007-11-25 19:21:57Z warmerdam $
+ * $Id: ogrmemdatasource.cpp 26302 2013-08-11 16:24:14Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemDataSource class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmemdatasource.cpp 13027 2007-11-25 19:21:57Z warmerdam $");
+CPL_CVSID("$Id: ogrmemdatasource.cpp 26302 2013-08-11 16:24:14Z rouault $");
 
 /************************************************************************/
 /*                          OGRMemDataSource()                          */
@@ -123,6 +123,8 @@ int OGRMemDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
index a2ed05b..d0b9313 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemlayer.cpp 24804 2012-08-19 13:27:13Z rouault $
+ * $Id: ogrmemlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmemlayer.cpp 24804 2012-08-19 13:27:13Z rouault $");
+CPL_CVSID("$Id: ogrmemlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRMemLayer()                             */
@@ -41,11 +42,6 @@ OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
                           OGRwkbGeometryType eReqType )
 
 {
-    if( poSRSIn == NULL )
-        poSRS = NULL;
-    else
-        poSRS = poSRSIn->Clone();
-    
     iNextReadFID = 0;
     iNextCreateFID = 0;
 
@@ -55,6 +51,12 @@ OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->SetGeomType( eReqType );
+    if( eReqType != wkbNone && poSRSIn != NULL )
+    {
+        OGRSpatialReference* poSRS = poSRSIn->Clone();
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        poSRS->Release();
+    }
     poFeatureDefn->Reference();
 
     bUpdatable = TRUE;
@@ -85,9 +87,6 @@ OGRMemLayer::~OGRMemLayer()
 
     if( poFeatureDefn )
         poFeatureDefn->Release();
-
-    if( poSRS )
-        poSRS->Release();
 }
 
 /************************************************************************/
@@ -115,7 +114,7 @@ OGRFeature *OGRMemLayer::GetNextFeature()
             continue;
 
         if( (m_poFilterGeom == NULL
-             || FilterGeometry( poFeature->GetGeometryRef() ) )
+             || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature ) ) )
         {
@@ -213,9 +212,16 @@ OGRErr OGRMemLayer::SetFeature( OGRFeature *poFeature )
     }
 
     papoFeatures[poFeature->GetFID()] = poFeature->Clone();
-    OGRGeometry* poGeom = papoFeatures[poFeature->GetFID()]->GetGeometryRef();
-    if( poGeom != NULL && poGeom->getSpatialReference() == NULL )
-        poGeom->assignSpatialReference(GetSpatialRef());
+    int i;
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i ++)
+    {
+        OGRGeometry* poGeom = papoFeatures[poFeature->GetFID()]->GetGeomFieldRef(i);
+        if( poGeom != NULL && poGeom->getSpatialReference() == NULL )
+        {
+            poGeom->assignSpatialReference(
+                poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
+        }
+    }
     nFeatureCount++;
 
     return OGRERR_NONE;
@@ -317,6 +323,7 @@ int OGRMemLayer::TestCapability( const char * pszCap )
         return bUpdatable;
 
     else if( EQUAL(pszCap,OLCCreateField) ||
+             EQUAL(pszCap,OLCCreateGeomField) ||
              EQUAL(pszCap,OLCDeleteField) ||
              EQUAL(pszCap,OLCReorderFields) ||
              EQUAL(pszCap,OLCAlterFieldDefn) )
@@ -554,12 +561,55 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
     return OGRERR_NONE;
 }
 
+
 /************************************************************************/
-/*                           GetSpatialRef()                            */
+/*                          CreateGeomField()                           */
 /************************************************************************/
 
-OGRSpatialReference *OGRMemLayer::GetSpatialRef()
+OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                     int bApproxOK )
 
 {
-    return poSRS;
+    if (!bUpdatable)
+        return OGRERR_FAILURE;
+
+/* -------------------------------------------------------------------- */
+/*      simple case, no features exist yet.                             */
+/* -------------------------------------------------------------------- */
+    if( nFeatureCount == 0 )
+    {
+        poFeatureDefn->AddGeomFieldDefn( poGeomField );
+        return OGRERR_NONE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add field definition and setup remap definition.                */
+/* -------------------------------------------------------------------- */
+    int  *panRemap;
+    int   i;
+
+    poFeatureDefn->AddGeomFieldDefn( poGeomField );
+
+    panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetGeomFieldCount());
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+    {
+        if( i < poFeatureDefn->GetGeomFieldCount() - 1 )
+            panRemap[i] = i;
+        else
+            panRemap[i] = -1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Remap all the internal features.  Hopefully there aren't any    */
+/*      external features referring to our OGRFeatureDefn!              */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < nMaxFeatureCount; i++ )
+    {
+        if( papoFeatures[i] != NULL )
+            papoFeatures[i]->RemapGeomFields( NULL, panRemap );
+    }
+
+    CPLFree( panRemap );
+
+    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
index 1975b0f..4891400 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
@@ -11,6 +11,7 @@
  *
  **********************************************************************
  * Copyright (c) 1999-2003, Stephane Villeneuve
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -270,7 +271,7 @@ int MIFFile::Open(const char *pszFname, const char *pszAccess,
     
     CPLErrorReset();
 
-    if (m_poMIDFile)
+    if (m_poMIFFile)
     {
         CPLError(CE_Failure, CPLE_FileIO,
                      "Open() failed: object already contains an open file");
@@ -361,53 +362,57 @@ int MIFFile::Open(const char *pszFname, const char *pszAccess,
     }
 
     /*-----------------------------------------------------------------
-     * Open .MID file
+     * Read MIF File Header
      *----------------------------------------------------------------*/
-    if (nFnameLen > 4 && strcmp(pszTmpFname+nFnameLen-4, ".MIF")==0)
-        strcpy(pszTmpFname+nFnameLen-4, ".MID");
-    else 
-        strcpy(pszTmpFname+nFnameLen-4, ".mid");
-
-#ifndef _WIN32
-    TABAdjustFilenameExtension(pszTmpFname);
-#endif
-
-    m_poMIDFile = new MIDDATAFile;
-
-    if (m_poMIDFile->Open(pszTmpFname, pszAccess) !=0)
+    if (m_eAccessMode == TABRead && ParseMIFHeader() != 0)
     {
+        Close();
+
         if (!bTestOpenNoError)
             CPLError(CE_Failure, CPLE_NotSupported,
-                     "Unable to open %s.", pszTmpFname);
+                     "Failed parsing header in %s.", m_pszFname);
         else
             CPLErrorReset();
 
         CPLFree(pszTmpFname);
-        Close();
 
         return -1;
     }
 
+    if ( m_nAttribut > 0 || m_eAccessMode == TABWrite )
+    {
+        /*-----------------------------------------------------------------
+        * Open .MID file
+        *----------------------------------------------------------------*/
+        if (nFnameLen > 4 && strcmp(pszTmpFname+nFnameLen-4, ".MIF")==0)
+            strcpy(pszTmpFname+nFnameLen-4, ".MID");
+        else 
+            strcpy(pszTmpFname+nFnameLen-4, ".mid");
 
-    CPLFree(pszTmpFname);
-    pszTmpFname = NULL;
+#ifndef _WIN32
+        TABAdjustFilenameExtension(pszTmpFname);
+#endif
 
-    /*-----------------------------------------------------------------
-     * Read MIF File Header
-     *----------------------------------------------------------------*/
-    if (m_eAccessMode == TABRead && ParseMIFHeader() != 0)
-    {
-        Close();
+        m_poMIDFile = new MIDDATAFile;
 
-        if (!bTestOpenNoError)
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Failed parsing header in %s.", m_pszFname);
-        else
-            CPLErrorReset();
+        if (m_poMIDFile->Open(pszTmpFname, pszAccess) !=0)
+        {
+            if (!bTestOpenNoError)
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Unable to open %s.", pszTmpFname);
+            else
+                CPLErrorReset();
 
-        return -1;
+            CPLFree(pszTmpFname);
+            Close();
+
+            return -1;
+        }
     }
 
+    CPLFree(pszTmpFname);
+    pszTmpFname = NULL;
+
     /*-----------------------------------------------------------------
      * In write access, set some defaults
      *----------------------------------------------------------------*/
@@ -418,7 +423,7 @@ int MIFFile::Open(const char *pszFname, const char *pszAccess,
     }
 
     /* Put the MID file at the correct location, on the first feature */
-    if (m_eAccessMode == TABRead && (m_poMIDFile->GetLine() == NULL))
+    if (m_eAccessMode == TABRead && (m_poMIDFile != NULL && m_poMIDFile->GetLine() == NULL))
     {
         Close();
 
@@ -430,10 +435,12 @@ int MIFFile::Open(const char *pszFname, const char *pszAccess,
 
     m_poMIFFile->SetTranslation(m_dfXMultiplier,m_dfYMultiplier,
                                 m_dfXDisplacement, m_dfYDisplacement);
-    m_poMIDFile->SetTranslation(m_dfXMultiplier,m_dfYMultiplier,
-                                m_dfXDisplacement, m_dfYDisplacement);
+    if( m_poMIDFile != NULL )
+        m_poMIDFile->SetTranslation(m_dfXMultiplier,m_dfYMultiplier,
+                                    m_dfXDisplacement, m_dfYDisplacement);
     m_poMIFFile->SetDelimiter(m_pszDelimiter);
-    m_poMIDFile->SetDelimiter(m_pszDelimiter);
+    if( m_poMIDFile != NULL )
+        m_poMIDFile->SetDelimiter(m_pszDelimiter);
 
     /*-------------------------------------------------------------
      * Set geometry type if the geometry objects are uniform.
@@ -858,8 +865,11 @@ void MIFFile::ResetReading()
           break;
     }
 
-    m_poMIDFile->Rewind();
-    m_poMIDFile->GetLine();
+    if( m_poMIDFile != NULL )
+    {
+        m_poMIDFile->Rewind();
+        m_poMIDFile->GetLine();
+    }
     
     // We're positioned on first feature.  Feature Ids start at 1.
     if (m_poCurFeature)
@@ -984,8 +994,11 @@ void MIFFile::PreParseFile()
           break;
     }
 
-    m_poMIDFile->Rewind();
-    m_poMIDFile->GetLine();
+    if( m_poMIDFile != NULL )
+    {
+        m_poMIDFile->Rewind();
+        m_poMIDFile->GetLine();
+    }
  
     m_bPreParsed = TRUE;
 
@@ -1291,7 +1304,8 @@ GBool MIFFile::NextFeature()
     {
         if (m_poMIFFile->IsValidFeature(pszLine))
         {
-            m_poMIDFile->GetLine();
+            if( m_poMIDFile != NULL )
+                m_poMIDFile->GetLine();
             m_nPreloadedId++;
             return TRUE;
         }
@@ -1328,7 +1342,7 @@ TABFeature *MIFFile::GetFeatureRef(int nFeatureId)
      * Make sure file is opened and Validate feature id by positioning
      * the read pointers for the .MAP and .DAT files to this feature id.
      *----------------------------------------------------------------*/
-    if (m_poMIDFile == NULL)
+    if (m_poMIFFile == NULL)
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
                  "GetFeatureRef() failed: file is not opened!");
@@ -1468,7 +1482,7 @@ TABFeature *MIFFile::GetFeatureRef(int nFeatureId)
      * Read fields from the .DAT file
      * GetRecordBlock() has already been called above...
      *----------------------------------------------------------------*/
-    if (m_poCurFeature->ReadRecordFromMIDFile(m_poMIDFile) != 0)
+    if (m_poMIDFile != NULL && m_poCurFeature->ReadRecordFromMIDFile(m_poMIDFile) != 0)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Error during reading Record.");
diff --git a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
index 1f68ead..a5a5f41 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
+++ b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
@@ -36,6 +36,17 @@ In addition to the standard parameters of the
     <p>The connection may contain the optional <b>
     Driver</b> parameter if a custom SQL server driver should be loaded (like FreeTDS). The default is <b>{SQL Server}</b></p>
 
+<h2>Layers</h2>
+
+<p>Starting with GDAL 1.11 if the user defines the environment variable
+<i>MSSQLSPATIAL_LIST_ALL_TABLES=YES</i> (and does not specify Tables= in the connection string),
+all regular user tables will be treated as layers. This option is useful if you want tables with 
+with no spatial data<p>
+
+<p>By default the MSSQL driver will only look for layers that are registered in the <i>geometry_columns</i> metadata table.
+Starting with GDAL 1.10 if the user defines the environment variable
+<i>MSSQLSPATIAL_USE_GEOMETRY_COLUMNS=NO</i> then the driver will look for all user spatial tables found in the system catalog<p>
+
 <h2>SQL statements</h2>
 
 <p>The MS SQL Spatial driver passes SQL statements directly to MS SQL by default,
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
index bd79abf..b6473c2 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mssqlspatial.h 25988 2013-05-05 14:09:05Z tamas $
+ * $Id: ogr_mssqlspatial.h 26395 2013-09-03 11:49:23Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -303,6 +303,8 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
 
     int                 bUseGeometryColumns;
 
+    int                 bListAllTables;
+
     // We maintain a list of known SRID to reduce the number of trips to
     // the database to get SRSes. 
     int                 nKnownSRID;
@@ -321,7 +323,7 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
     int                 Open( const char *, int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszSchemaName, const char *pszTableName, 
                                    const char *pszGeomCol,int nCoordDimension,
-                                   int nSRID, const char *pszSRText,
+                                   int nSRID, const char *pszSRText, 
                                    OGRwkbGeometryType eType, int bUpdate );
 
     const char          *GetName() { return pszName; }
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
index e023c79..fa960a1 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdatasource.cpp 25988 2013-05-05 14:09:05Z tamas $
+ * $Id: ogrmssqlspatialdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 25988 2013-05-05 14:09:05Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRMSSQLSpatialDataSource()                 */
@@ -50,6 +51,7 @@ OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource()
     nGeometryFormat = MSSQLGEOMETRY_NATIVE;
 
     bUseGeometryColumns = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_USE_GEOMETRY_COLUMNS", "YES"));
+    bListAllTables = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_LIST_ALL_TABLES", "NO"));
 }
 
 /************************************************************************/
@@ -251,27 +253,30 @@ OGRLayer * OGRMSSQLSpatialDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Handle the GEOM_TYPE option.                                    */
 /* -------------------------------------------------------------------- */
-    pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
-
-    if( !pszGeomType )
-        pszGeomType = "geometry";
-    
-    if( !EQUAL(pszGeomType, "geometry")
-        && !EQUAL(pszGeomType, "geography"))
+    if ( eType != wkbNone )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "FORMAT=%s not recognised or supported.", 
-                  pszGeomType );
+        pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
 
-        CPLFree( pszSchemaName );
-        CPLFree( pszTableName );
-        return NULL;
-    }
+        if( !pszGeomType )
+            pszGeomType = "geometry";
+        
+        if( !EQUAL(pszGeomType, "geometry")
+            && !EQUAL(pszGeomType, "geography"))
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "FORMAT=%s not recognised or supported.", 
+                      pszGeomType );
 
-    /* determine the geometry column name */
-    pszGeomColumn =  CSLFetchNameValue( papszOptions, "GEOM_NAME");
-    if (!pszGeomColumn)
-        pszGeomColumn = "ogr_geometry";
+            CPLFree( pszSchemaName );
+            CPLFree( pszTableName );
+            return NULL;
+        }
+
+        /* determine the geometry column name */
+        pszGeomColumn =  CSLFetchNameValue( papszOptions, "GEOM_NAME");
+        if (!pszGeomColumn)
+            pszGeomColumn = "ogr_geometry";
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the metadata tables                                  */
@@ -301,39 +306,44 @@ OGRLayer * OGRMSSQLSpatialDataSource::CreateLayer( const char * pszLayerName,
 /*      geometry_columns metadata table.                                */
 /* -------------------------------------------------------------------- */
 
-    if( eType != wkbNone )
+    CPLODBCStatement oStmt( &oSession );
+
+    if( eType != wkbNone && bUseGeometryColumns)
     {
         const char *pszGeometryType = OGRToOGCGeomType(eType);
+      
+        oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' "
+            "AND f_table_name = '%s'\n", pszSchemaName, pszTableName );
+    
+        oStmt.Appendf("INSERT INTO [geometry_columns] ([f_table_catalog], [f_table_schema] ,[f_table_name], "
+            "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n", 
+            pszCatalog, pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszGeometryType );
+    }
 
-        CPLODBCStatement oStmt( &oSession );
-        
-        if (bUseGeometryColumns)
-        {
-            oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' "
-                "AND f_table_name = '%s'\n", pszSchemaName, pszTableName );
-        
-            oStmt.Appendf("INSERT INTO [geometry_columns] ([f_table_catalog], [f_table_schema] ,[f_table_name], "
-                "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n", 
-                pszCatalog, pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszGeometryType );
-        }
-
+    if( eType == wkbNone ) 
+    { 
+        oStmt.Appendf("CREATE TABLE [%s].[%s] ([ogr_fid] [int] IDENTITY(1,1) NOT NULL"
+            "CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([ogr_fid] ASC))",
+            pszSchemaName, pszTableName, pszTableName);
+    }
+    else
+    {
         oStmt.Appendf("CREATE TABLE [%s].[%s] ([ogr_fid] [int] IDENTITY(1,1) NOT NULL, "
             "[%s] [%s] NULL, CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([ogr_fid] ASC))",
             pszSchemaName, pszTableName, pszGeomColumn, pszGeomType, pszTableName);
-
-        oSession.BeginTransaction();
+    }
+    oSession.BeginTransaction();
         
-        if( !oStmt.ExecuteSQL() )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                        "Error creating layer: %s", GetSession()->GetLastError() );
-
-            return NULL;
-        }
+    if( !oStmt.ExecuteSQL() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Error creating layer: %s", GetSession()->GetLastError() );
 
-        oSession.CommitTransaction();
+        return NULL;
     }
 
+    oSession.CommitTransaction();
+
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
@@ -343,14 +353,14 @@ OGRLayer * OGRMSSQLSpatialDataSource::CreateLayer( const char * pszLayerName,
 
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
-    
+
     char *pszWKT = NULL;
     if( poSRS && poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
     {
         CPLFree(pszWKT);
         pszWKT = NULL;
     }
-
+    
     if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszWKT, eType) == OGRERR_FAILURE)
     {
         CPLFree( pszSchemaName );
@@ -635,11 +645,33 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 
     char** papszTypes = NULL;
 
+    /* if requesting all user database table then this takes priority */ 
+ 	if (papszTableNames == NULL && bListAllTables) 
+ 	{ 
+ 	    CPLODBCStatement oStmt( &oSession ); 
+ 	         
+ 	    oStmt.Append( "select sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.objects. [...]
+ 	
+ 	    if( oStmt.ExecuteSQL() ) 
+ 	    { 
+ 	        while( oStmt.Fetch() ) 
+ 	        { 
+ 	            papszSchemaNames =  
+ 	                    CSLAddString( papszSchemaNames, oStmt.GetColData(0) ); 
+ 	            papszTableNames =  
+ 	                    CSLAddString( papszTableNames, oStmt.GetColData(1) ); 
+ 	            papszGeomColumnNames =  
+ 	                    CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) ); 
+ 	        } 
+ 	    } 
+ 	} 
+
     /* Determine the available tables if not specified. */
     if (papszTableNames == NULL && bUseGeometryColumns)
     {
         CPLODBCStatement oStmt( &oSession );
-            
+        
+        /* Use join to make sure the existence of the referred column/table */
         oStmt.Append( "SELECT f_table_schema, f_table_name, f_geometry_column, coord_dimension, g.srid, srtext, geometry_type FROM dbo.geometry_columns g JOIN INFORMATION_SCHEMA.COLUMNS ON f_table_schema = TABLE_SCHEMA and f_table_name = TABLE_NAME and f_geometry_column = COLUMN_NAME left outer join dbo.spatial_ref_sys s on g.srid = s.srid");
 
         if( oStmt.ExecuteSQL() )
@@ -663,7 +695,10 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             }
         }
         else
-            bUseGeometryColumns = FALSE;
+        {
+            /* probably the table is missing at all */
+            InitializeMetadataTables();
+        }
     }
 
     /* Query catalog for tables having geometry columns */
@@ -711,10 +746,10 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 
         if( strlen(papszGeomColumnNames[iTable]) > 0 )
             OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], papszGeomColumnNames[iTable], 
-            nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, eType, bUpdate );
+                    nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, eType, bUpdate );
         else
             OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], NULL, 
-                    nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, eType, bUpdate );
+                    nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, wkbNone, bUpdate );
     }
 
     CSLDestroy( papszTableNames );
@@ -743,9 +778,9 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic imlplementation for OGRSQL dialect.                 */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
index 14966b9..8a1a222 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatiallayer.cpp 25860 2013-04-05 07:20:37Z tamas $
+ * $Id: ogrmssqlspatiallayer.cpp 25989 2013-05-05 19:35:01Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -29,7 +29,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 25860 2013-04-05 07:20:37Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 25989 2013-05-05 19:35:01Z tamas $");
 /************************************************************************/
 /*                        OGRMSSQLSpatialLayer()                        */
 /************************************************************************/
@@ -123,13 +123,6 @@ CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
                 pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
                 continue;
             }
-            else if ( EQUAL(poStmt->GetColTypeName( iCol ), "image") )
-            {
-                /* for the select layers we get image type */
-                nGeomColumnType = MSSQLCOLTYPE_BINARY;
-                pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
-                continue;
-            }
         }
         else
         {
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
index 9bbf480..d344eda 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialselectlayer.cpp 20578 2010-09-12 11:23:32Z rouault $
+ * $Id: ogrmssqlspatialselectlayer.cpp 25989 2013-05-05 19:35:01Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialSelectLayer class, layer access to the results
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 20578 2010-09-12 11:23:32Z rouault $");
+CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 25989 2013-05-05 19:35:01Z tamas $");
 /************************************************************************/
 /*                     OGRMSSQLSpatialSelectLayer()                     */
 /************************************************************************/
@@ -55,11 +55,28 @@ OGRMSSQLSpatialSelectLayer::OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSourc
     {
         if ( EQUAL(poStmt->GetColTypeName( iColumn ), "image") )
         {
-            nGeomColumnType = MSSQLCOLTYPE_BINARY;
-            pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-            break;
+            SQLCHAR     szTableName[256];
+            SQLSMALLINT nTableNameLength = 0;
+
+            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_DESC_TABLE_NAME,
+                                     szTableName, sizeof(szTableName),
+                                     &nTableNameLength, NULL);
+
+            if (nTableNameLength > 0)
+            {
+                OGRLayer *poBaseLayer = poDS->GetLayerByName((const char*)szTableName);
+                if (poBaseLayer != NULL && EQUAL(poBaseLayer->GetGeometryColumn(), poStmt->GetColName(iColumn)))
+                {
+                    nGeomColumnType = MSSQLCOLTYPE_BINARY;
+                    pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+                    /* copy spatial reference */
+                    if (!poSRS && poBaseLayer->GetSpatialRef())
+                        poSRS = poBaseLayer->GetSpatialRef()->Clone();
+                    break;
+                }
+            }
         }
-        if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geometry") )
+        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geometry") )
         {
             nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
             pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
index 39d8bf1..be6a80f 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialtablelayer.cpp 25988 2013-05-05 14:09:05Z tamas $
+ * $Id: ogrmssqlspatialtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 25988 2013-05-05 14:09:05Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRMSSQLAppendEscaped( )                     */
@@ -140,6 +141,7 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
         
         if( oGetKey.Fetch() ) // more than one field in key! 
         {
+            oGetKey.Clear();
             CPLFree( pszFIDColumn );
             pszFIDColumn = NULL;
 
@@ -271,7 +273,7 @@ CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
 /* -------------------------------------------------------------------- */
 /*             Try to find out the spatial reference                    */
 /* -------------------------------------------------------------------- */
-    
+
     nSRSId = nSRId;
 
     if (pszSRText)
@@ -637,6 +639,9 @@ OGRFeature *OGRMSSQLSpatialTableLayer::GetFeature( long nFeatureId )
 OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( (pszQuery == NULL && this->pszQuery == NULL)
         || (pszQuery != NULL && this->pszQuery != NULL 
             && EQUAL(pszQuery,this->pszQuery)) )
diff --git a/ogr/ogrsf_frmts/mysql/GNUmakefile b/ogr/ogrsf_frmts/mysql/GNUmakefile
index 292ae45..e78398d 100644
--- a/ogr/ogrsf_frmts/mysql/GNUmakefile
+++ b/ogr/ogrsf_frmts/mysql/GNUmakefile
@@ -7,6 +7,11 @@ OBJ	=	ogrmysqldriver.o ogrmysqldatasource.o \
 
 CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(MYSQL_INC) $(CPPFLAGS)
 
+ifeq ($(MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION),yes)
+CPPFLAGS +=   -DMYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION
+endif
+
+
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
diff --git a/ogr/ogrsf_frmts/mysql/ogr_mysql.h b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
index 4d0fed8..a7ce7b7 100644
--- a/ogr/ogrsf_frmts/mysql/ogr_mysql.h
+++ b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mysql.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_mysql.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for MySQL OGR Driver Classes.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
index 65c275b..749a299 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqldatasource.cpp 24947 2012-09-22 09:54:23Z rouault $
+ * $Id: ogrmysqldatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDataSource class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqldatasource.cpp 24947 2012-09-22 09:54:23Z rouault $");
+/* Recent versions of mysql no longer declare load_defaults() in my_sys.h */
+/* but they still have it in the lib. Very fragile... */
+#ifdef MYSQL_NEEDS_LOAD_DEFAULTS_DECLARATION
+extern "C" {
+int load_defaults(const char *conf_file, const char **groups,
+                  int *argc, char ***argv);
+void free_defaults(char **argv);
+}
+#endif
+
+CPL_CVSID("$Id: ogrmysqldatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /************************************************************************/
 /*                         OGRMySQLDataSource()                         */
 /************************************************************************/
@@ -648,9 +659,9 @@ OGRLayer * OGRMySQLDataSource::ExecuteSQL( const char *pszSQLCommand,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Use generic implementation for OGRSQL dialect.                  */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
index 2650347..ebfaf26 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqllayer.cpp 20458 2010-08-27 19:33:46Z rouault $
+ * $Id: ogrmysqllayer.cpp 26679 2013-12-01 11:35:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLLayer class.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqllayer.cpp 20458 2010-08-27 19:33:46Z rouault $");
+CPL_CVSID("$Id: ogrmysqllayer.cpp 26679 2013-12-01 11:35:25Z rouault $");
 
 /************************************************************************/
 /*                           OGRMySQLLayer()                            */
@@ -203,7 +203,7 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 
             if( poGeometry != NULL )
             {
-                poGeometry->assignSpatialReference( poSRS );
+                poGeometry->assignSpatialReference( GetSpatialRef() );
                 poFeature->SetGeometryDirectly( poGeometry );
             }
             continue;
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
index 7d2f507..9cc3543 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqlresultlayer.cpp 20460 2010-08-27 20:06:26Z rouault $
+ * $Id: ogrmysqlresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLResultLayer class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 20460 2010-08-27 20:06:26Z rouault $");
+CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRMySQLResultLayer()                         */
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
index 706b4dc..3b0bc4e 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqltablelayer.cpp 25513 2013-01-16 19:04:39Z rouault $
+ * $Id: ogrmysqltablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLTableLayer class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqltablelayer.cpp 25513 2013-01-16 19:04:39Z rouault $");
+CPL_CVSID("$Id: ogrmysqltablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRMySQLTableLayer()                         */
@@ -411,15 +412,15 @@ void OGRMySQLTableLayer::BuildWhere()
 
     if( m_poFilterGeom != NULL && pszGeomColumn )
     {
-        char szEnvelope[4096];
+        char szEnvelope[400];
         OGREnvelope  sEnvelope;
         szEnvelope[0] = '\0';
         
         //POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
         m_poFilterGeom->getEnvelope( &sEnvelope );
         
-        sprintf(szEnvelope,
-                "POLYGON((%.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f))",
+        snprintf(szEnvelope, sizeof(szEnvelope),
+                "POLYGON((%.18g %.18g, %.18g %.18g, %.18g %.18g, %.18g %.18g, %.18g %.18g))",
                 sEnvelope.MinX, sEnvelope.MinY,
                 sEnvelope.MaxX, sEnvelope.MinY,
                 sEnvelope.MaxX, sEnvelope.MaxY,
@@ -547,6 +548,9 @@ char *OGRMySQLTableLayer::BuildFields()
 OGRErr OGRMySQLTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     CPLFree( this->pszQuery );
 
     if( pszQuery == NULL || strlen(pszQuery) == 0 )
diff --git a/ogr/ogrsf_frmts/nas/nashandler.cpp b/ogr/ogrsf_frmts/nas/nashandler.cpp
index 5ea4f9d..2589148 100644
--- a/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: nashandler.cpp 25656 2013-02-19 15:40:20Z ilucena $
+ * $Id: nashandler.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASHandler class.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index eadb582..b3abc61 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreader.cpp 25656 2013-02-19 15:40:20Z ilucena $
+ * $Id: nasreader.cpp 27132 2014-04-05 21:48:58Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASReader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,6 +32,7 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 #include "gmlutils.h"
+#include "cpl_multiproc.h"
 
 #define SUPPORT_GEOMETRY
 
@@ -47,6 +49,8 @@
 #include "nasreaderp.h"
 #include "cpl_conv.h"
 
+void *NASReader::hMutex = NULL;
+
 /************************************************************************/
 /*                          CreateGMLReader()                           */
 /************************************************************************/
@@ -127,9 +131,11 @@ const char* NASReader::GetSourceFileName()
 int NASReader::SetupParser()
 
 {
-    static int bXercesInitialized = FALSE;
+    {
+    CPLMutexHolderD(&hMutex);
+    static int bXercesInitialized = -1;
 
-    if( !bXercesInitialized )
+    if( bXercesInitialized < 0)
     {
         try
         {
@@ -141,10 +147,14 @@ int NASReader::SetupParser()
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Exception initializing Xerces based GML reader.\n%s", 
                       tr_strdup(toCatch.getMessage()) );
+            bXercesInitialized = FALSE;
             return FALSE;
         }
         bXercesInitialized = TRUE;
     }
+    if( !bXercesInitialized )
+        return FALSE;
+    }
 
     // Cleanup any old parser.
     if( m_poSAXReader != NULL )
@@ -844,7 +854,7 @@ int NASReader::SaveClasses( const char *pszFile )
 /*      looking for schema information.                                 */
 /************************************************************************/
 
-int NASReader::PrescanForSchema( int bGetExtents )
+int NASReader::PrescanForSchema( int bGetExtents, int bAnalyzeSRSPerFeature )
 
 {
     GMLFeature  *poFeature;
@@ -884,8 +894,12 @@ int NASReader::PrescanForSchema( int bGetExtents )
             {
                 double  dfXMin, dfXMax, dfYMin, dfYMax;
                 OGREnvelope sEnvelope;
-                OGRwkbGeometryType eGType = (OGRwkbGeometryType)
-                    poClass->GetGeometryType();
+
+                if( poClass->GetGeometryPropertyCount() == 0 )
+                    poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown ) );
+
+                OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
+                    poClass->GetGeometryProperty(0)->GetType();
 
                 // Merge SRSName into layer.
                 const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, FALSE);
@@ -897,7 +911,7 @@ int NASReader::PrescanForSchema( int bGetExtents )
                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
                     eGType = wkbNone;
 
-                poClass->SetGeometryType(
+                poClass->GetGeometryProperty(0)->SetType(
                     (int) OGRMergeGeometryTypes(
                         eGType, poGeometry->getGeometryType() ) );
 
@@ -923,9 +937,12 @@ int NASReader::PrescanForSchema( int bGetExtents )
             }
             else
             {
-                if( poClass->GetGeometryType() == (int) wkbUnknown
+                if( poClass->GetGeometryPropertyCount() == 1 &&
+                    poClass->GetGeometryProperty(0)->GetType() == (int) wkbUnknown
                     && poClass->GetFeatureCount() == 1 )
-                    poClass->SetGeometryType( wkbNone );
+                {
+                    poClass->ClearGeometryProperties();
+                }
             }
 #endif /* def SUPPORT_GEOMETRY */
         }
diff --git a/ogr/ogrsf_frmts/nas/nasreaderp.h b/ogr/ogrsf_frmts/nas/nasreaderp.h
index eaaf46a..5bd38df 100644
--- a/ogr/ogrsf_frmts/nas/nasreaderp.h
+++ b/ogr/ogrsf_frmts/nas/nasreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreaderp.h 25120 2012-10-13 22:38:57Z rouault $
+ * $Id: nasreaderp.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Private Declarations for OGR NAS Reader code.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -180,7 +181,7 @@ public:
     int              LoadClasses( const char *pszFile = NULL );
     int              SaveClasses( const char *pszFile = NULL );
 
-    int              PrescanForSchema(int bGetExtents = TRUE );
+    int              PrescanForSchema(int bGetExtents = TRUE, int bAnalyzeSRSPerFeature = TRUE );
     int              PrescanForTemplate( void );
     void             ResetReading();
 
@@ -222,6 +223,8 @@ public:
 
     int         SetFilteredClassName(const char* pszClassName);
     const char* GetFilteredClassName() { return m_pszFilteredClassName; }
+
+    static void* hMutex;
 };
 
 #endif /* _CPL_NASREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/nas/ogr_nas.h b/ogr/ogrsf_frmts/nas/ogr_nas.h
index c9bd1fa..0e6e4cf 100644
--- a/ogr/ogrsf_frmts/nas/ogr_nas.h
+++ b/ogr/ogrsf_frmts/nas/ogr_nas.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_nas.h 24105 2012-03-10 12:08:04Z rouault $
+ * $Id: ogr_nas.h 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Declarations for OGR wrapper classes for NAS, and NAS<->OGR
@@ -70,8 +70,6 @@ class OGRNASLayer : public OGRLayer
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     int                 TestCapability( const char * );
 };
 
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
index 85c86f3..bb59202 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnasdatasource.cpp 25553 2013-01-26 11:45:56Z rouault $
+ * $Id: ogrnasdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrnasdatasource.cpp 25553 2013-01-26 11:45:56Z rouault $");
+CPL_CVSID("$Id: ogrnasdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const char *apszURNNames[] =
 {
@@ -135,8 +136,11 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen )
         if( szPtr[0] != '<'
             || strstr(szPtr,"opengis.net/gml") == NULL
             || (strstr(szPtr,"NAS-Operationen.xsd") == NULL &&
+                strstr(szPtr,"NAS-Operationen_optional.xsd") == NULL &&
                 strstr(szPtr,"AAA-Fachschema.xsd") == NULL ) )
         {
+            /*CPLDebug( "NAS",
+                      "Skipping. No chevrons of NAS found [%s]\n", szPtr );*/
             VSIFClose( fp );
             return FALSE;
         }
@@ -264,11 +268,15 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
 
 {
     OGRNASLayer *poLayer;
-    OGRwkbGeometryType eGType
-        = (OGRwkbGeometryType) poClass->GetGeometryType();
+    OGRwkbGeometryType eGType = wkbNone;
+    
+    if( poClass->GetGeometryPropertyCount() != 0 )
+    {
+        eGType = (OGRwkbGeometryType) poClass->GetGeometryProperty(0)->GetType();
 
-    if( poClass->GetFeatureCount() == 0 )
-        eGType = wkbUnknown;
+        if( poClass->GetFeatureCount() == 0 )
+            eGType = wkbUnknown;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Translate SRS.                                                  */
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
index 8a490fb..b1d7a9d 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnasdriver.cpp 24105 2012-03-10 12:08:04Z rouault $
+ * $Id: ogrnasdriver.cpp 26335 2013-08-15 22:34:46Z rouault $
  *
  * Project:  OGR
  * Purpose:  OGRNASDriver implementation
@@ -29,8 +29,11 @@
 
 #include "ogr_nas.h"
 #include "cpl_conv.h"
+#include "nasreaderp.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: ogrnasdriver.cpp 26335 2013-08-15 22:34:46Z rouault $");
 
-CPL_CVSID("$Id: ogrnasdriver.cpp 24105 2012-03-10 12:08:04Z rouault $");
 
 /************************************************************************/
 /*                          ~OGRNASDriver()                           */
@@ -39,6 +42,9 @@ CPL_CVSID("$Id: ogrnasdriver.cpp 24105 2012-03-10 12:08:04Z rouault $");
 OGRNASDriver::~OGRNASDriver()
 
 {
+    if( NASReader::hMutex != NULL )
+        CPLDestroyMutex( NASReader::hMutex );
+    NASReader::hMutex = NULL;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
index 80db93f..e7a69e1 100644
--- a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnaslayer.cpp 25120 2012-10-13 22:38:57Z rouault $
+ * $Id: ogrnaslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrnaslayer.cpp 25120 2012-10-13 22:38:57Z rouault $");
+CPL_CVSID("$Id: ogrnaslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRNASLayer()                              */
@@ -59,6 +60,7 @@ OGRNASLayer::OGRNASLayer( const char * pszName,
     else
         poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     poFeatureDefn->SetGeomType( eReqType );
 
 /* -------------------------------------------------------------------- */
@@ -247,9 +249,15 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Wow, we got our desired feature. Return it.                     */
 /* -------------------------------------------------------------------- */
-        delete poNASFeature;
+        if( poGeom && poOGRFeature->SetGeometryDirectly( poGeom ) != OGRERR_NONE )
+        {
+            int iId = poNASFeature->GetClass()->GetPropertyIndex( "gml_id" );
+            const GMLProperty *poIdProp = poNASFeature->GetProperty(iId);
+            CPLError( CE_Warning, CPLE_AppDefined, "NAS: could not set geometry (gml_id:%s)",
+		      poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)" );
+        }
 
-        poOGRFeature->SetGeometryDirectly( poGeom );
+        delete poNASFeature;
 
         return poOGRFeature;
     }
@@ -329,14 +337,3 @@ int OGRNASLayer::TestCapability( const char * pszCap )
     else 
         return FALSE;
 }
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRNASLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
diff --git a/ogr/ogrsf_frmts/ntf/ntf.h b/ogr/ogrsf_frmts/ntf/ntf.h
index 3d9acfa..e116cd6 100644
--- a/ogr/ogrsf_frmts/ntf/ntf.h
+++ b/ogr/ogrsf_frmts/ntf/ntf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ntf.h 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  Main declarations for NTF translator.
@@ -409,8 +409,6 @@ class OGRNTFLayer : public OGRLayer
     
     int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     // special to NTF
     OGRFeature         *FeatureTranslate( NTFFileReader *, NTFRecord ** );
 };
@@ -485,8 +483,6 @@ class OGRNTFRasterLayer : public OGRLayer
 
     int                 GetFeatureCount( int = TRUE );
     
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     int                 TestCapability( const char * );
 };
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
index 794d6b6..67cb36b 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_estlayers.cpp 15637 2008-10-29 16:06:38Z warmerdam $
+ * $Id: ntf_estlayers.cpp 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader methods related to establishing the schemas
@@ -33,7 +33,7 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_estlayers.cpp 15637 2008-10-29 16:06:38Z warmerdam $");
+CPL_CVSID("$Id: ntf_estlayers.cpp 26466 2013-09-14 09:07:46Z rouault $");
 
 #define MAX_LINK        5000
 
@@ -1692,6 +1692,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
 /*      Create a new feature definition.                                */
 /* -------------------------------------------------------------------- */
         poDefn = new OGRFeatureDefn( pszLayerName );
+        poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
         poDefn->SetGeomType( eGeomType );
         poDefn->Reference();
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
index 51c377f..2633824 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_raster.cpp 21977 2011-03-18 19:53:18Z warmerdam $
+ * $Id: ntf_raster.cpp 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  Handle UK Ordnance Survey Raster DTM products.  Includes some
@@ -31,7 +31,7 @@
 
 #include "ntf.h"
 
-CPL_CVSID("$Id: ntf_raster.cpp 21977 2011-03-18 19:53:18Z warmerdam $");
+CPL_CVSID("$Id: ntf_raster.cpp 26466 2013-09-14 09:07:46Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -240,6 +240,7 @@ OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
     poFeatureDefn = new OGRFeatureDefn( szLayerName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint25D );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDSIn->GetSpatialRef());
 
     OGRFieldDefn      oHeight( "HEIGHT", OFTReal );
     poFeatureDefn->AddFieldDefn( &oHeight );
@@ -407,16 +408,6 @@ int OGRNTFRasterLayer::GetFeatureCount( int bForce )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRNTFRasterLayer::GetSpatialRef()
-
-{
-    return poDS->GetSpatialRef();
-}
-
-/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
index a2f5e05..7225aed 100644
--- a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntffilereader.cpp 25504 2013-01-14 22:18:55Z rouault $
+ * $Id: ntffilereader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader class implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ntffilereader.cpp 25504 2013-01-14 22:18:55Z rouault $");
+CPL_CVSID("$Id: ntffilereader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord **,
                                     NTFRecord * );
diff --git a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
index d68759b..90d761c 100644
--- a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntfrecord.cpp 25504 2013-01-14 22:18:55Z rouault $
+ * $Id: ntfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  NTFRecord class implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ntfrecord.cpp 25504 2013-01-14 22:18:55Z rouault $");
+CPL_CVSID("$Id: ntfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static int nFieldBufSize = 0;
 static char *pszFieldBuf = NULL;
diff --git a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
index aa9bd19..3aa84b3 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrntflayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogrntflayer.cpp 26467 2013-09-14 09:16:12Z rouault $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFLayer class.
@@ -30,7 +30,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntflayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrntflayer.cpp 26467 2013-09-14 09:16:12Z rouault $");
 
 /************************************************************************/
 /*                            OGRNTFLayer()                             */
@@ -214,13 +214,3 @@ OGRFeature * OGRNTFLayer::FeatureTranslate( NTFFileReader *poReader,
 
     return pfnTranslator( poReader, this, papoGroup );
 }
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRNTFLayer::GetSpatialRef()
-
-{
-    return poDS->GetSpatialRef();
-}
diff --git a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
index ec6e0d3..d76a8de 100644
--- a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
+++ b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrnulldriver.cpp 24668 2012-07-10 09:37:22Z rouault $
+ * $Id: ogrnulldriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  NULL output driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrnulldriver.cpp 24668 2012-07-10 09:37:22Z rouault $");
+CPL_CVSID("$Id: ogrnulldriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void CPL_DLL RegisterOGRNULL();
 
diff --git a/ogr/ogrsf_frmts/oci/ogr_oci.h b/ogr/ogrsf_frmts/oci/ogr_oci.h
index d65d9b1..4ebbf9f 100644
--- a/ogr/ogrsf_frmts/oci/ogr_oci.h
+++ b/ogr/ogrsf_frmts/oci/ogr_oci.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_oci.h 25656 2013-02-19 15:40:20Z ilucena $
+ * $Id: ogr_oci.h 26573 2013-10-30 13:34:41Z rouault $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Oracle Spatial OGR Driver Declarations. 
@@ -252,6 +252,7 @@ class OGROCILayer : public OGRLayer
   public:
                         OGROCILayer();
     virtual             ~OGROCILayer();
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) { return OGRLayer::FindFieldIndex( pszFieldName, bExactMatch ); }
 
     virtual void        ResetReading();
     virtual OGRFeature *GetNextRawFeature();
@@ -312,6 +313,7 @@ public:
     virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch );
 
     // following methods are not base class overrides
     void                SetOptions( char ** );
diff --git a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
index 38db743..8b83faa 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocidatasource.cpp 25759 2013-03-15 17:41:57Z ilucena $
+ * $Id: ogrocidatasource.cpp 26506 2013-09-30 18:17:55Z rouault $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIDataSource class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocidatasource.cpp 25759 2013-03-15 17:41:57Z ilucena $");
+CPL_CVSID("$Id: ogrocidatasource.cpp 26506 2013-09-30 18:17:55Z rouault $");
 
 static int anEPSGOracleMapping[] = 
 {
@@ -644,9 +644,9 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic implementation for OGRSQL dialect.                  */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
index f5f5f2a..3ced924 100644
--- a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocitablelayer.cpp 25770 2013-03-19 13:55:49Z ilucena $
+ * $Id: ogrocitablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCITableLayer class.  This class provides
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocitablelayer.cpp 25770 2013-03-19 13:55:49Z ilucena $");
+CPL_CVSID("$Id: ogrocitablelayer.cpp 26688 2013-12-02 19:07:41Z rouault $");
 
 static int nDiscarded = 0;
 static int nHits = 0;
@@ -674,6 +674,9 @@ char *OGROCITableLayer::BuildFields()
 OGRErr OGROCITableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( (pszQuery == NULL && this->pszQuery == NULL)
         || (pszQuery != NULL && this->pszQuery != NULL
             && strcmp(pszQuery,this->pszQuery) == 0) )
diff --git a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
index 7a7e457..9f63d0b 100644
--- a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrociwritablelayer.cpp 12355 2007-10-09 04:48:19Z ilucena $
+ * $Id: ogrociwritablelayer.cpp 26573 2013-10-30 13:34:41Z rouault $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIWritableLayer class.  This provides
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociwritablelayer.cpp 12355 2007-10-09 04:48:19Z ilucena $");
+CPL_CVSID("$Id: ogrociwritablelayer.cpp 26573 2013-10-30 13:34:41Z rouault $");
 
 /************************************************************************/
 /*                        OGROCIWritableLayer()                         */
@@ -492,3 +492,23 @@ OGRErr OGROCIWritableLayer::TranslateToSDOGeometry( OGRGeometry * poGeometry,
     return OGRERR_FAILURE;
 }
 
+int OGROCIWritableLayer::FindFieldIndex( const char *pszFieldName, int bExactMatch )
+{
+  int iField = GetLayerDefn()->GetFieldIndex( pszFieldName );
+
+  if( !bExactMatch && iField < 0 )
+  {
+      // try laundered version
+      OGROCISession *poSession = poDS->GetSession();
+      char *pszSafeName = CPLStrdup( pszFieldName );
+
+      poSession->CleanName( pszSafeName );
+
+      iField = GetLayerDefn()->GetFieldIndex( pszSafeName );
+
+      CPLFree( pszSafeName );
+  }
+
+  return iField;
+}
+
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
index 9deda8f..393fadd 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodbcdatasource.cpp 24960 2012-09-23 18:06:25Z rouault $
+ * $Id: ogrodbcdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrodbcdatasource.cpp 24960 2012-09-23 18:06:25Z rouault $");
+CPL_CVSID("$Id: ogrodbcdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /************************************************************************/
 /*                         OGRODBCDataSource()                          */
 /************************************************************************/
@@ -133,6 +134,20 @@ int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Check if it is a Walk MDB.                                      */
+/* -------------------------------------------------------------------- */
+    {
+        CPLODBCStatement oStmt( &oSession );
+
+        oStmt.Append( "SELECT LayerID, LayerName, minE, maxE, minN, maxN, Memo FROM WalkLayers" );
+
+        if( oStmt.ExecuteSQL() )
+        {
+            return FALSE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Return all tables as  non-spatial tables.                       */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oTableList( &oSession );
@@ -527,9 +542,9 @@ OGRLayer * OGRODBCDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic imlplementation for OGRSQL dialect.                 */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
index 10cbbc9..73fc8a0 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodbctablelayer.cpp 24961 2012-09-23 18:06:49Z rouault $
+ * $Id: ogrodbctablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCTableLayer class, access to an existing table.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_odbc.h"
 
-CPL_CVSID("$Id: ogrodbctablelayer.cpp 24961 2012-09-23 18:06:49Z rouault $");
+CPL_CVSID("$Id: ogrodbctablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /************************************************************************/
 /*                          OGRODBCTableLayer()                         */
 /************************************************************************/
@@ -306,6 +307,9 @@ OGRFeature *OGRODBCTableLayer::GetFeature( long nFeatureId )
 OGRErr OGRODBCTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( (pszQuery == NULL && this->pszQuery == NULL)
         || (pszQuery != NULL && this->pszQuery != NULL 
             && EQUAL(pszQuery,this->pszQuery)) )
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.cpp b/ogr/ogrsf_frmts/ods/ods_formula.cpp
index 79a7684..9a9d2d3 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula.cpp 23831 2012-01-30 23:12:23Z rouault $
+ * $Id: ods_formula.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: ODS formula Engine
  * Purpose:
@@ -7,7 +7,7 @@
  *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.h b/ogr/ogrsf_frmts/ods/ods_formula.h
index 0ae56bc..e55f4db 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.h
+++ b/ogr/ogrsf_frmts/ods/ods_formula.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula.h 23831 2012-01-30 23:12:23Z rouault $
+ * $Id: ods_formula.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
@@ -8,7 +8,7 @@
  *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -192,6 +192,7 @@ class IODSCellEvaluator
 public:
     virtual int EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
                               std::vector<ods_formula_node>& aoOutValues) = 0;
+    virtual ~IODSCellEvaluator() {}
 };
 
 int ods_formulaparse( ods_formula_parse_context *context );
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
index bd0526e..1715a18 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula_node.cpp 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: ods_formula_node.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
@@ -8,7 +8,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -250,7 +250,7 @@ void ods_formula_node::Dump( FILE * fp, int depth )
     char        spaces[60];
     int         i;
 
-    for( i = 0; i < depth*2 && i < (int) sizeof(spaces); i++ )
+    for( i = 0; i < depth*2 && i < (int) sizeof(spaces) - 1; i++ )
         spaces[i] = ' ';
     spaces[i] = '\0';
 
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
index a141c57..f5d5434 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
@@ -5,6 +5,7 @@
    
       Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -79,7 +80,7 @@
 #line 1 "ods_formula_parser.y"
 
 /******************************************************************************
- * $Id: ods_formula_parser.cpp 23831 2012-01-30 23:12:23Z rouault $
+ * $Id: ods_formula_parser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: OGR ODS Formula Engine
  * Purpose: expression and select parser grammar.
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp b/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
index 64d1d30..1657c60 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
@@ -5,6 +5,7 @@
    
       Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/ogr/ogrsf_frmts/ods/ogr_ods.h b/ogr/ogrsf_frmts/ods/ogr_ods.h
index f5ad580..fb82330 100644
--- a/ogr/ogrsf_frmts/ods/ogr_ods.h
+++ b/ogr/ogrsf_frmts/ods/ogr_ods.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_ods.h 24173 2012-03-29 21:09:52Z rouault $
+ * $Id: ogr_ods.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .ods driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
index 3cac4cf..ed3992b 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrodsdatasource.cpp 25415 2012-12-31 16:36:30Z rouault $
+ * $Id: ogrodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "ods_formula.h"
 #include <set>
 
-CPL_CVSID("$Id: ogrodsdatasource.cpp 25415 2012-12-31 16:36:30Z rouault $");
+CPL_CVSID("$Id: ogrodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
index fccc671..0986376 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrodsdriver.cpp 23831 2012-01-30 23:12:23Z rouault $
+ * $Id: ogrodsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_ods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrodsdriver.cpp 23831 2012-01-30 23:12:23Z rouault $");
+CPL_CVSID("$Id: ogrodsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRODS();
 
diff --git a/ogr/ogrsf_frmts/ods/testparser.cpp b/ogr/ogrsf_frmts/ods/testparser.cpp
index c2e226e..ae91a37 100644
--- a/ogr/ogrsf_frmts/ods/testparser.cpp
+++ b/ogr/ogrsf_frmts/ods/testparser.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: testparser.cpp 23831 2012-01-30 23:12:23Z rouault $
+ * $Id: testparser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: Test ODS formula Engine
  * Purpose:
  * Author: Even Rouault <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdi.h b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
index ff6c835..df38003 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdi.h
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdi.h 20207 2010-08-06 22:07:29Z rouault $
+ * $Id: ogrogdi.h 26688 2013-12-02 19:07:41Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Private definitions within the OGDI driver to implement
@@ -58,6 +58,8 @@ class OGROGDILayer : public OGRLayer
     int                 m_iNextShapeId;
     int                 m_nTotalShapeCount;
     int                 m_nFilteredOutShapes;
+    
+    OGRFeature *        GetNextRawFeature();
 
   public:
                         OGROGDILayer(OGROGDIDataSource *, const char *, 
@@ -78,8 +80,6 @@ class OGROGDILayer : public OGRLayer
 
     int                 TestCapability( const char * );
 
-    OGRSpatialReference *GetSpatialRef()  { return m_poSpatialRef; }
-
   private:
     void                BuildFeatureDefn();
 };
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
index 71cda9e..66bd3de 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdilayer.cpp 23014 2011-08-31 18:40:35Z rouault $
+ * $Id: ogrogdilayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDILayer class.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Daniel Morissette
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -56,7 +57,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdilayer.cpp 23014 2011-08-31 18:40:35Z rouault $");
+CPL_CVSID("$Id: ogrogdilayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGROGDILayer()                            */
@@ -204,9 +205,7 @@ void OGROGDILayer::ResetReading()
 OGRFeature *OGROGDILayer::GetNextFeature()
 
 {
-    OGRFeature  *poFeature=NULL;
-    ecs_Result  *psResult;
-    int         i;
+    OGRFeature  *poFeature;
 
     /* Reset reading if we are not the current layer */
     /* WARNING : this does not allow interleaved reading of layers */ 
@@ -216,10 +215,42 @@ OGRFeature *OGROGDILayer::GetNextFeature()
         ResetReading();
     }
 
+    while( TRUE )
+    {
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we need to apply an attribute test?                          */
+    /* -------------------------------------------------------------------- */
+        if( (m_poAttrQuery != NULL
+            && !m_poAttrQuery->Evaluate( poFeature ) ) 
+            || (m_poFilterGeom != NULL 
+                && !FilterGeometry( poFeature->GetGeometryRef() ) ) )
+        {
+            m_nFilteredOutShapes ++;
+            delete poFeature;
+        }
+        else
+            return poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGROGDILayer::GetNextRawFeature()
+{
+    ecs_Result  *psResult;
+    int         i;
+    OGRFeature  *poFeature;
+
 /* -------------------------------------------------------------------- */
 /*      Retrieve object from OGDI server and create new feature         */
 /* -------------------------------------------------------------------- */
-  TryAgain:
+
     psResult = cln_GetNextObject(m_nClientID);
     if (! ECSSUCCESS(psResult))
     {
@@ -353,19 +384,6 @@ OGRFeature *OGROGDILayer::GetNextFeature()
         poFeature->SetField( "text", ECSGEOM(psResult).text.desc );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we need to apply an attribute test?                          */
-/* -------------------------------------------------------------------- */
-    if( (m_poAttrQuery != NULL
-         && !m_poAttrQuery->Evaluate( poFeature ) ) 
-        || (m_poFilterGeom != NULL 
-            && !FilterGeometry( poFeature->GetGeometryRef() ) ) )
-    {
-        m_nFilteredOutShapes ++;
-        delete poFeature;
-        goto TryAgain;
-    }
-
     return poFeature;
 }
 
@@ -381,6 +399,11 @@ OGRFeature *OGROGDILayer::GetFeature( long nFeatureId )
     if (m_nTotalShapeCount != -1 && nFeatureId > m_nTotalShapeCount)
         return NULL;
 
+    /* Unset spatial filter */
+    OGRGeometry* poOldFilterGeom = ( m_poFilterGeom != NULL ) ? m_poFilterGeom->clone() : NULL;
+    if( poOldFilterGeom != NULL )
+        SetSpatialFilter(NULL);
+
     /* Reset reading if we are not the current layer */
     /* WARNING : this does not allow interleaved reading of layers */
     if( m_poODS->GetCurrentLayer() != this )
@@ -400,12 +423,23 @@ OGRFeature *OGROGDILayer::GetFeature( long nFeatureId )
         {
             // We probably reached EOF... keep track of shape count.
             m_nTotalShapeCount = m_iNextShapeId;
+            if( poOldFilterGeom != NULL )
+            {
+                SetSpatialFilter(poOldFilterGeom);
+                delete poOldFilterGeom;
+            }
             return NULL;
         }
     }
 
     // OK, we're ready to read the requested feature...
-    return GetNextFeature();
+    OGRFeature* poFeature = GetNextRawFeature();
+    if( poOldFilterGeom != NULL )
+    {
+        SetSpatialFilter(poOldFilterGeom);
+        delete poOldFilterGeom;
+    }
+    return poFeature;
 }
 
 /************************************************************************/
@@ -524,6 +558,7 @@ void OGROGDILayer::BuildFeatureDefn()
     
     m_poFeatureDefn->SetGeomType(eLayerGeomType);
     m_poFeatureDefn->Reference();
+    m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSpatialRef);
 
 /* -------------------------------------------------------------------- */
 /*      Fetch schema from OGDI server and map to OGR types              */
diff --git a/ogr/ogrsf_frmts/ogr_formats.html b/ogr/ogrsf_frmts/ogr_formats.html
index bd1ea61..dd8eca5 100644
--- a/ogr/ogrsf_frmts/ogr_formats.html
+++ b/ogr/ogrsf_frmts/ogr_formats.html
@@ -73,6 +73,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_cartodb.html">CartoDB</a>
+</td><td> CartoDB
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libcurl
+</td></tr>
+
 <tr><td> <a href="drv_csv.html">Comma Separated Value (.csv)</a>
 </td><td> CSV
 </td><td> Yes
@@ -87,6 +94,13 @@
 </td><td> No, needs libcurl
 </td></tr>
 
+<tr><td> <a href="drv_vfk.html">Czech Cadastral Exchange Data Format</a>
+</td><td> VFK
+</td><td> No
+</td><td> Yes
+</td><td> No, needs libsqlite3
+</td></tr>
+
 <tr><td> <a href="drv_dods.html">DODS/OPeNDAP</a>
 </td><td> DODS
 </td><td> No
@@ -164,6 +178,13 @@
 </td><td> No, needs ODBC library
 </td></tr>
 
+<tr><td> <a href="drv_geopackage.html">GeoPackage</a>
+</td><td> GPKG
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libsqlite3
+</td></tr>
+
 <tr><td> <a href="drv_georss.html">GeoRSS</a>
 </td><td> GeoRSS
 </td><td> Yes
@@ -178,6 +199,13 @@
 </td><td> No, needs libcurl
 </td></tr>
 
+<tr><td> <a href="http://trac.osgeo.org/gdal/wiki/GMEDriver">Google Maps Engine</a>
+</td><td> GME
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libcurl
+</td></tr>
+
 <tr><td> <a href="drv_gml.html">GML</a>
 </td><td> GML
 </td><td> Yes
@@ -206,7 +234,7 @@
 </td><td> Yes (read support needs libexpat)
 </td></tr>
 
-<tr><td> <a href="drv_grass.html">GRASS</a>
+<tr><td> <a href="drv_grass.html">GRASS Vector Format</a>
 </td><td> GRASS
 </td><td> No
 </td><td> Yes
@@ -354,6 +382,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_openfilegdb.html">ESRI FileGDB</a>
+</td><td> OpenFileGDB
+</td><td> No
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="drv_osm.html">OpenStreetMap XML and PBF</a>
 </td><td> OSM
 </td><td> No
@@ -459,22 +494,22 @@
 </td><td> No, needs libexpat
 </td></tr>
 
-<tr><td> <a href="drv_ntf.html">UK .NTF</a>
-</td><td> UK. NTF
+<tr><td> <a href="drv_sxf.html">Storage and eXchange Format</a>
+</td><td> SXF
 </td><td> No
 </td><td> Yes
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="drv_tiger.html">U.S. Census TIGER/Line</a>
-</td><td> TIGER
+<tr><td> <a href="drv_ntf.html">UK .NTF</a>
+</td><td> UK. NTF
 </td><td> No
 </td><td> Yes
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="drv_vfk.html">VFK data</a>
-</td><td> VFK
+<tr><td> <a href="drv_tiger.html">U.S. Census TIGER/Line</a>
+</td><td> TIGER
 </td><td> No
 </td><td> Yes
 </td><td> Yes
@@ -515,6 +550,20 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_walk.html">Walk</a>
+</td><td> Walk
+</td><td> No
+</td><td> Yes
+</td><td> No, needs ODBC library
+</td></tr>
+
+<tr><td> <a href="drv_wasp.html">WAsP .map format</a>
+</td><td> WAsP
+</td><td> Yes
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
 </table>
 
 </body>
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.dox b/ogr/ogrsf_frmts/ogrsf_frmts.dox
index 55b5b49..cdfc864 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.dox
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.dox
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.dox 25840 2013-04-02 19:10:04Z winkey $
+ * $Id: ogrsf_frmts.dox 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Documentation for ogrsf_frmts.h classes.
@@ -1005,6 +1005,8 @@ can also be used.
  <ul>
   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing layers.<p>
+  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
+        datasource support CreateGeomField() just after layer creation.<p>
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
@@ -1031,6 +1033,8 @@ can also be used.
  <ul>
   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.
   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing layers.<p>
+  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
+        datasource support CreateGeomField() just after layer creation.<p>
   <p>
  </ul>
 
@@ -1593,6 +1597,78 @@ by the OGRSFDriverManager.
 
 */
 
+/**
+
+ \fn OGRErr OGRLayer::GetExtent( int iGeomField,OGREnvelope *psExtent, int bForce = TRUE );
+
+ \brief Fetch the extent of this layer, on the specified geometry field.
+
+ Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
+ and it would be expensive to establish the extent then OGRERR_FAILURE
+ will be returned indicating that the extent isn't know.  If bForce is 
+ TRUE then some implementations will actually scan the entire layer once
+ to compute the MBR of all the features in the layer.
+
+ Depending on the drivers, the returned extent may or may not take the
+ spatial filter into account.  So it is safer to call GetExtent() without
+ setting a spatial filter.
+
+ Layers without any geometry may return OGRERR_FAILURE just indicating that
+ no meaningful extents could be collected.
+
+ Note that some implementations of this method may alter the read cursor
+ of the layer.
+
+ Note to driver implementators: if you implement GetExtent(int,OGREnvelope*,int),
+ you must also implement GetExtent(OGREnvelope*, int) to make it call
+ GetExtent(0,OGREnvelope*,int).
+
+ This method is the same as the C function OGR_L_GetExtentEx().
+
+ @param iGeomField the index of the geometry field on which to compute the extent.
+ @param psExtent the structure in which the extent value will be returned.
+ @param bForce Flag indicating whether the extent should be computed even
+ if it is expensive.
+
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+
+*/
+
+
+/**
+
+ \fn OGRErr OGR_L_GetExtentEx( OGRLayerH hLayer, int iGeomField, OGREnvelope *psExtent, int bForce);
+
+ \brief Fetch the extent of this layer, on the specified geometry field.
+
+ Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
+ and it would be expensive to establish the extent then OGRERR_FAILURE
+ will be returned indicating that the extent isn't know.  If bForce is 
+ TRUE then some implementations will actually scan the entire layer once
+ to compute the MBR of all the features in the layer.
+
+ Depending on the drivers, the returned extent may or may not take the
+ spatial filter into account.  So it is safer to call OGR_L_GetExtent() without
+ setting a spatial filter.
+
+ Layers without any geometry may return OGRERR_FAILURE just indicating that
+ no meaningful extents could be collected.
+
+ Note that some implementations of this method may alter the read cursor
+ of the layer.
+
+ This function is the same as the C++ method OGRLayer::GetExtent().
+
+ @param hLayer handle to the layer from which to get extent.
+ @param iGeomField the index of the geometry field on which to compute the extent.
+ @param psExtent the structure in which the extent value will be returned.
+ @param bForce Flag indicating whether the extent should be computed even
+ if it is expensive.
+
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+
+*/
+
 /** 
  \fn void OGRLayer::SetSpatialFilter( OGRGeometry * poFilter );
 
@@ -1715,6 +1791,160 @@ by the OGRSFDriverManager.
  
  */
 
+
+/** 
+ \fn void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poFilter );
+
+ \brief Set a new spatial filter. 
+
+ This method set the geometry to be used as a spatial filter when 
+ fetching features via the GetNextFeature() method.  Only features that
+ geometrically intersect the filter geometry will be returned.  
+
+ Currently this test is may be inaccurately implemented, but it is
+ guaranteed that all features who's envelope (as returned by
+ OGRGeometry::getEnvelope()) overlaps the envelope of the spatial filter
+ will be returned.  This can result in more shapes being returned that 
+ should strictly be the case. 
+
+ This method makes an internal copy of the passed geometry.  The 
+ passed geometry remains the responsibility of the caller, and may 
+ be safely destroyed. 
+
+ For the time being the passed filter geometry should be in the same
+ SRS as the geometry field definition it corresponds to (as returned by
+ GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef()).  In the
+ future this may be generalized.
+
+ Note that only the last spatial filter set is applied, even if several
+ successive calls are done with different iGeomField values.
+
+ Note to driver implementators: if you implement SetSpatialFilter(int,OGRGeometry*),
+ you must also implement SetSpatialFilter(OGRGeometry*) to make it call
+ SetSpatialFilter(0,OGRGeometry*).
+
+ This method is the same as the C function OGR_L_SetSpatialFilterEx().
+
+ @param iGeomField index of the geometry field on which the spatial filter
+ operates.
+ @param poFilter the geometry to use as a filtering region.  NULL may
+ be passed indicating that the current spatial filter should be cleared,
+ but no new one instituted.
+
+ @since GDAL 1.11
+ 
+ */
+
+/** 
+ \fn void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField, OGRGeometryH hGeom );
+
+ \brief Set a new spatial filter. 
+
+ This function set the geometry to be used as a spatial filter when 
+ fetching features via the OGR_L_GetNextFeature() function.  Only 
+ features that geometrically intersect the filter geometry will be 
+ returned.  
+
+ Currently this test is may be inaccurately implemented, but it is
+ guaranteed that all features who's envelope (as returned by
+ OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter
+ will be returned.  This can result in more shapes being returned that 
+ should strictly be the case. 
+
+ This function makes an internal copy of the passed geometry.  The 
+ passed geometry remains the responsibility of the caller, and may 
+ be safely destroyed. 
+
+ For the time being the passed filter geometry should be in the same
+ SRS as the geometry field definition it corresponds to (as returned by
+ GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef()).  In the
+ future this may be generalized.
+
+ Note that only the last spatial filter set is applied, even if several
+ successive calls are done with different iGeomField values.
+
+ This function is the same as the C++ method OGRLayer::SetSpatialFilter.
+
+ @param hLayer handle to the layer on which to set the spatial filter.
+ @param iGeomField index of the geometry field on which the spatial filter
+ operates.
+ @param hGeom handle to the geometry to use as a filtering region.  NULL may
+ be passed indicating that the current spatial filter should be cleared,
+ but no new one instituted.
+
+ @since GDAL 1.11
+ 
+ */
+
+/** 
+ \fn void OGRLayer::SetSpatialFilterRect( int iGeomField, 
+                                          double dfMinX, double dfMinY, 
+                                          double dfMaxX, double dfMaxY );
+
+ \brief Set a new rectangular spatial filter. 
+
+ This method set rectangle to be used as a spatial filter when 
+ fetching features via the GetNextFeature() method.  Only features that
+ geometrically intersect the given rectangle will be returned.  
+
+ The x/y values should be in the same coordinate system as as the geometry
+ field definition it corresponds to (as returned by
+ GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this 
+ method is normally implemented as creating a 5 vertex closed rectangular
+ polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
+ a convenience. 
+
+ The only way to clear a spatial filter set with this method is to 
+ call OGRLayer::SetSpatialFilter(NULL). 
+
+ This method is the same as the C function OGR_L_SetSpatialFilterRectEx().
+
+ @param iGeomField index of the geometry field on which the spatial filter
+ operates.
+ @param dfMinX the minimum X coordinate for the rectangular region.
+ @param dfMinY the minimum Y coordinate for the rectangular region.
+ @param dfMaxX the maximum X coordinate for the rectangular region.
+ @param dfMaxY the maximum Y coordinate for the rectangular region.
+ 
+ @since GDAL 1.11
+ */
+
+/** 
+ \fn void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
+                                        int iGeomField, 
+                                        double dfMinX, double dfMinY, 
+                                        double dfMaxX, double dfMaxY );
+
+ \brief Set a new rectangular spatial filter. 
+
+ This method set rectangle to be used as a spatial filter when 
+ fetching features via the OGR_L_GetNextFeature() method.  Only features that
+ geometrically intersect the given rectangle will be returned.  
+
+ The x/y values should be in the same coordinate system as as the geometry
+ field definition it corresponds to (as returned by
+ GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this 
+ method is normally implemented as creating a 5 vertex closed rectangular
+ polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
+ a convenience. 
+
+ The only way to clear a spatial filter set with this method is to 
+ call OGRLayer::SetSpatialFilter(NULL). 
+
+ This method is the same as the C++ method OGRLayer::SetSpatialFilterRect().
+
+ @param hLayer handle to the layer on which to set the spatial filter.
+ @param iGeomField index of the geometry field on which the spatial filter
+ operates.
+ @param dfMinX the minimum X coordinate for the rectangular region.
+ @param dfMinY the minimum Y coordinate for the rectangular region.
+ @param dfMaxX the maximum X coordinate for the rectangular region.
+ @param dfMaxY the maximum Y coordinate for the rectangular region.
+ 
+ @since GDAL 1.11
+ */
+
+
 /**
  \fn OGRGeometry *OGRLayer::GetSpatialFilter();
 
@@ -1840,12 +2070,56 @@ by the OGRSFDriverManager.
 
 /**
 
+ \fn int OGR_L_FindFieldIndex( OGRLayerH hLayer, const char *, int bExactMatch );
+
+ \brief Find the index of field in a layer.
+
+ The returned number is the index of the field in the layers, or -1 if the
+ field doesn't exist.
+
+ If bExactMatch is set to FALSE and the field doesn't exists in the given form
+ the driver might apply some changes to make it match, like those it might do
+ if the layer was created (eg. like LAUNDER in the OCI driver).
+ 
+ This method is the same as the C++ method OGRLayer::FindFieldIndex().
+
+ @return field index, or -1 if the field doesn't exist
+
+*/
+
+/**
+
+ \fn int OGRLayer::FindFieldIndex( const char *, int bExactMatch );
+
+ \brief Find the index of field in the layer.
+
+ The returned number is the index of the field in the layers, or -1 if the
+ field doesn't exist.
+
+ If bExactMatch is set to FALSE and the field doesn't exists in the given form
+ the driver might apply some changes to make it match, like those it might do
+ if the layer was created (eg. like LAUNDER in the OCI driver).
+ 
+ This method is the same as the C function OGR_L_FindFieldIndex().
+
+ @return field index, or -1 if the field doesn't exist
+
+*/
+
+/**
+
  \fn OGRSpatialReference *OGRLayer::GetSpatialRef();
 
  \brief Fetch the spatial reference system for this layer. 
 
  The returned object is owned by the OGRLayer and should not be modified
- or freed by the application.  
+ or freed by the application.
+ 
+ Starting with OGR 1.11, several geometry fields can be associated to a
+ feature definition. Each geometry field can have its own spatial reference
+ system, which is returned by OGRGeomFieldDefn::GetSpatialRef().
+ OGRLayer::GetSpatialRef() is equivalent to
+ GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef()
 
  This method is the same as the C function OGR_L_GetSpatialRef().
 
@@ -1878,7 +2152,9 @@ by the OGRSFDriverManager.
 
  This function will attempt to read the identified feature.  The nFID
  value cannot be OGRNullFID.  Success or failure of this operation is
- unaffected by the spatial or attribute filters.
+ unaffected by the spatial or attribute filters (and specialized implementations
+ in drivers should make sure that they do not take into account spatial or
+ attribute filters).
 
  If this method returns a non-NULL feature, it is guaranteed that its  
  feature id (OGRFeature::GetFID()) will be the same as nFID.
@@ -1888,7 +2164,8 @@ by the OGRSFDriverManager.
  call should always work if the feature exists as a fallback implementation
  just scans all the features in the layer looking for the desired feature.
  
- Sequential reads are generally considered interrupted by a GetFeature() call.
+ Sequential reads (with GetNextFeature()) are generally considered interrupted
+ by a GetFeature() call.
  
  The returned feature should be free with OGRFeature::DestroyFeature().
 
@@ -1909,7 +2186,9 @@ by the OGRSFDriverManager.
 
  This function will attempt to read the identified feature.  The nFID
  value cannot be OGRNullFID.  Success or failure of this operation is
- unaffected by the spatial or attribute filters.
+ unaffected by the spatial or attribute filters (and specialized implementations
+ in drivers should make sure that they do not take into account spatial or
+ attribute filters).
 
  If this function returns a non-NULL feature, it is guaranteed that its  
  feature id (OGR_F_GetFID()) will be the same as nFID.
@@ -1920,7 +2199,7 @@ by the OGRSFDriverManager.
  implementation just scans all the features in the layer looking for the 
  desired feature.
  
- Sequential reads are generally considered interrupted by a 
+ Sequential reads (with OGR_L_GetNextFeature()) are generally considered interrupted by a 
  OGR_L_GetFeature() call.
  
  The returned feature should be free with OGR_F_Destroy().
@@ -2114,6 +2393,9 @@ FALSE.<p>
  <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create 
 new fields on the current layer using CreateField(), otherwise FALSE.<p>
 
+ <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create 
+new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
+
  <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
 existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
 
@@ -2205,6 +2487,9 @@ FALSE.<p>
  <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create 
 new fields on the current layer using CreateField(), otherwise FALSE.<p>
 
+ <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create 
+new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
+
  <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
 existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
 
@@ -2719,6 +3004,69 @@ definition must be taken into account.
 @since OGR 1.9.0
 */
 
+
+/**
+\fn OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn *poField, 
+                  int bApproxOK = TRUE );
+
+\brief Create a new geometry field on a layer.
+
+You must use this to create new geometry fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the new field.  Applications should never modify the OGRFeatureDefn
+used by a layer directly.
+
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCCreateGeomField capability. Some drivers may only support this method while
+there are still no features in the layer. When it is supported, the existings features of the
+backing file/database should be updated accordingly.
+
+This function is the same as the C function OGR_L_CreateGeomField().
+
+ at param poField geometry field definition to write to disk. 
+ at param bApproxOK If TRUE, the field may be created in a slightly different
+form depending on the limitations of the format driver.
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.11
+*/
+ 
+/**
+
+ \fn OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+                          int bApproxOK );
+
+\brief Create a new geometry field on a layer.
+
+You must use this to create new geometry fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the new field.  Applications should never modify the OGRFeatureDefn
+used by a layer directly.
+
+This function should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+
+Not all drivers support this function. You can query a layer to check if it supports it
+with the OLCCreateField capability. Some drivers may only support this method while
+there are still no features in the layer. When it is supported, the existings features of the
+backing file/database should be updated accordingly.
+
+ This function is the same as the C++ method OGRLayer::CreateField().
+
+ @param hLayer handle to the layer to write the field definition.
+ @param hField handle of the geometry field definition to write to disk. 
+ @param bApproxOK If TRUE, the field may be created in a slightly different
+form depending on the limitations of the format driver.
+
+ @return OGRERR_NONE on success.
+
+ @since OGR 1.11
+*/
+
 /**
  \fn  void OGRLayer::GetStyleTable();
 
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h
index 2082922..0ff6c23 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.h
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.h 25581 2013-01-29 20:42:37Z warmerdam $
+ * $Id: ogrsf_frmts.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to format registration, and file opening.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -53,7 +54,7 @@ class OGRSFDriver;
  */
 
 /* Note: any virtual method added to this class must also be added in the */
-/* OGRLayerDecorator class. */
+/* OGRLayerDecorator and OGRMutexedLayer classes. */
 
 class CPL_DLL OGRLayer
 {
@@ -62,10 +63,14 @@ class CPL_DLL OGRLayer
     OGRGeometry *m_poFilterGeom;
     OGRPreparedGeometry *m_pPreparedFilterGeom; /* m_poFilterGeom compiled as a prepared geometry */
     OGREnvelope  m_sFilterEnvelope;
+    int          m_iGeomFieldFilter; // specify the index on which the spatial
+                                     // filter is active.
     
     int          FilterGeometry( OGRGeometry * );
     //int          FilterGeometry( OGRGeometry *, OGREnvelope* psGeometryEnvelope);
     int          InstallFilter( OGRGeometry * );
+    
+    OGRErr       GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce );
 
   public:
     OGRLayer();
@@ -76,6 +81,11 @@ class CPL_DLL OGRLayer
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
                                               double dfMaxX, double dfMaxY );
 
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField,
+                                            double dfMinX, double dfMinY,
+                                            double dfMaxX, double dfMaxY );
+
     virtual OGRErr      SetAttributeFilter( const char * );
 
     virtual void        ResetReading() = 0;
@@ -89,11 +99,14 @@ class CPL_DLL OGRLayer
     virtual const char *GetName();
     virtual OGRwkbGeometryType GetGeomType();
     virtual OGRFeatureDefn *GetLayerDefn() = 0;
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch );
 
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+    virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         GetFeatureCount( int bForce = TRUE );
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
+                                  int bForce = TRUE);
 
     virtual int         TestCapability( const char * ) = 0;
 
@@ -105,6 +118,9 @@ class CPL_DLL OGRLayer
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
 
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+
     virtual OGRErr      SyncToDisk();
 
     virtual OGRStyleTable *GetStyleTable();
@@ -175,6 +191,7 @@ class CPL_DLL OGRLayer
  protected:
     OGRStyleTable       *m_poStyleTable;
     OGRFeatureQuery     *m_poAttrQuery;
+    char                *m_pszAttrQueryString;
     OGRLayerAttrIndex   *m_poAttrIndex;
 
     int                  m_nRefCount;
@@ -250,6 +267,8 @@ class CPL_DLL OGRDataSource
 
     OGRSFDriver        *GetDriver() const;
     void                SetDriver( OGRSFDriver *poDriver );
+    
+    static int          IsGenericSQLDialect(const char* pszDialect);
 
   protected:
 
@@ -367,6 +386,7 @@ void CPL_DLL RegisterOGRTAB();
 void CPL_DLL RegisterOGRMIF();
 void CPL_DLL RegisterOGROGDI();
 void CPL_DLL RegisterOGRODBC();
+void CPL_DLL RegisterOGRWAsP();
 void CPL_DLL RegisterOGRPG();
 void CPL_DLL RegisterOGRMSSQLSpatial();
 void CPL_DLL RegisterOGRMySQL();
@@ -418,6 +438,7 @@ void CPL_DLL RegisterOGRGeomedia();
 void CPL_DLL RegisterOGRMDB();
 void CPL_DLL RegisterOGREDIGEO();
 void CPL_DLL RegisterOGRGFT();
+void CPL_DLL RegisterOGRGME();
 void CPL_DLL RegisterOGRSVG();
 void CPL_DLL RegisterOGRCouchDB();
 void CPL_DLL RegisterOGRIdrisi();
@@ -428,7 +449,12 @@ void CPL_DLL RegisterOGRXLS();
 void CPL_DLL RegisterOGRODS();
 void CPL_DLL RegisterOGRXLSX();
 void CPL_DLL RegisterOGRElastic();
+void CPL_DLL RegisterOGRGeoPackage();
 void CPL_DLL RegisterOGRPDF();
+void CPL_DLL RegisterOGRWalk();
+void CPL_DLL RegisterOGRCartoDB();
+void CPL_DLL RegisterOGRSXF();
+void CPL_DLL RegisterOGROpenFileGDB();
 CPL_C_END
 
 
diff --git a/ogr/ogrsf_frmts/openair/ogr_openair.h b/ogr/ogrsf_frmts/openair/ogr_openair.h
index 6b94054..e261d3b 100644
--- a/ogr/ogrsf_frmts/openair/ogr_openair.h
+++ b/ogr/ogrsf_frmts/openair/ogr_openair.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_openair.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_openair.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Definition of classes for OGR .sua driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -72,9 +72,6 @@ class OGROpenAirLayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 };
 
 /************************************************************************/
@@ -106,9 +103,6 @@ class OGROpenAirLabelLayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
index e3e577f..bdc5a54 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogropenairdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
+ * $Id: ogropenairdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogropenairdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
+CPL_CVSID("$Id: ogropenairdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGROpenAirDataSource()                        */
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
index e75435b..76a1faf 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogropenairdriver.cpp 20003 2010-07-10 19:46:28Z rouault $
+ * $Id: ogropenairdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_openair.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogropenairdriver.cpp 20003 2010-07-10 19:46:28Z rouault $");
+CPL_CVSID("$Id: ogropenairdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGROpenAir();
 
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
index c597536..a4f6473 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogropenairlabellayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogropenairlabellayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLabelLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogropenairlabellayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogropenairlabellayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      OGROpenAirLabelLayer()                          */
@@ -50,6 +50,7 @@ OGROpenAirLabelLayer::OGROpenAirLabelLayer( VSILFILE* fp )
     poFeatureDefn = new OGRFeatureDefn( "labels"  );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     OGRFieldDefn    oField1( "CLASS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
index 573d407..4668dbd 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogropenairlayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogropenairlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogropenairlayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogropenairlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGROpenAirLayer()                            */
@@ -53,6 +53,7 @@ OGROpenAirLayer::OGROpenAirLayer( VSILFILE* fp )
     poFeatureDefn = new OGRFeatureDefn( "airspaces" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPolygon );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     OGRFieldDefn    oField1( "CLASS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
diff --git a/ogr/ogrsf_frmts/openfilegdb/GNUmakefile b/ogr/ogrsf_frmts/openfilegdb/GNUmakefile
new file mode 100644
index 0000000..ba849e7
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogropenfilegdbdriver.o ogropenfilegdbdatasource.o ogropenfilegdblayer.o filegdbtable.o filegdbindex.o
+
+CPPFLAGS	:=	-I.. -I../.. -I../mem $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_openfilegdb.h filegdbtable.h filegdbtable_priv.h ../mem/ogr_mem.h
diff --git a/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
new file mode 100644
index 0000000..ae325b0
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
@@ -0,0 +1,100 @@
+<html>
+<head>
+<title>ESRI File Geodatabase (OpenFileGDB)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ESRI File Geodatabase (OpenFileGDB)</h1>
+
+<p>(Available in GDAL >= 1.11)</p>
+
+<p>
+The OpenFileGDB driver provides read access to File Geodatabases
+(.gdb directories) created by ArcGIS 9 and above.
+</p>
+<p>
+It can also read directly zipped .gdb directories (.gdb.zip)
+</p>
+<p>
+A specific .gdbtable file (including "system" tables) can also be opened
+directly.
+</p>
+
+<h2>Spatial filtering</h2>
+
+The driver cannot use the .spx files (when they are present) for spatial
+filtering. However, it will use the minimum bounding rectangle included at the
+beginning of the geometry blobs to speed up spatial filtering. By default, it
+will also build on the fly a in-memory spatial index during the first sequential
+read of a layer. Following spatial filtering operations on that layer will then
+benefit from that spatial index. The building of this in-memory spatial index
+can be disabled by setting the OPENFILEGDB_IN_MEMORY_SPI configuration option to
+NO.
+
+<h2>SQL support</h2>
+
+SQL statements are run through the OGR SQL engine. When attribute indexes (.atx
+files) exist, the driver will use them to speed up WHERE clauses or SetAttributeFilter()
+calls.
+
+<h3>Special SQL requests</h3>
+
+"GetLayerDefinition a_layer_name" and "GetLayerMetadata a_layer_name" can be
+used as special SQL requests to get respectively the definition and metadata of
+a FileGDB table as XML content (only available in Geodatabases created with
+ArcGIS 10 or above)
+
+<h2>Comparison with the FileGDB driver</h2>
+
+<p>
+(Comparison done with a FileGDB driver using FileGDB API SDK 1.3)
+</p>
+
+<p>
+Advantages of the OpenFileGDB driver:
+</p>
+
+<ul>
+<li>Can read ArcGIS 9.X Geodatabases, and not only 10 or above.</li>
+<li>Can open layers with any spatial reference system.</li>
+<li>Thread-safe (i.e. datasources can be processed in parallel).</li>
+<li>Uses the VSI Virtual File API, enabling the user
+    to read a Geodatabase in a ZIP file or stored on a HTTP server.</li>
+<li>Faster on databases with a big number of fields.</li>
+<li>Does not depend on a third-party library.</li>
+<li>Robust against corrupted Geodatabase files.</li>
+</ul>
+
+<p>
+Drawbacks of the OpenFileGDB driver:
+</p>
+
+<ul>
+<li>Read-only.</li>
+<li>Cannot use spatial indexes.</li>
+</ul>
+
+<h2>Examples</h2>
+
+<ul>
+    <li>Read layer from FileGDB and load into PostGIS:<p>
+    <code>ogr2ogr -overwrite -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" "C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
+    </li>
+    <li>Get detailed info for FileGDB:<p>
+    <code>ogrinfo -al "C:\somefolder\MyGDB.gdb"</code>
+    </li>
+    <li>Get detailed info for a zipped FileGDB:<p>
+    <code>ogrinfo -al "C:\somefolder\MyGDB.gdb.zip"</code>
+    </li>
+</ul>
+
+<h2>Links</h2>
+
+<ul>
+<li><a href="drv_filegdb.html">FileGDB driver</a>, relying on the FileGDB API SDK</li>
+<li>Reverse-engineered specification of the <a href="https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec">FileGDB format</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
new file mode 100644
index 0000000..ef314d5
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
@@ -0,0 +1,1796 @@
+/******************************************************************************
+ * $Id: filegdbindex.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements reading of FileGDB indexes
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "filegdbtable_priv.h"
+#include "cpl_string.h"
+#include "cpl_time.h"
+#include <algorithm>
+
+CPL_CVSID("$Id");
+
+namespace OpenFileGDB
+{
+
+/************************************************************************/
+/*                     FileGDBOGRDateToDoubleDate()                     */
+/************************************************************************/
+
+static int FileGDBOGRDateToDoubleDate( const OGRField* psField, double *pdfVal )
+{
+    struct tm brokendowntime;
+
+    brokendowntime.tm_year = psField->Date.Year - 1900;
+    brokendowntime.tm_mon = psField->Date.Month - 1;
+    brokendowntime.tm_mday = psField->Date.Day;
+    brokendowntime.tm_hour = psField->Date.Hour;
+    brokendowntime.tm_min = psField->Date.Minute;
+    brokendowntime.tm_sec = psField->Date.Second;
+
+    GIntBig nTime = CPLYMDHMSToUnixTime(&brokendowntime);
+
+    *pdfVal = nTime / 3600. / 24 + 25569;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        FileGDBTrivialIterator                        */
+/************************************************************************/
+
+class FileGDBTrivialIterator : public FileGDBIterator
+{
+        FileGDBIterator            *poParentIter;
+        FileGDBTable               *poTable;
+        int                         iRow;
+
+    public:
+                                     FileGDBTrivialIterator(FileGDBIterator *poParentIter);
+        virtual                     ~FileGDBTrivialIterator() { delete poParentIter; }
+
+        virtual FileGDBTable        *GetTable() { return poTable; }
+        virtual void                 Reset() { iRow = 0; }
+        virtual int                  GetNextRowSortedByFID();
+        virtual int                  GetRowCount()
+                { return poTable->GetTotalRecordCount(); }
+
+        virtual int                  GetNextRowSortedByValue()
+                { return poParentIter->GetNextRowSortedByValue(); }
+
+        virtual const OGRField*      GetMinValue(int& eOutType)
+                { return poParentIter->GetMinValue(eOutType); }
+        virtual const OGRField*      GetMaxValue(int& eOutType)
+                { return poParentIter->GetMaxValue(eOutType); }
+        virtual int                  GetMinMaxSumCount(double& dfMin, double& dfMax,
+                                                       double& dfSum, int& nCount)
+            { return poParentIter->GetMinMaxSumCount(dfMin, dfMax, dfSum, nCount); }
+};
+
+/************************************************************************/
+/*                        FileGDBNotIterator                            */
+/************************************************************************/
+
+class FileGDBNotIterator : public FileGDBIterator
+{
+        FileGDBIterator            *poIterBase;
+        FileGDBTable               *poTable;
+        int                         iRow;
+        int                         iNextRowBase;
+        int                         bNoHoles;
+
+    public:
+                                     FileGDBNotIterator(FileGDBIterator* poIterBase);
+        virtual                     ~FileGDBNotIterator();
+
+        virtual FileGDBTable        *GetTable() { return poTable; }
+        virtual void                 Reset();
+        virtual int                  GetNextRowSortedByFID();
+        virtual int                  GetRowCount();
+};
+
+/************************************************************************/
+/*                        FileGDBAndIterator                            */
+/************************************************************************/
+
+class FileGDBAndIterator : public FileGDBIterator
+{
+        FileGDBIterator             *poIter1;
+        FileGDBIterator             *poIter2;
+        int                          iNextRow1;
+        int                          iNextRow2;
+
+    public:
+                                     FileGDBAndIterator(FileGDBIterator* poIter1,
+                                                        FileGDBIterator* poIter2);
+        virtual                     ~FileGDBAndIterator();
+
+        virtual FileGDBTable        *GetTable() { return poIter1->GetTable(); }
+        virtual void                 Reset();
+        virtual int                  GetNextRowSortedByFID();
+};
+
+/************************************************************************/
+/*                        FileGDBOrIterator                             */
+/************************************************************************/
+
+class FileGDBOrIterator : public FileGDBIterator
+{
+        FileGDBIterator             *poIter1;
+        FileGDBIterator             *poIter2;
+        int                          bIteratorAreExclusive;
+        int                          iNextRow1;
+        int                          iNextRow2;
+        int                          bHasJustReset;
+
+    public:
+                                     FileGDBOrIterator(FileGDBIterator* poIter1,
+                                                       FileGDBIterator* poIter2,
+                                                       int bIteratorAreExclusive = FALSE);
+        virtual                     ~FileGDBOrIterator();
+
+        virtual FileGDBTable        *GetTable() { return poIter1->GetTable(); }
+        virtual void                 Reset();
+        virtual int                  GetNextRowSortedByFID();
+        virtual int                  GetRowCount();
+};
+
+/************************************************************************/
+/*                        FileGDBIndexIterator                          */
+/************************************************************************/
+
+#define MAX_DEPTH               3
+#define UUID_LEN_AS_STRING      38
+#define MAX_CAR_COUNT_STR       80
+#define MAX_UTF8_LEN_STR        (4 * MAX_CAR_COUNT_STR)
+#define FGDB_PAGE_SIZE          4096
+
+class FileGDBIndexIterator : public FileGDBIterator
+{
+        FileGDBTable        *poParent;
+        int                  bAscending;
+        VSILFILE            *fpCurIdx;
+        FileGDBFieldType     eFieldType;
+        GUInt32              nMaxPerPages;
+        GUInt32              nOffsetFirstValInPage;
+        GUInt32              nValueCountInIdx;
+        GUInt32              nIndexDepth;
+        FileGDBSQLOp         eOp;
+        OGRField             sValue;
+
+        int                  iFirstPageIdx[MAX_DEPTH],
+                             iLastPageIdx[MAX_DEPTH],
+                             iCurPageIdx[MAX_DEPTH];
+        GUInt32              nSubPagesCount[MAX_DEPTH];
+        GUInt32              nLastPageAccessed[MAX_DEPTH];
+
+        int                  iCurFeatureInPage, nFeaturesInPage;
+
+        int                  bEvaluateToFALSE;
+        int                  bEOF;
+
+        int                  iSorted;
+        int                  nSortedCount;
+        int                 *panSortedRows;
+        int                  SortRows();
+
+        GUInt16              asUTF16Str[MAX_CAR_COUNT_STR];
+        int                  nStrLen;
+        char                 szUUID[UUID_LEN_AS_STRING + 1];
+        GByte                abyPage[MAX_DEPTH][FGDB_PAGE_SIZE];
+        GByte                abyPageFeature[FGDB_PAGE_SIZE];
+
+        OGRField             sMin, sMax;
+        char                 szMin[MAX_UTF8_LEN_STR+1];
+        char                 szMax[MAX_UTF8_LEN_STR+1];
+        const OGRField*      GetMinMaxValue(OGRField* psField,
+                                            int& eOutType,
+                                            int bIsMin);
+
+        int                  ReadPageNumber(int iLevel);
+        int                  LoadNextPage(int iLevel);
+        int                  FindPages(int iLevel, int nPage);
+        int                  LoadNextFeaturePage();
+
+        int                  GetNextRow();
+
+                             FileGDBIndexIterator(FileGDBTable* poParent,
+                                                  int bAscending);
+        int                  SetConstraint(int nFieldIdx, FileGDBSQLOp op,
+                                           OGRFieldType eOGRFieldType,
+                                           const OGRField* psValue);
+
+        template <class Getter> void GetMinMaxSumCount(
+                                                  double& dfMin, double& dfMax,
+                                                  double& dfSum, int& nCount);
+    public:
+        virtual             ~FileGDBIndexIterator();
+
+        static FileGDBIterator*      Build(FileGDBTable* poParent,
+                                           int nFieldIdx,
+                                           int bAscending,
+                                           FileGDBSQLOp op,
+                                           OGRFieldType eOGRFieldType,
+                                           const OGRField* psValue);
+
+        virtual FileGDBTable        *GetTable() { return poParent; }
+        virtual void                 Reset();
+        virtual int                  GetNextRowSortedByFID();
+        virtual int                  GetRowCount();
+
+        virtual int                  GetNextRowSortedByValue() { return GetNextRow(); }
+
+        virtual const OGRField*      GetMinValue(int& eOutType);
+        virtual const OGRField*      GetMaxValue(int& eOutType);
+        virtual int                  GetMinMaxSumCount(double& dfMin, double& dfMax,
+                                                       double& dfSum, int& nCount);
+};
+
+/************************************************************************/
+/*                            GetMinValue()                             */
+/************************************************************************/
+
+const OGRField* FileGDBIterator::GetMinValue(int& eOutType)
+{
+    PrintError();
+    eOutType = -1;
+    return NULL;
+}
+
+/************************************************************************/
+/*                            GetMaxValue()                             */
+/************************************************************************/
+
+const OGRField* FileGDBIterator::GetMaxValue(int& eOutType)
+{
+    PrintError();
+    eOutType = -1;
+    return NULL;
+}
+
+/************************************************************************/
+/*                       GetNextRowSortedByValue()                      */
+/************************************************************************/
+
+int FileGDBIterator::GetNextRowSortedByValue()
+{
+    PrintError();
+    return -1;
+}
+
+/************************************************************************/
+/*                        GetMinMaxSumCount()                           */
+/************************************************************************/
+
+int FileGDBIterator::GetMinMaxSumCount(double& dfMin, double& dfMax,
+                                       double& dfSum, int& nCount)
+{
+    PrintError();
+    dfMin = 0.0;
+    dfMax = 0.0;
+    dfSum = 0.0;
+    nCount = 0;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                             Build()                                  */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIterator::Build(FileGDBTable* poParent,
+                                        int nFieldIdx,
+                                        int bAscending,
+                                        FileGDBSQLOp op,
+                                        OGRFieldType eOGRFieldType,
+                                        const OGRField* psValue)
+{
+    return FileGDBIndexIterator::Build(poParent, nFieldIdx, bAscending,
+                                       op, eOGRFieldType, psValue);
+}
+
+/************************************************************************/
+/*                           BuildIsNotNull()                           */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIterator::BuildIsNotNull(FileGDBTable* poParent,
+                                                 int nFieldIdx,
+                                                 int bAscending)
+{
+    FileGDBIterator* poIter = Build(poParent, nFieldIdx, bAscending,
+                                    FGSO_ISNOTNULL, OFTMaxType, NULL);
+    if( poIter != NULL )
+    {
+        /* Optimization */
+        if( poIter->GetRowCount() == poParent->GetTotalRecordCount() )
+        {
+            CPLAssert(poParent->GetValidRecordCount() == poParent->GetTotalRecordCount());
+            poIter = new FileGDBTrivialIterator(poIter);
+        }
+    }
+    return poIter;
+}
+
+/************************************************************************/
+/*                              BuildNot()                              */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIterator::BuildNot(FileGDBIterator* poIterBase)
+{
+    return new FileGDBNotIterator(poIterBase);
+}
+
+/************************************************************************/
+/*                               BuildAnd()                             */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIterator::BuildAnd(FileGDBIterator* poIter1,
+                                           FileGDBIterator* poIter2)
+{
+    return new FileGDBAndIterator(poIter1, poIter2);
+}
+
+/************************************************************************/
+/*                               BuildOr()                              */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIterator::BuildOr(FileGDBIterator* poIter1,
+                                          FileGDBIterator* poIter2,
+                                          int bIteratorAreExclusive)
+{
+    return new FileGDBOrIterator(poIter1, poIter2, bIteratorAreExclusive);
+}
+
+/************************************************************************/
+/*                           GetRowCount()                              */
+/************************************************************************/
+
+int FileGDBIterator::GetRowCount()
+{
+    Reset();
+    int nCount = 0;
+    while( GetNextRowSortedByFID() >= 0 )
+        nCount ++;
+    Reset();
+    return nCount;
+}
+
+/************************************************************************/
+/*                         FileGDBTrivialIterator()                     */
+/************************************************************************/
+
+FileGDBTrivialIterator::FileGDBTrivialIterator(FileGDBIterator* poParentIter) :
+        poParentIter(poParentIter), poTable(poParentIter->GetTable()), iRow(0)
+{
+}
+
+/************************************************************************/
+/*                        GetNextRowSortedByFID()                       */
+/************************************************************************/
+
+int FileGDBTrivialIterator::GetNextRowSortedByFID()
+{
+    if( iRow < poTable->GetTotalRecordCount() )
+        return iRow ++;
+    else
+        return -1;
+}
+
+/************************************************************************/
+/*                           FileGDBNotIterator()                       */
+/************************************************************************/
+
+FileGDBNotIterator::FileGDBNotIterator(FileGDBIterator* poIterBase) :
+    poIterBase(poIterBase), poTable(poIterBase->GetTable()), iRow(0), iNextRowBase(-1)
+{
+    bNoHoles = (poTable->GetValidRecordCount() == poTable->GetTotalRecordCount());
+}
+
+/************************************************************************/
+/*                          ~FileGDBNotIterator()                       */
+/************************************************************************/
+
+FileGDBNotIterator::~FileGDBNotIterator()
+{
+    delete poIterBase;
+}
+
+/************************************************************************/
+/*                             Reset()                                  */
+/************************************************************************/
+
+void FileGDBNotIterator::Reset()
+{
+    poIterBase->Reset();
+    iRow = 0;
+    iNextRowBase = -1;
+}
+
+/************************************************************************/
+/*                        GetNextRowSortedByFID()                       */
+/************************************************************************/
+
+int FileGDBNotIterator::GetNextRowSortedByFID()
+{
+    if( iNextRowBase < 0 )
+    {
+        iNextRowBase = poIterBase->GetNextRowSortedByFID();
+        if( iNextRowBase < 0 )
+            iNextRowBase = poTable->GetTotalRecordCount();
+    }
+
+    while( TRUE )
+    {
+        if( iRow < iNextRowBase )
+        {
+            if( bNoHoles )
+                return iRow ++;
+            else if( poTable->GetOffsetInTableForRow(iRow) )
+                return iRow ++;
+            else if( !poTable->HasGotError() )
+                iRow ++;
+            else
+                return -1;
+        }
+        else if( iRow == poTable->GetTotalRecordCount() )
+            return -1;
+        else
+        {
+            iRow = iNextRowBase + 1;
+            iNextRowBase = poIterBase->GetNextRowSortedByFID();
+            if( iNextRowBase < 0 )
+                iNextRowBase = poTable->GetTotalRecordCount();
+        }
+    }
+}
+
+/************************************************************************/
+/*                           GetRowCount()                              */
+/************************************************************************/
+
+int FileGDBNotIterator::GetRowCount()
+{
+    return poTable->GetValidRecordCount() - poIterBase->GetRowCount();
+}
+
+
+/************************************************************************/
+/*                          FileGDBAndIterator()                        */
+/************************************************************************/
+
+FileGDBAndIterator::FileGDBAndIterator(FileGDBIterator* poIter1,
+                                       FileGDBIterator* poIter2) :
+                                       poIter1(poIter1), poIter2(poIter2),
+                                       iNextRow1(-1), iNextRow2(-1)
+{
+    CPLAssert(poIter1->GetTable() == poIter2->GetTable());
+}
+
+/************************************************************************/
+/*                          ~FileGDBAndIterator()                       */
+/************************************************************************/
+
+FileGDBAndIterator::~FileGDBAndIterator()
+{
+    delete poIter1;
+    delete poIter2;
+}
+
+/************************************************************************/
+/*                             Reset()                                  */
+/************************************************************************/
+
+void FileGDBAndIterator::Reset()
+{
+    poIter1->Reset();
+    poIter2->Reset();
+    iNextRow1 = -1;
+    iNextRow2 = -1;
+}
+
+/************************************************************************/
+/*                        GetNextRowSortedByFID()                       */
+/************************************************************************/
+
+int FileGDBAndIterator::GetNextRowSortedByFID()
+{
+    if( iNextRow1 == iNextRow2 )
+    {
+        iNextRow1 = poIter1->GetNextRowSortedByFID();
+        iNextRow2 = poIter2->GetNextRowSortedByFID();
+        if( iNextRow1 < 0 || iNextRow2 < 0 )
+        {
+            return -1;
+        }
+    }
+
+    while( TRUE )
+    {
+        if( iNextRow1 < iNextRow2 )
+        {
+            iNextRow1 = poIter1->GetNextRowSortedByFID();
+            if( iNextRow1 < 0 )
+                return -1;
+        }
+        else if( iNextRow2 < iNextRow1 )
+        {
+            iNextRow2 = poIter2->GetNextRowSortedByFID();
+            if( iNextRow2 < 0 )
+                return -1;
+        }
+        else
+            return iNextRow1;
+    }
+}
+
+/************************************************************************/
+/*                          FileGDBOrIterator()                         */
+/************************************************************************/
+
+
+FileGDBOrIterator::FileGDBOrIterator(FileGDBIterator* poIter1,
+                                     FileGDBIterator* poIter2,
+                                     int bIteratorAreExclusive) :
+                            poIter1(poIter1), poIter2(poIter2),
+                            bIteratorAreExclusive(bIteratorAreExclusive),
+                            iNextRow1(-1), iNextRow2(-1), bHasJustReset(TRUE)
+{
+    CPLAssert(poIter1->GetTable() == poIter2->GetTable());
+}
+
+/************************************************************************/
+/*                          ~FileGDBOrIterator()                        */
+/************************************************************************/
+
+FileGDBOrIterator::~FileGDBOrIterator()
+{
+    delete poIter1;
+    delete poIter2;
+}
+
+/************************************************************************/
+/*                             Reset()                                  */
+/************************************************************************/
+
+void FileGDBOrIterator::Reset()
+{
+    poIter1->Reset();
+    poIter2->Reset();
+    iNextRow1 = -1;
+    iNextRow2 = -1;
+    bHasJustReset = TRUE;
+}
+
+/************************************************************************/
+/*                        GetNextRowSortedByFID()                       */
+/************************************************************************/
+
+int FileGDBOrIterator::GetNextRowSortedByFID()
+{
+    if( bHasJustReset )
+    {
+        bHasJustReset = FALSE;
+        iNextRow1 = poIter1->GetNextRowSortedByFID();
+        iNextRow2 = poIter2->GetNextRowSortedByFID();
+    }
+
+    if( iNextRow1 < 0 )
+    {
+        int iVal = iNextRow2;
+        iNextRow2 = poIter2->GetNextRowSortedByFID();
+        return iVal;
+    }
+    if( iNextRow2 < 0 || iNextRow1 < iNextRow2 )
+    {
+        int iVal = iNextRow1;
+        iNextRow1 = poIter1->GetNextRowSortedByFID();
+        return iVal;
+    }
+    if( iNextRow2 < iNextRow1 )
+    {
+        int iVal = iNextRow2;
+        iNextRow2 = poIter2->GetNextRowSortedByFID();
+        return iVal;
+    }
+
+    if( bIteratorAreExclusive )
+        PrintError();
+
+    int iVal = iNextRow1;
+    iNextRow1 = poIter1->GetNextRowSortedByFID();
+    iNextRow2 = poIter2->GetNextRowSortedByFID();
+    return iVal;
+}
+
+/************************************************************************/
+/*                           GetRowCount()                              */
+/************************************************************************/
+
+int FileGDBOrIterator::GetRowCount()
+{
+    if( bIteratorAreExclusive )
+        return poIter1->GetRowCount() + poIter2->GetRowCount();
+    else
+        return FileGDBIterator::GetRowCount();
+}
+
+/************************************************************************/
+/*                         FileGDBIndexIterator()                       */
+/************************************************************************/
+
+FileGDBIndexIterator::FileGDBIndexIterator(FileGDBTable* poParent, int bAscending) :
+                    poParent(poParent), bAscending(bAscending),
+                    fpCurIdx(NULL), eFieldType(FGFT_UNDEFINED),
+                    nMaxPerPages(0), nOffsetFirstValInPage(0),
+                    nValueCountInIdx(0), nIndexDepth(0), eOp(FGSO_ISNOTNULL),
+                    iCurFeatureInPage(-1), nFeaturesInPage(0),
+                    bEvaluateToFALSE(FALSE), bEOF(FALSE),
+                    iSorted(0), nSortedCount(-1), panSortedRows(NULL),
+                    nStrLen(0)
+{
+    memset(iFirstPageIdx, 0xFF, MAX_DEPTH * sizeof(int));
+    memset(iLastPageIdx, 0xFF, MAX_DEPTH * sizeof(int));
+    memset(iCurPageIdx, 0xFF, MAX_DEPTH * sizeof(int));
+    memset(nSubPagesCount, 0, MAX_DEPTH * sizeof(int));
+    memset(nLastPageAccessed, 0, MAX_DEPTH * sizeof(int));
+    memset(&sValue, 0, sizeof(sValue));
+}
+
+/************************************************************************/
+/*                         ~FileGDBIndexIterator()                      */
+/************************************************************************/
+
+FileGDBIndexIterator::~FileGDBIndexIterator()
+{
+    if( fpCurIdx )
+        VSIFCloseL(fpCurIdx);
+    fpCurIdx = NULL;
+    VSIFree(panSortedRows);
+}
+
+/************************************************************************/
+/*                             Build()                                  */
+/************************************************************************/
+
+FileGDBIterator* FileGDBIndexIterator::Build( FileGDBTable* poParent,
+                                              int nFieldIdx,
+                                              int bAscending,
+                                              FileGDBSQLOp op,
+                                              OGRFieldType eOGRFieldType,
+                                              const OGRField* psValue )
+{
+    FileGDBIndexIterator* poIndexIterator =
+                new FileGDBIndexIterator(poParent, bAscending);
+    if( poIndexIterator->SetConstraint(nFieldIdx, op, eOGRFieldType, psValue) )
+    {
+        return poIndexIterator;
+    }
+    delete poIndexIterator;
+    return NULL;
+}
+
+/************************************************************************/
+/*                           FileGDBSQLOpToStr()                        */
+/************************************************************************/
+
+static const char* FileGDBSQLOpToStr(FileGDBSQLOp op)
+{
+    switch( op )
+    {
+        case FGSO_ISNOTNULL : return "IS NOT NULL";
+        case FGSO_LT: return "<";;
+        case FGSO_LE: return "<=";
+        case FGSO_EQ: return "=";
+        case FGSO_GE: return ">=";
+        case FGSO_GT: return ">";
+    }
+    return "unknown_op";
+}
+
+/************************************************************************/
+/*                           FileGDBValueToStr()                        */
+/************************************************************************/
+
+static const char* FileGDBValueToStr(OGRFieldType eOGRFieldType,
+                                     const OGRField* psValue)
+{
+    if( psValue == NULL )
+        return "";
+
+    switch( eOGRFieldType )
+    {
+        case OFTInteger: return CPLSPrintf("%d", psValue->Integer);
+        case OFTReal: return CPLSPrintf("%.18g", psValue->Real);
+        case OFTString: return psValue->String;
+        case OFTDateTime: return CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
+                                            psValue->Date.Year,
+                                            psValue->Date.Month,
+                                            psValue->Date.Day,
+                                            psValue->Date.Hour,
+                                            psValue->Date.Minute,
+                                            psValue->Date.Second);
+        case OFTDate: return CPLSPrintf("%04d/%02d/%02d",
+                                            psValue->Date.Year,
+                                            psValue->Date.Month,
+                                            psValue->Date.Day);
+        case OFTTime: return CPLSPrintf("%02d:%02d:%02d",
+                                            psValue->Date.Hour,
+                                            psValue->Date.Minute,
+                                            psValue->Date.Second);
+        default:
+            break;
+    }
+    return "";
+}
+
+/************************************************************************/
+/*                           SetConstraint()                            */
+/************************************************************************/
+
+int FileGDBIndexIterator::SetConstraint(int nFieldIdx,
+                                        FileGDBSQLOp op,
+                                        OGRFieldType eOGRFieldType,
+                                        const OGRField* psValue)
+{
+    const int errorRetValue = FALSE;
+    CPLAssert(fpCurIdx == NULL);
+
+    returnErrorIf(nFieldIdx < 0 || nFieldIdx >= poParent->GetFieldCount() );
+    FileGDBField* poField = poParent->GetField(nFieldIdx);
+    returnErrorIf(!(poField->HasIndex()) );
+
+    eFieldType = poField->GetType();
+    eOp = op;
+
+    returnErrorIf(eFieldType != FGFT_INT16 && eFieldType != FGFT_INT32 &&
+                  eFieldType != FGFT_FLOAT32 && eFieldType != FGFT_FLOAT64 &&
+                  eFieldType != FGFT_STRING && eFieldType != FGFT_DATETIME &&
+                  eFieldType != FGFT_UUID_1 && eFieldType != FGFT_UUID_2 );
+
+    const char* pszAtxName = CPLFormFilename(CPLGetPath(poParent->GetFilename().c_str()),
+                    CPLGetBasename(poParent->GetFilename().c_str()), CPLSPrintf("%s.atx",
+                    poField->GetIndex()->GetIndexName().c_str()));
+    fpCurIdx = VSIFOpenL( pszAtxName, "rb" );
+    returnErrorIf(fpCurIdx == NULL );
+
+    VSIFSeekL(fpCurIdx, 0, SEEK_END);
+    vsi_l_offset nFileSize = VSIFTellL(fpCurIdx);
+    returnErrorIf(nFileSize < FGDB_PAGE_SIZE + 22 );
+
+    VSIFSeekL(fpCurIdx, nFileSize - 22, SEEK_SET);
+    GByte abyTrailer[22];
+    returnErrorIf(VSIFReadL( abyTrailer, 22, 1, fpCurIdx ) != 1 );
+
+    nMaxPerPages = (FGDB_PAGE_SIZE - 12) / (4 + abyTrailer[0]);
+    nOffsetFirstValInPage = 12 + nMaxPerPages * 4;
+
+    GUInt32 nMagic1 = GetUInt32(abyTrailer + 2, 0);
+    returnErrorIf(nMagic1 != 1 );
+
+    nIndexDepth = GetUInt32(abyTrailer + 6, 0);
+    /* CPLDebug("OpenFileGDB", "nIndexDepth = %u", nIndexDepth); */
+    returnErrorIf(!(nIndexDepth >= 1 && nIndexDepth <= MAX_DEPTH + 1) );
+
+    nValueCountInIdx = GetUInt32(abyTrailer + 10, 0);
+    /* CPLDebug("OpenFileGDB", "nValueCountInIdx = %u", nValueCountInIdx); */
+    /* negative like in sample_clcV15_esri_v10.gdb/a00000005.FDO_UUID.atx */
+    if( (int)nValueCountInIdx < 0 )
+        return FALSE;
+    /* QGIS_TEST_101.gdb/a00000006.FDO_UUID.atx */
+    if( nValueCountInIdx == 0 )
+    {
+        VSIFSeekL(fpCurIdx, 4, SEEK_SET);
+        GByte abyBuffer[4];
+        returnErrorIf(VSIFReadL( abyBuffer, 4, 1, fpCurIdx ) != 1 );
+        nValueCountInIdx = GetUInt32(abyBuffer, 0);
+    }
+    /* PreNIS.gdb/a00000006.FDO_UUID.atx has depth 2 and the value of */
+    /* nValueCountInIdx is 11 which is not the number of non-null values */
+    else if( nValueCountInIdx < nMaxPerPages && nIndexDepth > 1 )
+        return FALSE;
+    returnErrorIf(nValueCountInIdx > (GUInt32)poParent->GetValidRecordCount() );
+
+    switch( eFieldType )
+    {
+        case FGFT_INT16:
+            returnErrorIf(abyTrailer[0] != sizeof(GUInt16));
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTInteger);
+                sValue.Integer = psValue->Integer;
+            }
+            break;
+        case FGFT_INT32:
+            returnErrorIf(abyTrailer[0] != sizeof(GUInt32));
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTInteger);
+                sValue.Integer = psValue->Integer;
+            }
+            break;
+        case FGFT_FLOAT32:
+            returnErrorIf(abyTrailer[0] != sizeof(float));
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTReal);
+                sValue.Real = psValue->Real;
+            }
+            break;
+        case FGFT_FLOAT64:
+            returnErrorIf(abyTrailer[0] != sizeof(double));
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTReal);
+                sValue.Real = psValue->Real;
+            }
+            break;
+        case FGFT_STRING:
+        {
+            returnErrorIf((abyTrailer[0] % 2) != 0);
+            returnErrorIf(abyTrailer[0] == 0);
+            returnErrorIf(abyTrailer[0] > 2 * MAX_CAR_COUNT_STR);
+            nStrLen = abyTrailer[0] / 2;
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTString);
+                wchar_t *pWide = CPLRecodeToWChar( psValue->String,
+                                                CPL_ENC_UTF8,
+                                                CPL_ENC_UCS2 );
+                returnErrorIf(pWide == NULL);
+                int nCount = 0;
+                while( pWide[nCount] != 0 )
+                {
+                    returnErrorAndCleanupIf(nCount == nStrLen, CPLFree(pWide));
+                    asUTF16Str[nCount] = pWide[nCount];
+                    nCount ++;
+                }
+                while( nCount < nStrLen )
+                {
+                    asUTF16Str[nCount] = 32; /* space character */
+                    nCount ++;
+                }
+                CPLFree(pWide);
+            }
+            break;
+        }
+
+        case FGFT_DATETIME:
+        {
+            returnErrorIf( abyTrailer[0] != sizeof(double));
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTReal &&
+                              eOGRFieldType != OFTDateTime &&
+                              eOGRFieldType != OFTDate &&
+                              eOGRFieldType != OFTTime);
+                if( eOGRFieldType == OFTReal )
+                    sValue.Real = psValue->Real;
+                else
+                    FileGDBOGRDateToDoubleDate(psValue, &(sValue.Real));
+            }
+            break;
+        }
+
+        case FGFT_UUID_1:
+        case FGFT_UUID_2:
+        {
+            returnErrorIf(abyTrailer[0] != UUID_LEN_AS_STRING);
+            if( eOp != FGSO_ISNOTNULL )
+            {
+                returnErrorIf(eOGRFieldType != OFTString);
+                memset(szUUID, 0, UUID_LEN_AS_STRING + 1);
+                strncpy(szUUID, psValue->String, UUID_LEN_AS_STRING);
+                bEvaluateToFALSE = (eOp == FGSO_EQ &&
+                        strlen(psValue->String) != UUID_LEN_AS_STRING);
+            }
+            break;
+        }
+
+        default:
+            CPLAssert(FALSE);
+            break;
+    }
+
+    if( nValueCountInIdx > 0 )
+    {
+        if( nIndexDepth == 1 )
+        {
+            iFirstPageIdx[0] = iLastPageIdx[0] = 0;
+        }
+        else
+        {
+            returnErrorIf(!FindPages(0, 1) );
+        }
+    }
+
+    CPLDebug("OpenFileGDB", "Using index on field %s (%s %s)",
+            poField->GetName().c_str(),
+            FileGDBSQLOpToStr(eOp),
+            FileGDBValueToStr(eOGRFieldType, psValue));
+
+    Reset();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          FileGDBUTF16StrCompare()                    */
+/************************************************************************/
+
+static int FileGDBUTF16StrCompare(const GUInt16* pasFirst,
+                                  const GUInt16* pasSecond,
+                                  int nStrLen)
+{
+    for(int i=0;i<nStrLen;i++)
+    {
+        if( pasFirst[i] < pasSecond[i] )
+            return -1;
+        if( pasFirst[i] > pasSecond[i] )
+            return 1;
+    }
+    return 0;
+}
+
+/************************************************************************/
+/*                              COMPARE()                               */
+/************************************************************************/
+
+#define COMPARE(a,b) (((a)<(b)) ? -1 : ((a)==(b)) ? 0 : 1)
+
+/************************************************************************/
+/*                             FindPages()                              */
+/************************************************************************/
+
+int FileGDBIndexIterator::FindPages(int iLevel, int nPage)
+{
+    const int errorRetValue = FALSE;
+    VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
+    returnErrorIf(VSIFReadL( abyPage[iLevel], FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1 );
+
+    nSubPagesCount[iLevel] = GetUInt32(abyPage[iLevel] + 4, 0);
+    returnErrorIf(nSubPagesCount[iLevel] == 0 ||
+                  nSubPagesCount[iLevel] > nMaxPerPages);
+    if( nIndexDepth == 2 )
+        returnErrorIf(nValueCountInIdx > nMaxPerPages * (nSubPagesCount[0] + 1));
+
+    if( eOp == FGSO_ISNOTNULL )
+    {
+        iFirstPageIdx[iLevel] = 0;
+        iLastPageIdx[iLevel] = nSubPagesCount[iLevel];
+        return TRUE;
+    }
+
+    GUInt32 i;
+#ifdef DEBUG_INDEX_CONSISTENCY
+    double dfLastMax = 0.0;
+    int nLastMax = 0;
+    GUInt16 asLastMax[MAX_CAR_COUNT_STR] = { 0 };
+    char szLastMaxUUID[UUID_LEN_AS_STRING + 1] = { 0 };
+#endif
+    iFirstPageIdx[iLevel] = iLastPageIdx[iLevel] = -1;
+
+    for( i = 0; i < nSubPagesCount[iLevel]; i ++ )
+    {
+        int nComp;
+
+        switch( eFieldType )
+        {
+            case FGFT_INT16:
+            {
+                GInt16 nVal = GetInt16(abyPage[iLevel] + nOffsetFirstValInPage, i);
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 && nVal < nLastMax);
+                nLastMax = nVal;
+#endif
+                nComp = COMPARE(sValue.Integer, nVal);
+                break;
+            }
+
+            case FGFT_INT32:
+            {
+                GInt32 nVal = GetInt32(abyPage[iLevel] + nOffsetFirstValInPage, i);
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 && nVal < nLastMax);
+                nLastMax = nVal;
+#endif
+                nComp = COMPARE(sValue.Integer, nVal);
+                break;
+            }
+
+            case FGFT_FLOAT32:
+            {
+                float fVal = GetFloat32(abyPage[iLevel] + nOffsetFirstValInPage, i);
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 && fVal < dfLastMax);
+                dfLastMax = fVal;
+#endif
+                nComp = COMPARE(sValue.Real, fVal);
+                break;
+            }
+
+            case FGFT_FLOAT64:
+            case FGFT_DATETIME:
+            {
+                double dfVal = GetFloat64(abyPage[iLevel] + nOffsetFirstValInPage, i);
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 && dfVal < dfLastMax);
+                dfLastMax = dfVal;
+#endif
+                nComp = COMPARE(sValue.Real, dfVal);
+                break;
+            }
+
+            case FGFT_STRING:
+            {
+                GUInt16* pasMax;
+#ifdef CPL_MSB
+                GUInt16 asMax[MAX_CAR_COUNT_STR];
+                pasMax = asMax;
+                memcpy(asMax, abyPage[iLevel] + nOffsetFirstValInPage +
+                        nStrLen * sizeof(GUInt16) * i, nStrLen * sizeof(GUInt16));
+                for(int j=0;j<nStrLen;j++)
+                    CPL_LSBPTR16(&asMax[j]);
+#else
+                pasMax = (GUInt16*)(abyPage[iLevel] + nOffsetFirstValInPage +
+                                                nStrLen * sizeof(GUInt16) * i);
+#endif
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 &&
+                        FileGDBUTF16StrCompare(pasMax, asLastMax, nStrLen) < 0);
+                memcpy(asLastMax, pasMax, nStrLen * 2);
+#endif
+                nComp = FileGDBUTF16StrCompare(asUTF16Str, pasMax, nStrLen);
+                break;
+            }
+
+            case FGFT_UUID_1:
+            case FGFT_UUID_2:
+            {
+                const char* psNonzMaxUUID = (char*)(abyPage[iLevel] +
+                        nOffsetFirstValInPage + UUID_LEN_AS_STRING * i);
+#ifdef DEBUG_INDEX_CONSISTENCY
+                returnErrorIf(i > 0 &&
+                    memcmp(psNonzMaxUUID, szLastMaxUUID, UUID_LEN_AS_STRING) < 0);
+                memcpy(szLastMaxUUID, psNonzMaxUUID, UUID_LEN_AS_STRING);
+#endif
+                nComp = memcmp(szUUID, psNonzMaxUUID, UUID_LEN_AS_STRING);
+                break;
+            }
+
+            default:
+                CPLAssert(FALSE);
+                nComp = 0;
+                break;
+        }
+
+        int bStop = FALSE;
+        switch( eOp )
+        {
+            /* dfVal = 1 2 2 3 3 4 */
+            /* sValue.Real = 3 */
+            /* nComp = (sValue.Real < dfVal) ? -1 : (sValue.Real == dfVal) ? 0 : 1; */
+            case FGSO_LT:
+            case FGSO_LE:
+                if( iFirstPageIdx[iLevel] < 0 )
+                {
+                    iFirstPageIdx[iLevel] = iLastPageIdx[iLevel] = (int)i;
+                }
+                else
+                {
+                    iLastPageIdx[iLevel] = (int)i;
+                    if( nComp < 0 )
+                    {
+                        bStop = TRUE;
+                    }
+                }
+                break;
+
+            case FGSO_EQ:
+                if( iFirstPageIdx[iLevel] < 0 )
+                {
+                    if( nComp <= 0 )
+                        iFirstPageIdx[iLevel] = iLastPageIdx[iLevel] = (int)i;
+                }
+                else
+                {
+                    if( nComp == 0 )
+                        iLastPageIdx[iLevel] = (int)i;
+                    else
+                        bStop = TRUE;
+                }
+                break;
+
+            case FGSO_GE:
+                if( iFirstPageIdx[iLevel] < 0 )
+                {
+                    if( nComp <= 0 )
+                    {
+                        iFirstPageIdx[iLevel] = (int)i;
+                        iLastPageIdx[iLevel] = nSubPagesCount[iLevel];
+                        bStop = TRUE;
+                    }
+                }
+                break;
+
+            case FGSO_GT:
+                if( iFirstPageIdx[iLevel] < 0 )
+                {
+                    if( nComp < 0 )
+                    {
+                        iFirstPageIdx[iLevel] = (int)i;
+                        iLastPageIdx[iLevel] = nSubPagesCount[iLevel];
+                        bStop = TRUE;
+                    }
+                }
+                break;
+
+            default:
+                CPLAssert(FALSE);
+                break;
+        }
+        if( bStop )
+            break;
+    }
+
+    if( iFirstPageIdx[iLevel] < 0 )
+    {
+        iFirstPageIdx[iLevel] = iLastPageIdx[iLevel] = nSubPagesCount[iLevel];
+    }
+    else if( iLastPageIdx[iLevel] < (int)nSubPagesCount[iLevel] )
+    {
+        iLastPageIdx[iLevel] ++;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             Reset()                                  */
+/************************************************************************/
+
+void FileGDBIndexIterator::Reset()
+{
+    iCurPageIdx[0] = (bAscending) ? iFirstPageIdx[0] -1 : iLastPageIdx[0] + 1;
+    memset(iFirstPageIdx + 1, 0xFF, (MAX_DEPTH - 1) * sizeof(int));
+    memset(iLastPageIdx + 1, 0xFF, (MAX_DEPTH - 1) * sizeof(int));
+    memset(iCurPageIdx + 1, 0xFF, (MAX_DEPTH - 1) * sizeof(int));
+    memset(nLastPageAccessed, 0, MAX_DEPTH * sizeof(int));
+    iCurFeatureInPage = 0;
+    nFeaturesInPage = 0;
+    iSorted = 0;
+
+    bEOF = ( nValueCountInIdx == 0 || bEvaluateToFALSE );
+}
+
+/************************************************************************/
+/*                           ReadPageNumber()                           */
+/************************************************************************/
+
+int FileGDBIndexIterator::ReadPageNumber(int iLevel)
+{
+    const int errorRetValue = 0;
+    GUInt32 nPage = GetUInt32(abyPage[iLevel] + 8, iCurPageIdx[iLevel]);
+    if( nPage == nLastPageAccessed[iLevel] )
+    {
+        if( !LoadNextPage(iLevel) )
+            return 0;
+        nPage = GetUInt32(abyPage[iLevel] + 8, iCurPageIdx[iLevel]);
+    }
+    nLastPageAccessed[iLevel] = nPage;
+    returnErrorIf(nPage < 2);
+    return nPage;
+}
+
+/************************************************************************/
+/*                           LoadNextPage()                             */
+/************************************************************************/
+
+int FileGDBIndexIterator::LoadNextPage(int iLevel)
+{
+    const int errorRetValue = FALSE;
+    if( (bAscending && iCurPageIdx[iLevel] == iLastPageIdx[iLevel]) ||
+        (!bAscending && iCurPageIdx[iLevel] == iFirstPageIdx[iLevel]) )
+    {
+        if( iLevel == 0 || !LoadNextPage(iLevel - 1) )
+            return FALSE;
+
+        GUInt32 nPage = ReadPageNumber(iLevel-1);
+        returnErrorIf(!FindPages(iLevel, nPage) );
+
+        iCurPageIdx[iLevel] = (bAscending) ? iFirstPageIdx[iLevel] :
+                                             iLastPageIdx[iLevel];
+    }
+    else
+    {
+        if( bAscending )
+            iCurPageIdx[iLevel] ++;
+        else
+            iCurPageIdx[iLevel] --;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        LoadNextFeaturePage()                         */
+/************************************************************************/
+
+int FileGDBIndexIterator::LoadNextFeaturePage()
+{
+    const int errorRetValue = FALSE;
+    GUInt32 nPage;
+
+    if( nIndexDepth == 1 )
+    {
+        if( iCurPageIdx[0] == iLastPageIdx[0] )
+        {
+            return FALSE;
+        }
+        if( bAscending )
+            iCurPageIdx[0] ++;
+        else
+            iCurPageIdx[0] --;
+        nPage = 1;
+    }
+    else
+    {
+        if( !LoadNextPage( nIndexDepth - 2 ) )
+        {
+            return FALSE;
+        }
+        nPage = ReadPageNumber(nIndexDepth - 2);
+        returnErrorIf(nPage < 2);
+    }
+
+    VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
+    returnErrorIf(VSIFReadL( abyPageFeature, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1);
+
+    GUInt32 nFeatures = GetUInt32(abyPageFeature + 4, 0);
+    returnErrorIf(nFeatures > nMaxPerPages);
+
+    nFeaturesInPage = (int)nFeatures;
+    iCurFeatureInPage = (bAscending) ? 0 : nFeaturesInPage - 1;
+    if( nFeatures == 0 )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              GetNextRow()                            */
+/************************************************************************/
+
+int FileGDBIndexIterator::GetNextRow()
+{
+    const int errorRetValue = -1;
+    if( bEOF )
+        return -1;
+
+    while( TRUE )
+    {
+        if( iCurFeatureInPage >= nFeaturesInPage || iCurFeatureInPage < 0 )
+        {
+            if( !LoadNextFeaturePage() )
+            {
+                bEOF = TRUE;
+                return -1;
+            }
+        }
+
+        int bMatch;
+        if( eOp == FGSO_ISNOTNULL )
+        {
+            bMatch = TRUE;
+        }
+        else
+        {
+            int nComp;
+            bMatch = FALSE;
+            switch( eFieldType )
+            {
+                case FGFT_INT16:
+                {
+                    GInt16 nVal = GetInt16(abyPageFeature + nOffsetFirstValInPage,
+                                           iCurFeatureInPage);
+                    nComp = COMPARE(sValue.Integer, nVal);
+                    break;
+                }
+
+                case FGFT_INT32:
+                {
+                    GInt32 nVal = GetInt32(abyPageFeature + nOffsetFirstValInPage,
+                                           iCurFeatureInPage);
+                    nComp = COMPARE(sValue.Integer, nVal);
+                    break;
+                }
+
+                case FGFT_FLOAT32:
+                {
+                    float fVal = GetFloat32(abyPageFeature + nOffsetFirstValInPage,
+                                           iCurFeatureInPage);
+                    nComp = COMPARE(sValue.Real, fVal);
+                    break;
+                }
+
+                case FGFT_FLOAT64:
+                case FGFT_DATETIME:
+                {
+                    double dfVal = GetFloat64(abyPageFeature + nOffsetFirstValInPage,
+                                           iCurFeatureInPage);
+                    nComp = COMPARE(sValue.Real, dfVal);
+                    break;
+                }
+
+                case FGFT_STRING:
+                {
+#ifdef CPL_MSB
+                    GUInt16 asVal[MAX_CAR_COUNT_STR];
+                    memcpy(asVal, abyPageFeature + nOffsetFirstValInPage +
+                                    nStrLen * 2 * iCurFeatureInPage, nStrLen * 2);
+                    for(int j=0;j<nStrLen;j++)
+                        CPL_LSBPTR16(&asVal[j]);
+                    nComp = FileGDBUTF16StrCompare(asUTF16Str, asVal, nStrLen);
+#else
+                    nComp = FileGDBUTF16StrCompare(asUTF16Str,
+                                (GUInt16*)(abyPageFeature + nOffsetFirstValInPage +
+                                    nStrLen * 2 * iCurFeatureInPage), nStrLen);
+#endif
+                    break;
+                }
+
+                case FGFT_UUID_1:
+                case FGFT_UUID_2:
+                {
+                    nComp = memcmp(szUUID,
+                                abyPageFeature + nOffsetFirstValInPage +
+                                UUID_LEN_AS_STRING *iCurFeatureInPage,
+                                UUID_LEN_AS_STRING);
+                    break;
+                }
+
+                default:
+                    CPLAssert(FALSE);
+                    nComp = 0;
+                    break;
+            }
+
+            switch( eOp )
+            {
+                case FGSO_LT:
+                    if( nComp <= 0 && bAscending )
+                    {
+                        bEOF = TRUE;
+                        return -1;
+                    }
+                    bMatch = TRUE;
+                    break;
+
+                case FGSO_LE:
+                    if( nComp < 0 && bAscending )
+                    {
+                        bEOF = TRUE;
+                        return -1;
+                    }
+                    bMatch = TRUE;
+                    break;
+
+                case FGSO_EQ:
+                    if( nComp < 0 && bAscending )
+                    {
+                        bEOF = TRUE;
+                        return -1;
+                    }
+                    bMatch = ( nComp == 0 );
+                    break;
+
+                case FGSO_GE:
+                    bMatch = ( nComp <= 0 );
+                    break;
+
+                case FGSO_GT:
+                    bMatch = ( nComp < 0 );
+                    break;
+
+                default:
+                    CPLAssert(FALSE);
+                    break;
+            }
+        }
+
+        if( bMatch )
+        {
+            GUInt32 nFID = GetUInt32(abyPageFeature + 12, iCurFeatureInPage);
+            if( bAscending )
+                iCurFeatureInPage ++;
+            else
+                iCurFeatureInPage --;
+            returnErrorAndCleanupIf(nFID < 1 ||
+                nFID > (GUInt32)poParent->GetTotalRecordCount(), bEOF = TRUE);
+            return (int) (nFID - 1);
+        }
+        else
+        {
+            if( bAscending )
+                iCurFeatureInPage ++;
+            else
+                iCurFeatureInPage --;
+        }
+    }
+}
+
+/************************************************************************/
+/*                             SortRows()                               */
+/************************************************************************/
+
+int FileGDBIndexIterator::SortRows()
+{
+    nSortedCount = 0;
+    iSorted = 0;
+    int nSortedAlloc = 0;
+    Reset();
+    while( TRUE )
+    {
+        int nRow = GetNextRow();
+        if( nRow < 0 )
+            break;
+        if( nSortedCount == nSortedAlloc )
+        {
+            int nNewSortedAlloc = 4 * nSortedAlloc / 3 + 16;
+            int* panNewSortedRows = (int*)VSIRealloc(panSortedRows,
+                                            sizeof(int) * nNewSortedAlloc);
+            if( panNewSortedRows == NULL )
+            {
+                nSortedCount = 0;
+                return FALSE;
+            }
+            nSortedAlloc = nNewSortedAlloc;
+            panSortedRows = panNewSortedRows;
+        }
+        panSortedRows[nSortedCount ++] = nRow;
+    }
+    if( nSortedCount == 0 )
+        return FALSE;
+    std::sort(panSortedRows, panSortedRows + nSortedCount);
+    if( eOp == FGSO_ISNOTNULL && (int)nValueCountInIdx != nSortedCount )
+        PrintError();
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        GetNextRowSortedByFID()                       */
+/************************************************************************/
+
+int FileGDBIndexIterator::GetNextRowSortedByFID()
+{
+    if( eOp == FGSO_EQ )
+        return GetNextRow();
+
+    if( iSorted < nSortedCount )
+        return panSortedRows[iSorted ++];
+
+    if( nSortedCount < 0 )
+    {
+        if( !SortRows() )
+            return -1;
+        return panSortedRows[iSorted ++];
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+/************************************************************************/
+/*                           GetRowCount()                              */
+/************************************************************************/
+
+int FileGDBIndexIterator::GetRowCount()
+{
+    if( eOp == FGSO_ISNOTNULL )
+        return (int)nValueCountInIdx;
+
+    if( nSortedCount >= 0 )
+        return nSortedCount;
+
+    int nRowCount = 0;
+    int bSaveAscending = bAscending;
+    bAscending = TRUE; /* for a tiny bit of more efficiency */
+    Reset();
+    while( GetNextRow() >= 0 )
+        nRowCount ++;
+    bAscending = bSaveAscending;
+    Reset();
+    return nRowCount;
+}
+
+/************************************************************************/
+/*                            GetMinMaxValue()                          */
+/************************************************************************/
+
+const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
+                                                     int& eOutType,
+                                                     int bIsMin)
+{
+    const OGRField* errorRetValue = NULL;
+    eOutType = -1;
+    if( nValueCountInIdx == 0 )
+        return NULL;
+
+    GByte abyPage[FGDB_PAGE_SIZE];
+    GUInt32 nPage = 1;
+    for( GUInt32 iLevel = 0; iLevel < nIndexDepth - 1; iLevel ++ )
+    {
+        VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
+        returnErrorIf(VSIFReadL( abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1 );
+        GUInt32 nSubPagesCount = GetUInt32(abyPage + 4, 0);
+        returnErrorIf(nSubPagesCount == 0 || nSubPagesCount > nMaxPerPages);
+
+        if( bIsMin )
+            nPage = GetUInt32(abyPage + 8, 0);
+        else
+            nPage = GetUInt32(abyPage + 8, nSubPagesCount);
+        returnErrorIf(nPage < 2 );
+    }
+
+    VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
+    returnErrorIf(VSIFReadL( abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1);
+
+    GUInt32 nFeatures = GetUInt32(abyPage + 4, 0);
+    returnErrorIf(nFeatures < 1 || nFeatures > nMaxPerPages);
+
+    int iFeature = (bIsMin) ? 0 : nFeatures-1;
+
+    switch( eFieldType )
+    {
+        case FGFT_INT16:
+        {
+            GInt16 nVal = GetInt16(abyPage + nOffsetFirstValInPage, iFeature);
+            psField->Integer = nVal;
+            eOutType = OFTInteger;
+            return psField;
+        }
+
+        case FGFT_INT32:
+        {
+            GInt32 nVal = GetInt32(abyPage + nOffsetFirstValInPage, iFeature);
+            psField->Integer = nVal;
+            eOutType = OFTInteger;
+            return psField;
+        }
+
+        case FGFT_FLOAT32:
+        {
+            float fVal = GetFloat32(abyPage + nOffsetFirstValInPage, iFeature);
+            psField->Real = fVal;
+            eOutType = OFTReal;
+            return psField;
+        }
+
+        case FGFT_FLOAT64:
+        {
+            double dfVal = GetFloat64(abyPage + nOffsetFirstValInPage, iFeature);
+            psField->Real = dfVal;
+            eOutType = OFTReal;
+            return psField;
+        }
+
+        case FGFT_DATETIME:
+        {
+            double dfVal = GetFloat64(abyPage + nOffsetFirstValInPage, iFeature);
+            FileGDBDoubleDateToOGRDate(dfVal, psField);
+            eOutType = OFTDateTime;
+            return psField;
+        }
+
+        case FGFT_STRING:
+        {
+            wchar_t awsVal[MAX_CAR_COUNT_STR+1];
+            for(int j=0;j<nStrLen;j++)
+            {
+                GUInt16 nCh = GetUInt16(abyPage + nOffsetFirstValInPage +
+                    nStrLen * sizeof(GUInt16) * iFeature, j);
+                awsVal[j] = nCh;
+            }
+            awsVal[nStrLen] = 0;
+            char* pszOut = CPLRecodeFromWChar(awsVal, CPL_ENC_UCS2, CPL_ENC_UTF8);
+            returnErrorIf(pszOut == NULL );
+            returnErrorAndCleanupIf(strlen(pszOut) >
+                                        MAX_UTF8_LEN_STR, VSIFree(pszOut) );
+            strcpy(psField->String, pszOut);
+            CPLFree(pszOut);
+            eOutType = OFTString;
+            return psField;
+        }
+
+        case FGFT_UUID_1:
+        case FGFT_UUID_2:
+        {
+            memcpy(psField->String, abyPage + nOffsetFirstValInPage +
+                   UUID_LEN_AS_STRING *iFeature, UUID_LEN_AS_STRING);
+            psField->String[UUID_LEN_AS_STRING] = 0;
+            eOutType = OFTString;
+            return psField;
+        }
+
+        default:
+            CPLAssert(FALSE);
+            break;
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                            GetMinValue()                             */
+/************************************************************************/
+
+const OGRField* FileGDBIndexIterator::GetMinValue(int& eOutType)
+{
+    if( eOp != FGSO_ISNOTNULL )
+        return FileGDBIterator::GetMinValue(eOutType);
+    if( eFieldType == FGFT_STRING || eFieldType == FGFT_UUID_1 ||
+        eFieldType == FGFT_UUID_2 )
+        sMin.String = szMin;
+    return GetMinMaxValue(&sMin, eOutType, TRUE);
+}
+
+/************************************************************************/
+/*                            GetMaxValue()                             */
+/************************************************************************/
+
+const OGRField* FileGDBIndexIterator::GetMaxValue(int& eOutType)
+{
+    if( eOp != FGSO_ISNOTNULL )
+        return FileGDBIterator::GetMinValue(eOutType);
+    if( eFieldType == FGFT_STRING || eFieldType == FGFT_UUID_1 ||
+        eFieldType == FGFT_UUID_2 )
+        sMax.String = szMax;
+    return GetMinMaxValue(&sMax, eOutType, FALSE);
+}
+
+/************************************************************************/
+/*                        GetMinMaxSumCount()                           */
+/************************************************************************/
+
+struct Int16Getter
+{
+    public:
+        static double GetAsDouble(const GByte* pBaseAddr, int iOffset)
+        {
+            return GetInt16(pBaseAddr, iOffset);
+        }
+};
+
+struct Int32Getter
+{
+    public:
+        static double GetAsDouble(const GByte* pBaseAddr, int iOffset)
+        {
+            return GetInt32(pBaseAddr, iOffset);
+        }
+};
+
+struct Float32Getter
+{
+    public:
+        static double GetAsDouble(const GByte* pBaseAddr, int iOffset)
+        {
+            return GetFloat32(pBaseAddr, iOffset);
+        }
+};
+
+struct Float64Getter
+{
+    public:
+        static double GetAsDouble(const GByte* pBaseAddr, int iOffset)
+        {
+            return GetFloat64(pBaseAddr, iOffset);
+        }
+};
+
+template <class Getter> void FileGDBIndexIterator::GetMinMaxSumCount(
+        double& dfMin, double& dfMax, double& dfSum, int& nCount)
+{
+    int nLocalCount = 0;
+    double dfLocalSum = 0.0;
+    double dfVal = 0.0;
+
+    while( TRUE )
+    {
+        if( iCurFeatureInPage >= nFeaturesInPage )
+        {
+            if( !LoadNextFeaturePage() )
+            {
+                break;
+            }
+        }
+
+        dfVal = Getter::GetAsDouble(abyPageFeature + nOffsetFirstValInPage,
+                                   iCurFeatureInPage);
+
+        dfLocalSum += dfVal;
+        if( nLocalCount == 0 )
+            dfMin = dfVal;
+        nLocalCount ++;
+        iCurFeatureInPage ++;
+    }
+
+    dfSum = dfLocalSum;
+    nCount = nLocalCount;
+    dfMax = dfVal;
+}
+
+int FileGDBIndexIterator::GetMinMaxSumCount(double& dfMin, double& dfMax,
+                                            double& dfSum, int& nCount)
+{
+    const int errorRetValue = FALSE;
+    dfMin = 0.0;
+    dfMax = 0.0;
+    dfSum = 0.0;
+    nCount = 0;
+    returnErrorIf(eOp != FGSO_ISNOTNULL );
+    returnErrorIf(eFieldType != FGFT_INT16 && eFieldType != FGFT_INT32 &&
+                  eFieldType != FGFT_FLOAT32 && eFieldType != FGFT_FLOAT64 &&
+                  eFieldType != FGFT_DATETIME );
+
+    int bSaveAscending = bAscending;
+    bAscending = TRUE;
+    Reset();
+
+    switch( eFieldType )
+    {
+        case FGFT_INT16:
+        {
+            GetMinMaxSumCount<Int16Getter>(dfMin, dfMax, dfSum, nCount);
+            break;
+        }
+        case FGFT_INT32:
+        {
+            GetMinMaxSumCount<Int32Getter>(dfMin, dfMax, dfSum, nCount);
+            break;
+        }
+        case FGFT_FLOAT32:
+        {
+            GetMinMaxSumCount<Float32Getter>(dfMin, dfMax, dfSum, nCount);
+            break;
+        }
+        case FGFT_FLOAT64:
+        case FGFT_DATETIME:
+        {
+            GetMinMaxSumCount<Float64Getter>(dfMin, dfMax, dfSum, nCount);
+            break;
+        }
+        default:
+            CPLAssert(FALSE);
+            break;
+    }
+
+    bAscending = bSaveAscending;
+    Reset();
+
+    return TRUE;
+}
+
+}; /* namespace OpenFileGDB */
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
new file mode 100644
index 0000000..ae2d74a
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
@@ -0,0 +1,2556 @@
+/******************************************************************************
+ * $Id: filegdbtable.cpp 27152 2014-04-10 20:47:42Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements reading of FileGDB tables
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "filegdbtable_priv.h"
+#include "cpl_string.h"
+#include "cpl_time.h"
+#include "ogrpgeogeometry.h" /* SHPT_ constants and OGRCreateFromMultiPatchPart() */
+
+CPL_CVSID("$Id");
+
+#define TEST_BIT(ar, bit)                       (ar[(bit) / 8] & (1 << ((bit) % 8)))
+#define BIT_ARRAY_SIZE_IN_BYTES(bitsize)        (((bitsize)+7)/8)
+
+#define UUID_SIZE_IN_BYTES              16
+
+#define IS_VALID_LAYER_GEOM_TYPE(byVal)         ((byVal) <= FGTGT_POLYGON || (byVal) == FGTGT_MULTIPATCH)
+
+/* Reserve one extra byte in case the last field is a string */
+/*       or 2 for 2 ReadVarIntAndAddNoCheck() in a row */
+/*       or 4 for SkipVarUInt() with nIter = 4 */
+/*       or for 4 ReadVarUInt64NoCheck */
+#define ZEROES_AFTER_END_OF_BUFFER      4
+
+namespace OpenFileGDB
+{
+
+/************************************************************************/
+/*                      FileGDBTablePrintError()                        */
+/************************************************************************/
+
+void FileGDBTablePrintError(const char* pszFile, int nLineNumber)
+{
+    CPLError(CE_Failure, CPLE_AppDefined, "Error occured in %s at line %d",
+             pszFile, nLineNumber);
+}
+
+/************************************************************************/
+/*                            FileGDBTable()                            */
+/************************************************************************/
+
+FileGDBTable::FileGDBTable()
+{
+    Init();
+}
+
+/************************************************************************/
+/*                           ~FileGDBTable()                            */
+/************************************************************************/
+
+FileGDBTable::~FileGDBTable()
+{
+    Close();
+}
+
+/************************************************************************/
+/*                                Init()                                */
+/************************************************************************/
+
+void FileGDBTable::Init()
+{
+    osFilename = "";
+    fpTable = NULL;
+    fpTableX = NULL;
+    memset(&sCurField, 0, sizeof(sCurField));
+    bError = FALSE;
+    nCurRow = -1;
+    nLastCol = -1;
+    pabyIterVals = NULL;
+    iAccNullable = 0;
+    nRowBlobLength = 0;
+    /* eCurFieldType = OFTInteger; */
+    eTableGeomType = FGTGT_NONE;
+    nValidRecordCount = 0;
+    nTotalRecordCount = 0;
+    iGeomField = -1;
+    nCountNullableFields = 0;
+    nNullableFieldsSizeInBytes = 0;
+    nBufferMaxSize = 0;
+    pabyBuffer = NULL;
+    nFilterXMin = 0;
+    nFilterXMax = 0;
+    nFilterYMin = 0;
+    nFilterYMax = 0;
+    osObjectIdColName = "";
+    nChSaved = -1;
+    pabyTablXBlockMap = NULL;
+    bHasReadGDBIndexes = FALSE;
+    nOffsetFieldDesc = 0;
+    nFieldDescLength = 0;
+    anFeatureOffsets.resize(0);
+    nOffsetHeaderEnd = 0;
+}
+
+/************************************************************************/
+/*                                Close()                               */
+/************************************************************************/
+
+void FileGDBTable::Close()
+{
+    if( fpTable )
+        VSIFCloseL(fpTable);
+    fpTable = NULL;
+
+    if( fpTableX )
+        VSIFCloseL(fpTableX);
+    fpTableX = NULL;
+
+    CPLFree(pabyBuffer);
+    pabyBuffer = NULL;
+
+    for(size_t i=0;i<apoFields.size();i++)
+        delete apoFields[i];
+    apoFields.resize(0);
+
+    CPLFree(pabyTablXBlockMap);
+    pabyTablXBlockMap = NULL;
+
+    for(size_t i=0;i<apoIndexes.size();i++)
+        delete apoIndexes[i];
+    apoIndexes.resize(0);
+
+    Init();
+}
+
+/************************************************************************/
+/*                              GetFieldIdx()                           */
+/************************************************************************/
+
+int FileGDBTable::GetFieldIdx(const std::string& osName) const
+{
+    for(size_t i=0;i<apoFields.size();i++)
+    {
+        if( apoFields[i]->GetName() == osName )
+            return (int)i;
+    }
+    return -1;
+}
+
+/************************************************************************/
+/*                          ReadVarUInt()                               */
+/************************************************************************/
+
+template < class OutType, class ControleType >
+static int ReadVarUInt(GByte*& pabyIter, GByte* pabyEnd, OutType& nOutVal)
+{
+    const int errorRetValue = FALSE;
+    if( !(ControleType::check_bounds) )
+    {
+        /* nothing */
+    }
+    else if( ControleType::verbose_error )
+    {
+        returnErrorIf(pabyIter >= pabyEnd);
+    }
+    else
+    {
+        if( pabyIter >= pabyEnd )
+            return FALSE;
+    }
+    OutType b = *pabyIter;
+    if( (b & 0x80) == 0 )
+    {
+        pabyIter ++;
+        nOutVal = b;
+        return TRUE;
+    }
+    GByte* pabyLocalIter = pabyIter + 1;
+    int nShift = 7;
+    OutType nVal = ( b & 0x7F );
+    while(TRUE)
+    {
+        if( !(ControleType::check_bounds) )
+        {
+            /* nothing */
+        }
+        else if( ControleType::verbose_error )
+        {
+            returnErrorIf(pabyLocalIter >= pabyEnd);
+        }
+        else
+        {
+            if( pabyLocalIter >= pabyEnd )
+                return FALSE;
+        }
+        b = *pabyLocalIter;
+        pabyLocalIter ++;
+        nVal |= ( b & 0x7F ) << nShift;
+        if( (b & 0x80) == 0 )
+        {
+            pabyIter = pabyLocalIter;
+            nOutVal = nVal;
+            return TRUE;
+        }
+        nShift += 7;
+    }
+}
+
+struct ControleTypeVerboseErrorTrue
+{
+    static const bool check_bounds = true;
+    static const bool verbose_error = true;
+};
+
+struct ControleTypeVerboseErrorFalse
+{
+    static const bool check_bounds = true;
+    static const bool verbose_error = false;
+};
+
+struct ControleTypeNone
+{
+    static const bool check_bounds = false;
+    static const bool verbose_error = false;
+};
+
+static int ReadVarUInt32(GByte*& pabyIter, GByte* pabyEnd, GUInt32& nOutVal)
+{
+    return ReadVarUInt<GUInt32, ControleTypeVerboseErrorTrue>(pabyIter, pabyEnd, nOutVal);
+}
+
+static void ReadVarUInt32NoCheck(GByte*& pabyIter, GUInt32& nOutVal)
+{
+    GByte* pabyEnd = NULL;
+    ReadVarUInt<GUInt32, ControleTypeNone>(pabyIter, pabyEnd, nOutVal);
+}
+
+static int ReadVarUInt32Silent(GByte*& pabyIter, GByte* pabyEnd, GUInt32& nOutVal)
+{
+    return ReadVarUInt<GUInt32, ControleTypeVerboseErrorFalse>(pabyIter, pabyEnd, nOutVal);
+}
+
+static void ReadVarUInt64NoCheck(GByte*& pabyIter, GUIntBig& nOutVal)
+{
+    GByte* pabyEnd = NULL;
+    ReadVarUInt<GUIntBig, ControleTypeNone>(pabyIter, pabyEnd, nOutVal);
+}
+
+/************************************************************************/
+/*                      IsLikelyFeatureAtOffset()                       */
+/************************************************************************/
+
+int FileGDBTable::IsLikelyFeatureAtOffset(GUInt32 nFileSize,
+                                          GUInt32 nOffset,
+                                          GUInt32* pnSize,
+                                          int* pbDeletedRecord)
+{
+    VSIFSeekL(fpTable, nOffset, SEEK_SET);
+    GByte abyBuffer[4];
+    if( VSIFReadL(abyBuffer, 4, 1, fpTable) != 1 )
+        return FALSE;
+
+    nRowBlobLength = GetUInt32(abyBuffer, 0);
+    if( nRowBlobLength < (GUInt32)nNullableFieldsSizeInBytes ||
+        nRowBlobLength > nFileSize - nOffset ||
+        nRowBlobLength > INT_MAX - ZEROES_AFTER_END_OF_BUFFER ||
+        nRowBlobLength > 10 * (nFileSize / nValidRecordCount) )
+    {
+        /* Is it a deleted record ? */
+        if( (int)nRowBlobLength < 0 && nRowBlobLength != 0x80000000U )
+        {
+            nRowBlobLength = (GUInt32) (-(int)nRowBlobLength);
+            if( nRowBlobLength < (GUInt32)nNullableFieldsSizeInBytes ||
+                nRowBlobLength > nFileSize - nOffset ||
+                nRowBlobLength > INT_MAX - ZEROES_AFTER_END_OF_BUFFER ||
+                nRowBlobLength > 10 * (nFileSize / nValidRecordCount) )
+                return FALSE;
+            else
+                *pbDeletedRecord = TRUE;
+        }
+        else
+            return FALSE;
+    }
+    else
+        *pbDeletedRecord = FALSE;
+
+    if( nRowBlobLength > nBufferMaxSize )
+    {
+        GByte* pabyNewBuffer = (GByte*) VSIRealloc( pabyBuffer,
+                                nRowBlobLength + ZEROES_AFTER_END_OF_BUFFER );
+        if( pabyNewBuffer == NULL )
+            return FALSE;
+
+        pabyBuffer = pabyNewBuffer;
+        nBufferMaxSize = nRowBlobLength;
+    }
+    if( pabyBuffer == NULL ) return FALSE; /* to please Coverity. Not needed */
+    if( nCountNullableFields > 0 )
+    {
+        if( VSIFReadL(pabyBuffer, nNullableFieldsSizeInBytes, 1, fpTable) != 1 )
+            return FALSE;
+    }
+    size_t i;
+    iAccNullable = 0;
+    int bExactSizeKnown = TRUE;
+    GUInt32 nRequiredLength = nNullableFieldsSizeInBytes;
+    for(i=0;i<apoFields.size();i++)
+    {
+        if( apoFields[i]->bNullable )
+        {
+            int bIsNull = TEST_BIT(pabyBuffer, iAccNullable);
+            iAccNullable ++;
+            if( bIsNull )
+                continue;
+        }
+
+        switch( apoFields[i]->eType )
+        {
+            case FGFT_STRING:
+            case FGFT_XML:
+            case FGFT_GEOMETRY:
+            case FGFT_BINARY:
+            {
+                nRequiredLength += 1; /* varuint32 so at least one byte */
+                bExactSizeKnown = FALSE;
+                break;
+            }
+
+            /* Only 4 bytes ? */
+            case FGFT_RASTER: nRequiredLength += sizeof(GInt32); break;
+
+            case FGFT_INT16: nRequiredLength += sizeof(GInt16); break;
+            case FGFT_INT32: nRequiredLength += sizeof(GInt32); break;
+            case FGFT_FLOAT32: nRequiredLength += sizeof(float); break;
+            case FGFT_FLOAT64: nRequiredLength += sizeof(double); break;
+            case FGFT_DATETIME: nRequiredLength += sizeof(double); break;
+            case FGFT_UUID_1:
+            case FGFT_UUID_2: nRequiredLength += UUID_SIZE_IN_BYTES; break;
+
+            default:
+                CPLAssert(FALSE);
+                break;
+        }
+    }
+    if( !bExactSizeKnown )
+    {
+        if( nRowBlobLength < nRequiredLength )
+            return FALSE;
+        if( VSIFReadL(pabyBuffer + nNullableFieldsSizeInBytes,
+                nRowBlobLength - nNullableFieldsSizeInBytes, 1, fpTable) != 1 )
+            return FALSE;
+
+        iAccNullable = 0;
+        nRequiredLength = nNullableFieldsSizeInBytes;
+        for(i=0;i<apoFields.size();i++)
+        {
+            if( apoFields[i]->bNullable )
+            {
+                int bIsNull = TEST_BIT(pabyBuffer, iAccNullable);
+                iAccNullable ++;
+                if( bIsNull )
+                    continue;
+            }
+
+            switch( apoFields[i]->eType )
+            {
+                case FGFT_STRING:
+                case FGFT_XML:
+                {
+                    GByte* pabyIter = pabyBuffer + nRequiredLength;
+                    GUInt32 nLength;
+                    if( !ReadVarUInt32Silent(pabyIter, pabyBuffer + nRowBlobLength, nLength) ||
+                        pabyIter - (pabyBuffer + nRequiredLength) > 5 )
+                        return FALSE;
+                    nRequiredLength = pabyIter - pabyBuffer;
+                    if( nLength > nRowBlobLength - nRequiredLength )
+                        return FALSE;
+                    for( GUInt32 j=0;j<nLength;j++ )
+                    {
+                        if( pabyIter[j] == 0 )
+                            return FALSE;
+                    }
+                    if( !CPLIsUTF8((const char*)pabyIter, nLength) )
+                        return FALSE;
+                    nRequiredLength += nLength;
+                    break;
+                }
+
+                case FGFT_GEOMETRY:
+                case FGFT_BINARY:
+                {
+                    GByte* pabyIter = pabyBuffer + nRequiredLength;
+                    GUInt32 nLength;
+                    if( !ReadVarUInt32Silent(pabyIter, pabyBuffer + nRowBlobLength, nLength) ||
+                        pabyIter - (pabyBuffer + nRequiredLength) > 5 )
+                        return FALSE;
+                    nRequiredLength = pabyIter - pabyBuffer;
+                    if( nLength > nRowBlobLength - nRequiredLength )
+                        return FALSE;
+                    nRequiredLength += nLength;
+                    break;
+                }
+
+                /* Only 4 bytes ? */
+                case FGFT_RASTER: nRequiredLength += sizeof(GInt32); break;
+
+                case FGFT_INT16: nRequiredLength += sizeof(GInt16); break;
+                case FGFT_INT32: nRequiredLength += sizeof(GInt32); break;
+                case FGFT_FLOAT32: nRequiredLength += sizeof(float); break;
+                case FGFT_FLOAT64: nRequiredLength += sizeof(double); break;
+                case FGFT_DATETIME: nRequiredLength += sizeof(double); break;
+                case FGFT_UUID_1:
+                case FGFT_UUID_2: nRequiredLength += UUID_SIZE_IN_BYTES; break;
+
+                default:
+                    CPLAssert(FALSE);
+                    break;
+            }
+            if( nRequiredLength > nRowBlobLength )
+                return FALSE;
+        }
+    }
+
+    *pnSize = 4 + nRequiredLength;
+    return nRequiredLength == nRowBlobLength;
+}
+
+/************************************************************************/
+/*                      GuessFeatureLocations()                         */
+/************************************************************************/
+
+int FileGDBTable::GuessFeatureLocations()
+{
+    GUInt32 nFileSize;
+    VSIFSeekL(fpTable, 0, SEEK_END);
+    nFileSize = (GUInt32) MIN(~((GUInt32)0), VSIFTellL(fpTable));
+
+    GUInt32 nOffset = 40 + nFieldDescLength;
+    
+    if( nOffsetFieldDesc != 40 )
+    {
+        /* Check if there is a deleted field description at offset 40 */
+        GByte abyBuffer[14];
+        VSIFSeekL(fpTable, 40, SEEK_SET);
+        if( VSIFReadL(abyBuffer, 14, 1, fpTable) != 1 )
+            return FALSE;
+        int nSize = GetInt32(abyBuffer, 0);
+        int nVersion = GetInt32(abyBuffer + 4, 0);
+        if( nSize < 0 && -nSize < 1024 * 1024 &&
+            (nVersion == 3 || nVersion == 4) &&
+            IS_VALID_LAYER_GEOM_TYPE(abyBuffer[8]) &&
+            abyBuffer[9] == 3 && abyBuffer[10] == 0 && abyBuffer[11] == 0 )
+        {
+            nOffset = 40 + (-nSize);
+        }
+        else
+        {
+            nOffset = 40;
+        }
+    }
+
+    int nInvalidRecords = 0;
+    while(nOffset < nFileSize)
+    {
+        GUInt32 nSize;
+        int bDeletedRecord;
+        if( !IsLikelyFeatureAtOffset(nFileSize, nOffset, &nSize, &bDeletedRecord) )
+        {
+            nOffset ++;
+        }
+        else
+        {
+            /*CPLDebug("OpenFileGDB", "Feature found at offset %d (size = %d)",
+                     nOffset, nSize);*/
+            if( bDeletedRecord )
+            {
+                nInvalidRecords ++;
+                anFeatureOffsets.push_back(0);
+            }
+            else
+                anFeatureOffsets.push_back(nOffset);
+            nOffset += nSize;
+        }
+    }
+    nTotalRecordCount = (int) anFeatureOffsets.size();
+    if( nTotalRecordCount - nInvalidRecords > nValidRecordCount )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "More features found (%d) than declared number of valid features (%d). "
+                 "So deleted features will likely be reported.",
+                 nTotalRecordCount - nInvalidRecords, nValidRecordCount);
+        nValidRecordCount = nTotalRecordCount - nInvalidRecords;
+    }
+
+    return nTotalRecordCount > 0;
+}
+
+/************************************************************************/
+/*                            ReadTableXHeader()                        */
+/************************************************************************/
+
+int FileGDBTable::ReadTableXHeader()
+{
+    const int errorRetValue = FALSE;
+    GByte abyHeader[16];
+
+    // Read .gdbtablx file header
+    returnErrorIf(VSIFReadL( abyHeader, 16, 1, fpTableX ) != 1 );
+    GUInt32 n1024Blocks = GetUInt32(abyHeader + 4, 0);
+
+    nTotalRecordCount = GetInt32(abyHeader + 8, 0);
+    if( n1024Blocks == 0 )
+        returnErrorIf(nTotalRecordCount != 0 );
+    else
+        returnErrorIf(nTotalRecordCount < 0 );
+
+    if( n1024Blocks != 0 )
+    {
+        GByte abyTrailer[16];
+
+        VSIFSeekL( fpTableX, 5 * 1024 * (vsi_l_offset)n1024Blocks + 16, SEEK_SET );
+        returnErrorIf(VSIFReadL( abyTrailer, 16, 1, fpTableX ) != 1 );
+
+        GUInt32 nMagic = GetUInt32(abyTrailer, 0);
+
+        GUInt32 nBitsForBlockMap = GetUInt32(abyTrailer + 4, 0);
+        returnErrorIf(nBitsForBlockMap > INT_MAX / 1024);
+
+        GUInt32 n1024BlocksBis = GetUInt32(abyTrailer + 8, 0);
+        returnErrorIf(n1024BlocksBis != n1024Blocks );
+
+        /* GUInt32 nMagic2 = GetUInt32(abyTrailer + 12, 0); */
+
+        returnErrorIf(nMagic != 0 && nMagic != 32 );
+        if( nMagic == 0 )
+        {
+            returnErrorIf(nBitsForBlockMap != n1024Blocks );
+            /* returnErrorIf(nMagic2 != 0 ); */
+        }
+        else
+        {
+            returnErrorIf((GUInt32)nTotalRecordCount > nBitsForBlockMap * 1024 );
+#ifdef DEBUG_VERBOSE
+            CPLDebug("OpenFileGDB", "%s .gdbtablx has block map array",
+                     osFilename.c_str());
+#endif
+
+            // Allocate a bit mask array for blocks of 1024 features.
+            int nSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(nBitsForBlockMap);
+            pabyTablXBlockMap = (GByte*) VSIMalloc( nSizeInBytes );
+            returnErrorIf(pabyTablXBlockMap == NULL );
+            returnErrorIf(VSIFReadL( pabyTablXBlockMap, nSizeInBytes, 1, fpTableX ) != 1 );
+            /* returnErrorIf(nMagic2 == 0 ); */
+
+            // Check that the map is consistant with n1024Blocks
+            GUInt32 nCountBlocks = 0;
+            for(GUInt32 i=0;i<nBitsForBlockMap;i++)
+                nCountBlocks += TEST_BIT(pabyTablXBlockMap, i) != 0;
+            returnErrorIf(nCountBlocks != n1024Blocks );
+        }
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                 Open()                               */
+/************************************************************************/
+
+int FileGDBTable::Open(const char* pszFilename)
+{
+    const int errorRetValue = FALSE;
+    CPLAssert(fpTable == NULL);
+
+    osFilename = pszFilename;
+
+    fpTable = VSIFOpenL( pszFilename, "rb" );
+    returnErrorIf(fpTable == NULL );
+
+    // Read .gdtable file header
+    GByte abyHeader[40];
+    returnErrorIf(VSIFReadL( abyHeader, 40, 1, fpTable ) != 1 );
+    nValidRecordCount = GetInt32(abyHeader + 4, 0);
+    returnErrorIf(nValidRecordCount < 0 );
+
+    if( nValidRecordCount > 0 &&
+        !CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_IGNORE_GDBTABLX", "FALSE")) )
+    {
+        const char* pszTableXName = CPLFormFilename(CPLGetPath(pszFilename),
+                                        CPLGetBasename(pszFilename), "gdbtablx");
+        fpTableX = VSIFOpenL( pszTableXName, "rb" );
+        if( fpTableX == NULL )
+        {
+            const char* pszIgnoreGDBTablXAbsence =
+                CPLGetConfigOption("OPENFILEGDB_IGNORE_GDBTABLX_ABSENCE", NULL);
+            if( pszIgnoreGDBTablXAbsence == NULL )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "%s could not be found. "
+                        "Trying to guess feature locations, but this might fail or "
+                        "return incorrect results", pszTableXName);
+            }
+            else if( !CSLTestBoolean(pszIgnoreGDBTablXAbsence) )
+            {
+                returnErrorIf(fpTableX == NULL );
+            }
+        }
+        else if( !ReadTableXHeader() )
+            return FALSE;
+    }
+
+    if( fpTableX != NULL )
+    {
+        returnErrorIf(nValidRecordCount > nTotalRecordCount );
+
+#ifdef DEBUG_VERBOSE
+        if( nTotalRecordCount != nValidRecordCount )
+        {
+            CPLDebug("OpenFileGDB", "%s: nTotalRecordCount=%d nValidRecordCount=%d",
+                    pszFilename,
+                    nTotalRecordCount, nValidRecordCount);
+        }
+#endif
+    }
+
+    nOffsetFieldDesc = GetUInt32(abyHeader + 32, 0);
+
+#ifdef DEBUG_VERBOSE
+    if( nOffsetFieldDesc != 40 )
+    {
+        CPLDebug("OpenFileGDB", "%s: nOffsetFieldDesc=%d",
+                 pszFilename, nOffsetFieldDesc);
+    }
+#endif
+
+    // Skip to field description section
+    VSIFSeekL( fpTable, nOffsetFieldDesc, SEEK_SET );
+    returnErrorIf(VSIFReadL( abyHeader, 14, 1, fpTable ) != 1 );
+    nFieldDescLength = GetUInt32(abyHeader, 0);
+
+    nOffsetHeaderEnd = nOffsetFieldDesc + nFieldDescLength;
+
+    returnErrorIf(nFieldDescLength > 1024 * 1024 || nFieldDescLength < 10 );
+    GByte byTableGeomType = abyHeader[8];
+    if( IS_VALID_LAYER_GEOM_TYPE(byTableGeomType) )
+        eTableGeomType = (FileGDBTableGeometryType) byTableGeomType;
+    else
+        CPLDebug("OpenFileGDB", "Unknown table geometry type: %d", byTableGeomType);
+    GUInt16 iField, nFields;
+    nFields = GetUInt16(abyHeader + 12, 0);
+
+    /* No interest in guessing a trivial file */
+    returnErrorIf( fpTableX == NULL && nFields == 0) ;
+
+    GUInt32 nRemaining = nFieldDescLength - 10;
+    nBufferMaxSize = nRemaining;
+    pabyBuffer = (GByte*)VSIMalloc(nBufferMaxSize);
+    returnErrorIf(pabyBuffer == NULL );
+    returnErrorIf(VSIFReadL(pabyBuffer, nRemaining, 1, fpTable) != 1 );
+
+    GByte* pabyIter = pabyBuffer;
+    for(iField = 0; iField < nFields; iField ++)
+    {
+        returnErrorIf(nRemaining < 1 );
+        GByte nCarCount = pabyIter[0];
+
+        pabyIter ++;
+        nRemaining --;
+        returnErrorIf(nRemaining < (GUInt32)(2 * nCarCount + 1) );
+        std::string osName;
+        for(int j=0;j<nCarCount;j++) //FIXME? UTF16
+            osName += pabyIter[2 * j];
+        pabyIter += 2 * nCarCount;
+        nRemaining -= 2 * nCarCount;
+
+        returnErrorIf(nRemaining < 1 );
+        nCarCount = pabyIter[0];
+        pabyIter ++;
+        nRemaining --;
+        returnErrorIf(nRemaining < (GUInt32)(2 * nCarCount + 1) );
+        std::string osAlias;
+        for(int j=0;j<nCarCount;j++) //FIXME? UTF16
+            osAlias += pabyIter[2 * j];
+        pabyIter += 2 * nCarCount;
+        nRemaining -= 2 * nCarCount;
+
+        returnErrorIf(nRemaining < 1 );
+        GByte byFieldType = pabyIter[0];
+        pabyIter ++;
+        nRemaining --;
+
+        if( byFieldType > FGFT_XML)
+        {
+            CPLDebug("OpenFileGDB", "Unhandled field type : %d", byFieldType);
+            returnError();
+        }
+
+        FileGDBFieldType eType = (FileGDBFieldType) byFieldType;
+        if( eType != FGFT_GEOMETRY && eType != FGFT_RASTER )
+        {
+            GByte flags = 0;
+            int nMaxWidth = 0;
+            GByte defaultValueLength = 0;
+
+            switch( eType )
+            {
+                case FGFT_STRING:
+                    returnErrorIf(nRemaining < 6 );
+                    nMaxWidth = GetInt32(pabyIter, 0);
+                    returnErrorIf(nMaxWidth < 0);
+                    flags = pabyIter[4];
+                    defaultValueLength = pabyIter[5];
+                    pabyIter += 6;
+                    nRemaining -= 6;
+                    break;
+
+                case FGFT_OBJECTID:
+                case FGFT_BINARY:
+                case FGFT_UUID_1:
+                case FGFT_UUID_2:
+                case FGFT_XML:
+                    returnErrorIf(nRemaining < 2 );
+                    flags = pabyIter[1];
+                    pabyIter += 2;
+                    nRemaining -= 2;
+                    break;
+
+                default:
+                    returnErrorIf(nRemaining < 3 );
+                    flags = pabyIter[1];
+                    defaultValueLength = pabyIter[2];
+                    pabyIter += 3;
+                    nRemaining -= 3;
+                    break;
+            }
+
+            if( (flags & 4) != 0 )
+            {
+                /* Default value */
+                /* Found on PreNIS.gdb/a0000000d.gdbtable */
+                returnErrorIf(nRemaining < defaultValueLength );
+                pabyIter += defaultValueLength;
+                nRemaining -= defaultValueLength;
+            }
+
+            if( eType == FGFT_OBJECTID )
+            {
+                returnErrorIf(osObjectIdColName.size() > 0 );
+                osObjectIdColName = osName;
+                continue;
+            }
+
+            FileGDBField* poField = new FileGDBField(this);
+            poField->osName = osName;
+            poField->osAlias = osAlias;
+            poField->eType = eType;
+            poField->bNullable = (flags & 1);
+            poField->nMaxWidth = nMaxWidth;
+            apoFields.push_back(poField);
+        }
+        else
+        {
+
+            FileGDBRasterField* poRasterField = NULL;
+            FileGDBGeomField* poField;
+            if( eType == FGFT_GEOMETRY )
+            {
+                returnErrorIf(iGeomField >= 0 );
+                poField = new FileGDBGeomField(this);
+            }
+            else
+            {
+                poRasterField = new FileGDBRasterField(this);
+                poField = poRasterField;
+            }
+
+            poField->osName = osName;
+            poField->osAlias = osAlias;
+            poField->eType = eType;
+            if( eType == FGFT_GEOMETRY )
+                iGeomField = (int)apoFields.size();
+            apoFields.push_back(poField);
+
+            returnErrorIf(nRemaining < 2 );
+            GByte flags = pabyIter[1];
+            poField->bNullable = (flags & 1);
+            pabyIter += 2;
+            nRemaining -= 2;
+
+            if( eType == FGFT_RASTER )
+            {
+                returnErrorIf(nRemaining < 1 );
+                nCarCount = pabyIter[0];
+                pabyIter ++;
+                nRemaining --;
+                returnErrorIf(nRemaining < (GUInt32)(2 * nCarCount + 1) );
+                std::string osRasterColumn;
+                for(int j=0;j<nCarCount;j++) //FIXME? UTF16
+                    osRasterColumn += pabyIter[2 * j];
+                pabyIter += 2 * nCarCount;
+                nRemaining -= 2 * nCarCount;
+                poRasterField->osRasterColumnName = osRasterColumn;
+            }
+
+            returnErrorIf(nRemaining < 2 );
+            GUInt16 nLengthWKT = GetUInt16(pabyIter, 0);
+            pabyIter += sizeof(nLengthWKT);
+            nRemaining -= sizeof(nLengthWKT);
+
+            returnErrorIf(nRemaining < (GUInt32)(1 + nLengthWKT) );
+            for(int j=0;j<nLengthWKT/2;j++) //FIXME? UTF16
+                poField->osWKT += pabyIter[2 * j];
+            pabyIter += nLengthWKT;
+            nRemaining -= nLengthWKT;
+
+            GByte abyGeomFlags = pabyIter[0];
+            pabyIter ++;
+            nRemaining --;
+            poField->bHasM = (abyGeomFlags & 2) != 0;
+            poField->bHasZ = (abyGeomFlags & 4) != 0;
+            returnErrorIf(
+                    nRemaining < (GUInt32)(sizeof(double) * ( 8 + (poField->bHasM + poField->bHasZ) * 3 )) );
+
+#define READ_DOUBLE(field) do { \
+    field = GetFloat64(pabyIter, 0); \
+    pabyIter += sizeof(double); \
+    nRemaining -= sizeof(double); } while(0)
+
+            READ_DOUBLE(poField->dfXOrigin);
+            READ_DOUBLE(poField->dfYOrigin);
+            READ_DOUBLE(poField->dfXYScale);
+
+            if( poField->bHasM )
+            {
+                READ_DOUBLE(poField->dfMOrigin);
+                READ_DOUBLE(poField->dfMScale);
+            }
+
+            if( poField->bHasZ )
+            {
+                READ_DOUBLE(poField->dfZOrigin);
+                READ_DOUBLE(poField->dfZScale);
+            }
+
+            READ_DOUBLE(poField->dfXYTolerance);
+
+            if( poField->bHasM )
+            {
+                READ_DOUBLE(poField->dfMTolerance);
+            }
+
+            if( poField->bHasZ )
+            {
+                READ_DOUBLE(poField->dfZTolerance);
+            }
+
+            if( eType == FGFT_RASTER )
+            {
+                /* Always one byte at end ? */
+                returnErrorIf(nRemaining < 1 );
+                pabyIter += 1;
+                nRemaining -= 1;
+            }
+            else
+            {
+                READ_DOUBLE(poField->dfXMin);
+                READ_DOUBLE(poField->dfYMin);
+                READ_DOUBLE(poField->dfXMax);
+                READ_DOUBLE(poField->dfYMax);
+
+                /* Purely empiric logic ! */
+                while( TRUE )
+                {
+                    returnErrorIf(nRemaining < 5 );
+
+                    if( pabyIter[0] == 0x00 && pabyIter[1] >= 1 && pabyIter[1] <= 3 &&
+                        pabyIter[2] == 0x00 && pabyIter[3] == 0x00 && pabyIter[4] == 0x00 )
+                    {
+                        GByte nToSkip = pabyIter[1];
+                        pabyIter += 5;
+                        nRemaining -= 5;
+                        returnErrorIf(nRemaining < (GUInt32)(nToSkip * 8) );
+                        pabyIter += nToSkip * 8;
+                        nRemaining -= nToSkip * 8;
+                        break;
+                    }
+                    else
+                    {
+                        returnErrorIf(nRemaining < 8 );
+                        pabyIter += 8;
+                        nRemaining -= 8;
+                    }
+                }
+            }
+        }
+
+        nCountNullableFields += apoFields[apoFields.size()-1]->bNullable;
+    }
+    nNullableFieldsSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(nCountNullableFields);
+
+#ifdef DEBUG_VERBOSE
+    if( nRemaining > 0 )
+    {
+        CPLDebug("OpenFileGDB", "%u remaining (ignored) bytes in field header section",
+                 nRemaining);
+    }
+#endif
+
+    if( nValidRecordCount > 0 && fpTableX == NULL )
+        return GuessFeatureLocations();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          SkipVarUInt()                               */
+/************************************************************************/
+
+/* Bound check only valid if nIter <= 4 */
+static int SkipVarUInt(GByte*& pabyIter, GByte* pabyEnd, int nIter = 1)
+{
+    const int errorRetValue = FALSE;
+    GByte* pabyLocalIter = pabyIter;
+    returnErrorIf(pabyLocalIter /*+ nIter - 1*/ >= pabyEnd);
+    while( nIter -- > 0 )
+    {
+        while(TRUE)
+        {
+            GByte b = *pabyLocalIter;
+            pabyLocalIter ++;
+            if( (b & 0x80) == 0 )
+                break;
+        }
+    }
+    pabyIter = pabyLocalIter;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                      ReadVarIntAndAddNoCheck()                       */
+/************************************************************************/
+
+static void ReadVarIntAndAddNoCheck(GByte*& pabyIter, GIntBig& nOutVal)
+{
+    GUInt32 b;
+
+    b = *pabyIter;
+    GUIntBig nVal = (b & 0x3F);
+    int nSign = 1;
+    if( (b & 0x40) != 0 )
+        nSign = -1;
+    if( (b & 0x80) == 0 )
+    {
+        pabyIter ++;
+        nOutVal += nVal * nSign;
+        return;
+    }
+
+    GByte* pabyLocalIter = pabyIter + 1;
+    int nShift = 6;
+    while(TRUE)
+    {
+        GUIntBig b = *pabyLocalIter;
+        pabyLocalIter ++;
+        nVal |= ( b & 0x7F ) << nShift;
+        if( (b & 0x80) == 0 )
+        {
+            pabyIter = pabyLocalIter;
+            nOutVal += nVal * nSign;
+            return;
+        }
+        nShift += 7;
+    }
+}
+
+/************************************************************************/
+/*                       GetOffsetInTableForRow()                       */
+/************************************************************************/
+
+GUInt32 FileGDBTable::GetOffsetInTableForRow(int iRow)
+{
+    const int errorRetValue = 0;
+    returnErrorIf(iRow < 0 || iRow >= nTotalRecordCount );
+
+    if( fpTableX == NULL )
+        return anFeatureOffsets[iRow];
+
+    if( pabyTablXBlockMap != NULL )
+    {
+        GUInt32 nCountBlocksBefore = 0;
+        int iBlock = iRow / 1024;
+
+        // Check if the block is not empty
+        if( TEST_BIT(pabyTablXBlockMap, iBlock) == 0 )
+            return 0;
+
+        for(int i=0;i<iBlock;i++)
+            nCountBlocksBefore += TEST_BIT(pabyTablXBlockMap, i) != 0;
+        int iCorrectedRow = nCountBlocksBefore * 1024 + (iRow % 1024);
+        VSIFSeekL(fpTableX, 16 + 5 * iCorrectedRow, SEEK_SET);
+    }
+    else
+    {
+        VSIFSeekL(fpTableX, 16 + 5 * iRow, SEEK_SET);
+    }
+
+    GByte abyBuffer[4];
+    bError = VSIFReadL(abyBuffer, 4, 1, fpTableX) != 1;
+    returnErrorIf(bError );
+    GUInt32 nOffset = GetUInt32(abyBuffer, 0);
+
+#ifdef DEBUG_VERBOSE
+    if( iRow == 0 && nOffset != 0 &&
+        nOffset != nOffsetHeaderEnd && nOffset != nOffsetHeaderEnd + 4 )
+        CPLDebug("OpenFileGDB", "%s: first feature offset = %d. Expected %d",
+                 osFilename.c_str(), nOffset, nOffsetHeaderEnd);
+#endif
+
+    return nOffset;
+}
+
+/************************************************************************/
+/*                            SelectRow()                               */
+/************************************************************************/
+
+int FileGDBTable::SelectRow(int iRow)
+{
+    const int errorRetValue = FALSE;
+    returnErrorAndCleanupIf(iRow < 0 || iRow >= nTotalRecordCount, nCurRow = -1 );
+
+    if( nCurRow != iRow )
+    {
+        GUInt32 nOffsetTable = GetOffsetInTableForRow(iRow);
+        if( nOffsetTable == 0 )
+        {
+            nCurRow = -1;
+            return FALSE;
+        }
+
+        VSIFSeekL(fpTable, nOffsetTable, SEEK_SET);
+        GByte abyBuffer[4];
+        returnErrorAndCleanupIf(
+                VSIFReadL(abyBuffer, 4, 1, fpTable) != 1, nCurRow = -1 );
+
+        nRowBlobLength = GetUInt32(abyBuffer, 0);
+        if( !(apoFields.size() == 0 && nRowBlobLength == 0) )
+        {
+            /* CPLDebug("OpenFileGDB", "nRowBlobLength = %u", nRowBlobLength); */
+            returnErrorAndCleanupIf(
+                    nRowBlobLength < (GUInt32)nNullableFieldsSizeInBytes ||
+                    nRowBlobLength > INT_MAX - ZEROES_AFTER_END_OF_BUFFER, nCurRow = -1 );
+
+            if( nRowBlobLength > nBufferMaxSize )
+            {
+                GByte* pabyNewBuffer = (GByte*) VSIRealloc( pabyBuffer,
+                                nRowBlobLength + ZEROES_AFTER_END_OF_BUFFER );
+                returnErrorAndCleanupIf(pabyNewBuffer == NULL, nCurRow = -1 );
+
+                pabyBuffer = pabyNewBuffer;
+                nBufferMaxSize = nRowBlobLength;
+            }
+            returnErrorAndCleanupIf(
+                VSIFReadL(pabyBuffer, nRowBlobLength, 1, fpTable) != 1, nCurRow = -1 );
+            /* Protection for 4 ReadVarUInt64NoCheck */
+            CPLAssert(ZEROES_AFTER_END_OF_BUFFER == 4);
+            pabyBuffer[nRowBlobLength] = 0;
+            pabyBuffer[nRowBlobLength+1] = 0;
+            pabyBuffer[nRowBlobLength+2] = 0;
+            pabyBuffer[nRowBlobLength+3] = 0;
+        }
+
+        nCurRow = iRow;
+        nLastCol = -1;
+        pabyIterVals = pabyBuffer + nNullableFieldsSizeInBytes;
+        iAccNullable = 0;
+        bError = FALSE;
+        nChSaved = -1;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                      FileGDBDoubleDateToOGRDate()                    */
+/************************************************************************/
+
+int FileGDBDoubleDateToOGRDate(double dfVal, OGRField* psField)
+{
+    struct tm brokendowntime;
+
+    /* 25569 = Number of days between 1899/12/30 00:00:00 and 1970/01/01 00:00:00 */
+    CPLUnixTimeToYMDHMS((GIntBig)((dfVal - 25569) * 3600 * 24), &brokendowntime);
+
+    psField->Date.Year = (GInt16)(brokendowntime.tm_year + 1900);
+    psField->Date.Month = (GByte)brokendowntime.tm_mon + 1;
+    psField->Date.Day = (GByte)brokendowntime.tm_mday;
+    psField->Date.Hour = (GByte)brokendowntime.tm_hour;
+    psField->Date.Minute = (GByte)brokendowntime.tm_min;
+    psField->Date.Second = (GByte)brokendowntime.tm_sec;
+    psField->Date.TZFlag = 0;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GetFieldValue()                             */
+/************************************************************************/
+
+const OGRField* FileGDBTable::GetFieldValue(int iCol)
+{
+    const OGRField* errorRetValue = NULL;
+
+    returnErrorIf(nCurRow < 0 );
+    returnErrorIf((GUInt32)iCol >= apoFields.size() );
+    returnErrorIf(bError );
+
+    GByte* pabyEnd = pabyBuffer + nRowBlobLength;
+
+    /* In case a string was previously read */
+    if( nChSaved >= 0 )
+    {
+        *pabyIterVals = (GByte)nChSaved;
+        nChSaved = -1;
+    }
+
+    if( iCol <= nLastCol )
+    {
+        nLastCol = -1;
+        pabyIterVals = pabyBuffer + nNullableFieldsSizeInBytes;
+        iAccNullable = 0;
+    }
+
+    // Skip previous fields
+    for( int j = nLastCol + 1; j < iCol; j++ )
+    {
+        if( apoFields[j]->bNullable )
+        {
+            int bIsNull = TEST_BIT(pabyBuffer, iAccNullable);
+            iAccNullable ++;
+            if( bIsNull )
+                continue;
+        }
+
+        GUInt32 nLength;
+        switch( apoFields[j]->eType )
+        {
+            case FGFT_STRING:
+            case FGFT_XML:
+            case FGFT_GEOMETRY:
+            case FGFT_BINARY:
+            {
+                if( !ReadVarUInt32(pabyIterVals, pabyEnd, nLength) )
+                {
+                    bError = TRUE;
+                    returnError();
+                }
+                break;
+            }
+
+            /* Only 4 bytes ? */
+            case FGFT_RASTER: nLength = sizeof(GInt32); break;
+
+            case FGFT_INT16: nLength = sizeof(GInt16); break;
+            case FGFT_INT32: nLength = sizeof(GInt32); break;
+            case FGFT_FLOAT32: nLength = sizeof(float); break;
+            case FGFT_FLOAT64: nLength = sizeof(double); break;
+            case FGFT_DATETIME: nLength = sizeof(double); break;
+            case FGFT_UUID_1:
+            case FGFT_UUID_2: nLength = UUID_SIZE_IN_BYTES; break;
+
+            default:
+                nLength = 0;
+                CPLAssert(FALSE);
+                break;
+        }
+
+        if( nLength > (GUInt32)(pabyEnd - pabyIterVals) )
+        {
+            bError = TRUE;
+            returnError();
+        }
+        pabyIterVals += nLength;
+    }
+
+    nLastCol = iCol;
+
+    if( apoFields[iCol]->bNullable )
+    {
+        int bIsNull = TEST_BIT(pabyBuffer, iAccNullable);
+        iAccNullable ++;
+        if( bIsNull )
+        {
+            return NULL;
+        }
+    }
+
+    switch( apoFields[iCol]->eType )
+    {
+        case FGFT_STRING:
+        case FGFT_XML:
+        {
+            GUInt32 nLength;
+            if( !ReadVarUInt32(pabyIterVals, pabyEnd, nLength) )
+            {
+                bError = TRUE;
+                returnError();
+            }
+            if( nLength > (GUInt32)(pabyEnd - pabyIterVals) )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTString; */
+            sCurField.String = (char*) pabyIterVals;
+            pabyIterVals += nLength;
+
+            /* This is a trick to avoid a alloc()+copy(). We null-terminate */
+            /* after the string, and save the pointer and value to restore */
+            nChSaved = *pabyIterVals;
+            *pabyIterVals = '\0';
+
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %s", iCol, nCurRow, sCurField.String); */ 
+
+            break;
+        }
+
+        case FGFT_INT16:
+        {
+            if( pabyIterVals + sizeof(GInt16) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTInteger; */
+            sCurField.Integer = GetInt16(pabyIterVals, 0);
+            
+            pabyIterVals += sizeof(GInt16);
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
+
+            break;
+        }
+
+        case FGFT_INT32:
+        {
+            if( pabyIterVals + sizeof(GInt32) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTInteger; */
+            sCurField.Integer = GetInt32(pabyIterVals, 0);
+            
+            pabyIterVals += sizeof(GInt32);
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
+
+            break;
+        }
+
+        case FGFT_FLOAT32:
+        {
+            if( pabyIterVals + sizeof(float) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTReal; */
+            sCurField.Real = GetFloat32(pabyIterVals, 0);
+            
+            pabyIterVals += sizeof(float);
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %f", iCol, nCurRow, sCurField.Real); */
+
+            break;
+        }
+
+        case FGFT_FLOAT64:
+        {
+            if( pabyIterVals + sizeof(double) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTReal; */
+            sCurField.Real = GetFloat64(pabyIterVals, 0);
+            
+            pabyIterVals += sizeof(double);
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %f", iCol, nCurRow, sCurField.Real); */
+
+            break;
+        }
+
+        case FGFT_DATETIME:
+        {
+            if( pabyIterVals + sizeof(double) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* Number of days since 1899/12/30 00:00:00 */
+            double dfVal = GetFloat64(pabyIterVals, 0);
+
+            FileGDBDoubleDateToOGRDate(dfVal, &sCurField);
+            /* eCurFieldType = OFTDateTime; */
+
+            pabyIterVals += sizeof(double);
+
+            break;
+        }
+
+        case FGFT_GEOMETRY:
+        case FGFT_BINARY:
+        {
+            GUInt32 nLength;
+            if( !ReadVarUInt32(pabyIterVals, pabyEnd, nLength) )
+            {
+                bError = TRUE;
+                returnError();
+            }
+            if( nLength > (GUInt32)(pabyEnd - pabyIterVals) )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTBinary; */
+            sCurField.Binary.nCount = nLength;
+            sCurField.Binary.paData = (GByte*) pabyIterVals;
+
+            pabyIterVals += nLength;
+
+            /* Null terminate binary in case it is used as a string */
+            nChSaved = *pabyIterVals;
+            *pabyIterVals = '\0';
+
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d bytes", iCol, nCurRow, snLength); */
+
+            break;
+        }
+
+        /* Only 4 bytes ? */
+        case FGFT_RASTER:
+        {
+            if( pabyIterVals + sizeof(GInt32) > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* GInt32 nVal = GetInt32(pabyIterVals, 0); */
+
+            /* eCurFieldType = OFTBinary; */
+            sCurField.Set.nMarker1 = OGRUnsetMarker;
+            sCurField.Set.nMarker2 = OGRUnsetMarker;
+
+            pabyIterVals += sizeof(GInt32);
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
+            break;
+        }
+
+        case FGFT_UUID_1:
+        case FGFT_UUID_2:
+        {
+            if( pabyIterVals + UUID_SIZE_IN_BYTES > pabyEnd )
+            {
+                bError = TRUE;
+                returnError();
+            }
+
+            /* eCurFieldType = OFTString; */
+            sCurField.String = achGUIDBuffer;
+            /*78563412BC9AF0DE1234567890ABCDEF --> {12345678-9ABC-DEF0-1234-567890ABCDEF} */
+            sprintf(achGUIDBuffer,
+                    "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+                    pabyIterVals[3], pabyIterVals[2], pabyIterVals[1], pabyIterVals[0],
+                    pabyIterVals[5], pabyIterVals[4],
+                    pabyIterVals[7], pabyIterVals[6],
+                    pabyIterVals[8], pabyIterVals[9],
+                    pabyIterVals[10], pabyIterVals[11], pabyIterVals[12],
+                    pabyIterVals[13], pabyIterVals[14], pabyIterVals[15]);
+
+            pabyIterVals += UUID_SIZE_IN_BYTES;
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %s", iCol, nCurRow, sCurField.String); */
+
+            break;
+        }
+
+        default:
+            CPLAssert(FALSE);
+            break;
+    }
+
+    if( iCol == (int)apoFields.size() - 1 && pabyIterVals < pabyEnd )
+    {
+        CPLDebug("OpenFileGDB", "%d bytes remaining at end of record %d",
+                 (int)(pabyEnd - pabyIterVals), nCurRow);
+    }
+
+    return &sCurField;
+}
+
+/************************************************************************/
+/*                           GetIndexCount()                            */
+/************************************************************************/
+
+int FileGDBTable::GetIndexCount()
+{
+    const int errorRetValue = 0;
+    if( bHasReadGDBIndexes )
+        return (int) apoIndexes.size();
+
+    bHasReadGDBIndexes = TRUE;
+
+    const char* pszIndexesName = CPLFormFilename(CPLGetPath(osFilename.c_str()),
+                                    CPLGetBasename(osFilename.c_str()), "gdbindexes");
+    VSILFILE* fpIndexes = VSIFOpenL( pszIndexesName, "rb" );
+    VSIStatBufL sStat;
+    if( fpIndexes == NULL )
+    {
+        if ( VSIStatExL( pszIndexesName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+            returnError();
+        else
+            return 0;
+    }
+
+    VSIFSeekL(fpIndexes, 0, SEEK_END);
+    vsi_l_offset nFileSize = VSIFTellL(fpIndexes);
+    returnErrorAndCleanupIf(nFileSize > 1024 * 1024, VSIFCloseL(fpIndexes) );
+
+    GByte* pabyIdx = (GByte*)VSIMalloc((size_t)nFileSize);
+    returnErrorAndCleanupIf(pabyIdx == NULL, VSIFCloseL(fpIndexes) );
+
+    VSIFSeekL(fpIndexes, 0, SEEK_SET);
+    int nRead = (int)VSIFReadL( pabyIdx, (size_t)nFileSize, 1, fpIndexes );
+    VSIFCloseL(fpIndexes);
+    returnErrorAndCleanupIf(nRead != 1, VSIFree(pabyIdx) );
+
+    GByte* pabyCur = pabyIdx;
+    GByte* pabyEnd = pabyIdx + nFileSize;
+    returnErrorAndCleanupIf(pabyEnd - pabyCur < 4, VSIFree(pabyIdx) );
+    GUInt32 nIndexCount = GetUInt32(pabyCur, 0);
+    pabyCur += 4;
+
+    // FileGDB v9 indexes structure not handled yet. Start with 13 98 85 03
+    if( nIndexCount == 0x03859813 )
+    {
+        CPLDebug("OpenFileGDB", ".gdbindexes v9 not handled yet");
+        VSIFree(pabyIdx);
+        return 0;
+    }
+    returnErrorAndCleanupIf(nIndexCount >= (size_t)(GetFieldCount() + 1) * 10, VSIFree(pabyIdx) );
+
+    GUInt32 i;
+    for(i=0;i<nIndexCount;i++)
+    {
+        returnErrorAndCleanupIf((GUInt32)(pabyEnd - pabyCur) < sizeof(GUInt32), VSIFree(pabyIdx) );
+        GUInt32 nIdxNameCarCount = GetUInt32(pabyCur, 0);
+        pabyCur += sizeof(GUInt32);
+        returnErrorAndCleanupIf(nIdxNameCarCount > 1024, VSIFree(pabyIdx) );
+        returnErrorAndCleanupIf((GUInt32)(pabyEnd - pabyCur) < 2 * nIdxNameCarCount, VSIFree(pabyIdx) );
+        std::string osIndexName;
+        GUInt32 j;
+        for(j=0;j<nIdxNameCarCount;j++) //FIXME? UTF16
+            osIndexName += pabyCur[2 * j];
+        pabyCur += 2 * nIdxNameCarCount;
+
+        // Skip magic fields
+        pabyCur += 2 + 4 + 2 + 4;
+
+        returnErrorAndCleanupIf((GUInt32)(pabyEnd - pabyCur) < sizeof(GUInt32), VSIFree(pabyIdx) );
+        GUInt32 nColNameCarCount = GetUInt32(pabyCur, 0);
+        pabyCur += sizeof(GUInt32);
+        returnErrorAndCleanupIf(nColNameCarCount > 1024, VSIFree(pabyIdx) );
+        returnErrorAndCleanupIf((GUInt32)(pabyEnd - pabyCur) < 2 * nColNameCarCount, VSIFree(pabyIdx) );
+        std::string osFieldName;
+        for(j=0;j<nColNameCarCount;j++) //FIXME? UTF16
+            osFieldName += pabyCur[2 * j];
+        pabyCur += 2 * nColNameCarCount;
+
+        // Skip magic field
+        pabyCur += 2;
+
+        FileGDBIndex* poIndex = new FileGDBIndex();
+        poIndex->osIndexName = osIndexName;
+        poIndex->osFieldName = osFieldName;
+        apoIndexes.push_back(poIndex);
+
+        if( osFieldName != osObjectIdColName )
+        {
+            int nFieldIdx = GetFieldIdx(osFieldName);
+            if( nFieldIdx < 0 )
+            {
+                CPLDebug("OpenFileGDB",
+                         "Index defined for field %s that does not exist",
+                         osFieldName.c_str());
+            }
+            else
+            {
+                if( apoFields[nFieldIdx]->poIndex != NULL )
+                {
+                    CPLDebug("OpenFileGDB",
+                             "There is already one index defined for field %s",
+                              osFieldName.c_str());
+                }
+                else
+                {
+                    apoFields[nFieldIdx]->poIndex = poIndex;
+                }
+            }
+        }
+    }
+
+    VSIFree(pabyIdx);
+
+    return (int) apoIndexes.size();
+}
+
+/************************************************************************/
+/*                       InstallFilterEnvelope()                        */
+/************************************************************************/
+
+#define MAX_GUINTBIG    (~((GUIntBig)0))
+
+void FileGDBTable::InstallFilterEnvelope(const OGREnvelope* psFilterEnvelope)
+{
+    if( psFilterEnvelope != NULL )
+    {
+        CPLAssert( iGeomField >= 0 );
+        FileGDBGeomField* poGeomField = (FileGDBGeomField*) GetField(iGeomField);
+
+        /* We store the bounding box as unscaled coordinates, so that BBOX */
+        /* intersection is done with integer comparisons */
+        if( psFilterEnvelope->MinX >= poGeomField->dfXOrigin )
+            nFilterXMin = (GUIntBig)(0.5 + (psFilterEnvelope->MinX -
+                                poGeomField->dfXOrigin) * poGeomField->dfXYScale);
+        else
+            nFilterXMin = 0;
+        if( psFilterEnvelope->MaxX - poGeomField->dfXOrigin <
+                                        MAX_GUINTBIG / poGeomField->dfXYScale )
+            nFilterXMax = (GUIntBig)(0.5 + (psFilterEnvelope->MaxX -
+                            poGeomField->dfXOrigin) * poGeomField->dfXYScale);
+        else
+            nFilterXMax = MAX_GUINTBIG;
+        if( psFilterEnvelope->MinY >= poGeomField->dfYOrigin )
+            nFilterYMin = (GUIntBig)(0.5 + (psFilterEnvelope->MinY -
+                                poGeomField->dfYOrigin) * poGeomField->dfXYScale);
+        else
+            nFilterYMin = 0;
+        if( psFilterEnvelope->MaxY - poGeomField->dfYOrigin <
+                                        MAX_GUINTBIG / poGeomField->dfXYScale )
+            nFilterYMax = (GUIntBig)(0.5 + (psFilterEnvelope->MaxY -
+                                poGeomField->dfYOrigin) * poGeomField->dfXYScale);
+        else
+            nFilterYMax = MAX_GUINTBIG;
+    }
+    else
+    {
+        nFilterXMin = 0;
+        nFilterXMax = 0;
+        nFilterYMin = 0;
+        nFilterYMax = 0;
+    }
+}
+
+/************************************************************************/
+/*                         GetFeatureExtent()                           */
+/************************************************************************/
+
+int FileGDBTable::GetFeatureExtent(const OGRField* psField,
+                                   OGREnvelope* psOutFeatureEnvelope)
+{
+    const int errorRetValue = FALSE;
+    GByte* pabyCur = psField->Binary.paData;
+    GByte* pabyEnd = pabyCur + psField->Binary.nCount;
+    GUInt32 nGeomType;
+    int nToSkip = 0;
+
+    CPLAssert( iGeomField >= 0 );
+    FileGDBGeomField* poGeomField = (FileGDBGeomField*) GetField(iGeomField);
+
+    ReadVarUInt32NoCheck(pabyCur, nGeomType);
+
+    switch( (nGeomType & 0xff) )
+    {
+        case SHPT_NULL:
+            return FALSE;
+
+        case SHPT_POINTZ:
+        case SHPT_POINTZM:
+        case SHPT_POINT:
+        case SHPT_POINTM:
+        {
+            GUIntBig x, y;
+            ReadVarUInt64NoCheck(pabyCur, x);
+            x --;
+            ReadVarUInt64NoCheck(pabyCur, y);
+            y --;
+            psOutFeatureEnvelope->MinX = x / poGeomField->dfXYScale + poGeomField->dfXOrigin;
+            psOutFeatureEnvelope->MinY = y / poGeomField->dfXYScale + poGeomField->dfYOrigin;
+            psOutFeatureEnvelope->MaxX = psOutFeatureEnvelope->MinX;
+            psOutFeatureEnvelope->MaxY = psOutFeatureEnvelope->MinY;
+            return TRUE;
+        }
+
+        case SHPT_MULTIPOINTZM:
+        case SHPT_MULTIPOINTZ:
+        case SHPT_MULTIPOINT:
+        case SHPT_MULTIPOINTM:
+        {
+            break;
+        }
+
+        case SHPT_ARC:
+        case SHPT_ARCZ:
+        case SHPT_ARCZM:
+        case SHPT_ARCM:
+        case SHPT_POLYGON:
+        case SHPT_POLYGONZ:
+        case SHPT_POLYGONZM:
+        case SHPT_POLYGONM:
+        {
+            nToSkip = 1;
+            break;
+        }
+
+        case SHPT_GENERALPOLYLINE:
+        case SHPT_GENERALMULTIPATCH:
+        case SHPT_MULTIPATCHM:
+        case SHPT_MULTIPATCH:
+        {
+            nToSkip = 2;
+            break;
+        }
+
+        default:
+            return FALSE;
+    }
+
+    GUInt32 nPoints;
+    ReadVarUInt32NoCheck(pabyCur, nPoints);
+    if( nPoints == 0 )
+        return TRUE;
+    returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, nToSkip) );
+    
+    GUIntBig vxmin, vymin, vdx, vdy;
+
+    returnErrorIf(pabyCur >= pabyEnd);
+    ReadVarUInt64NoCheck(pabyCur, vxmin);
+    ReadVarUInt64NoCheck(pabyCur, vymin);
+    ReadVarUInt64NoCheck(pabyCur, vdx);
+    ReadVarUInt64NoCheck(pabyCur, vdy);
+    
+    psOutFeatureEnvelope->MinX = vxmin / poGeomField->dfXYScale + poGeomField->dfXOrigin;
+    psOutFeatureEnvelope->MinY = vymin / poGeomField->dfXYScale + poGeomField->dfYOrigin;
+    psOutFeatureEnvelope->MaxX = (vxmin + vdx) / poGeomField->dfXYScale + poGeomField->dfXOrigin;
+    psOutFeatureEnvelope->MaxY = (vymin + vdy) / poGeomField->dfXYScale + poGeomField->dfYOrigin;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                 DoesGeometryIntersectsFilterEnvelope()               */
+/************************************************************************/
+
+int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
+{
+    const int errorRetValue = TRUE;
+    GByte* pabyCur = psField->Binary.paData;
+    GByte* pabyEnd = pabyCur + psField->Binary.nCount;
+    GUInt32 nGeomType;
+    int nToSkip = 0;
+
+    ReadVarUInt32NoCheck(pabyCur, nGeomType);
+
+    switch( (nGeomType & 0xff) )
+    {
+        case SHPT_NULL:
+            return TRUE;
+
+        case SHPT_POINTZ:
+        case SHPT_POINTZM:
+        case SHPT_POINT:
+        case SHPT_POINTM:
+        {
+            GUIntBig x, y;
+            ReadVarUInt64NoCheck(pabyCur, x);
+            x --;
+            if( x < nFilterXMin || x > nFilterXMax )
+                return FALSE;
+            ReadVarUInt64NoCheck(pabyCur, y);
+            y --;
+            return( y >= nFilterYMin && y <= nFilterYMax );
+        }
+
+        case SHPT_MULTIPOINTZM:
+        case SHPT_MULTIPOINTZ:
+        case SHPT_MULTIPOINT:
+        case SHPT_MULTIPOINTM:
+        {
+            break;
+        }
+
+        case SHPT_ARC:
+        case SHPT_ARCZ:
+        case SHPT_ARCZM:
+        case SHPT_ARCM:
+        case SHPT_POLYGON:
+        case SHPT_POLYGONZ:
+        case SHPT_POLYGONZM:
+        case SHPT_POLYGONM:
+        {
+            nToSkip = 1;
+            break;
+        }
+
+        case SHPT_GENERALPOLYLINE:
+        case SHPT_GENERALPOLYGON:
+        {
+            nToSkip = 1 + ((nGeomType & 0x20000000) ? 1 : 0);
+            break;
+        }
+
+        case SHPT_GENERALMULTIPATCH:
+        case SHPT_MULTIPATCHM:
+        case SHPT_MULTIPATCH:
+        {
+            nToSkip = 2;
+            break;
+        }
+
+        default:
+            return TRUE;
+    }
+
+    GUInt32 nPoints;
+    ReadVarUInt32NoCheck(pabyCur, nPoints);
+    if( nPoints == 0 )
+        return TRUE;
+    returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, nToSkip) );
+    
+    GUIntBig vxmin, vymin, vdx, vdy;
+
+    returnErrorIf(pabyCur >= pabyEnd);
+    ReadVarUInt64NoCheck(pabyCur, vxmin);
+    if( vxmin > nFilterXMax )
+        return FALSE;
+    ReadVarUInt64NoCheck(pabyCur, vymin);
+    if( vymin > nFilterYMax )
+        return FALSE;
+    ReadVarUInt64NoCheck(pabyCur, vdx);
+    if( vxmin + vdx < nFilterXMin )
+        return FALSE;
+    ReadVarUInt64NoCheck(pabyCur, vdy);
+    return vymin + vdy >= nFilterYMin;
+}
+
+/************************************************************************/
+/*                           FileGDBField()                             */
+/************************************************************************/
+
+FileGDBField::FileGDBField(FileGDBTable* poParent) :
+    poParent(poParent), eType(FGFT_UNDEFINED), bNullable(FALSE),
+    nMaxWidth(0), poIndex(NULL)
+{
+}
+
+/************************************************************************/
+/*                          ~FileGDBField()                             */
+/************************************************************************/
+
+FileGDBField::~FileGDBField()
+{
+}
+
+
+/************************************************************************/
+/*                            HasIndex()                                */
+/************************************************************************/
+
+int FileGDBField::HasIndex()
+{
+     poParent->GetIndexCount();
+     return poIndex != NULL;
+}
+
+/************************************************************************/
+/*                            GetIndex()                                */
+/************************************************************************/
+
+FileGDBIndex *FileGDBField::GetIndex()
+{
+     poParent->GetIndexCount();
+     return poIndex;
+}
+
+/************************************************************************/
+/*                           FileGDBGeomField()                         */
+/************************************************************************/
+
+FileGDBGeomField::FileGDBGeomField(FileGDBTable* poParent) :
+    FileGDBField(poParent), bHasZ(FALSE), bHasM(FALSE),
+    dfXOrigin(0.0), dfYOrigin(0.0), dfXYScale(0.0), dfMOrigin(0.0),
+    dfMScale(0.0), dfZOrigin(0.0), dfZScale(0.0), dfXYTolerance(0.0),
+    dfMTolerance(0.0), dfZTolerance(0.0), dfXMin(0.0), dfYMin(0.0),
+    dfXMax(0.0), dfYMax(0.0)
+{
+}
+
+/************************************************************************/
+/*                      FileGDBOGRGeometryConverterImpl                 */
+/************************************************************************/
+
+class FileGDBOGRGeometryConverterImpl : public FileGDBOGRGeometryConverter
+{
+        const FileGDBGeomField      *poGeomField;
+        GUInt32                     *panPointCount;
+        GUInt32                      nPointCountMax;
+#ifdef ASSUME_INNER_RINGS_IMMEDIATELY_AFTER_OUTER_RING
+        int                          bUseOrganize;
+#endif
+
+        int                         ReadPartDefs( GByte*& pabyCur,
+                                                  GByte* pabyEnd,
+                                                  GUInt32& nPoints,
+                                                  GUInt32& nParts,
+                                                  int bHasCurveDesc,
+                                                  int bIsMultiPatch );
+        template <class XYSetter> int ReadXYArray(XYSetter& setter,
+                                                  GByte*& pabyCur,
+                                                  GByte* pabyEnd,
+                                                  GUInt32 nPoints,
+                                                  GIntBig& dx,
+                                                  GIntBig& dy);
+        template <class ZSetter> int ReadZArray(ZSetter& setter,
+                                                GByte*& pabyCur,
+                                                GByte* pabyEnd,
+                                                GUInt32 nPoints,
+                                                GIntBig& dz);
+
+    public:
+                                        FileGDBOGRGeometryConverterImpl(
+                                            const FileGDBGeomField* poGeomField);
+       virtual                         ~FileGDBOGRGeometryConverterImpl();
+
+       virtual OGRGeometry*             GetAsGeometry(const OGRField* psField);
+};
+
+/************************************************************************/
+/*                  FileGDBOGRGeometryConverterImpl()                   */
+/************************************************************************/
+
+FileGDBOGRGeometryConverterImpl::FileGDBOGRGeometryConverterImpl(
+                                    const FileGDBGeomField* poGeomField) :
+                                                poGeomField(poGeomField)
+{
+    panPointCount = NULL;
+    nPointCountMax = 0;
+#ifdef ASSUME_INNER_RINGS_IMMEDIATELY_AFTER_OUTER_RING
+    bUseOrganize = CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL) != NULL;
+#endif
+}
+
+/************************************************************************/
+/*                 ~FileGDBOGRGeometryConverter()                       */
+/************************************************************************/
+
+FileGDBOGRGeometryConverterImpl::~FileGDBOGRGeometryConverterImpl()
+{
+    CPLFree(panPointCount);
+}
+
+/************************************************************************/
+/*                          ReadPartDefs()                              */
+/************************************************************************/
+
+int FileGDBOGRGeometryConverterImpl::ReadPartDefs( GByte*& pabyCur,
+                                GByte* pabyEnd,
+                                GUInt32& nPoints,
+                                GUInt32& nParts,
+                                int bHasCurveDesc,
+                                int bIsMultiPatch )
+{
+    const int errorRetValue = FALSE;
+    returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nPoints));
+    if( nPoints == 0 )
+    {
+        nParts = 0;
+        return TRUE;
+    }
+    returnErrorIf(nPoints > (GUInt32)(pabyEnd - pabyCur) );
+    if( bIsMultiPatch )
+        returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd) );
+    returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nParts));
+    returnErrorIf(nParts > (GUInt32)(pabyEnd - pabyCur));
+    if( bHasCurveDesc )
+        returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd) );
+    if( nParts == 0 )
+        return TRUE;
+    GUInt32 i;
+    returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, 4) );
+    if( nParts > nPointCountMax )
+    {
+        GUInt32* panPointCountNew =
+            (GUInt32*) VSIRealloc( panPointCount, nParts * sizeof(GUInt32) );
+        returnErrorIf(panPointCountNew == NULL );
+        panPointCount = panPointCountNew;
+        nPointCountMax = nParts;
+    }
+    GUIntBig nSumNPartsM1 = 0;
+    for(i=0;i<nParts-1;i++)
+    {
+        GUInt32 nTmp;
+        returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nTmp));
+        returnErrorIf(nTmp > (GUInt32)(pabyEnd - pabyCur) );
+        panPointCount[i] = nTmp;
+        nSumNPartsM1 += nTmp;
+    }
+    returnErrorIf(nSumNPartsM1 > nPoints );
+    panPointCount[nParts-1] = (GUInt32)(nPoints - nSumNPartsM1);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         XYLineStringSetter                           */
+/************************************************************************/
+
+class FileGDBOGRLineString: public OGRLineString
+{
+    public:
+        FileGDBOGRLineString() {}
+
+        OGRRawPoint * GetPoints() const { return paoPoints; }
+};
+
+class FileGDBOGRLinearRing: public OGRLinearRing
+{
+    public:
+        FileGDBOGRLinearRing() {}
+
+        OGRRawPoint * GetPoints() const { return paoPoints; }
+};
+
+class XYLineStringSetter
+{
+        OGRRawPoint* paoPoints;
+    public:
+        XYLineStringSetter(OGRRawPoint* paoPoints) : paoPoints(paoPoints) {}
+
+        void set(int i, double dfX, double dfY)
+        {
+            paoPoints[i].x = dfX;
+            paoPoints[i].y = dfY;
+        }
+};
+
+/************************************************************************/
+/*                         XYMultiPointSetter                           */
+/************************************************************************/
+
+class XYMultiPointSetter
+{
+        OGRMultiPoint* poMPoint;
+    public:
+        XYMultiPointSetter(OGRMultiPoint* poMPoint) : poMPoint(poMPoint) {}
+
+        void set(int i, double dfX, double dfY)
+        {
+            (void)i;
+            poMPoint->addGeometryDirectly(new OGRPoint(dfX, dfY));
+        }
+};
+
+/************************************************************************/
+/*                             XYArraySetter                            */
+/************************************************************************/
+
+class XYArraySetter
+{
+        double* padfX;
+        double* padfY;
+    public:
+        XYArraySetter(double* padfX, double* padfY) : padfX(padfX), padfY(padfY) {}
+
+        void set(int i, double dfX, double dfY)
+        {
+            padfX[i] = dfX;
+            padfY[i] = dfY;
+        }
+};
+
+/************************************************************************/
+/*                          ReadXYArray()                               */
+/************************************************************************/
+
+template <class XYSetter> int FileGDBOGRGeometryConverterImpl::ReadXYArray(XYSetter& setter,
+                                                        GByte*& pabyCur,
+                                                        GByte* pabyEnd,
+                                                        GUInt32 nPoints,
+                                                        GIntBig& dx,
+                                                        GIntBig& dy)
+{
+    const int errorRetValue = FALSE;
+    GIntBig dxLocal = dx;
+    GIntBig dyLocal = dy;
+
+    for(GUInt32 i = 0; i < nPoints; i++ )
+    {
+        returnErrorIf(pabyCur /*+ 1*/ >= pabyEnd);
+
+        ReadVarIntAndAddNoCheck(pabyCur, dxLocal);
+        ReadVarIntAndAddNoCheck(pabyCur, dyLocal);
+
+        double dfX = dxLocal / poGeomField->GetXYScale() + poGeomField->GetXOrigin();
+        double dfY = dyLocal / poGeomField->GetXYScale() + poGeomField->GetYOrigin();
+        setter.set(i, dfX, dfY);
+    }
+
+    dx = dxLocal;
+    dy = dyLocal;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          ZLineStringSetter                           */
+/************************************************************************/
+
+class ZLineStringSetter
+{
+        OGRLineString* poLS;
+    public:
+        ZLineStringSetter(OGRLineString* poLS) : poLS(poLS) {}
+
+        void set(int i, double dfZ)
+        {
+            poLS->setZ(i, dfZ);
+        }
+};
+
+/************************************************************************/
+/*                         ZMultiPointSetter                           */
+/************************************************************************/
+
+class ZMultiPointSetter
+{
+        OGRMultiPoint* poMPoint;
+    public:
+        ZMultiPointSetter(OGRMultiPoint* poMPoint) : poMPoint(poMPoint) {}
+
+        void set(int i, double dfZ)
+        {
+            ((OGRPoint*)poMPoint->getGeometryRef(i))->setZ(dfZ);
+        }
+};
+
+/************************************************************************/
+/*                             ZArraySetter                            */
+/************************************************************************/
+
+class ZArraySetter
+{
+        double* padfZ;
+    public:
+        ZArraySetter(double* padfZ) : padfZ(padfZ) {}
+
+        void set(int i, double dfZ)
+        {
+            padfZ[i] = dfZ;
+        }
+};
+
+/************************************************************************/
+/*                          ReadZArray()                                */
+/************************************************************************/
+
+template <class ZSetter> int FileGDBOGRGeometryConverterImpl::ReadZArray(ZSetter& setter,
+                                                      GByte*& pabyCur,
+                                                      GByte* pabyEnd,
+                                                      GUInt32 nPoints,
+                                                      GIntBig& dz)
+{
+    const int errorRetValue = FALSE;
+    for(GUInt32 i = 0; i < nPoints; i++ )
+    {
+        returnErrorIf(pabyCur >= pabyEnd);
+        ReadVarIntAndAddNoCheck(pabyCur, dz);
+
+        double dfZ = dz / poGeomField->GetZScale() + poGeomField->GetZOrigin();
+        setter.set(i, dfZ);
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GetAsGeometry()                             */
+/************************************************************************/
+
+OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psField)
+{
+    OGRGeometry* errorRetValue = NULL;
+    GByte* pabyCur = psField->Binary.paData;
+    GByte* pabyEnd = pabyCur + psField->Binary.nCount;
+    GUInt32 nGeomType, i, nPoints, nParts;
+    GUIntBig x, y, z;
+    GIntBig dx, dy, dz;
+
+    ReadVarUInt32NoCheck(pabyCur, nGeomType);
+
+    int bHasZ = (nGeomType & 0x80000000) != 0;
+    switch( (nGeomType & 0xff) )
+    {
+        case SHPT_NULL:
+            return NULL;
+
+        case SHPT_POINTZ:
+        case SHPT_POINTZM:
+            bHasZ = TRUE; /* go on */
+        case SHPT_POINT:
+        case SHPT_POINTM:
+        {
+            double dfX, dfY, dfZ;
+            ReadVarUInt64NoCheck(pabyCur, x);
+            ReadVarUInt64NoCheck(pabyCur, y);
+
+            dfX = (x - 1) / poGeomField->GetXYScale() + poGeomField->GetXOrigin();
+            dfY = (y - 1) / poGeomField->GetXYScale() + poGeomField->GetYOrigin();
+            if( bHasZ )
+            {
+                ReadVarUInt64NoCheck(pabyCur, z);
+                dfZ = (z - 1) / poGeomField->GetZScale() + poGeomField->GetZOrigin();
+                return new OGRPoint(dfX, dfY, dfZ);
+            }
+            else
+            {
+                return new OGRPoint(dfX, dfY);
+            }
+            break;
+        }
+
+        case SHPT_MULTIPOINTZM:
+        case SHPT_MULTIPOINTZ:
+            bHasZ = TRUE; /* go on */
+        case SHPT_MULTIPOINT:
+        case SHPT_MULTIPOINTM:
+        {
+            returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nPoints) );
+            if( nPoints == 0 )
+            {
+                OGRMultiPoint* poMP = new OGRMultiPoint();
+                if( bHasZ )
+                    poMP->setCoordinateDimension(3);
+                return poMP;
+            }
+
+            returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, 4) );
+
+            dx = dy = dz = 0;
+
+            OGRMultiPoint* poMP = new OGRMultiPoint();
+            XYMultiPointSetter mpSetter(poMP);
+            if( !ReadXYArray<XYMultiPointSetter>(mpSetter,
+                             pabyCur, pabyEnd, nPoints, dx, dy) )
+            {
+                delete poMP;
+                returnError();
+            }
+
+            if( bHasZ )
+            {
+                poMP->setCoordinateDimension(3);
+                ZMultiPointSetter mpzSetter(poMP);
+                if( !ReadZArray<ZMultiPointSetter>(mpzSetter,
+                                pabyCur, pabyEnd, nPoints, dz) )
+                {
+                    delete poMP;
+                    returnError();
+                }
+            }
+
+            return poMP;
+            break;
+        }
+
+        case SHPT_ARCZ:
+        case SHPT_ARCZM:
+            bHasZ = TRUE; /* go on */
+        case SHPT_ARC:
+        case SHPT_ARCM:
+        case SHPT_GENERALPOLYLINE:
+        {
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
+                              (nGeomType & 0x20000000) != 0,
+                              FALSE) );
+
+            if( nPoints == 0 || nParts == 0 )
+            {
+                OGRLineString* poLS = new OGRLineString();
+                if( bHasZ )
+                    poLS->setCoordinateDimension(3);
+                return poLS;
+            }
+
+            OGRMultiLineString* poMLS = NULL;
+            FileGDBOGRLineString* poLS = NULL;
+            if( nParts > 1 )
+                poMLS = new OGRMultiLineString();
+
+            dx = dy = dz = 0;
+            for(i=0;i<nParts;i++)
+            {
+                poLS = new FileGDBOGRLineString();
+                poLS->setNumPoints(panPointCount[i], FALSE);
+                if( nParts > 1 )
+                    poMLS->addGeometryDirectly(poLS);
+
+                XYLineStringSetter lsSetter(poLS->GetPoints());
+                if( !ReadXYArray<XYLineStringSetter>(lsSetter,
+                                 pabyCur, pabyEnd,
+                                 panPointCount[i],
+                                 dx, dy) )
+                {
+                    if( nParts > 1 )
+                        delete poMLS;
+                    else
+                        delete poLS;
+                    returnError();
+                }
+            }
+
+            if( bHasZ )
+            {
+                for(i=0;i<nParts;i++)
+                {
+                    if( nParts > 1 )
+                        poLS = (FileGDBOGRLineString*) poMLS->getGeometryRef(i);
+
+                    ZLineStringSetter lszSetter(poLS);
+                    if( !ReadZArray<ZLineStringSetter>(lszSetter,
+                                    pabyCur, pabyEnd,
+                                    panPointCount[i], dz) )
+                    {
+                        if( nParts > 1 )
+                            delete poMLS;
+                        else
+                            delete poLS;
+                        returnError();
+                    }
+                }
+            }
+
+            if( poMLS )
+                return poMLS;
+            else
+                return poLS;
+
+            break;
+        }
+
+        case SHPT_POLYGONZ:
+        case SHPT_POLYGONZM:
+            bHasZ = TRUE; /* go on */
+        case SHPT_POLYGON:
+        case SHPT_POLYGONM:
+        case SHPT_GENERALPOLYGON:
+        {
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
+                              (nGeomType & 0x20000000) != 0,
+                              FALSE) );
+
+            if( nPoints == 0 || nParts == 0 )
+            {
+                OGRPolygon* poPoly = new OGRPolygon();
+                if( bHasZ )
+                    poPoly->setCoordinateDimension(3);
+                return poPoly;
+            }
+
+            OGRLinearRing** papoRings = new OGRLinearRing*[nParts];
+
+            dx = dy = dz = 0;
+            for(i=0;i<nParts;i++)
+            {
+                FileGDBOGRLinearRing* poRing = new FileGDBOGRLinearRing();
+                papoRings[i] = poRing;
+                poRing->setNumPoints(panPointCount[i], FALSE);
+
+                XYLineStringSetter lsSetter(poRing->GetPoints());
+                if( !ReadXYArray<XYLineStringSetter>(lsSetter,
+                                 pabyCur, pabyEnd,
+                                 panPointCount[i],
+                                 dx, dy) )
+                {
+                    while( (int)i >= 0 )
+                        delete papoRings[i--];
+                    delete[] papoRings;
+                    returnError();
+                }
+            }
+
+            if( bHasZ )
+            {
+                for(i=0;i<nParts;i++)
+                {
+                    papoRings[i]->setCoordinateDimension(3);
+
+                    ZLineStringSetter lszSetter(papoRings[i]);
+                    if( !ReadZArray<ZLineStringSetter>(lszSetter,
+                                    pabyCur, pabyEnd,
+                                    panPointCount[i], dz) )
+                    {
+                        while( (int)i >= 0 )
+                            delete papoRings[i--];
+                        delete[] papoRings;
+                        returnError();
+                    }
+                }
+            }
+
+            OGRGeometry* poRet;
+            if( nParts == 1 )
+            {
+                OGRPolygon* poPoly = new OGRPolygon();
+                poRet = poPoly;
+                poPoly->addRingDirectly(papoRings[0]);
+            }
+            else
+#ifdef ASSUME_INNER_RINGS_IMMEDIATELY_AFTER_OUTER_RING
+                if( bUseOrganize || !(papoRings[0]->isClockwise()) )
+#endif
+            {
+                /* Slow method : not used by default */
+                OGRPolygon** papoPolygons = new OGRPolygon*[nParts];
+                for(i=0;i<nParts;i++)
+                {
+                    papoPolygons[i] = new OGRPolygon();
+                    papoPolygons[i]->addRingDirectly(papoRings[i]);
+                }
+                delete[] papoRings;
+                papoRings = NULL;
+                const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
+                poRet = OGRGeometryFactory::organizePolygons(
+                    (OGRGeometry**) papoPolygons, nParts, NULL, papszOptions );
+                delete[] papoPolygons;
+            }
+#ifdef ASSUME_INNER_RINGS_IMMEDIATELY_AFTER_OUTER_RING
+            else
+            {
+                /* Inner rings are CCW oriented and follow immediately the outer */
+                /* ring (that is CW oriented) in which they are included */
+                OGRMultiPolygon* poMulti = NULL;
+                OGRPolygon* poPoly = new OGRPolygon();
+                OGRPolygon* poCur = poPoly;
+                poRet = poCur;
+                /* We have already checked that the first ring is CW */
+                poPoly->addRingDirectly(papoRings[0]);
+                OGREnvelope sEnvelope;
+                papoRings[0]->getEnvelope(&sEnvelope);
+                for(i=1;i<nParts;i++)
+                {
+                    int bIsCW = papoRings[i]->isClockwise();
+                    if( bIsCW )
+                    {
+                        if( poMulti == NULL )
+                        {
+                            poMulti = new OGRMultiPolygon();
+                            poRet = poMulti;
+                            poMulti->addGeometryDirectly(poCur);
+                        }
+                        OGRPolygon* poPoly = new OGRPolygon();
+                        poCur = poPoly;
+                        poMulti->addGeometryDirectly(poCur);
+                        poPoly->addRingDirectly(papoRings[i]);
+                        papoRings[i]->getEnvelope(&sEnvelope);
+                    }
+                    else
+                    {
+                        poCur->addRingDirectly(papoRings[i]);
+                        OGRPoint oPoint;
+                        papoRings[i]->getPoint(0, &oPoint);
+                        CPLAssert(oPoint.getX() >= sEnvelope.MinX &&
+                                  oPoint.getX() <= sEnvelope.MaxX &&
+                                  oPoint.getY() >= sEnvelope.MinY &&
+                                  oPoint.getY() <= sEnvelope.MaxY);
+                    }
+                }
+            }
+#endif
+
+            delete[] papoRings;
+            return poRet;
+
+            break;
+        }
+
+        case SHPT_MULTIPATCHM:
+        case SHPT_MULTIPATCH:
+            bHasZ = TRUE; /* go on */
+        case SHPT_GENERALMULTIPATCH:
+        {
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, FALSE, TRUE ) );
+
+            if( nPoints == 0 || nParts == 0 )
+            {
+                OGRPolygon* poPoly = new OGRPolygon();
+                if( bHasZ )
+                    poPoly->setCoordinateDimension(3);
+                return poPoly;
+            }
+            int* panPartType = (int*) VSIMalloc(sizeof(int) * nParts);
+            double* padfXYZ =  (double*) VSIMalloc(3 * sizeof(double) * nPoints);
+            double* padfX = padfXYZ;
+            double* padfY = padfXYZ + nPoints;
+            double* padfZ = padfXYZ + 2 * nPoints;
+            if( panPartType == NULL || padfXYZ == NULL  )
+            {
+                VSIFree(panPartType);
+                VSIFree(padfXYZ);
+                returnError();
+            }
+            for(i=0;i<nParts;i++)
+            {
+                GUInt32 nPartType;
+                if( !ReadVarUInt32(pabyCur, pabyEnd, nPartType) )
+                {
+                    VSIFree(panPartType);
+                    VSIFree(padfXYZ);
+                    returnError();
+                }
+                panPartType[i] = (int)nPartType;
+            }
+            dx = dy = dz = 0;
+
+            XYArraySetter arraySetter(padfX, padfY);
+            if( !ReadXYArray<XYArraySetter>(arraySetter,
+                             pabyCur, pabyEnd, nPoints, dx, dy) )
+            {
+                VSIFree(panPartType);
+                VSIFree(padfXYZ);
+                returnError();
+            }
+
+            if( bHasZ )
+            {
+                ZArraySetter arrayzSetter(padfZ);
+                if( !ReadZArray<ZArraySetter>(arrayzSetter,
+                                pabyCur, pabyEnd, nPoints, dz) )
+                {
+                    VSIFree(panPartType);
+                    VSIFree(padfXYZ);
+                    returnError();
+                }
+            }
+            else
+            {
+                memset(padfZ, 0, nPoints * sizeof(double));
+            }
+
+            OGRMultiPolygon* poMP = new OGRMultiPolygon();
+            OGRPolygon* poLastPoly = NULL;
+            int iAccPoints = 0;
+            for(i=0;i<nParts;i++)
+            {
+                OGRCreateFromMultiPatchPart(poMP, poLastPoly,
+                                            panPartType[i],
+                                            (int) panPointCount[i],
+                                            padfX + iAccPoints,
+                                            padfY + iAccPoints,
+                                            padfZ + iAccPoints);
+                iAccPoints += (int) panPointCount[i];
+            }
+
+            if( poLastPoly != NULL )
+            {
+                poMP->addGeometryDirectly( poLastPoly );
+                poLastPoly = NULL;
+            }
+
+            VSIFree(panPartType);
+            VSIFree(padfXYZ);
+
+            return poMP;
+
+            break;
+        }
+
+        default:
+            CPLDebug("OpenFileGDB", "Unhandled geometry type = %d", (int)nGeomType);
+            break;
+/*
+#define SHPT_GENERALPOINT       52
+#define SHPT_GENERALMULTIPOINT  53
+*/
+    }
+    return NULL;
+}
+
+
+/************************************************************************/
+/*                           BuildConverter()                           */
+/************************************************************************/
+
+FileGDBOGRGeometryConverter* FileGDBOGRGeometryConverter::BuildConverter(
+                                        const FileGDBGeomField* poGeomField)
+{
+    return new FileGDBOGRGeometryConverterImpl(poGeomField);
+}
+
+/************************************************************************/
+/*                      GetGeometryTypeFromESRI()                       */
+/************************************************************************/
+
+static const struct
+{
+    const char          *pszStr;
+    OGRwkbGeometryType   eType;
+} AssocESRIGeomTypeToOGRGeomType[] =
+{
+    { "esriGeometryPoint", wkbPoint },
+    { "esriGeometryMultipoint", wkbMultiPoint },
+    { "esriGeometryLine", wkbMultiLineString },
+    { "esriGeometryPolyline", wkbMultiLineString },
+    { "esriGeometryPolygon", wkbMultiPolygon },
+    { "esriGeometryMultiPatch", wkbMultiPolygon }
+};
+
+OGRwkbGeometryType FileGDBOGRGeometryConverter::GetGeometryTypeFromESRI(
+                                                    const char* pszESRIType)
+{
+    for(size_t i=0;i<sizeof(AssocESRIGeomTypeToOGRGeomType)/
+                     sizeof(AssocESRIGeomTypeToOGRGeomType[0]);i++)
+    {
+        if( strcmp(pszESRIType, AssocESRIGeomTypeToOGRGeomType[i].pszStr) == 0 )
+            return AssocESRIGeomTypeToOGRGeomType[i].eType;
+    }
+    CPLDebug("OpenFileGDB", "Unhandled geometry type : %s", pszESRIType);
+    return wkbUnknown;
+}
+
+}; /* namespace OpenFileGDB */
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
new file mode 100644
index 0000000..ddaa437
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
@@ -0,0 +1,376 @@
+/******************************************************************************
+ * $Id: filegdbtable.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements reading of FileGDB tables
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _FILEGDBTABLE_H_INCLUDED
+#define _FILEGDBTABLE_H_INCLUDED
+
+#include "ogr_core.h"
+#include "cpl_vsi.h"
+#include "ogr_geometry.h"
+
+#include <string>
+#include <vector>
+
+namespace OpenFileGDB
+{
+
+/************************************************************************/
+/*                        FileGDBTableGeometryType                      */
+/************************************************************************/
+
+/* FGTGT = (F)ile(G)DB(T)able(G)eometry(T)ype */
+typedef enum
+{
+    FGTGT_NONE = 0,
+    FGTGT_POINT = 1,
+    FGTGT_MULTIPOINT = 2,
+    FGTGT_LINE = 3,
+    FGTGT_POLYGON = 4,
+    FGTGT_MULTIPATCH = 9
+} FileGDBTableGeometryType;
+
+/************************************************************************/
+/*                          FileGDBFieldType                            */
+/************************************************************************/
+
+/* FGFT = (F)ile(G)DB(F)ield(T)ype */
+typedef enum
+{
+    FGFT_UNDEFINED = -1,
+    FGFT_INT16 = 0,
+    FGFT_INT32 = 1,
+    FGFT_FLOAT32 = 2,
+    FGFT_FLOAT64 = 3,
+    FGFT_STRING = 4,
+    FGFT_DATETIME = 5,
+    FGFT_OBJECTID = 6,
+    FGFT_GEOMETRY = 7,
+    FGFT_BINARY = 8,
+    FGFT_RASTER = 9,
+    FGFT_UUID_1 = 10,
+    FGFT_UUID_2 = 11,
+    FGFT_XML = 12
+} FileGDBFieldType;
+
+/************************************************************************/
+/*                          FileGDBField                                */
+/************************************************************************/
+
+class FileGDBTable;
+class FileGDBIndex;
+
+class FileGDBField
+{
+        friend class FileGDBTable;
+
+        FileGDBTable    *poParent;
+
+        std::string      osName;
+        std::string      osAlias;
+        FileGDBFieldType eType;
+
+        int               bNullable;
+        int               nMaxWidth; /* for string */
+
+        FileGDBIndex*     poIndex;
+
+    public:
+
+                            FileGDBField(FileGDBTable* poParent);
+        virtual            ~FileGDBField();
+
+        const std::string&  GetName() const { return osName; }
+        const std::string&  GetAlias() const { return osAlias; }
+        FileGDBFieldType    GetType() const { return eType; }
+        int                 IsNullable() const { return bNullable; }
+        int                 GetMaxWidth() const { return nMaxWidth; }
+
+        int                 HasIndex();
+        FileGDBIndex       *GetIndex();
+};
+
+/************************************************************************/
+/*                         FileGDBGeomField                             */
+/************************************************************************/
+
+class FileGDBGeomField: public FileGDBField
+{
+        friend class FileGDBTable;
+
+        std::string       osWKT;
+        int               bHasZ;
+        int               bHasM;
+        double            dfXOrigin;
+        double            dfYOrigin;
+        double            dfXYScale;
+        double            dfMOrigin;
+        double            dfMScale;
+        double            dfZOrigin;
+        double            dfZScale;
+        double            dfXYTolerance;
+        double            dfMTolerance;
+        double            dfZTolerance;
+        double            dfXMin;
+        double            dfYMin;
+        double            dfXMax;
+        double            dfYMax;
+
+    public:
+                          FileGDBGeomField(FileGDBTable* poParent);
+        virtual          ~FileGDBGeomField() {}
+
+        const std::string& GetWKT() const { return osWKT; }
+
+        double             GetXMin() const { return dfXMin; }
+        double             GetYMin() const { return dfYMin; }
+        double             GetXMax() const { return dfXMax; }
+        double             GetYMax() const { return dfYMax; }
+
+        int                HasZ() const { return bHasZ; }
+        int                HasM() const { return bHasM; }
+
+        double             GetXOrigin() const { return dfXOrigin; }
+        double             GetYOrigin() const { return dfYOrigin; }
+        double             GetXYScale() const { return dfXYScale; }
+        double             GetXYTolerance() const { return dfXYTolerance; }
+
+        double             GetZOrigin() const { return dfZOrigin; }
+        double             GetZScale() const { return dfZScale; }
+        double             GetZTolerance() const { return dfZTolerance; }
+
+        double             GetMOrigin() const { return dfMOrigin; }
+        double             GetMScale() const { return dfMScale; }
+        double             GetMTolerance() const { return dfMTolerance; }
+};
+
+/************************************************************************/
+/*                         FileGDBRasterField                           */
+/************************************************************************/
+
+class FileGDBRasterField: public FileGDBGeomField
+{
+        friend class FileGDBTable;
+
+        std::string       osRasterColumnName;
+
+    public:
+                          FileGDBRasterField(FileGDBTable* poParent) : FileGDBGeomField(poParent) {}
+        virtual          ~FileGDBRasterField() {}
+
+        const std::string& GetRasterColumnName() const { return osRasterColumnName; }
+
+};
+
+/************************************************************************/
+/*                           FileGDBIndex                               */
+/************************************************************************/
+
+class FileGDBIndex
+{
+        friend class FileGDBTable;
+        std::string                 osIndexName;
+        std::string                 osFieldName;
+
+    public:
+                            FileGDBIndex() {}
+        virtual            ~FileGDBIndex() {}
+
+        const std::string&  GetIndexName() const { return osIndexName; }
+        const std::string&  GetFieldName() const { return osFieldName; }
+};
+
+/************************************************************************/
+/*                           FileGDBTable                               */
+/************************************************************************/
+
+class FileGDBTable
+{
+        VSILFILE                   *fpTable;
+        VSILFILE                   *fpTableX;
+        std::string                 osFilename;
+        std::vector<FileGDBField*>  apoFields;
+        std::string                 osObjectIdColName;
+
+        int                         bHasReadGDBIndexes;
+        std::vector<FileGDBIndex*>  apoIndexes;
+
+        GUInt32                     nOffsetFieldDesc;
+        GUInt32                     nFieldDescLength;
+
+        std::vector<GUInt32>        anFeatureOffsets;
+
+        GByte*                      pabyTablXBlockMap;
+
+        char                        achGUIDBuffer[32 + 6 + 1];
+        int                         nChSaved;
+
+        int                         bError;
+        int                         nCurRow;
+        int                         nLastCol;
+        GByte*                      pabyIterVals;
+        int                         iAccNullable;
+        GUInt32                     nRowBlobLength;
+        OGRField                    sCurField;
+        /* OGRFieldType                eCurFieldType; */
+
+        FileGDBTableGeometryType    eTableGeomType;
+        int                         nValidRecordCount;
+        int                         nTotalRecordCount;
+        int                         iGeomField;
+        int                         nCountNullableFields;
+        int                         nNullableFieldsSizeInBytes;
+
+        GUInt32                     nBufferMaxSize;
+        GByte*                      pabyBuffer;
+
+        void                        Init();
+
+        GUIntBig                    nFilterXMin, nFilterXMax, nFilterYMin, nFilterYMax;
+        
+        GUInt32                     nOffsetHeaderEnd;
+
+        int                         ReadTableXHeader();
+        int                         IsLikelyFeatureAtOffset(GUInt32 nFileSize,
+                                                GUInt32 nOffset, GUInt32* pnSize,
+                                                int* pbDeletedRecord);
+        int                         GuessFeatureLocations();
+
+    public:
+
+                                FileGDBTable();
+                               ~FileGDBTable();
+
+       int                      Open(const char* pszFilename);
+       void                     Close();
+
+       const std::string&       GetFilename() const { return osFilename; }
+       FileGDBTableGeometryType GetGeometryType() const { return eTableGeomType; }
+       int                      GetValidRecordCount() const { return nValidRecordCount; }
+       int                      GetTotalRecordCount() const { return nTotalRecordCount; }
+       int                      GetFieldCount() const { return (int)apoFields.size(); }
+       FileGDBField*            GetField(int i) const { return apoFields[i]; }
+       int                      GetGeomFieldIdx() const { return iGeomField; }
+       const FileGDBGeomField*  GetGeomField() const { return (iGeomField >= 0) ? (FileGDBGeomField*)apoFields[iGeomField] : NULL; }
+       const std::string&       GetObjectIdColName() const { return osObjectIdColName; }
+
+       int                      GetFieldIdx(const std::string& osName) const;
+
+       int                      GetIndexCount();
+       const FileGDBIndex*      GetIndex(int i) const { return apoIndexes[i]; }
+
+       GUInt32                  GetOffsetInTableForRow(int iRow);
+
+       /* Next call to SelectRow() or GetFieldValue() invalidates previously returned values */
+       int                      SelectRow(int iRow);
+       int                      HasGotError() const { return bError; }
+       int                      GetCurRow() const { return nCurRow; }
+       const OGRField*          GetFieldValue(int iCol);
+
+       int                      GetFeatureExtent(const OGRField* psGeomField,
+                                                 OGREnvelope* psOutFeatureEnvelope);
+
+       void                     InstallFilterEnvelope(const OGREnvelope* psFilterEnvelope);
+       int                      DoesGeometryIntersectsFilterEnvelope(const OGRField* psGeomField);
+};
+
+/************************************************************************/
+/*                           FileGDBSQLOp                               */
+/************************************************************************/
+
+typedef enum
+{
+    FGSO_ISNOTNULL,
+    FGSO_LT,
+    FGSO_LE,
+    FGSO_EQ,
+    FGSO_GE,
+    FGSO_GT
+} FileGDBSQLOp;
+
+/************************************************************************/
+/*                           FileGDBIterator                            */
+/************************************************************************/
+
+class FileGDBIterator
+{
+    public:
+        virtual                     ~FileGDBIterator() {}
+
+        virtual FileGDBTable        *GetTable() = 0;
+        virtual void                 Reset() = 0;
+        virtual int                  GetNextRowSortedByFID() = 0;
+        virtual int                  GetRowCount();
+
+        /* Only available on a BuildIsNotNull() iterator */
+        virtual const OGRField*      GetMinValue(int& eOutOGRFieldType);
+        virtual const OGRField*      GetMaxValue(int& eOutOGRFieldType);
+        /* will reset the iterator */
+        virtual int                  GetMinMaxSumCount(double& dfMin, double& dfMax,
+                                                       double& dfSum, int& nCount);
+
+        /* Only available on a BuildIsNotNull() or Build() iterator */
+        virtual int                  GetNextRowSortedByValue();
+
+        static FileGDBIterator*      Build(FileGDBTable* poParent,
+                                           int nFieldIdx,
+                                           int bAscending,
+                                           FileGDBSQLOp op,
+                                           OGRFieldType eOGRFieldType,
+                                           const OGRField* psValue);
+        static FileGDBIterator*      BuildIsNotNull(FileGDBTable* poParent,
+                                                    int nFieldIdx,
+                                                    int bAscending);
+        static FileGDBIterator*      BuildNot(FileGDBIterator* poIterBase);
+        static FileGDBIterator*      BuildAnd(FileGDBIterator* poIter1,
+                                              FileGDBIterator* poIter2);
+        static FileGDBIterator*      BuildOr(FileGDBIterator* poIter1,
+                                             FileGDBIterator* poIter2,
+                                             int bIteratorAreExclusive = FALSE);
+};
+
+/************************************************************************/
+/*                       FileGDBOGRGeometryConverter                    */
+/************************************************************************/
+
+class FileGDBOGRGeometryConverter
+{
+    public:
+       virtual                            ~FileGDBOGRGeometryConverter() {}
+
+       virtual OGRGeometry*                GetAsGeometry(const OGRField* psField) = 0;
+
+       static FileGDBOGRGeometryConverter* BuildConverter(const FileGDBGeomField* poGeomField);
+       static OGRwkbGeometryType           GetGeometryTypeFromESRI(const char* pszESRIGeometyrType);
+};
+
+int FileGDBDoubleDateToOGRDate(double dfVal, OGRField* psField);
+
+}; /* namespace OpenFileGDB */
+
+#endif /* ndef _FILEGDBTABLE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h
new file mode 100644
index 0000000..b9cd381
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * $Id: filegdbtable_priv.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements reading of FileGDB tables
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _FILEGDBTABLE_PRIV_H_INCLUDED
+#define _FILEGDBTABLE_PRIV_H_INCLUDED
+
+#include "filegdbtable.h"
+#include "cpl_error.h"
+
+namespace OpenFileGDB
+{
+
+/************************************************************************/
+/*                              GetInt16()                              */
+/************************************************************************/
+
+static GInt16 GetInt16(const GByte* pBaseAddr, int iOffset)
+{
+    GInt16 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR16(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                              GetUInt16()                             */
+/************************************************************************/
+
+static GUInt16 GetUInt16(const GByte* pBaseAddr, int iOffset)
+{
+    GUInt16 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR16(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                              GetInt32()                              */
+/************************************************************************/
+
+static GInt32 GetInt32(const GByte* pBaseAddr, int iOffset)
+{
+    GInt32 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR32(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                              GetUInt32()                             */
+/************************************************************************/
+
+static GUInt32 GetUInt32(const GByte* pBaseAddr, int iOffset)
+{
+    GUInt32 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR32(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                             GetFloat32()                             */
+/************************************************************************/
+
+static float GetFloat32(const GByte* pBaseAddr, int iOffset)
+{
+    float fVal;
+    memcpy(&fVal, pBaseAddr + sizeof(fVal) * iOffset, sizeof(fVal));
+    CPL_LSBPTR32(&fVal);
+    return fVal;
+}
+
+/************************************************************************/
+/*                             GetFloat64()                             */
+/************************************************************************/
+
+static double GetFloat64(const GByte* pBaseAddr, int iOffset)
+{
+    double dfVal;
+    memcpy(&dfVal, pBaseAddr + sizeof(dfVal) * iOffset, sizeof(dfVal));
+    CPL_LSBPTR64(&dfVal);
+    return dfVal;
+}
+
+void FileGDBTablePrintError(const char* pszFile, int nLineNumber);
+
+#define PrintError()        FileGDBTablePrintError(__FILE__, __LINE__)
+
+/************************************************************************/
+/*                          returnError()                               */
+/************************************************************************/
+
+#define returnError() \
+    do { PrintError(); return (errorRetValue); } while(0)
+
+/************************************************************************/
+/*                         returnErrorIf()                              */
+/************************************************************************/
+
+#define returnErrorIf(expr) \
+    do { if( (expr) ) returnError(); } while(0)
+
+/************************************************************************/
+/*                       returnErrorAndCleanupIf()                      */
+/************************************************************************/
+
+#define returnErrorAndCleanupIf(expr, cleanup) \
+    do { if( (expr) ) { cleanup; returnError(); } } while(0)
+
+}; /* namespace OpenFileGDB */
+
+#endif /* _FILEGDBTABLE_PRIV_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/makefile.vc b/ogr/ogrsf_frmts/openfilegdb/makefile.vc
new file mode 100644
index 0000000..dd30436
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	ogropenfilegdbdriver.obj ogropenfilegdbdatasource.obj ogropenfilegdblayer.obj filegdbtable.obj filegdbindex.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS =	-I.. -I..\.. -I..\mem
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
new file mode 100644
index 0000000..03acd75
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
@@ -0,0 +1,205 @@
+/******************************************************************************
+* $Id: ogr_openfilegdb.h 27044 2014-03-16 23:41:27Z rouault $
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Implements Open FileGDB OGR driver.
+* Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+*
+******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#ifndef _OGR_OPENFILEGDB_H_INCLUDED
+#define _OGR_OPENFILEGDB_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "filegdbtable.h"
+#include "swq.h"
+#include "cpl_quad_tree.h"
+
+#include <vector>
+#include <map>
+
+using namespace OpenFileGDB;
+
+/************************************************************************/
+/*                      OGROpenFileGDBLayer                             */
+/************************************************************************/
+
+class OGROpenFileGDBDataSource;
+class OGROpenFileGDBGeomFieldDefn;
+class OGROpenFileGDBFeatureDefn;
+
+typedef enum
+{
+    SPI_IN_BUILDING,
+    SPI_COMPLETED,
+    SPI_INVALID,
+} SPIState;
+
+class OGROpenFileGDBLayer : public OGRLayer
+{
+    friend class OGROpenFileGDBGeomFieldDefn;
+    friend class OGROpenFileGDBFeatureDefn;
+
+    CPLString         m_osGDBFilename;
+    CPLString         m_osName;
+    FileGDBTable     *m_poLyrTable;
+    OGROpenFileGDBFeatureDefn   *m_poFeatureDefn;
+    int               m_iGeomFieldIdx;
+    int               m_iCurFeat;
+    std::string       m_osDefinition;
+    std::string       m_osDocumentation;
+    std::string       m_osFIDName;
+    OGRwkbGeometryType m_eGeomType;
+    int               m_bValidLayerDefn;
+    int               m_bEOF;
+
+    int               BuildLayerDefinition();
+    int               BuildGeometryColumnGDBv10();
+    OGRFeature       *GetCurrentFeature();
+
+    FileGDBOGRGeometryConverter* m_poGeomConverter;
+    
+    int               m_iFieldToReadAsBinary;
+
+    FileGDBIterator      *m_poIterator;
+    int                   m_bIteratorSufficientToEvaluateFilter;
+    FileGDBIterator*      BuildIteratorFromExprNode(swq_expr_node* poNode);
+
+    FileGDBIterator*      m_poIterMinMax;
+
+    SPIState            m_eSpatialIndexState;
+    CPLQuadTree        *m_pQuadTree;
+    void              **m_pahFilteredFeatures;
+    int                 m_nFilteredFeatureCount;
+    static void         GetBoundsFuncEx(const void* hFeature,
+                                        CPLRectObj* pBounds,
+                                        void* pQTUserData);
+
+public:
+
+                        OGROpenFileGDBLayer(const char* pszGDBFilename,
+                                            const char* pszName,
+                                            const std::string& osDefinition,
+                                            const std::string& osDocumentation,
+                                            const char* pszGeomName = NULL,
+                                            OGRwkbGeometryType eGeomType = wkbUnknown);
+  virtual              ~OGROpenFileGDBLayer();
+  
+  const std::string&    GetXMLDefinition() { return m_osDefinition; }
+  const std::string&    GetXMLDocumentation() { return m_osDocumentation; }
+  int                   GetAttrIndexUse() { return (m_poIterator == NULL) ? 0 : (m_bIteratorSufficientToEvaluateFilter) ? 2 : 1; }
+  const OGRField*       GetMinMaxValue(OGRFieldDefn* poFieldDefn, int bIsMin,
+                                       int& eOutType);
+  int                   GetMinMaxSumCount(OGRFieldDefn* poFieldDefn,
+                                          double& dfMin, double& dfMax,
+                                          double& dfSum, int& nCount);
+  int                   HasIndexForField(const char* pszFieldName);
+  FileGDBIterator*      BuildIndex(const char* pszFieldName,
+                                   int bAscending,
+                                   swq_op op,
+                                   swq_expr_node* poValue);
+  SPIState              GetSpatialIndexState() const { return m_eSpatialIndexState; }
+
+  virtual const char* GetName() { return m_osName.c_str(); }
+  virtual OGRwkbGeometryType GetGeomType();
+
+  virtual const char* GetFIDColumn();
+
+  virtual void        ResetReading();
+  virtual OGRFeature* GetNextFeature();
+  virtual OGRFeature* GetFeature( long nFeatureId );
+  virtual OGRErr      SetNextByIndex( long nIndex );
+
+  virtual int         GetFeatureCount( int bForce = TRUE );
+  virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+  virtual OGRFeatureDefn* GetLayerDefn();
+
+  virtual void        SetSpatialFilter( OGRGeometry * );
+
+  virtual OGRErr      SetAttributeFilter( const char* pszFilter );
+
+  virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                       OGROpenFileGDBDataSource                       */
+/************************************************************************/
+
+class OGROpenFileGDBDataSource : public OGRDataSource
+{
+  char                          *m_pszName;
+  CPLString                      m_osDirName;
+  std::vector <OGRLayer*>        m_apoLayers;
+  std::vector <OGRLayer*>        m_apoHiddenLayers;
+  char                         **m_papszFiles;
+  std::map<std::string, int>     m_osMapNameToIdx;
+
+  /* For debugging/testing */
+  int                            bLastSQLUsedOptimizedImplementation;
+
+  int                 OpenFileGDBv10(int iGDBItems,
+                                     int nInterestTable);
+  int                 OpenFileGDBv9 (int iGDBFeatureClasses,
+                                     int iGDBObjectClasses,
+                                     int nInterestTable);
+
+  int                 FileExists(const char* pszFilename);
+
+public:
+           OGROpenFileGDBDataSource();
+  virtual ~OGROpenFileGDBDataSource();
+
+  int                 Open(const char * );
+
+  virtual const char* GetName() { return m_pszName; }
+  virtual int         GetLayerCount() { return static_cast<int>(m_apoLayers.size()); }
+
+  virtual OGRLayer*   GetLayer( int );
+  virtual OGRLayer*   GetLayerByName( const char* pszName );
+
+  virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                  OGRGeometry *poSpatialFilter,
+                                  const char *pszDialect );
+  virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
+
+  virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                        OGROpenFileGDBDriver                          */
+/************************************************************************/
+
+class OGROpenFileGDBDriver : public OGRSFDriver
+{
+public:
+  virtual ~OGROpenFileGDBDriver();
+
+  virtual const char *GetName();
+  virtual OGRDataSource *Open( const char *, int );
+  virtual int TestCapability( const char * );
+};
+
+int OGROpenFileGDBIsComparisonOp(int op);
+
+#endif /* ndef _OGR_OPENFILEGDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
new file mode 100644
index 0000000..e759e29
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
@@ -0,0 +1,1147 @@
+/******************************************************************************
+ * $Id: ogropenfilegdbdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements Open FileGDB OGR driver.
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_openfilegdb.h"
+#include "ogr_mem.h"
+#include <map>
+
+CPL_CVSID("$Id");
+
+/************************************************************************/
+/*                      OGROpenFileGDBDataSource()                      */
+/************************************************************************/
+OGROpenFileGDBDataSource::OGROpenFileGDBDataSource()
+{
+    m_pszName = NULL;
+    m_papszFiles = NULL;
+    bLastSQLUsedOptimizedImplementation = FALSE;
+}
+
+/************************************************************************/
+/*                     ~OGROpenFileGDBDataSource()                      */
+/************************************************************************/
+OGROpenFileGDBDataSource::~OGROpenFileGDBDataSource()
+
+{
+    size_t i;
+    for( i = 0; i < m_apoLayers.size(); i++ )
+        delete m_apoLayers[i];
+    for( i = 0; i < m_apoHiddenLayers.size(); i++ )
+        delete m_apoHiddenLayers[i];
+    CPLFree(m_pszName);
+    CSLDestroy(m_papszFiles);
+}
+
+/************************************************************************/
+/*                             FileExists()                             */
+/************************************************************************/
+
+int OGROpenFileGDBDataSource::FileExists(const char* pszFilename)
+{
+    if( m_papszFiles )
+        return CSLFindString(m_papszFiles, CPLGetFilename(pszFilename)) >= 0;
+    else
+    {
+        VSIStatBufL sStat;
+        return VSIStatExL(pszFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
+    }
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGROpenFileGDBDataSource::Open( const char* pszFilename )
+
+{
+    FileGDBTable oTable;
+
+    m_pszName = CPLStrdup(pszFilename);
+
+    m_osDirName = pszFilename;
+    int nInterestTable = -1;
+    const char* pszFilenameWithoutPath = CPLGetFilename(pszFilename);
+    if( strlen(pszFilenameWithoutPath) == strlen("a00000000.gdbtable") &&
+        pszFilenameWithoutPath[0] == 'a' &&
+        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &nInterestTable) == 1 )
+    {
+        m_osDirName = CPLGetPath(m_osDirName);
+    }
+    else
+    {
+        nInterestTable = -1;
+    }
+
+    if( EQUAL(CPLGetExtension(m_osDirName), "zip") &&
+        strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) != 0 )
+    {
+        m_osDirName = "/vsizip/" + m_osDirName;
+    }
+    else  if( EQUAL(CPLGetExtension(m_osDirName), "tar") &&
+        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) != 0 )
+    {
+        m_osDirName = "/vsitar/" + m_osDirName;
+    }
+
+    if( strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) == 0 ||
+        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) == 0)
+    {
+        /* Look for one subdirectory ending with .gdb extension */
+        char** papszDir = CPLReadDir(m_osDirName);
+        int iCandidate = -1;
+        for( int i=0; papszDir && papszDir[i] != NULL; i++ )
+        {
+            VSIStatBufL sStat;
+            if( EQUAL(CPLGetExtension(papszDir[i]), "gdb") &&
+                VSIStatL( CPLSPrintf("%s/%s", m_osDirName.c_str(), papszDir[i]), &sStat ) == 0 &&
+                VSI_ISDIR(sStat.st_mode) )
+            {
+                if( iCandidate < 0 )
+                    iCandidate = i;
+                else
+                {
+                    iCandidate = -1;
+                    break;
+                }
+            }
+        }
+        if( iCandidate >= 0 )
+        {
+            m_osDirName += "/";
+            m_osDirName += papszDir[iCandidate];
+        }
+        CSLDestroy(papszDir);
+    }
+
+    m_papszFiles = VSIReadDir(m_osDirName);
+
+    /* Explore catalog table */
+    const char* psza00000001 = CPLFormFilename(m_osDirName, "a00000001", "gdbtable");
+    if( !FileExists(psza00000001) || !oTable.Open(psza00000001) )
+    {
+        if( nInterestTable >= 0 && FileExists(m_pszName) )
+        {
+            const char* pszLyrName = CPLSPrintf("a%08x", nInterestTable);
+            OGROpenFileGDBLayer* poLayer = new OGROpenFileGDBLayer(
+                                m_pszName, pszLyrName, "", "");
+            const char* pszTablX = CPLResetExtension(m_pszName, "gdbtablx");
+            if( !FileExists(pszTablX) &&
+                poLayer->GetLayerDefn()->GetFieldCount() == 0 &&
+                poLayer->GetFeatureCount() == 0 )
+            {
+                delete poLayer;
+                return FALSE;
+            }
+            m_apoLayers.push_back(poLayer);
+            return TRUE;
+        }
+        return FALSE;
+    }
+
+    if( !(oTable.GetFieldCount() >= 2 &&
+          oTable.GetField(0)->GetName() == "Name" &&
+          oTable.GetField(0)->GetType() == FGFT_STRING &&
+          oTable.GetField(1)->GetName() == "FileFormat" &&
+          (oTable.GetField(1)->GetType() == FGFT_INT16 ||
+           oTable.GetField(1)->GetType() == FGFT_INT32) ) )
+    {
+        return FALSE;
+    }
+
+    int iGDBItems = -1; /* V10 */
+    int iGDBFeatureClasses = -1; /* V9.X */
+    int iGDBObjectClasses = -1; /* V9.X */
+    int i;
+
+    std::vector<std::string> aosTableNames;
+    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    {
+        if( !oTable.SelectRow(i) )
+        {
+            if( oTable.HasGotError() )
+                break;
+            aosTableNames.push_back("");
+            continue;
+        }
+
+        const OGRField* psField = oTable.GetFieldValue(0);
+        if( psField != NULL )
+        {
+            aosTableNames.push_back(psField->String);
+
+            if( strcmp(psField->String, "GDB_Items") == 0 )
+            {
+                iGDBItems = i;
+            }
+            else if( strcmp(psField->String, "GDB_FeatureClasses") == 0 )
+            {
+                iGDBFeatureClasses = i;
+            }
+            else if( strcmp(psField->String, "GDB_ObjectClasses") == 0 )
+            {
+                iGDBObjectClasses = i;
+            }
+            m_osMapNameToIdx[psField->String] = 1 + i;
+        }
+        else
+        {
+            aosTableNames.push_back("");
+        }
+    }
+
+    oTable.Close();
+
+    if( iGDBItems >= 0 )
+    {
+        int bRet = OpenFileGDBv10(iGDBItems,
+                                  nInterestTable);
+        if( !bRet )
+            return FALSE;
+    }
+    else if( iGDBFeatureClasses >= 0 && iGDBObjectClasses >= 0 )
+    {
+        int bRet = OpenFileGDBv9(iGDBFeatureClasses,
+                                 iGDBObjectClasses,
+                                 nInterestTable);
+        if( !bRet )
+            return FALSE;
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No GDB_Items nor GDB_FeatureClasses table");
+        return FALSE;
+    }
+
+    if( m_apoLayers.size() == 0 && nInterestTable >= 0 )
+    {
+        if( FileExists(m_pszName) )
+        {
+            const char* pszLyrName;
+            if( nInterestTable <= (int)aosTableNames.size()  &&
+                aosTableNames[nInterestTable-1].size() != 0 )
+                pszLyrName = aosTableNames[nInterestTable-1].c_str();
+            else
+                pszLyrName = CPLSPrintf("a%08x", nInterestTable);
+            m_apoLayers.push_back(new OGROpenFileGDBLayer(
+                m_pszName, pszLyrName, "", ""));
+        }
+        else
+        {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************/
+/*                         OpenFileGDBv10()                            */
+/***********************************************************************/
+
+int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
+                                             int nInterestTable)
+{
+    FileGDBTable oTable;
+    int i;
+
+    CPLDebug("OpenFileGDB", "FileGDB v10 or later");
+
+    if( !oTable.Open(CPLFormFilename(m_osDirName,
+            CPLSPrintf("a%08x.gdbtable", iGDBItems + 1), NULL)) )
+        return FALSE;
+
+    int iName = oTable.GetFieldIdx("Name");
+    int iDefinition = oTable.GetFieldIdx("Definition");
+    int iDocumentation = oTable.GetFieldIdx("Documentation");
+    if( iName < 0 || iDefinition < 0 || iDocumentation < 0 ||
+        oTable.GetField(iName)->GetType() != FGFT_STRING ||
+        oTable.GetField(iDefinition)->GetType() != FGFT_XML ||
+        oTable.GetField(iDocumentation)->GetType() != FGFT_XML )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Wrong structure for GDB_Items table");
+        return FALSE;
+    }
+
+    int nCandidateLayers = 0, nLayersSDC = 0;
+    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    {
+        if( !oTable.SelectRow(i) )
+        {
+            if( oTable.HasGotError() )
+                break;
+            continue;
+        }
+
+        const OGRField* psField = oTable.GetFieldValue(iDefinition);
+        if( psField != NULL &&
+            (strstr(psField->String, "DEFeatureClassInfo") != NULL ||
+                strstr(psField->String, "DETableInfo") != NULL) )
+        {
+            CPLString osDefinition(psField->String);
+
+            psField = oTable.GetFieldValue(iDocumentation);
+            CPLString osDocumentation( psField != NULL ? psField->String : "" );
+
+            psField = oTable.GetFieldValue(iName);
+            if( psField != NULL )
+            {
+                std::map<std::string, int>::const_iterator oIter =
+                                            m_osMapNameToIdx.find(psField->String);
+                int idx = 0;
+                if( oIter != m_osMapNameToIdx.end() )
+                    idx = oIter->second;
+                if( idx > 0 && (nInterestTable < 0 || nInterestTable == idx) )
+                {
+                    const char* pszFilename = CPLFormFilename(
+                        m_osDirName, CPLSPrintf("a%08x", idx), "gdbtable");
+                    if( FileExists(pszFilename) )
+                    {
+                        nCandidateLayers ++;
+
+                        if( m_papszFiles != NULL )
+                        {
+                            const char* pszSDC = CPLResetExtension(pszFilename, "gdbtable.sdc");
+                            if( FileExists(pszSDC) )
+                            {
+                                nLayersSDC ++;
+                                CPLError(CE_Warning, CPLE_AppDefined,
+                                        "%s layer has a %s file whose format is unhandled",
+                                        psField->String, pszSDC);
+                                continue;
+                            }
+                        }
+
+                        m_apoLayers.push_back(
+                            new OGROpenFileGDBLayer(pszFilename,
+                                                    psField->String,
+                                                    osDefinition,
+                                                    osDocumentation));
+                    }
+                }
+            }
+        }
+    }
+
+    if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
+        nCandidateLayers == nLayersSDC )
+        return FALSE;
+
+    return TRUE;
+}
+
+/***********************************************************************/
+/*                         OpenFileGDBv9()                             */
+/***********************************************************************/
+
+int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
+                                            int iGDBObjectClasses,
+                                            int nInterestTable)
+{
+    FileGDBTable oTable;
+    int i;
+
+    CPLDebug("OpenFileGDB", "FileGDB v9");
+
+    /* Fetch names of layers */
+    if( !oTable.Open(CPLFormFilename(m_osDirName,
+            CPLSPrintf("a%08x", iGDBObjectClasses + 1), "gdbtable")) )
+        return FALSE;
+
+    int iName = oTable.GetFieldIdx("Name");
+    if( iName < 0 ||
+        oTable.GetField(iName)->GetType() != FGFT_STRING )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Wrong structure for GDB_ObjectClasses table");
+        return FALSE;
+    }
+    std::vector<std::string> aosNames;
+    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    {
+        if( !oTable.SelectRow(i) )
+        {
+            if( oTable.HasGotError() )
+                break;
+            aosNames.push_back("");
+            continue;
+        }
+
+        const OGRField* psField = oTable.GetFieldValue(iName);
+        if( psField != NULL )
+        {
+            aosNames.push_back(psField->String);
+        }
+    }
+    oTable.Close();
+
+    /* Find tables that are layers */
+    if( !oTable.Open(CPLFormFilename(m_osDirName,
+            CPLSPrintf("a%08x", iGDBFeatureClasses + 1), "gdbtable")) )
+        return FALSE;
+
+    int iObjectClassID = oTable.GetFieldIdx("ObjectClassID");
+    int iGeometryType = oTable.GetFieldIdx("GeometryType");
+    int iShapeField = oTable.GetFieldIdx("ShapeField");
+    if( iObjectClassID < 0 || iGeometryType < 0 || iShapeField < 0 ||
+        oTable.GetField(iObjectClassID)->GetType() != FGFT_INT32 ||
+        oTable.GetField(iGeometryType)->GetType() != FGFT_INT32 ||
+        oTable.GetField(iShapeField)->GetType() != FGFT_STRING )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Wrong structure for GDB_FeatureClasses table");
+        return FALSE;
+    }
+
+    int nCandidateLayers = 0, nLayersSDC = 0;
+    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    {
+        if( !oTable.SelectRow(i) )
+        {
+            if( oTable.HasGotError() )
+                break;
+            continue;
+        }
+
+        const OGRField* psField;
+
+        psField = oTable.GetFieldValue(iGeometryType);
+        if( psField == NULL )
+            continue;
+        int nGeomType = psField->Integer;
+        OGRwkbGeometryType eGeomType = wkbUnknown;
+        switch( nGeomType )
+        {
+            case FGTGT_NONE: /* doesn't make sense ! */ break;
+            case FGTGT_POINT: eGeomType = wkbPoint; break;
+            case FGTGT_MULTIPOINT: eGeomType = wkbMultiPoint; break;
+            case FGTGT_LINE: eGeomType = wkbMultiLineString; break;
+            case FGTGT_POLYGON: eGeomType = wkbMultiPolygon; break;
+            case FGTGT_MULTIPATCH: eGeomType = wkbMultiPolygon; break;
+        }
+
+        psField = oTable.GetFieldValue(iShapeField);
+        if( psField == NULL )
+            continue;
+        CPLString osGeomFieldName(psField->String);
+
+        psField = oTable.GetFieldValue(iObjectClassID);
+        if( psField == NULL )
+            continue;
+
+        int idx = psField->Integer;
+        if( psField != NULL && idx > 0 && idx <= (int)aosNames.size() &&
+            aosNames[idx-1].size() > 0 )
+        {
+            const std::string osName(aosNames[idx-1]);
+            std::map<std::string, int>::const_iterator oIter =
+                                                m_osMapNameToIdx.find(osName);
+            idx = 0;
+            if( oIter != m_osMapNameToIdx.end() )
+                idx = oIter->second;
+
+            if( idx > 0 && ( nInterestTable < 0 || nInterestTable == idx) )
+            {
+                const char* pszFilename = CPLFormFilename(
+                            m_osDirName, CPLSPrintf("a%08x", idx), "gdbtable");
+                if( FileExists(pszFilename) )
+                {
+                    nCandidateLayers ++;
+
+                    if( m_papszFiles != NULL )
+                    {
+                        const char* pszSDC = CPLResetExtension(pszFilename, "gdbtable.sdc");
+                        if( FileExists(pszSDC) )
+                        {
+                            nLayersSDC ++;
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                    "%s layer has a %s file whose format is unhandled",
+                                    osName.c_str(), pszSDC);
+                            continue;
+                        }
+                    }
+
+                    m_apoLayers.push_back(new OGROpenFileGDBLayer(
+                        pszFilename, osName.c_str(), "", "",
+                        osGeomFieldName.c_str(), eGeomType));
+                }
+            }
+        }
+    }
+
+    if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
+        nCandidateLayers == nLayersSDC )
+        return FALSE;
+
+    return TRUE;
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int OGROpenFileGDBDataSource::TestCapability( const char * pszCap )
+{
+    (void)pszCap;
+    return FALSE;
+}
+
+/***********************************************************************/
+/*                            GetLayer()                               */
+/***********************************************************************/
+
+OGRLayer* OGROpenFileGDBDataSource::GetLayer( int iIndex )
+{
+    if( iIndex < 0 || iIndex >= (int) m_apoLayers.size() )
+        return NULL;
+    return m_apoLayers[iIndex];
+}
+
+/***********************************************************************/
+/*                          GetLayerByName()                           */
+/***********************************************************************/
+
+OGRLayer* OGROpenFileGDBDataSource::GetLayerByName( const char* pszName )
+{
+    OGRLayer* poLayer;
+
+    poLayer = OGRDataSource::GetLayerByName(pszName);
+    if( poLayer != NULL )
+        return poLayer;
+
+    for(size_t i=0;i<m_apoHiddenLayers.size();i++)
+    {
+        if( EQUAL(m_apoHiddenLayers[i]->GetName(), pszName) )
+            return m_apoHiddenLayers[i];
+    }
+
+    std::map<std::string, int>::const_iterator oIter = m_osMapNameToIdx.find(pszName);
+    if( oIter != m_osMapNameToIdx.end() )
+    {
+        int idx = oIter->second;
+        const char* pszFilename = CPLFormFilename(
+                            m_osDirName, CPLSPrintf("a%08x", idx), "gdbtable");
+        if( FileExists(pszFilename) )
+        {
+            poLayer = new OGROpenFileGDBLayer(
+                                    pszFilename, pszName, "", "");
+            m_apoHiddenLayers.push_back(poLayer);
+            return poLayer;
+        }
+    }
+    return NULL;
+}
+
+
+/************************************************************************/
+/*                   OGROpenFileGDBSingleFeatureLayer                   */
+/************************************************************************/
+
+class OGROpenFileGDBSingleFeatureLayer : public OGRLayer
+{
+  private:
+    char               *pszVal;
+    OGRFeatureDefn     *poFeatureDefn;
+    int                 iNextShapeId;
+
+  public:
+                        OGROpenFileGDBSingleFeatureLayer( const char* pszLayerName,
+                                                          const char *pszVal );
+                        ~OGROpenFileGDBSingleFeatureLayer();
+
+    virtual void        ResetReading() { iNextShapeId = 0; }
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+    virtual int         TestCapability( const char * ) { return FALSE; }
+};
+
+/************************************************************************/
+/*                 OGROpenFileGDBSingleFeatureLayer()                   */
+/************************************************************************/
+
+OGROpenFileGDBSingleFeatureLayer::OGROpenFileGDBSingleFeatureLayer(const char* pszLayerName,
+                                                                   const char *pszVal )
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    poFeatureDefn->Reference();
+    OGRFieldDefn oField( "FIELD_1", OFTString );
+    poFeatureDefn->AddFieldDefn( &oField );
+
+    iNextShapeId = 0;
+    this->pszVal = pszVal ? CPLStrdup(pszVal) : NULL;
+}
+
+/************************************************************************/
+/*                 ~OGROpenFileGDBSingleFeatureLayer()                  */
+/************************************************************************/
+
+OGROpenFileGDBSingleFeatureLayer::~OGROpenFileGDBSingleFeatureLayer()
+{
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+    CPLFree(pszVal);
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature * OGROpenFileGDBSingleFeatureLayer::GetNextFeature()
+{
+    if (iNextShapeId != 0)
+        return NULL;
+
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    if (pszVal)
+        poFeature->SetField(0, pszVal);
+    poFeature->SetFID(iNextShapeId ++);
+    return poFeature;
+}
+
+/***********************************************************************/
+/*                     OGROpenFileGDBSimpleSQLLayer                    */
+/***********************************************************************/
+
+class OGROpenFileGDBSimpleSQLLayer: public OGRLayer
+{
+        OGRLayer        *poBaseLayer;
+        FileGDBIterator *poIter;
+        OGRFeatureDefn  *poFeatureDefn;
+
+    public:
+        OGROpenFileGDBSimpleSQLLayer(OGRLayer* poBaseLayer,
+                                     FileGDBIterator* poIter,
+                                     int nColumns,
+                                     swq_col_def* pasColDefs);
+       ~OGROpenFileGDBSimpleSQLLayer();
+
+       virtual void        ResetReading();
+       virtual OGRFeature* GetNextFeature();
+       virtual OGRFeature* GetFeature( long nFeatureId );
+       virtual OGRFeatureDefn* GetLayerDefn() { return poFeatureDefn; }
+       virtual int         TestCapability( const char * );
+       virtual const char* GetFIDColumn() { return poBaseLayer->GetFIDColumn(); }
+       virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce )
+                            { return poBaseLayer->GetExtent(psExtent, bForce); }
+       virtual int         GetFeatureCount(int bForce);
+};
+
+/***********************************************************************/
+/*                    OGROpenFileGDBSimpleSQLLayer()                   */
+/***********************************************************************/
+
+OGROpenFileGDBSimpleSQLLayer::OGROpenFileGDBSimpleSQLLayer(
+                                            OGRLayer* poBaseLayer,
+                                            FileGDBIterator* poIter,
+                                            int nColumns,
+                                            swq_col_def* pasColDefs) :
+        poBaseLayer(poBaseLayer), poIter(poIter)
+{
+    if( nColumns == 1 && strcmp(pasColDefs[0].field_name, "*") == 0 )
+    {
+        poFeatureDefn = poBaseLayer->GetLayerDefn();
+        poFeatureDefn->Reference();
+    }
+    else
+    {
+        poFeatureDefn = new OGRFeatureDefn(poBaseLayer->GetName());
+        poFeatureDefn->SetGeomType(poBaseLayer->GetGeomType());
+        poFeatureDefn->Reference();
+        if( poBaseLayer->GetGeomType() != wkbNone )
+        {
+            poFeatureDefn->GetGeomFieldDefn(0)->SetName(poBaseLayer->GetGeometryColumn());
+            poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poBaseLayer->GetSpatialRef());
+        }
+        for(int i=0;i<nColumns;i++)
+        {
+            if( strcmp(pasColDefs[i].field_name, "*") == 0 )
+            {
+                for(int j=0;j<poBaseLayer->GetLayerDefn()->GetFieldCount();j++)
+                    poFeatureDefn->AddFieldDefn(poBaseLayer->GetLayerDefn()->GetFieldDefn(j));
+            }
+            else
+            {
+                OGRFieldDefn* poFieldDefn = poBaseLayer->GetLayerDefn()->GetFieldDefn(
+                    poBaseLayer->GetLayerDefn()->GetFieldIndex(pasColDefs[i].field_name));
+                CPLAssert(poFieldDefn != NULL ); /* already checked before */
+                poFeatureDefn->AddFieldDefn(poFieldDefn);
+            }
+        }
+    }
+    ResetReading();
+}
+
+/***********************************************************************/
+/*                   ~OGROpenFileGDBSimpleSQLLayer()                   */
+/***********************************************************************/
+
+OGROpenFileGDBSimpleSQLLayer::~OGROpenFileGDBSimpleSQLLayer()
+{
+    if( poFeatureDefn )
+    {
+        poFeatureDefn->Release();
+    }
+    delete poIter;
+}
+
+/***********************************************************************/
+/*                          ResetReading()                             */
+/***********************************************************************/
+
+void OGROpenFileGDBSimpleSQLLayer::ResetReading()
+{
+    poIter->Reset();
+}
+
+/***********************************************************************/
+/*                          GetFeature()                               */
+/***********************************************************************/
+
+OGRFeature* OGROpenFileGDBSimpleSQLLayer::GetFeature( long nFeatureId )
+{
+    OGRFeature* poSrcFeature = poBaseLayer->GetFeature(nFeatureId);
+    if( poSrcFeature == NULL )
+        return NULL;
+
+    if( poFeatureDefn == poBaseLayer->GetLayerDefn() )
+        return poSrcFeature;
+    else
+    {
+        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+        poFeature->SetFrom(poSrcFeature);
+        poFeature->SetFID(poSrcFeature->GetFID());
+        delete poSrcFeature;
+        return poFeature;
+    }
+}
+
+/***********************************************************************/
+/*                         GetNextFeature()                            */
+/***********************************************************************/
+
+OGRFeature* OGROpenFileGDBSimpleSQLLayer::GetNextFeature()
+{
+    while(TRUE)
+    {
+        int nRow = poIter->GetNextRowSortedByValue();
+        if( nRow < 0 )
+            return NULL;
+        OGRFeature* poFeature = GetFeature(nRow + 1);
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL ||
+                m_poAttrQuery->Evaluate( poFeature ) ) )
+        {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
+
+/***********************************************************************/
+/*                         GetFeatureCount()                           */
+/***********************************************************************/
+
+int OGROpenFileGDBSimpleSQLLayer::GetFeatureCount( int bForce )
+{
+
+    /* No filter */
+    if( m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+    {
+        return poIter->GetRowCount();
+    }
+
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int OGROpenFileGDBSimpleSQLLayer::TestCapability( const char * pszCap )
+{
+
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
+    {
+        return( m_poFilterGeom == NULL && m_poAttrQuery == NULL );
+    }
+    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCRandomRead) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    {
+        return TRUE; /* ? */
+    }
+
+    return FALSE;
+}
+
+/***********************************************************************/
+/*                            ExecuteSQL()                             */
+/***********************************************************************/
+
+OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                                OGRGeometry *poSpatialFilter,
+                                                const char *pszDialect )
+{
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerDefinition                                 */
+/* -------------------------------------------------------------------- */
+    if (EQUALN(pszSQLCommand, "GetLayerDefinition ", strlen("GetLayerDefinition ")))
+    {
+        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
+            GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
+        if (poLayer)
+        {
+            OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
+                "LayerDefinition", poLayer->GetXMLDefinition().c_str() );
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerMetadata                                   */
+/* -------------------------------------------------------------------- */
+    if (EQUALN(pszSQLCommand, "GetLayerMetadata ", strlen("GetLayerMetadata ")))
+    {
+        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
+            GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
+        if (poLayer)
+        {
+            OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
+                "LayerMetadata", poLayer->GetXMLDocumentation().c_str() );
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerAttrIndexUse (only for debugging purposes) */
+/* -------------------------------------------------------------------- */
+    if (EQUALN(pszSQLCommand, "GetLayerAttrIndexUse ", strlen("GetLayerAttrIndexUse ")))
+    {
+        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
+            GetLayerByName(pszSQLCommand + strlen("GetLayerAttrIndexUse "));
+        if (poLayer)
+        {
+            OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
+                "LayerAttrIndexUse", CPLSPrintf("%d", poLayer->GetAttrIndexUse()) );
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerSpatialIndexState (only for debugging purposes) */
+/* -------------------------------------------------------------------- */
+    if (EQUALN(pszSQLCommand, "GetLayerSpatialIndexState ", strlen("GetLayerSpatialIndexState ")))
+    {
+        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
+            GetLayerByName(pszSQLCommand + strlen("GetLayerSpatialIndexState "));
+        if (poLayer)
+        {
+            OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
+                "LayerSpatialIndexState", CPLSPrintf("%d", poLayer->GetSpatialIndexState()) );
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLastSQLUsedOptimizedImplementation (only for debugging purposes) */
+/* -------------------------------------------------------------------- */
+    if (EQUAL(pszSQLCommand, "GetLastSQLUsedOptimizedImplementation"))
+    {
+        OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
+            "GetLastSQLUsedOptimizedImplementation",
+                    CPLSPrintf("%d", bLastSQLUsedOptimizedImplementation) );
+        return poRet;
+    }
+
+    bLastSQLUsedOptimizedImplementation = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Special cases for SQL optimizations                             */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand, "SELECT ", strlen("SELECT ")) &&
+        (pszDialect == NULL || EQUAL(pszDialect, "") || EQUAL(pszDialect, "OGRSQL")) &&
+        CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
+    {
+        swq_select oSelect;
+        if( oSelect.preparse(pszSQLCommand) != OGRERR_NONE )
+            return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      MIN/MAX/SUM/AVG/COUNT optimization                              */
+/* -------------------------------------------------------------------- */
+        if( oSelect.join_count == 0 && oSelect.poOtherSelect == NULL &&
+            oSelect.table_count == 1 && oSelect.order_specs == 0 )
+        {
+            OGROpenFileGDBLayer* poLayer = 
+                (OGROpenFileGDBLayer*)GetLayerByName( oSelect.table_defs[0].table_name);
+            if( poLayer )
+            {
+                OGRMemLayer* poMemLayer = NULL;
+
+                int i;
+                for(i = 0; i < oSelect.result_columns; i ++ )
+                {
+                    swq_col_func col_func = oSelect.column_defs[i].col_func;
+                    if( !(col_func == SWQCF_MIN || col_func == SWQCF_MAX ||
+                          col_func == SWQCF_COUNT || col_func == SWQCF_AVG ||
+                          col_func == SWQCF_SUM) )
+                        break;
+
+                    if( oSelect.column_defs[i].field_name == NULL )
+                        break;
+                    if( oSelect.column_defs[i].distinct_flag )
+                        break;
+                    if( oSelect.column_defs[i].target_type != SWQ_OTHER )
+                        break;
+
+                    int idx = poLayer->GetLayerDefn()->GetFieldIndex(
+                                            oSelect.column_defs[i].field_name);
+                    if( idx < 0 )
+                        break;
+
+                    OGRFieldDefn* poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(idx);
+
+                    if( col_func == SWQCF_SUM && poFieldDefn->GetType() == OFTDateTime )
+                        break;
+
+                    int eOutOGRType = -1;
+                    int nCount = 0;
+                    double dfSum = 0.0;
+                    const OGRField* psField = NULL;
+                    OGRField sField;
+                    if( col_func == SWQCF_MIN || col_func == SWQCF_MAX )
+                    {
+                        psField = poLayer->GetMinMaxValue(
+                                 poFieldDefn, col_func == SWQCF_MIN, eOutOGRType);
+                        if( eOutOGRType < 0 )
+                            break;
+                    }
+                    else
+                    {
+                        double dfMin = 0.0, dfMax = 0.0;
+                        if( !poLayer->GetMinMaxSumCount(poFieldDefn, dfMin, dfMax,
+                                                        dfSum, nCount) )
+                            break;
+                        psField = &sField;
+                        if( col_func == SWQCF_AVG )
+                        {
+                            if( nCount == 0 )
+                            {
+                                eOutOGRType = OFTReal;
+                                psField = NULL;
+                            }
+                            else
+                            {
+                                if( poFieldDefn->GetType() == OFTDateTime )
+                                {
+                                    eOutOGRType = OFTDateTime;
+                                    FileGDBDoubleDateToOGRDate(dfSum / nCount, &sField);
+                                }
+                                else
+                                {
+                                    eOutOGRType = OFTReal;
+                                    sField.Real = dfSum / nCount;
+                                }
+                            }
+                        }
+                        else if( col_func == SWQCF_COUNT )
+                        {
+                            sField.Integer = nCount;
+                            eOutOGRType = OFTInteger;
+                        }
+                        else
+                        {
+                            sField.Real = dfSum;
+                            eOutOGRType = OFTReal;
+                        }
+                    }
+
+                    if( poMemLayer == NULL )
+                    {
+                        poMemLayer = new OGRMemLayer("SELECT", NULL, wkbNone);
+                        OGRFeature* poFeature = new OGRFeature(poMemLayer->GetLayerDefn());
+                        poMemLayer->CreateFeature(poFeature);
+                        delete poFeature;
+                    }
+
+                    const char* pszMinMaxFieldName =
+                        CPLSPrintf( "%s_%s", (col_func == SWQCF_MIN) ? "MIN" :
+                                             (col_func == SWQCF_MAX) ? "MAX" :
+                                             (col_func == SWQCF_AVG) ? "AVG" :
+                                             (col_func == SWQCF_SUM) ? "SUM" :
+                                                                       "COUNT",
+                                            oSelect.column_defs[i].field_name);
+                    OGRFieldDefn oFieldDefn(pszMinMaxFieldName,
+                                            (OGRFieldType) eOutOGRType);
+                    poMemLayer->CreateField(&oFieldDefn);
+                    if( psField != NULL )
+                    {
+                        OGRFeature* poFeature = poMemLayer->GetFeature(0);
+                        poFeature->SetField(oFieldDefn.GetNameRef(), (OGRField*) psField);
+                        poMemLayer->SetFeature(poFeature);
+                        delete poFeature;
+                    }
+                }
+                if( i != oSelect.result_columns )
+                {
+                    delete poMemLayer;
+                }
+                else
+                {
+                    CPLDebug("OpenFileGDB",
+                        "Using optimized MIN/MAX/SUM/AVG/COUNT implementation");
+                    bLastSQLUsedOptimizedImplementation = TRUE;
+                    return poMemLayer;
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      ORDER BY optimization                                           */
+/* -------------------------------------------------------------------- */
+        if( oSelect.join_count == 0 && oSelect.poOtherSelect == NULL &&
+            oSelect.table_count == 1 && oSelect.order_specs == 1 )
+        {
+            OGROpenFileGDBLayer* poLayer = 
+                (OGROpenFileGDBLayer*)GetLayerByName( oSelect.table_defs[0].table_name);
+            if( poLayer != NULL &&
+                poLayer->HasIndexForField(oSelect.order_defs[0].field_name) )
+            {
+                OGRErr eErr = OGRERR_NONE;
+                if( oSelect.where_expr != NULL )
+                {
+                    /* The where must be a simple comparison on the column */
+                    /* that is used for ordering */
+                    if( oSelect.where_expr->eNodeType == SNT_OPERATION &&
+                        OGROpenFileGDBIsComparisonOp(oSelect.where_expr->nOperation) &&
+                        oSelect.where_expr->nOperation != SWQ_NE &&
+                        oSelect.where_expr->nSubExprCount == 2 &&
+                        (oSelect.where_expr->papoSubExpr[0]->eNodeType == SNT_COLUMN ||
+                         oSelect.where_expr->papoSubExpr[0]->eNodeType == SNT_CONSTANT) &&
+                        oSelect.where_expr->papoSubExpr[0]->field_type == SWQ_STRING &&
+                        EQUAL(oSelect.where_expr->papoSubExpr[0]->string_value,
+                              oSelect.order_defs[0].field_name) &&
+                        oSelect.where_expr->papoSubExpr[1]->eNodeType == SNT_CONSTANT )
+                    {
+                        /* ok */
+                    }
+                    else
+                        eErr = OGRERR_FAILURE;
+                }
+                if( eErr == OGRERR_NONE )
+                {
+                    int i;
+                    for(i = 0; i < oSelect.result_columns; i ++ )
+                    {
+                        if( oSelect.column_defs[i].col_func != SWQCF_NONE )
+                            break;
+                        if( oSelect.column_defs[i].field_name == NULL )
+                            break;
+                        if( oSelect.column_defs[i].distinct_flag )
+                            break;
+                        if( oSelect.column_defs[i].target_type != SWQ_OTHER )
+                            break;
+                        if( strcmp(oSelect.column_defs[i].field_name, "*") != 0 &&
+                            poLayer->GetLayerDefn()->GetFieldIndex(
+                                        oSelect.column_defs[i].field_name) < 0 )
+                            break;
+                    }
+                    if( i != oSelect.result_columns )
+                        eErr = OGRERR_FAILURE;
+                }
+                if( eErr == OGRERR_NONE )
+                {
+                    swq_op op = SWQ_UNKNOWN;
+                    swq_expr_node* poValue = NULL;
+                    if( oSelect.where_expr != NULL )
+                    {
+                        op = (swq_op)oSelect.where_expr->nOperation;
+                        poValue = oSelect.where_expr->papoSubExpr[1];
+                    }
+
+                    FileGDBIterator *poIter = poLayer->BuildIndex(
+                                    oSelect.order_defs[0].field_name,
+                                    oSelect.order_defs[0].ascending_flag,
+                                    op, poValue);
+
+                    /* Check that they are no NULL values */
+                    if( oSelect.where_expr == NULL &&
+                        poIter->GetRowCount() != poLayer->GetFeatureCount(FALSE) )
+                    {
+                        delete poIter;
+                        poIter = NULL;
+                    }
+
+                    if( poIter != NULL )
+                    {
+                        CPLDebug("OpenFileGDB", "Using OGROpenFileGDBSimpleSQLLayer");
+                        bLastSQLUsedOptimizedImplementation = TRUE;
+                        return new OGROpenFileGDBSimpleSQLLayer(poLayer,
+                                                                poIter,
+                                                                oSelect.result_columns,
+                                                                oSelect.column_defs);
+                    }
+                }
+            }
+        }
+    }
+
+    return OGRDataSource::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
+}
+
+/***********************************************************************/
+/*                           ReleaseResultSet()                        */
+/***********************************************************************/
+
+void OGROpenFileGDBDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
+{
+    delete poResultsSet;
+}
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
new file mode 100644
index 0000000..aac9604
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * $Id: ogropenfilegdbdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements Open FileGDB OGR driver.
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_openfilegdb.h"
+
+CPL_CVSID("$Id");
+
+// g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal
+
+extern "C" void RegisterOGROpenFileGDB();
+
+/************************************************************************/
+/*                     ~OGROpenFileGDBDriver()                          */
+/************************************************************************/
+OGROpenFileGDBDriver::~OGROpenFileGDBDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGROpenFileGDBDriver::GetName()
+
+{
+    return "OpenFileGDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+#define ENDS_WITH(str, strLen, end) \
+    (strLen >= strlen(end) && EQUAL(str + strLen - strlen(end), end))
+
+OGRDataSource *OGROpenFileGDBDriver::Open( const char* pszFilename, int bUpdate )
+
+{
+    VSIStatBufL stat;
+    if( bUpdate )
+        return NULL;
+#ifdef FOR_FUSIL
+    CPLString osOrigFilename(pszFilename);
+#endif
+
+    // First check if we have to do any work.
+    size_t nLen = strlen(pszFilename);
+    if( ENDS_WITH(pszFilename, nLen, ".gdb") ||
+        ENDS_WITH(pszFilename, nLen, ".gdb/") )
+    {
+        /* Check that the filename is really a directory, to avoid confusion with */
+        /* Garmin MapSource - gdb format which can be a problem when the */
+        /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
+        /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
+        if( strncmp(pszFilename, "/vsicurl/https://github.com/",
+                    strlen("/vsicurl/https://github.com/")) == 0 ||
+            VSIStatL( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
+        {
+            /* In case we don't manage to list the directory, try to stat one file */
+            if( !(strncmp(pszFilename, "/vsicurl/", strlen("/vsicurl/")) == 0 &&
+                  VSIStatL( CPLFormFilename(pszFilename, "a00000001", "gdbtable"), &stat ) == 0) )
+            {
+                return NULL;
+            }
+        }
+    }
+    /* We also accept zipped GDB */
+    else if( ENDS_WITH(pszFilename, nLen, ".gdb.zip") ||
+             ENDS_WITH(pszFilename, nLen, ".gdb.tar") ||
+                /* Canvec GBs */
+             (ENDS_WITH(pszFilename, nLen, ".zip") &&
+              (strstr(pszFilename, "_gdb") != NULL ||
+               strstr(pszFilename, "_GDB") != NULL)) )
+    {
+
+    }
+    /* We also accept tables themselves */
+    else if( ENDS_WITH(pszFilename, nLen, ".gdbtable") )
+    {
+
+    }
+#ifdef FOR_FUSIL
+    /* To be able to test fuzzer on any auxiliary files used (indexes, etc.) */
+    else if( strlen(CPLGetBasename(pszFilename)) == 9 &&
+             CPLGetBasename(pszFilename)[0] == 'a' )
+    {
+        pszFilename = CPLFormFilename(CPLGetPath(pszFilename),
+                                      CPLGetBasename(pszFilename),
+                                      "gdbtable");
+    }
+    else if( strlen(CPLGetBasename(CPLGetBasename(pszFilename))) == 9 &&
+             CPLGetBasename(CPLGetBasename(pszFilename))[0] == 'a' )
+    {
+        pszFilename = CPLFormFilename(CPLGetPath(pszFilename),
+                                      CPLGetBasename(CPLGetBasename(pszFilename)),
+                                      "gdbtable");
+    }
+#endif
+    else
+    {
+        return NULL;
+    }
+
+#ifdef FOR_FUSIL
+    const char* pszSrcDir = CPLGetConfigOption("FUSIL_SRC_DIR", NULL);
+    if( pszSrcDir != NULL && VSIStatL( osOrigFilename, &stat ) == 0 &&
+        VSI_ISREG(stat.st_mode) )
+    {
+        /* Copy all files from FUSIL_SRC_DIR to directory of pszFilename */
+        /* except pszFilename itself */
+        CPLString osSave(pszFilename);
+        char** papszFiles = VSIReadDir(pszSrcDir);
+        for(int i=0; papszFiles[i] != NULL; i++)
+        {
+            if( strcmp(papszFiles[i], CPLGetFilename(osOrigFilename)) != 0 )
+            {
+                CPLCopyFile(CPLFormFilename(CPLGetPath(osOrigFilename), papszFiles[i], NULL),
+                            CPLFormFilename(pszSrcDir, papszFiles[i], NULL));
+            }
+        }
+        CSLDestroy(papszFiles);
+        pszFilename = CPLFormFilename("", osSave.c_str(), NULL);
+    }
+#endif
+
+    OGROpenFileGDBDataSource* poDS = new OGROpenFileGDBDataSource();
+    if( poDS->Open( pszFilename ) )
+    {
+        return poDS;
+    }
+    else
+    {
+        delete poDS;
+        return NULL;
+    }
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int OGROpenFileGDBDriver::TestCapability( const char * pszCap )
+{
+    (void)pszCap;
+    return FALSE;
+}
+
+/***********************************************************************/
+/*                       RegisterOGROpenFileGDB()                      */
+/***********************************************************************/
+
+void RegisterOGROpenFileGDB()
+
+{
+    if (! GDAL_CHECK_VERSION("OGR OpenFileGDB"))
+        return;
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGROpenFileGDBDriver );
+}
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
new file mode 100644
index 0000000..63a0160
--- /dev/null
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
@@ -0,0 +1,1635 @@
+/******************************************************************************
+ * $Id: ogropenfilegdblayer.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements Open FileGDB OGR driver.
+ * Author:   Even Rouault, <even dot rouault at mines-dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_openfilegdb.h"
+#include "cpl_minixml.h"
+#include <algorithm>
+
+CPL_CVSID("$Id");
+
+/************************************************************************/
+/*                      OGROpenFileGDBGeomFieldDefn                     */
+/************************************************************************/
+class OGROpenFileGDBGeomFieldDefn: public OGRGeomFieldDefn
+{
+        OGROpenFileGDBLayer* m_poLayer;
+
+    public:
+        OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer* poLayer,
+                                    const char *pszNameIn,
+                                    OGRwkbGeometryType eGeomTypeIn) :
+                OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
+        {
+        };
+
+        ~OGROpenFileGDBGeomFieldDefn() {}
+
+        void UnsetLayer() { m_poLayer = NULL; }
+
+        virtual OGRSpatialReference* GetSpatialRef()
+        {
+            if( poSRS )
+                return poSRS;
+            if( m_poLayer != NULL )
+                (void) m_poLayer->BuildLayerDefinition();
+            return poSRS;
+        }
+};
+
+/************************************************************************/
+/*                      OGROpenFileGDBFeatureDefn                       */
+/************************************************************************/
+class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
+{
+        OGROpenFileGDBLayer* m_poLayer;
+        int m_bHasBuildFieldDefn;
+
+    public:
+        OGROpenFileGDBFeatureDefn( OGROpenFileGDBLayer* poLayer,
+                                   const char * pszName ) :
+                        OGRFeatureDefn(pszName), m_poLayer(poLayer)
+        {
+            m_bHasBuildFieldDefn = FALSE;
+        }
+
+        ~OGROpenFileGDBFeatureDefn() {}
+
+        void UnsetLayer()
+        {
+            if( nGeomFieldCount )
+                ((OGROpenFileGDBGeomFieldDefn*)papoGeomFieldDefn[0])->UnsetLayer();
+            m_poLayer = NULL;
+        }
+
+        virtual int GetFieldCount()
+        {
+            if( nFieldCount )
+                return nFieldCount;
+            if( !m_bHasBuildFieldDefn && m_poLayer != NULL )
+            {
+                m_bHasBuildFieldDefn = TRUE;
+                (void) m_poLayer->BuildLayerDefinition();
+            }
+            return nFieldCount;
+        }
+};
+
+/************************************************************************/
+/*                      OGROpenFileGDBLayer()                           */
+/************************************************************************/
+
+OGROpenFileGDBLayer::OGROpenFileGDBLayer(const char* pszGDBFilename,
+                                         const char* pszName,
+                                         const std::string& osDefinition,
+                                         const std::string& osDocumentation,
+                                         const char* pszGeomName,
+                                         OGRwkbGeometryType eGeomType) :
+            m_osGDBFilename(pszGDBFilename),
+            m_osName(pszName),
+            m_poLyrTable(NULL),
+            m_poFeatureDefn(NULL),
+            m_iGeomFieldIdx(-1),
+            m_iCurFeat(0),
+            m_osDefinition(osDefinition),
+            m_osDocumentation(osDocumentation),
+            m_eGeomType(eGeomType),
+            m_bValidLayerDefn(-1),
+            m_bEOF(FALSE),
+            m_poGeomConverter(NULL),
+            m_iFieldToReadAsBinary(-1),
+            m_poIterator(NULL),
+            m_bIteratorSufficientToEvaluateFilter(FALSE),
+            m_poIterMinMax(NULL),
+            m_eSpatialIndexState(SPI_IN_BUILDING),
+            m_pQuadTree(NULL),
+            m_pahFilteredFeatures(NULL),
+            m_nFilteredFeatureCount(-1)
+{
+    m_poFeatureDefn = new OGROpenFileGDBFeatureDefn(this, pszName);
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+
+    if( m_osDefinition.size() && BuildGeometryColumnGDBv10() )
+    {
+        ;
+    }
+    else if( eGeomType != wkbNone )
+    {
+        m_poFeatureDefn->AddGeomFieldDefn(
+            new OGROpenFileGDBGeomFieldDefn(this, pszGeomName, eGeomType), FALSE);
+    }
+}
+
+/***********************************************************************/
+/*                      ~OGROpenFileGDBLayer()                         */
+/***********************************************************************/
+
+OGROpenFileGDBLayer::~OGROpenFileGDBLayer()
+{
+    delete m_poLyrTable;
+    if( m_poFeatureDefn )
+    {
+        m_poFeatureDefn->UnsetLayer();
+        m_poFeatureDefn->Release();
+    }
+    delete m_poIterator;
+    delete m_poIterMinMax;
+    delete m_poGeomConverter;
+    if( m_pQuadTree != NULL )
+        CPLQuadTreeDestroy(m_pQuadTree);
+    CPLFree(m_pahFilteredFeatures);
+}
+
+/************************************************************************/
+/*                     BuildGeometryColumnGDBv10()                      */
+/************************************************************************/
+
+int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
+{
+    CPLXMLNode* psTree = CPLParseXMLString(m_osDefinition.c_str());
+    if( psTree == NULL )
+    {
+        return FALSE;
+    }
+
+    CPLStripXMLNamespace( psTree, NULL, TRUE );
+    /* CPLSerializeXMLTreeToFile( psTree, "/dev/stderr" ); */
+    CPLXMLNode* psInfo = CPLSearchXMLNode( psTree, "=DEFeatureClassInfo" );
+    if( psInfo == NULL )
+        psInfo = CPLSearchXMLNode( psTree, "=DETableInfo" );
+    if( psInfo == NULL )
+    {
+        CPLDestroyXMLNode(psTree);
+        return FALSE;
+    }
+
+    /* We cannot trust the XML definition to build the field definitions. */
+    /* It sometimes misses a few fields ! */
+
+    int bHasZ = CSLTestBoolean(CPLGetXMLValue( psInfo, "HasZ", "NO" ));
+    const char* pszShapeType = CPLGetXMLValue(psInfo, "ShapeType", NULL);
+    const char* pszShapeFieldName = CPLGetXMLValue(psInfo, "ShapeFieldName", NULL);
+    if( pszShapeType != NULL && pszShapeFieldName != NULL )
+    {
+        m_eGeomType =
+            FileGDBOGRGeometryConverter::GetGeometryTypeFromESRI(pszShapeType);
+        if( bHasZ )
+            m_eGeomType = (OGRwkbGeometryType)( m_eGeomType | wkb25DBit );
+
+        const char* pszWKT = CPLGetXMLValue( psInfo, "SpatialReference.WKT", NULL );
+        int nWKID = atoi(CPLGetXMLValue( psInfo, "SpatialReference.WKID", "0" ));
+
+        OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn =
+            new OGROpenFileGDBGeomFieldDefn(NULL, pszShapeFieldName, m_eGeomType);
+
+        OGRSpatialReference* poSRS = NULL;
+        if( nWKID > 0 )
+        {
+            poSRS = new OGRSpatialReference();
+            if( poSRS->importFromEPSG(nWKID) != OGRERR_NONE )
+            {
+                delete poSRS;
+                poSRS = NULL;
+            }
+        }
+        if( poSRS == NULL && pszWKT != NULL && pszWKT[0] != '{' )
+        {
+            poSRS = new OGRSpatialReference( pszWKT );
+            if( poSRS->morphFromESRI() != OGRERR_NONE )
+            {
+                delete poSRS;
+                poSRS = NULL;
+            }
+        }
+        if( poSRS != NULL )
+        {
+            poGeomFieldDefn->SetSpatialRef(poSRS);
+            poSRS->Dereference();
+        }
+        m_poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
+    }
+    else
+    {
+        m_eGeomType = wkbNone;
+    }
+    CPLDestroyXMLNode(psTree);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                      BuildLayerDefinition()                          */
+/************************************************************************/
+
+int OGROpenFileGDBLayer::BuildLayerDefinition()
+{
+    if( m_bValidLayerDefn >= 0 )
+        return m_bValidLayerDefn;
+
+    m_poLyrTable = new FileGDBTable();
+    if( !(m_poLyrTable->Open(m_osGDBFilename)) )
+    {
+        delete m_poLyrTable;
+        m_poLyrTable = NULL;
+        m_bValidLayerDefn = FALSE;
+        return FALSE;
+    }
+
+    m_bValidLayerDefn = TRUE;
+
+    m_iGeomFieldIdx = m_poLyrTable->GetGeomFieldIdx();
+    if( m_iGeomFieldIdx >= 0 )
+    {
+        FileGDBGeomField* poGDBGeomField =
+            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
+        m_poGeomConverter = FileGDBOGRGeometryConverter::BuildConverter(poGDBGeomField);
+
+        if( CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_IN_MEMORY_SPI", "YES")) )
+        {
+            CPLRectObj sGlobalBounds;
+            sGlobalBounds.minx = poGDBGeomField->GetXMin();
+            sGlobalBounds.miny = poGDBGeomField->GetYMin();
+            sGlobalBounds.maxx = poGDBGeomField->GetXMax();
+            sGlobalBounds.maxy = poGDBGeomField->GetYMax();
+            m_pQuadTree = CPLQuadTreeCreate(&sGlobalBounds,
+                                            NULL);
+            CPLQuadTreeSetMaxDepth(m_pQuadTree,
+                CPLQuadTreeGetAdvisedMaxDepth(m_poLyrTable->GetValidRecordCount()));
+        }
+        else
+        {
+            m_eSpatialIndexState = SPI_INVALID;
+        }
+    }
+
+    if( m_osDefinition.size() == 0 && m_iGeomFieldIdx >= 0 )
+    {
+        FileGDBGeomField* poGDBGeomField =
+            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
+        const char* pszName = poGDBGeomField->GetName().c_str();
+        FileGDBTableGeometryType eGDBGeomType = m_poLyrTable->GetGeometryType();
+
+        OGRwkbGeometryType eGeomType = wkbUnknown;
+        switch( eGDBGeomType )
+        {
+            case FGTGT_NONE: /* doesn't make sense ! */ break;
+            case FGTGT_POINT: eGeomType = wkbPoint; break;
+            case FGTGT_MULTIPOINT: eGeomType = wkbMultiPoint; break;
+            case FGTGT_LINE: eGeomType = wkbMultiLineString; break;
+            case FGTGT_POLYGON: eGeomType = wkbMultiPolygon; break;
+            case FGTGT_MULTIPATCH: eGeomType = wkbMultiPolygon; break;
+        }
+        if( m_eGeomType == wkbUnknown )
+            m_eGeomType = eGeomType;
+        if( eGeomType != m_eGeomType )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Inconsistency for layer geometry type");
+        }
+
+        OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn;
+        if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
+        {
+            poGeomFieldDefn =
+                    new OGROpenFileGDBGeomFieldDefn(NULL, pszName, m_eGeomType);
+            m_poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
+        }
+        else
+        {
+            poGeomFieldDefn = (OGROpenFileGDBGeomFieldDefn*)
+                                        m_poFeatureDefn->GetGeomFieldDefn(0);
+            poGeomFieldDefn->SetType(m_eGeomType);
+        }
+
+        OGRSpatialReference* poSRS = NULL;
+        if( poGDBGeomField->GetWKT().size() && 
+            poGDBGeomField->GetWKT()[0] != '{' )
+        {
+            poSRS = new OGRSpatialReference( poGDBGeomField->GetWKT().c_str() );
+            if( poSRS->morphFromESRI() != OGRERR_NONE )
+            {
+                delete poSRS;
+                poSRS = NULL;
+            }
+        }
+        if( poSRS != NULL )
+        {
+            poGeomFieldDefn->SetSpatialRef(poSRS);
+            poSRS->Dereference();
+        }
+    }
+
+    for(int i=0;i<m_poLyrTable->GetFieldCount();i++)
+    {
+        if( i == m_iGeomFieldIdx )
+            continue;
+
+        const FileGDBField* poGDBField = m_poLyrTable->GetField(i);
+        OGRFieldType eType = OFTString;
+        int nWidth = 0;
+        switch( poGDBField->GetType() )
+        {
+            case FGFT_INT16:
+            case FGFT_INT32:
+                eType = OFTInteger;
+                break;
+            case FGFT_FLOAT32:
+            case FGFT_FLOAT64:
+                eType = OFTReal;
+                break;
+            case FGFT_STRING:
+                nWidth = poGDBField->GetMaxWidth();
+                eType = OFTString;
+                break;
+            case FGFT_UUID_1:
+            case FGFT_UUID_2:
+            case FGFT_XML:
+                eType = OFTString;
+                break;
+            case FGFT_DATETIME:
+                eType = OFTDateTime;
+                break;
+            case FGFT_UNDEFINED:
+            case FGFT_OBJECTID:
+            case FGFT_GEOMETRY:
+                CPLAssert(FALSE);
+                break;
+            case FGFT_BINARY:
+            case FGFT_RASTER:
+            {
+                /* Special case for v9 GDB_UserMetadata table */
+                if( m_iFieldToReadAsBinary < 0 &&
+                    poGDBField->GetName() == "Xml" &&
+                    poGDBField->GetType() == FGFT_BINARY )
+                {
+                    m_iFieldToReadAsBinary = i;
+                    eType = OFTString;
+                }
+                else
+                    eType = OFTBinary;
+                break;
+            }
+        }
+        OGRFieldDefn oFieldDefn(poGDBField->GetName().c_str(), eType);
+        /* oFieldDefn.SetWidth(nWidth); */
+        m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           GetGeomType()                              */
+/************************************************************************/
+
+OGRwkbGeometryType OGROpenFileGDBLayer::GetGeomType()
+{
+    if( m_eGeomType == wkbUnknown )
+    {
+        (void) BuildLayerDefinition();
+    }
+
+    return m_eGeomType;
+}
+
+/***********************************************************************/
+/*                          GetLayerDefn()                             */
+/***********************************************************************/
+
+OGRFeatureDefn* OGROpenFileGDBLayer::GetLayerDefn()
+{
+    return m_poFeatureDefn;
+}
+
+/***********************************************************************/
+/*                          GetFIDColumn()                             */
+/***********************************************************************/
+
+const char* OGROpenFileGDBLayer::GetFIDColumn()
+{
+    if( m_osFIDName.size() )
+        return m_osFIDName.c_str();
+
+    if( !BuildLayerDefinition() )
+        return "";
+    return m_poLyrTable->GetObjectIdColName().c_str();
+}
+
+/***********************************************************************/
+/*                          ResetReading()                             */
+/***********************************************************************/
+
+void OGROpenFileGDBLayer::ResetReading()
+{
+    if( m_iCurFeat != 0 )
+    {
+        if( m_eSpatialIndexState == SPI_IN_BUILDING )
+            m_eSpatialIndexState = SPI_INVALID;
+    }
+    m_bEOF = FALSE;
+    m_iCurFeat = 0;
+    if( m_poIterator )
+        m_poIterator->Reset();
+}
+
+/***********************************************************************/
+/*                         SetSpatialFilter()                          */
+/***********************************************************************/
+
+void OGROpenFileGDBLayer::SetSpatialFilter( OGRGeometry *poGeom )
+{
+    if( !BuildLayerDefinition() )
+        return;
+
+    OGRLayer::SetSpatialFilter(poGeom);
+
+    if( m_bFilterIsEnvelope )
+    {
+        OGREnvelope sLayerEnvelope;
+        if( GetExtent(&sLayerEnvelope, FALSE) == OGRERR_NONE )
+        {
+            if( m_sFilterEnvelope.MinX <= sLayerEnvelope.MinX &&
+                m_sFilterEnvelope.MinY <= sLayerEnvelope.MinY &&
+                m_sFilterEnvelope.MaxX >= sLayerEnvelope.MaxX &&
+                m_sFilterEnvelope.MaxY >= sLayerEnvelope.MaxY )
+            {
+                CPLDebug("OpenFileGDB", "Disabling spatial filter since it "
+                         "contains the layer spatial extent");
+                poGeom = NULL;
+                OGRLayer::SetSpatialFilter(poGeom);
+            }
+        }
+    }
+
+    if( poGeom != NULL )
+    {
+        if( m_eSpatialIndexState == SPI_COMPLETED )
+        {
+            CPLRectObj aoi;
+            aoi.minx = m_sFilterEnvelope.MinX;
+            aoi.miny = m_sFilterEnvelope.MinY;
+            aoi.maxx = m_sFilterEnvelope.MaxX;
+            aoi.maxy = m_sFilterEnvelope.MaxY;
+            CPLFree(m_pahFilteredFeatures);
+            m_nFilteredFeatureCount = -1;
+            m_pahFilteredFeatures = CPLQuadTreeSearch(m_pQuadTree,
+                                                      &aoi,
+                                                      &m_nFilteredFeatureCount);
+            if( m_nFilteredFeatureCount >= 0 )
+            {
+                size_t* panStart = (size_t*)m_pahFilteredFeatures;
+                std::sort(panStart, panStart + m_nFilteredFeatureCount);
+            }
+        }
+        m_poLyrTable->InstallFilterEnvelope(&m_sFilterEnvelope);
+    }
+    else
+    {
+        CPLFree(m_pahFilteredFeatures);
+        m_pahFilteredFeatures = NULL;
+        m_nFilteredFeatureCount = -1;
+        m_poLyrTable->InstallFilterEnvelope(NULL);
+    }
+}
+
+/***********************************************************************/
+/*                            CompValues()                             */
+/***********************************************************************/
+
+static int CompValues(OGRFieldDefn* poFieldDefn,
+                      const swq_expr_node* poValue1,
+                      const swq_expr_node* poValue2)
+{
+    switch( poFieldDefn->GetType() )
+    {
+        case OFTInteger:
+        {
+            int n1, n2;
+            if (poValue1->field_type == SWQ_FLOAT)
+                n1 = (int) poValue1->float_value;
+            else
+                n1 = poValue1->int_value;
+            if (poValue2->field_type == SWQ_FLOAT)
+                n2 = (int) poValue2->float_value;
+            else
+                n2 = poValue2->int_value;
+            if( n1 < n2 )
+                return -1;
+            if( n1 == n2 )
+                return 0;
+            else 
+                return 1;
+            break;
+        }
+
+        case OFTReal:
+            if( poValue1->float_value < poValue2->float_value )
+                return -1;
+            if( poValue1->float_value == poValue2->float_value )
+                return 0;
+            else
+                return 1;
+            break;
+
+        case OFTString:
+            return strcmp(poValue1->string_value, poValue2->string_value);
+            break;
+
+        case OFTDate:
+        case OFTTime:
+        case OFTDateTime:
+        {
+            if ((poValue1->field_type == SWQ_TIMESTAMP ||
+                 poValue1->field_type == SWQ_DATE ||
+                 poValue1->field_type == SWQ_TIME) &&
+                (poValue2->field_type == SWQ_TIMESTAMP ||
+                 poValue2->field_type == SWQ_DATE ||
+                 poValue2->field_type == SWQ_TIME))
+            {
+                return strcmp(poValue1->string_value, poValue2->string_value);
+            }
+            return 0;
+            break;
+        }
+
+        default:
+            return 0;
+            break;
+    }
+}
+
+/***********************************************************************/
+/*                    OGROpenFileGDBIsComparisonOp()                   */
+/***********************************************************************/
+
+int OGROpenFileGDBIsComparisonOp(int op)
+{
+    return (op == SWQ_EQ || op == SWQ_NE || op == SWQ_LT ||
+            op == SWQ_LE || op == SWQ_GT || op == SWQ_GE);
+}
+
+/***********************************************************************/
+/*                        AreExprExclusive()                           */
+/***********************************************************************/
+
+static const struct 
+{
+    swq_op op1;
+    swq_op op2;
+    int    expected_comp_1;
+    int    expected_comp_2;
+}
+asPairsOfComparisons[] = 
+{
+    { SWQ_EQ, SWQ_EQ, -1, 1 },
+    { SWQ_LT, SWQ_GT, -1, 0 },
+    { SWQ_GT, SWQ_LT, 0, 1 },
+    { SWQ_LT, SWQ_GE, -1, 999 },
+    { SWQ_LE, SWQ_GE, -1, 999 },
+    { SWQ_LE, SWQ_GT, -1, 999 },
+    { SWQ_GE, SWQ_LE, 1, 999 },
+    { SWQ_GE, SWQ_LT, 1, 999 },
+    { SWQ_GT, SWQ_LE, 1, 999 }
+};
+
+static int AreExprExclusive(OGRFeatureDefn* poFeatureDefn,
+                            const swq_expr_node* poNode1,
+                            const swq_expr_node* poNode2)
+{
+    if( poNode1->eNodeType != SNT_OPERATION )
+        return FALSE;
+    if( poNode2->eNodeType != SNT_OPERATION )
+        return FALSE;
+
+    const size_t nParis = sizeof(asPairsOfComparisons) / sizeof(asPairsOfComparisons[0]);
+    for(size_t i = 0; i < nParis; i++ )
+    {
+        if( poNode1->nOperation == asPairsOfComparisons[i].op1 &&
+            poNode2->nOperation == asPairsOfComparisons[i].op2 &&
+            poNode1->nSubExprCount == 2 &&
+            poNode2->nSubExprCount == 2 )
+        {
+            swq_expr_node *poColumn1 = poNode1->papoSubExpr[0];
+            swq_expr_node *poValue1 = poNode1->papoSubExpr[1];
+            swq_expr_node *poColumn2 = poNode2->papoSubExpr[0];
+            swq_expr_node *poValue2 = poNode2->papoSubExpr[1];
+            if( poColumn1->eNodeType == SNT_COLUMN &&
+                poValue1->eNodeType == SNT_CONSTANT &&
+                poColumn2->eNodeType == SNT_COLUMN &&
+                poValue2->eNodeType == SNT_CONSTANT &&
+                poColumn1->field_index == poColumn2->field_index &&
+                poColumn1->field_index < poFeatureDefn->GetFieldCount() )
+            {
+                OGRFieldDefn *poFieldDefn;
+                poFieldDefn = poFeatureDefn->GetFieldDefn(poColumn1->field_index);
+
+                int nComp = CompValues(poFieldDefn, poValue1, poValue2);
+                return nComp == asPairsOfComparisons[i].expected_comp_1 ||
+                       nComp == asPairsOfComparisons[i].expected_comp_2;
+            }
+            return FALSE;
+        }
+    }
+
+    if( (poNode2->nOperation == SWQ_ISNULL &&
+         OGROpenFileGDBIsComparisonOp(poNode1->nOperation) &&
+         poNode1->nSubExprCount == 2 &&
+         poNode2->nSubExprCount == 1) ||
+        (poNode1->nOperation == SWQ_ISNULL &&
+         OGROpenFileGDBIsComparisonOp(poNode2->nOperation) &&
+         poNode2->nSubExprCount == 2 &&
+         poNode1->nSubExprCount == 1))
+    {
+        swq_expr_node *poColumn1 = poNode1->papoSubExpr[0];
+        swq_expr_node *poColumn2 = poNode2->papoSubExpr[0];
+        if( poColumn1->eNodeType == SNT_COLUMN &&
+            poColumn2->eNodeType == SNT_COLUMN &&
+            poColumn1->field_index == poColumn2->field_index &&
+            poColumn1->field_index < poFeatureDefn->GetFieldCount() )
+        {
+            return TRUE;
+        }
+    }
+
+    /* In doubt: return FALSE */
+    return FALSE;
+}
+
+
+/***********************************************************************/
+/*                     FillTargetValueFromSrcExpr()                    */
+/***********************************************************************/
+
+static
+int FillTargetValueFromSrcExpr( OGRFieldDefn* poFieldDefn,
+                                OGRField* poTargetValue,
+                                const swq_expr_node* poSrcValue )
+{
+    switch( poFieldDefn->GetType() )
+    {
+        case OFTInteger:
+            if (poSrcValue->field_type == SWQ_FLOAT)
+                poTargetValue->Integer = (int) poSrcValue->float_value;
+            else
+                poTargetValue->Integer = poSrcValue->int_value;
+            break;
+
+        case OFTReal:
+            poTargetValue->Real = poSrcValue->float_value;
+            break;
+
+        case OFTString:
+            poTargetValue->String = poSrcValue->string_value;
+            break;
+
+        case OFTDate:
+        case OFTTime:
+        case OFTDateTime:
+            if (poSrcValue->field_type == SWQ_TIMESTAMP ||
+                poSrcValue->field_type == SWQ_DATE ||
+                poSrcValue->field_type == SWQ_TIME)
+            {
+                int nYear = 0, nMonth = 0, nDay = 0, nHour = 0, nMin = 0, nSec = 0;
+                if( sscanf(poSrcValue->string_value, "%04d/%02d/%02d %02d:%02d:%02d",
+                           &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec) == 6 ||
+                    sscanf(poSrcValue->string_value, "%04d/%02d/%02d",
+                           &nYear, &nMonth, &nDay) == 3 ||
+                    sscanf(poSrcValue->string_value, "%02d:%02d:%02d",
+                           &nHour, &nMin, &nSec) == 3 )
+                {
+                    poTargetValue->Date.Year = (GInt16)nYear;
+                    poTargetValue->Date.Month = (GByte)nMonth;
+                    poTargetValue->Date.Day = (GByte)nDay;
+                    poTargetValue->Date.Hour = (GByte)nHour;
+                    poTargetValue->Date.Minute = (GByte)nMin;
+                    poTargetValue->Date.Second = (GByte)nSec;
+                    poTargetValue->Date.TZFlag = 0;
+                }
+                else
+                    return FALSE;
+            }
+            else
+                return FALSE;
+            break;
+
+        default:
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/***********************************************************************/
+/*                        GetColumnSubNode()                           */
+/***********************************************************************/
+
+static swq_expr_node* GetColumnSubNode(swq_expr_node* poNode)
+{
+    if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nSubExprCount == 2 )
+    {
+        if( poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN )
+            return poNode->papoSubExpr[0];
+        if( poNode->papoSubExpr[1]->eNodeType == SNT_COLUMN )
+            return poNode->papoSubExpr[1];
+    }
+    return NULL;
+}
+
+/***********************************************************************/
+/*                        GetConstantSubNode()                         */
+/***********************************************************************/
+
+static swq_expr_node* GetConstantSubNode(swq_expr_node* poNode)
+{
+    if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nSubExprCount == 2 )
+    {
+        if( poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT )
+            return poNode->papoSubExpr[1];
+        if( poNode->papoSubExpr[0]->eNodeType == SNT_CONSTANT )
+            return poNode->papoSubExpr[0];
+    }
+    return NULL;
+}
+/***********************************************************************/
+/*                     BuildIteratorFromExprNode()                     */
+/***********************************************************************/
+
+FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* poNode)
+{
+    if( m_bIteratorSufficientToEvaluateFilter == FALSE )
+        return NULL;
+
+    if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
+    {
+        /* Even if there's only one branch of the 2 that results to an iterator, */
+        /* it is usefull. Of course, the iterator will not be sufficient to evaluate */
+        /* the filter, but it will be a super-set of the features */
+        FileGDBIterator* poIter1 = BuildIteratorFromExprNode(poNode->papoSubExpr[0]);
+
+        /* In case the first branch didn't result to an iterator, temporarily */
+        /* restore the flag */
+        int bSaveIteratorSufficientToEvaluateFilter = m_bIteratorSufficientToEvaluateFilter;
+        m_bIteratorSufficientToEvaluateFilter = -1;
+        FileGDBIterator* poIter2 = BuildIteratorFromExprNode(poNode->papoSubExpr[1]);
+        m_bIteratorSufficientToEvaluateFilter = bSaveIteratorSufficientToEvaluateFilter;
+
+        if( poIter1 != NULL && poIter2 != NULL )
+            return FileGDBIterator::BuildAnd(poIter1, poIter2);
+        m_bIteratorSufficientToEvaluateFilter = FALSE;
+        if( poIter1 != NULL )
+            return poIter1;
+        if( poIter2 != NULL )
+            return poIter2;
+    }
+
+    else if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nOperation == SWQ_OR && poNode->nSubExprCount == 2 )
+    {
+        /* For a OR, we need an iterator for the 2 branches */
+        FileGDBIterator* poIter1 = BuildIteratorFromExprNode(poNode->papoSubExpr[0]);
+        if( poIter1 != NULL )
+        {
+            FileGDBIterator* poIter2 = BuildIteratorFromExprNode(poNode->papoSubExpr[1]);
+            if( poIter2 == NULL )
+            {
+                delete poIter1;
+            }
+            else
+            {
+                return FileGDBIterator::BuildOr(poIter1, poIter2,
+                                        AreExprExclusive(GetLayerDefn(),
+                                                        poNode->papoSubExpr[0],
+                                                        poNode->papoSubExpr[1]));
+            }
+        }
+    }
+
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             OGROpenFileGDBIsComparisonOp(poNode->nOperation) &&
+             poNode->nSubExprCount == 2 )
+    {
+        swq_expr_node *poColumn = GetColumnSubNode(poNode);
+        swq_expr_node *poValue = GetConstantSubNode(poNode);
+        if( poColumn != NULL && poValue != NULL &&
+            poColumn->field_index < GetLayerDefn()->GetFieldCount())
+        {
+            OGRFieldDefn *poFieldDefn;
+            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+
+            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+            {
+                OGRField sValue;
+
+                if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue, poValue) )
+                {
+                    FileGDBSQLOp eOp;
+                    if( poColumn == poNode->papoSubExpr[0] )
+                    {
+                        switch( poNode->nOperation )
+                        {
+                            case SWQ_LE: eOp = FGSO_LE; break;
+                            case SWQ_LT: eOp = FGSO_LT; break;
+                            case SWQ_NE: eOp = FGSO_EQ; /* yes : EQ */ break;
+                            case SWQ_EQ: eOp = FGSO_EQ; break;
+                            case SWQ_GE: eOp = FGSO_GE; break;
+                            case SWQ_GT: eOp = FGSO_GT; break;
+                            default: eOp = FGSO_EQ; CPLAssert(FALSE); break;
+                        }
+                    }
+                    else
+                    {
+                        /* If "constant op column", then we must reverse */
+                        /* the operator */
+                        switch( poNode->nOperation )
+                        {
+                            case SWQ_LE: eOp = FGSO_GE; break;
+                            case SWQ_LT: eOp = FGSO_GT; break;
+                            case SWQ_NE: eOp = FGSO_EQ; /* yes : EQ */ break;
+                            case SWQ_EQ: eOp = FGSO_EQ; break;
+                            case SWQ_GE: eOp = FGSO_LE; break;
+                            case SWQ_GT: eOp = FGSO_LT; break;
+                            default: eOp = FGSO_EQ; CPLAssert(FALSE); break;
+                        }
+                    }
+
+                    FileGDBIterator* poIter = FileGDBIterator::Build(
+                        m_poLyrTable, nTableColIdx, TRUE,
+                        eOp, poFieldDefn->GetType(), &sValue);
+                    if( poIter != NULL )
+                        m_bIteratorSufficientToEvaluateFilter = TRUE;
+                    if( poIter && poNode->nOperation == SWQ_NE )
+                        return FileGDBIterator::BuildNot(poIter);
+                    else
+                        return poIter;
+                }
+            }
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_ISNULL && poNode->nSubExprCount == 1 )
+    {
+        swq_expr_node *poColumn = poNode->papoSubExpr[0];
+        if( poColumn->eNodeType == SNT_COLUMN &&
+            poColumn->field_index < GetLayerDefn()->GetFieldCount() )
+        {
+            OGRFieldDefn *poFieldDefn;
+            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+
+            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+            {
+                FileGDBIterator* poIter = FileGDBIterator::BuildIsNotNull(
+                                                    m_poLyrTable, nTableColIdx, TRUE);
+                if( poIter )
+                {
+                    m_bIteratorSufficientToEvaluateFilter = TRUE;
+                    poIter = FileGDBIterator::BuildNot(poIter);
+                }
+                return poIter;
+            }
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+                poNode->nOperation == SWQ_NOT && poNode->nSubExprCount == 1 &&
+                poNode->papoSubExpr[0]->eNodeType == SNT_OPERATION &&
+                poNode->papoSubExpr[0]->nOperation == SWQ_ISNULL &&
+                poNode->papoSubExpr[0]->nSubExprCount == 1 )
+    {
+        swq_expr_node *poColumn = poNode->papoSubExpr[0]->papoSubExpr[0];
+        if( poColumn->eNodeType == SNT_COLUMN &&
+            poColumn->field_index < GetLayerDefn()->GetFieldCount() )
+        {
+            OGRFieldDefn *poFieldDefn;
+            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+
+            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+            {
+                FileGDBIterator* poIter = FileGDBIterator::BuildIsNotNull(
+                                                m_poLyrTable, nTableColIdx, TRUE);
+                if( poIter )
+                    m_bIteratorSufficientToEvaluateFilter = TRUE;
+                return poIter;
+            }
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nOperation == SWQ_BETWEEN && poNode->nSubExprCount == 3 )
+    {
+        swq_expr_node *poColumn = poNode->papoSubExpr[0];
+        swq_expr_node *poValue1 = poNode->papoSubExpr[1];
+        swq_expr_node *poValue2 = poNode->papoSubExpr[2];
+        if( poColumn->eNodeType == SNT_COLUMN &&
+            poColumn->field_index < GetLayerDefn()->GetFieldCount() &&
+            poValue1->eNodeType == SNT_CONSTANT &&
+            poValue2->eNodeType == SNT_CONSTANT )
+        {
+            OGRFieldDefn *poFieldDefn;
+            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+
+            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+            {
+                OGRField sValue1, sValue2;
+
+                if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue1, poValue1) &&
+                    FillTargetValueFromSrcExpr(poFieldDefn, &sValue2, poValue2) )
+                {
+                    FileGDBIterator* poIter1 = FileGDBIterator::Build(
+                                            m_poLyrTable, nTableColIdx, TRUE,
+                                            FGSO_GE,
+                                            poFieldDefn->GetType(), &sValue1);
+                    FileGDBIterator* poIter2 = FileGDBIterator::Build(
+                                            m_poLyrTable, nTableColIdx, TRUE,
+                                            FGSO_LE,
+                                            poFieldDefn->GetType(), &sValue2);
+                    if( poIter1 != NULL && poIter2 != NULL )
+                    {
+                        m_bIteratorSufficientToEvaluateFilter = TRUE;
+                        return FileGDBIterator::BuildAnd(poIter1, poIter2);
+                    }
+                    delete poIter1;
+                    delete poIter2;
+                }
+            }
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_IN && poNode->nSubExprCount >= 2 )
+    {
+        swq_expr_node *poColumn = poNode->papoSubExpr[0];
+        if( poColumn->eNodeType == SNT_COLUMN &&
+            poColumn->field_index < GetLayerDefn()->GetFieldCount() )
+        {
+            int bAllConstants = TRUE;
+            int i;
+            for(i=1;i<poNode->nSubExprCount;i++)
+            {
+                if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT )
+                    bAllConstants = FALSE;
+            }
+            OGRFieldDefn *poFieldDefn;
+            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+
+            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            if( bAllConstants && nTableColIdx >= 0 &&
+                m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+            {
+                FileGDBIterator* poRet = NULL;
+                for(i=1;i<poNode->nSubExprCount;i++)
+                {
+                    OGRField sValue;
+                    if( !FillTargetValueFromSrcExpr(poFieldDefn, &sValue,
+                                                    poNode->papoSubExpr[i]) )
+                    {
+                        delete poRet;
+                        poRet = NULL;
+                        break;
+                    }
+                    FileGDBIterator* poIter = FileGDBIterator::Build(
+                                        m_poLyrTable, nTableColIdx, TRUE, FGSO_EQ,
+                                        poFieldDefn->GetType(), &sValue);
+                    if( poIter == NULL )
+                    {
+                        delete poRet;
+                        poRet = NULL;
+                        break;
+                    }
+                    if( poRet == NULL )
+                        poRet = poIter;
+                    else
+                        poRet = FileGDBIterator::BuildOr(poRet, poIter);
+                }
+                if( poRet != NULL )
+                {
+                    m_bIteratorSufficientToEvaluateFilter = TRUE;
+                    return poRet;
+                }
+            }
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_NOT && poNode->nSubExprCount == 1 )
+    {
+        FileGDBIterator* poIter = BuildIteratorFromExprNode(poNode->papoSubExpr[0]);
+        /* If we have an iterator that is only partial w.r.t the full clause */
+        /* then we cannot do anything with it unfortunately */
+        if( m_bIteratorSufficientToEvaluateFilter == FALSE )
+        {
+            if( poIter != NULL )
+                CPLDebug("OpenFileGDB", "Disabling use of indexes");
+            delete poIter;
+        }
+        else if( poIter != NULL )
+        {
+            return FileGDBIterator::BuildNot(poIter);
+        }
+    }
+
+
+    if( m_bIteratorSufficientToEvaluateFilter == TRUE )
+        CPLDebug("OpenFileGDB", "Disabling use of indexes");
+    m_bIteratorSufficientToEvaluateFilter = FALSE;
+    return NULL;
+}
+
+/***********************************************************************/
+/*                         SetAttributeFilter()                        */
+/***********************************************************************/
+
+OGRErr OGROpenFileGDBLayer::SetAttributeFilter( const char* pszFilter )
+{
+    if( !BuildLayerDefinition() )
+        return OGRERR_FAILURE;
+
+    delete m_poIterator;
+    m_poIterator = NULL;
+    m_bIteratorSufficientToEvaluateFilter = FALSE;
+
+    OGRErr eErr = OGRLayer::SetAttributeFilter(pszFilter);
+    if( eErr != OGRERR_NONE ||
+        !CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
+        return eErr;
+
+    if( m_poAttrQuery != NULL && m_nFilteredFeatureCount < 0 )
+    {
+        swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWGExpr();
+        m_bIteratorSufficientToEvaluateFilter = -1;
+        m_poIterator = BuildIteratorFromExprNode(poNode);
+        if( m_poIterator != NULL && m_eSpatialIndexState == SPI_IN_BUILDING )
+            m_eSpatialIndexState = SPI_INVALID;
+        if( m_bIteratorSufficientToEvaluateFilter < 0 )
+            m_bIteratorSufficientToEvaluateFilter = FALSE;
+    }
+    return eErr;
+}
+
+/***********************************************************************/
+/*                         GetCurrentFeature()                         */
+/***********************************************************************/
+
+OGRFeature* OGROpenFileGDBLayer::GetCurrentFeature()
+{
+    OGRFeature *poFeature = NULL;
+    int iOGRIdx = 0;
+    int iRow = m_poLyrTable->GetCurRow();
+    for(int iGDBIdx=0;iGDBIdx<m_poLyrTable->GetFieldCount();iGDBIdx++)
+    {
+        if( iGDBIdx == m_iGeomFieldIdx )
+        {
+            if( m_poFeatureDefn->GetGeomFieldDefn(0)->IsIgnored() )
+            {
+                if( m_eSpatialIndexState == SPI_IN_BUILDING )
+                    m_eSpatialIndexState = SPI_INVALID;
+                continue;
+            }
+
+            const OGRField* psField = m_poLyrTable->GetFieldValue(iGDBIdx);
+            if( psField != NULL )
+            {
+                if( m_eSpatialIndexState == SPI_IN_BUILDING )
+                {
+                    OGREnvelope sFeatureEnvelope;
+                    if( m_poLyrTable->GetFeatureExtent(psField,
+                                                       &sFeatureEnvelope) )
+                    {
+                        CPLRectObj sBounds;
+                        sBounds.minx = sFeatureEnvelope.MinX;
+                        sBounds.miny = sFeatureEnvelope.MinY;
+                        sBounds.maxx = sFeatureEnvelope.MaxX;
+                        sBounds.maxy = sFeatureEnvelope.MaxY;
+                        CPLQuadTreeInsertWithBounds(m_pQuadTree,
+                                                    (void*)(size_t)iRow,
+                                                    &sBounds);
+                    }
+                }
+
+                if( m_poFilterGeom != NULL &&
+                    m_eSpatialIndexState != SPI_COMPLETED &&
+                    !m_poLyrTable->DoesGeometryIntersectsFilterEnvelope(psField) )
+                {
+                    delete poFeature;
+                    return NULL;
+                }
+
+                OGRGeometry* poGeom = m_poGeomConverter->GetAsGeometry(psField);
+                if( poGeom != NULL )
+                {
+                    OGRwkbGeometryType eFlattenType = wkbFlatten(poGeom->getGeometryType());
+                    if( eFlattenType == wkbPolygon )
+                        poGeom = OGRGeometryFactory::forceToMultiPolygon(poGeom);
+                    else if( eFlattenType == wkbLineString )
+                        poGeom = OGRGeometryFactory::forceToMultiLineString(poGeom);
+                    poGeom->assignSpatialReference(
+                        m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef() );
+
+                    if( poFeature == NULL )
+                        poFeature = new OGRFeature(m_poFeatureDefn);
+                    poFeature->SetGeometryDirectly( poGeom );
+                }
+            }
+        }
+        else
+        {
+            if( !m_poFeatureDefn->GetFieldDefn(iOGRIdx)->IsIgnored() )
+            {
+                const OGRField* psField = m_poLyrTable->GetFieldValue(iGDBIdx);
+                if( psField != NULL )
+                {
+                    if( poFeature == NULL )
+                        poFeature = new OGRFeature(m_poFeatureDefn);
+
+                    if( iGDBIdx == m_iFieldToReadAsBinary )
+                        poFeature->SetField(iOGRIdx, (const char*) psField->Binary.paData);
+                    else
+                        poFeature->SetField(iOGRIdx, (OGRField*) psField);
+                }
+            }
+            iOGRIdx ++;
+        }
+    }
+
+    if( poFeature == NULL )
+        poFeature = new OGRFeature(m_poFeatureDefn);
+    poFeature->SetFID(iRow + 1);
+    return poFeature;
+}
+
+/***********************************************************************/
+/*                         GetNextFeature()                            */
+/***********************************************************************/
+
+OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
+{
+    if( !BuildLayerDefinition() || m_bEOF )
+        return NULL;
+
+    while( TRUE )
+    {
+        OGRFeature *poFeature = NULL;
+
+        if( m_nFilteredFeatureCount >= 0 )
+        {
+            while( TRUE )
+            {
+                if( m_iCurFeat >= m_nFilteredFeatureCount )
+                {
+                    return NULL;
+                }
+                int iRow = (int)(size_t)m_pahFilteredFeatures[m_iCurFeat++];
+                if( m_poLyrTable->SelectRow(iRow) )
+                {
+                    poFeature = GetCurrentFeature();
+                    if( poFeature )
+                        break;
+                }
+                else if( m_poLyrTable->HasGotError() )
+                {
+                    m_bEOF = TRUE;
+                    return NULL;
+                }
+            }
+        }
+        else if( m_poIterator != NULL )
+        {
+            while( TRUE )
+            {
+                int iRow = m_poIterator->GetNextRowSortedByFID();
+                if( iRow < 0 )
+                    return NULL;
+                if( m_poLyrTable->SelectRow(iRow) )
+                {
+                    poFeature = GetCurrentFeature();
+                    if( poFeature )
+                        break;
+                }
+                else if( m_poLyrTable->HasGotError() )
+                {
+                    m_bEOF = TRUE;
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            while( TRUE )
+            {
+                if( m_iCurFeat == m_poLyrTable->GetTotalRecordCount() )
+                {
+                    return NULL;
+                }
+                if( m_poLyrTable->SelectRow(m_iCurFeat++) )
+                {
+                    poFeature = GetCurrentFeature();
+                    if( m_eSpatialIndexState == SPI_IN_BUILDING &&
+                        m_iCurFeat == m_poLyrTable->GetTotalRecordCount() )
+                    {
+                        CPLDebug("OpenFileGDB", "SPI_COMPLETED");
+                        m_eSpatialIndexState = SPI_COMPLETED;
+                    }
+                    if( poFeature )
+                        break;
+                }
+                else if( m_poLyrTable->HasGotError() )
+                {
+                    m_bEOF = TRUE;
+                    return NULL;
+                }
+            }
+        }
+
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL ||
+                (m_poIterator != NULL && m_bIteratorSufficientToEvaluateFilter) ||
+                m_poAttrQuery->Evaluate( poFeature ) ) )
+        {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
+
+/***********************************************************************/
+/*                          GetFeature()                               */
+/***********************************************************************/
+
+OGRFeature* OGROpenFileGDBLayer::GetFeature( long nFeatureId )
+{
+    if( !BuildLayerDefinition() )
+        return NULL;
+
+    if( nFeatureId < 1 || nFeatureId > m_poLyrTable->GetTotalRecordCount() )
+        return NULL;
+    if( !m_poLyrTable->SelectRow((int)nFeatureId - 1) )
+        return NULL;
+
+    /* Temporarily disable spatial filter */
+    OGRGeometry* poOldSpatialFilter = m_poFilterGeom;
+    m_poFilterGeom = NULL;
+    /* and also spatial index state to avoid features to be inserted */
+    /* multiple times in spatial index */
+    SPIState eOldState = m_eSpatialIndexState;
+    m_eSpatialIndexState = SPI_INVALID;
+
+    OGRFeature* poFeature = GetCurrentFeature();
+
+    /* Set it back */
+    m_poFilterGeom = poOldSpatialFilter;
+    m_eSpatialIndexState = eOldState;
+
+    return poFeature;
+}
+
+/***********************************************************************/
+/*                         SetNextByIndex()                            */
+/***********************************************************************/
+
+OGRErr OGROpenFileGDBLayer::SetNextByIndex( long nIndex )
+{
+    if( m_poIterator != NULL )
+        return OGRLayer::SetNextByIndex(nIndex);
+
+    if( !BuildLayerDefinition() )
+        return OGRERR_FAILURE;
+
+    if( m_eSpatialIndexState == SPI_IN_BUILDING )
+        m_eSpatialIndexState = SPI_INVALID;
+
+    if( m_nFilteredFeatureCount >= 0 )
+    {
+        if( nIndex < 0 || nIndex >= m_nFilteredFeatureCount )
+            return OGRERR_FAILURE;
+        m_iCurFeat = nIndex;
+        return OGRERR_NONE;
+    }
+    else if( m_poLyrTable->GetValidRecordCount() == m_poLyrTable->GetTotalRecordCount() )
+    {
+        if( nIndex < 0 || nIndex >= m_poLyrTable->GetValidRecordCount() )
+            return OGRERR_FAILURE;
+        m_iCurFeat = nIndex;
+        return OGRERR_NONE;
+    }
+    else
+        return OGRLayer::SetNextByIndex(nIndex);
+}
+
+/***********************************************************************/
+/*                           GetExtent()                               */
+/***********************************************************************/
+
+OGRErr OGROpenFileGDBLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+{
+    (void)bForce;
+
+    if( !BuildLayerDefinition() )
+        return OGRERR_FAILURE;
+
+    if( m_iGeomFieldIdx >= 0 && m_poLyrTable->GetValidRecordCount() > 0 )
+    {
+        FileGDBGeomField* poGDBGeomField =
+            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
+        psExtent->MinX = poGDBGeomField->GetXMin();
+        psExtent->MinY = poGDBGeomField->GetYMin();
+        psExtent->MaxX = poGDBGeomField->GetXMax();
+        psExtent->MaxY = poGDBGeomField->GetYMax();
+        return OGRERR_NONE;
+    }
+    else
+        return OGRERR_FAILURE;
+}
+
+/***********************************************************************/
+/*                         GetFeatureCount()                           */
+/***********************************************************************/
+
+int OGROpenFileGDBLayer::GetFeatureCount( int bForce )
+{
+    if( !BuildLayerDefinition() )
+        return 0;
+
+    /* No filter */
+    if( (m_poFilterGeom == NULL || m_iGeomFieldIdx < 0 ) &&
+        m_poAttrQuery == NULL )
+    {
+        return m_poLyrTable->GetValidRecordCount();
+    }
+    else if( m_nFilteredFeatureCount >= 0 && m_poAttrQuery == NULL )
+    {
+        return m_nFilteredFeatureCount;
+    }
+
+    /* Only geometry filter ? */
+    if( m_poAttrQuery == NULL && m_bFilterIsEnvelope )
+    {
+        int nCount = 0;
+        if( m_eSpatialIndexState == SPI_IN_BUILDING && m_iCurFeat != 0 )
+            m_eSpatialIndexState = SPI_INVALID;
+        
+        int nFilteredFeatureCountAlloc = 0;
+        if( m_eSpatialIndexState == SPI_IN_BUILDING )
+        {
+            CPLFree(m_pahFilteredFeatures);
+            m_pahFilteredFeatures = NULL;
+            m_nFilteredFeatureCount = 0;
+        }
+
+        for(int i=0;i<m_poLyrTable->GetTotalRecordCount();i++)
+        {
+            if( !m_poLyrTable->SelectRow(i) )
+            {
+                if( m_poLyrTable->HasGotError() )
+                    break;
+                else
+                    continue;
+            }
+
+            const OGRField* psField = m_poLyrTable->GetFieldValue(m_iGeomFieldIdx);
+            if( psField != NULL )
+            {
+                if( m_eSpatialIndexState == SPI_IN_BUILDING )
+                {
+                    OGREnvelope sFeatureEnvelope;
+                    if( m_poLyrTable->GetFeatureExtent(psField,
+                                                       &sFeatureEnvelope) )
+                    {
+                        CPLRectObj sBounds;
+                        sBounds.minx = sFeatureEnvelope.MinX;
+                        sBounds.miny = sFeatureEnvelope.MinY;
+                        sBounds.maxx = sFeatureEnvelope.MaxX;
+                        sBounds.maxy = sFeatureEnvelope.MaxY;
+                        CPLQuadTreeInsertWithBounds(m_pQuadTree,
+                                                    (void*)(size_t)i,
+                                                    &sBounds);
+                    }
+                }
+
+                if( m_poLyrTable->DoesGeometryIntersectsFilterEnvelope(psField) )
+                {
+                    OGRGeometry* poGeom = m_poGeomConverter->GetAsGeometry(psField);
+                    if( poGeom != NULL && FilterGeometry( poGeom ))
+                    {
+                        if( m_eSpatialIndexState == SPI_IN_BUILDING )
+                        {
+                            if( nCount == nFilteredFeatureCountAlloc )
+                            {
+                                nFilteredFeatureCountAlloc = 4 * nFilteredFeatureCountAlloc / 3 + 1024;
+                                m_pahFilteredFeatures = (void**)CPLRealloc(
+                                    m_pahFilteredFeatures, sizeof(void*) * nFilteredFeatureCountAlloc);
+                            }
+                            m_pahFilteredFeatures[nCount] = (void*)(size_t)i;
+                        }
+                        nCount ++;
+                    }
+                    delete poGeom;
+                }
+            }
+        }
+        if( m_eSpatialIndexState == SPI_IN_BUILDING )
+        {
+            m_nFilteredFeatureCount = nCount;
+            m_eSpatialIndexState = SPI_COMPLETED;
+        }
+
+        return nCount;
+    }
+    /* Only simple attribute filter ? */
+    else if( m_poFilterGeom == NULL &&
+             m_poIterator != NULL && m_bIteratorSufficientToEvaluateFilter )
+    {
+        return m_poIterator->GetRowCount();
+    }
+
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int OGROpenFileGDBLayer::TestCapability( const char * pszCap )
+{
+    if( !BuildLayerDefinition() )
+        return FALSE;
+
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
+    {
+        return( (m_poFilterGeom == NULL || m_iGeomFieldIdx < 0 ) &&
+                m_poAttrQuery == NULL );
+    }
+    else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
+    {
+        return ( m_poLyrTable->GetValidRecordCount() ==
+                 m_poLyrTable->GetTotalRecordCount() &&
+                 m_poIterator == NULL );
+    }
+    else if( EQUAL(pszCap,OLCRandomRead) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCIgnoreFields) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    {
+        return TRUE; /* ? */
+    }
+
+    return FALSE;
+}
+
+/***********************************************************************/
+/*                         HasIndexForField()                          */
+/***********************************************************************/
+
+int OGROpenFileGDBLayer::HasIndexForField(const char* pszFieldName)
+{
+    if( !BuildLayerDefinition() )
+        return FALSE;
+    
+    int nTableColIdx = m_poLyrTable->GetFieldIdx(pszFieldName);
+    return ( nTableColIdx >= 0 &&
+             m_poLyrTable->GetField(nTableColIdx)->HasIndex() );
+}
+
+/***********************************************************************/
+/*                             BuildIndex()                            */
+/***********************************************************************/
+
+FileGDBIterator* OGROpenFileGDBLayer::BuildIndex(const char* pszFieldName,
+                                                 int bAscending,
+                                                 swq_op op,
+                                                 swq_expr_node* poValue)
+{
+    if( !BuildLayerDefinition() )
+        return NULL;
+
+    int idx = GetLayerDefn()->GetFieldIndex(pszFieldName);
+    if( idx < 0 )
+        return NULL;
+    OGRFieldDefn* poFieldDefn = GetLayerDefn()->GetFieldDefn(idx);
+
+    int nTableColIdx = m_poLyrTable->GetFieldIdx(pszFieldName);
+    if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+    {
+        if( op == SWQ_UNKNOWN )
+            return FileGDBIterator::BuildIsNotNull(m_poLyrTable, nTableColIdx, bAscending);
+        else
+        {
+            OGRField sValue;
+            if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue, poValue) )
+            {
+                FileGDBSQLOp eOp;
+                switch( op )
+                {
+                    case SWQ_LE: eOp = FGSO_LE; break;
+                    case SWQ_LT: eOp = FGSO_LT; break;
+                    case SWQ_EQ: eOp = FGSO_EQ; break;
+                    case SWQ_GE: eOp = FGSO_GE; break;
+                    case SWQ_GT: eOp = FGSO_GT; break;
+                    default: return NULL;
+                }
+
+                return FileGDBIterator::Build(
+                                m_poLyrTable, nTableColIdx, bAscending,
+                                eOp, poFieldDefn->GetType(), &sValue);
+            }
+        }
+    }
+    return NULL;
+}
+
+/***********************************************************************/
+/*                          GetMinMaxValue()                           */
+/***********************************************************************/
+
+const OGRField* OGROpenFileGDBLayer::GetMinMaxValue(OGRFieldDefn* poFieldDefn,
+                                                    int bIsMin,
+                                                    int& eOutType)
+{
+    eOutType = OFTMaxType;
+    if( !BuildLayerDefinition() )
+        return NULL;
+
+    int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+    if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+    {
+        delete m_poIterMinMax;
+        m_poIterMinMax = FileGDBIterator::BuildIsNotNull(
+                                                m_poLyrTable, nTableColIdx, TRUE);
+        if( m_poIterMinMax != NULL )
+        {
+            const OGRField* poRet = (bIsMin ) ?
+                m_poIterMinMax->GetMinValue(eOutType) :
+                m_poIterMinMax->GetMaxValue(eOutType);
+            if( poRet == NULL )
+                eOutType = poFieldDefn->GetType();
+            return poRet;
+        }
+    }
+    return NULL;
+}
+
+/***********************************************************************/
+/*                        GetMinMaxSumCount()                          */
+/***********************************************************************/
+
+int OGROpenFileGDBLayer::GetMinMaxSumCount(OGRFieldDefn* poFieldDefn,
+                                           double& dfMin, double& dfMax,
+                                           double& dfSum, int& nCount)
+{
+    dfMin = 0.0;
+    dfMax = 0.0;
+    dfSum = 0.0;
+    nCount = 0;
+    if( !BuildLayerDefinition() )
+        return FALSE;
+
+    int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+    if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
+    {
+        FileGDBIterator* poIter = FileGDBIterator::BuildIsNotNull(
+                                                m_poLyrTable, nTableColIdx, TRUE);
+        if( poIter != NULL )
+        {
+            int nRet = poIter->GetMinMaxSumCount(dfMin, dfMax, dfSum, nCount);
+            delete poIter;
+            return nRet;
+        }
+    }
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/osm/drv_osm.html b/ogr/ogrsf_frmts/osm/drv_osm.html
index 3914992..0c11e35 100644
--- a/ogr/ogrsf_frmts/osm/drv_osm.html
+++ b/ogr/ogrsf_frmts/osm/drv_osm.html
@@ -35,7 +35,7 @@ The customization is essentially which OSM attributes and keys should be transla
 
 <h3>"other_tags" field</h3>
 
-When keys are not strictly identified in the <i>osmconf.ini</i> file, the key value pair is appended
+When keys are not strictly identified in the <i>osmconf.ini</i> file, the key/value pair is appended
 in a "other_tags" field, with a syntax compatible with the PostgreSQL HSTORE type. See the
 <i>COLUMN_TYPES</i> layer creation option of the <a href="drv_pg.html">PG driver</a>.<p>
 
@@ -44,6 +44,14 @@ For example :
 ogr2ogr -f PostgreSQL "PG:dbname=osm" test.pbf -lco COLUMN_TYPES=other_tags=hstore
 </pre>
 
+<h3>"all_tags" field</h3>
+
+(OGR >= 1.11)<p>
+
+Similar to "other_tags", except that it contains both keys specifically identified to be reported as
+dedicated fields, as well as other keys.<p>
+"all_tags" is disabled by default, and when enabled, it is exclusive with "other_tags".
+
 <h3>Internal working and performance tweaking</h3>
 
 The driver will use an internal SQLite database to resolve geometries. If that database remains under 100 MB
diff --git a/ogr/ogrsf_frmts/osm/gpb.h b/ogr/ogrsf_frmts/osm/gpb.h
index 08438f6..3f262c9 100644
--- a/ogr/ogrsf_frmts/osm/gpb.h
+++ b/ogr/ogrsf_frmts/osm/gpb.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gpb.h 25370 2012-12-27 21:20:05Z rouault $
+ * $Id: gpb.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  * Purpose:  Google Protocol Buffer generic handling functions
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -223,7 +223,7 @@ static void SkipVarInt(GByte** ppabyData)
         pabyData += nDataLength;
 
 /************************************************************************/
-/*                         SkipUnkownField()                            */
+/*                         SkipUnknownField()                           */
 /************************************************************************/
 
 #define SKIP_UNKNOWN_FIELD_INLINE(pabyData, pabyDataLimit, verbose) \
@@ -264,10 +264,10 @@ static void SkipVarInt(GByte** ppabyData)
         }
 
 static
-int SkipUnkownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbose) CPL_NO_INLINE;
+int SkipUnknownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbose) CPL_NO_INLINE;
 
 static
-int SkipUnkownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbose)
+int SkipUnknownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbose)
 {
     GByte* pabyDataBefore = pabyData;
     SKIP_UNKNOWN_FIELD_INLINE(pabyData, pabyDataLimit, verbose);
@@ -278,7 +278,7 @@ end_error:
 
 #define SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, verbose) \
     { \
-        int _nOffset = SkipUnkownField(nKey, pabyData, pabyDataLimit, verbose); \
+        int _nOffset = SkipUnknownField(nKey, pabyData, pabyDataLimit, verbose); \
         if (_nOffset < 0) \
             GOTO_END_ERROR; \
         pabyData += _nOffset; \
diff --git a/ogr/ogrsf_frmts/osm/ogr_osm.h b/ogr/ogrsf_frmts/osm/ogr_osm.h
index 9cb18a9..a441bc7 100644
--- a/ogr/ogrsf_frmts/osm/ogr_osm.h
+++ b/ogr/ogrsf_frmts/osm/ogr_osm.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_osm.h 25362 2012-12-27 17:02:54Z rouault $
+ * $Id: ogr_osm.h 27138 2014-04-07 20:32:14Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/OpenStreeMap driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,6 +30,9 @@
 #ifndef _OGR_OSM_H_INCLUDED
 #define _OGR_OSM_H_INCLUDED
 
+// replace O(log2(N)) complexity of FindNode() by O(1)
+#define ENABLE_NODE_LOOKUP_BY_HASHING 1
+
 #include "ogrsf_frmts.h"
 #include "cpl_string.h"
 
@@ -59,8 +62,9 @@ class OGROSMDataSource;
 class OGROSMLayer : public OGRLayer
 {
     friend class OGROSMDataSource;
-    
+
     OGROSMDataSource    *poDS;
+    int                  nIdxLayer;
     OGRFeatureDefn      *poFeatureDefn;
     OGRSpatialReference *poSRS;
     long                 nFeatureCount;
@@ -84,6 +88,9 @@ class OGROSMLayer : public OGRLayer
     int                   bHasUser;
     int                   bHasChangeset;
     int                   bHasOtherTags;
+    int                   nIndexOtherTags;
+    int                   bHasAllTags;
+    int                   nIndexAllTags;
 
     int                   bHasWarnedTooManyFeatures;
 
@@ -92,7 +99,9 @@ class OGROSMLayer : public OGRLayer
 
     int                   bUserInterested;
 
-    int                  AddToArray(OGRFeature* poFeature);
+    int                  AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold);
+
+    int                   AddInOtherOrAllTags(const char* pszK);
 
     char                  szLaunderedFieldName[256];
     const char*           GetLaunderedFieldName(const char* pszName);
@@ -107,25 +116,28 @@ class OGROSMLayer : public OGRLayer
 
   public:
                         OGROSMLayer( OGROSMDataSource* poDS,
+                                     int nIdxLayer,
                                      const char* pszName );
     virtual             ~OGROSMLayer();
 
     virtual OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
-    virtual OGRSpatialReference * GetSpatialRef() { return poSRS; }
     
     virtual void        ResetReading();
     virtual int         TestCapability( const char * );
                                      
     virtual OGRFeature *GetNextFeature();
     virtual int         GetFeatureCount( int bForce );
-    
+        
+    virtual OGRErr      SetAttributeFilter( const char* pszAttrQuery );
+
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
 
     const OGREnvelope*  GetSpatialFilterEnvelope();
 
     int                 AddFeature(OGRFeature* poFeature,
                                    int bAttrFilterAlreadyEvaluated,
-                                   int* pbFilteredOut = NULL);
+                                   int* pbFilteredOut = NULL,
+                                   int bCheckFeatureThreshold = TRUE);
     void                ForceResetReading();
 
     void                AddField(const char* pszName, OGRFieldType eFieldType);
@@ -151,7 +163,9 @@ class OGROSMLayer : public OGRLayer
 
     void                SetHasOtherTags(int bIn) { bHasOtherTags = bIn; }
     int                 HasOtherTags() const { return bHasOtherTags; }
-    int                 AddInOtherTag(const char* pszK);
+
+    void                SetHasAllTags(int bIn) { bHasAllTags = bIn; }
+    int                 HasAllTags() const { return bHasAllTags; }
 
     void                SetFieldsFromTags(OGRFeature* poFeature,
                                           GIntBig nID,
@@ -227,6 +241,14 @@ typedef struct
     int                 bAttrFilterAlreadyEvaluated : 1;
 } WayFeaturePair;
 
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+typedef struct
+{
+    int nInd;           /* values are indexes of panReqIds */
+    int nNext;          /* values are indexes of psCollisionBuckets, or -1 to stop the chain */
+} CollisionBucket;
+#endif
+
 class OGROSMDataSource : public OGRDataSource
 {
     friend class OGROSMLayer;
@@ -307,6 +329,17 @@ class OGROSMDataSource : public OGRDataSource
 
     unsigned int        nReqIds;
     GIntBig            *panReqIds;
+
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+    int                 bEnableHashedIndex;
+    /* values >= 0 are indexes of panReqIds. */
+    /*        == -1 for unoccupied */
+    /*        < -1 are expressed as -nIndexToCollisonBuckets-2 where nIndexToCollisonBuckets point to psCollisionBuckets */
+    int                *panHashedIndexes; 
+    CollisionBucket    *psCollisionBuckets;
+    int                 bHashedIndexValid;
+#endif
+
     LonLat             *pasLonLatArray;
 
     IndexedKVP         *pasAccumulatedTags; /* points to content of pabyNonRedundantValues or aoMapIndexedKeys */
@@ -409,7 +442,7 @@ class OGROSMDataSource : public OGRDataSource
     int                 Open ( const char* pszFilename, int bUpdateIn );
 
     int                 ResetReading();
-    int                 ParseNextChunk();
+    int                 ParseNextChunk(int nIdxLayer);
     OGRErr              GetExtent( OGREnvelope *psExtent );
     int                 IsInterleavedReading();
 
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
index 457f06e..0dd6258 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrosmdatasource.cpp 25363 2012-12-27 17:20:24Z rouault $
+ * $Id: ogrosmdatasource.cpp 27139 2014-04-07 20:39:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -101,6 +101,16 @@
 /* Max number of features that are accumulated in panUnsortedReqIds */
 #define MAX_ACCUMULATED_NODES       1000000
 
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+/* Size of panHashedIndexes array. Must be in the list at */
+/* http://planetmath.org/goodhashtableprimes , and greater than MAX_ACCUMULATED_NODES */
+#define HASHED_INDEXES_ARRAY_SIZE   3145739
+//#define HASHED_INDEXES_ARRAY_SIZE   1572869
+#define COLLISION_BUCKET_ARRAY_SIZE ((MAX_ACCUMULATED_NODES / 100) * 40)
+/* hash function = identity ! */
+#define HASH_ID_FUNC(x)             ((GUIntBig)(x))
+#endif // ENABLE_NODE_LOOKUP_BY_HASHING
+
 //#define FAKE_LOOKUP_NODES
 
 //#define DEBUG_MEM_USAGE
@@ -111,7 +121,7 @@ size_t GetMaxTotalAllocs();
 static void WriteVarInt64(GUIntBig nSVal, GByte** ppabyData);
 static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData);
 
-CPL_CVSID("$Id: ogrosmdatasource.cpp 25363 2012-12-27 17:20:24Z rouault $");
+CPL_CVSID("$Id: ogrosmdatasource.cpp 27139 2014-04-07 20:39:34Z rouault $");
 
 class DSToBeOpened
 {
@@ -234,6 +244,12 @@ OGROSMDataSource::OGROSMDataSource()
 
     nReqIds = 0;
     panReqIds = NULL;
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+    bEnableHashedIndex = TRUE;
+    panHashedIndexes = NULL;
+    psCollisionBuckets = NULL;
+    bHashedIndexValid = FALSE;
+#endif
     pasLonLatArray = NULL;
     nUnsortedReqIds = 0;
     panUnsortedReqIds = NULL;
@@ -289,6 +305,10 @@ OGROSMDataSource::~OGROSMDataSource()
     }
 
     CPLFree(panReqIds);
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+    CPLFree(panHashedIndexes);
+    CPLFree(psCollisionBuckets);
+#endif
     CPLFree(pasLonLatArray);
     CPLFree(panUnsortedReqIds);
 
@@ -659,6 +679,12 @@ int OGROSMDataSource::FlushCurrentSectorCompressedCase()
 
         return TRUE;
     }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot write in temporary node file %s : %s",
+                 osNodesFilename.c_str(), VSIStrerror(errno));
+    }
 
     return FALSE;
 }
@@ -675,6 +701,12 @@ int OGROSMDataSource::FlushCurrentSectorNonCompressedCase()
         nNodesFileSize += SECTOR_SIZE;
         return TRUE;
     }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot write in temporary node file %s : %s",
+                 osNodesFilename.c_str(), VSIStrerror(errno));
+    }
 
     return FALSE;
 }
@@ -815,7 +847,9 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
                 poFeature, pasNodes[i].nID, FALSE, pasNodes[i].nTags, pasTags, &pasNodes[i].sInfo );
 
             int bFilteredOut = FALSE;
-            if( !papoLayers[IDX_LYR_POINTS]->AddFeature(poFeature, FALSE, &bFilteredOut) )
+            if( !papoLayers[IDX_LYR_POINTS]->AddFeature(poFeature, FALSE,
+                                                        &bFilteredOut,
+                                                        !bFeatureAdded) )
             {
                 bStopParsing = TRUE;
                 break;
@@ -836,12 +870,88 @@ static void OGROSMNotifyNodes (unsigned int nNodes, OSMNode* pasNodes,
 /*                            LookupNodes()                             */
 /************************************************************************/
 
+//#define DEBUG_COLLISIONS 1
+
 void OGROSMDataSource::LookupNodes( )
 {
     if( bCustomIndexing )
         LookupNodesCustom();
     else
         LookupNodesSQLite();
+
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+    if( nReqIds > 1 && bEnableHashedIndex )
+    {
+        memset(panHashedIndexes, 0xFF, HASHED_INDEXES_ARRAY_SIZE * sizeof(int));
+        bHashedIndexValid = TRUE;
+#ifdef DEBUG_COLLISIONS
+        int nCollisions = 0;
+#endif
+        int iNextFreeBucket = 0;
+        for(unsigned int i = 0; i < nReqIds; i++)
+        {
+            int nIndInHashArray = HASH_ID_FUNC(panReqIds[i]) % HASHED_INDEXES_ARRAY_SIZE;
+            int nIdx = panHashedIndexes[nIndInHashArray];
+            if( nIdx == -1 )
+            {
+                panHashedIndexes[nIndInHashArray] = i;
+            }
+            else
+            {
+#ifdef DEBUG_COLLISIONS
+                nCollisions ++;
+#endif
+                int iBucket;
+                if( nIdx >= 0 )
+                {
+                    if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
+                    {
+                        CPLDebug("OSM", "Too many collisions. Disabling hashed indexing");
+                        bHashedIndexValid = FALSE;
+                        bEnableHashedIndex = FALSE;
+                        break;
+                    }
+                    iBucket = iNextFreeBucket;
+                    psCollisionBuckets[iNextFreeBucket].nInd = nIdx;
+                    psCollisionBuckets[iNextFreeBucket].nNext = -1;
+                    panHashedIndexes[nIndInHashArray] = -iNextFreeBucket - 2;
+                    iNextFreeBucket ++;
+                }
+                else
+                    iBucket = -nIdx - 2;
+                if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
+                {
+                    CPLDebug("OSM", "Too many collisions. Disabling hashed indexing");
+                    bHashedIndexValid = FALSE;
+                    bEnableHashedIndex = FALSE;
+                    break;
+                }
+                while( TRUE )
+                {
+                    int iNext = psCollisionBuckets[iBucket].nNext;
+                    if( iNext < 0 )
+                    {
+                        psCollisionBuckets[iBucket].nNext = iNextFreeBucket;
+                        psCollisionBuckets[iNextFreeBucket].nInd = i;
+                        psCollisionBuckets[iNextFreeBucket].nNext = -1;
+                        iNextFreeBucket ++;
+                        break;
+                    }
+                    iBucket = iNext;
+                }
+            }
+        }
+#ifdef DEBUG_COLLISIONS
+        /* Collision rate in practice is around 12% on France, Germany, ... */
+        /* Maximum seen ~ 15.9% on a planet file but often much smaller. */
+        CPLDebug("OSM", "nCollisions = %d/%d (%.1f %%), iNextFreeBucket = %d/%d",
+                 nCollisions, nReqIds, nCollisions * 100.0 / nReqIds,
+                 iNextFreeBucket, COLLISION_BUCKET_ARRAY_SIZE);
+#endif
+    }
+    else
+        bHashedIndexValid = FALSE;
+#endif // ENABLE_NODE_LOOKUP_BY_HASHING
 }
 
 /************************************************************************/
@@ -1483,16 +1593,16 @@ int OGROSMDataSource::FindNode(GIntBig nID)
 {
     int iFirst = 0;
     int iLast = nReqIds - 1;
-    while(iFirst <= iLast)
+    while(iFirst < iLast)
     {
         int iMid = (iFirst + iLast) / 2;
-        if( nID < panReqIds[iMid])
-            iLast = iMid - 1;
-        else if( nID > panReqIds[iMid])
+        if( nID > panReqIds[iMid])
             iFirst = iMid + 1;
         else
-            return iMid;
+            iLast = iMid;
     }
+    if( iFirst == iLast && nID == panReqIds[iFirst] )
+        return iFirst;
     return -1;
 }
 
@@ -1516,23 +1626,66 @@ void OGROSMDataSource::ProcessWaysBatch()
 
         unsigned int nFound = 0;
         unsigned int i;
-        int nIdx = -1;
-        for(i=0;i<psWayFeaturePairs->nRefs;i++)
+
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+        if( bHashedIndexValid )
         {
-            if( nIdx >= 0 && psWayFeaturePairs->panNodeRefs[i] == psWayFeaturePairs->panNodeRefs[i-1] + 1 )
+            for(i=0;i<psWayFeaturePairs->nRefs;i++)
             {
-                if( nIdx+1 < (int)nReqIds && panReqIds[nIdx+1] == psWayFeaturePairs->panNodeRefs[i] )
-                    nIdx ++;
-                else
+                int nIndInHashArray =
+                    HASH_ID_FUNC(psWayFeaturePairs->panNodeRefs[i]) %
+                        HASHED_INDEXES_ARRAY_SIZE;
+                int nIdx = panHashedIndexes[nIndInHashArray];
+                if( nIdx < -1 )
+                {
+                    int iBucket = -nIdx - 2;
+                    while( TRUE )
+                    {
+                        nIdx = psCollisionBuckets[iBucket].nInd;
+                        if( panReqIds[nIdx] == psWayFeaturePairs->panNodeRefs[i] )
+                            break;
+                        iBucket = psCollisionBuckets[iBucket].nNext;
+                        if( iBucket < 0 )
+                        {
+                            nIdx = -1;
+                            break;
+                        }
+                    }
+                }
+                else if( panReqIds[nIdx] != psWayFeaturePairs->panNodeRefs[i] )
                     nIdx = -1;
+
+                if (nIdx >= 0)
+                {
+                    pasLonLatCache[nFound].nLon = pasLonLatArray[nIdx].nLon;
+                    pasLonLatCache[nFound].nLat = pasLonLatArray[nIdx].nLat;
+                    nFound ++;
+                }
             }
-            else
-                nIdx = FindNode( psWayFeaturePairs->panNodeRefs[i] );
-            if (nIdx >= 0)
+        }
+        else
+#endif // ENABLE_NODE_LOOKUP_BY_HASHING
+        {
+            int nIdx = -1;
+            for(i=0;i<psWayFeaturePairs->nRefs;i++)
             {
-                pasLonLatCache[nFound].nLon = pasLonLatArray[nIdx].nLon;
-                pasLonLatCache[nFound].nLat = pasLonLatArray[nIdx].nLat;
-                nFound ++;
+                if( nIdx >= 0 && psWayFeaturePairs->panNodeRefs[i] ==
+                                 psWayFeaturePairs->panNodeRefs[i-1] + 1 )
+                {
+                    if( nIdx+1 < (int)nReqIds && panReqIds[nIdx+1] ==
+                                        psWayFeaturePairs->panNodeRefs[i] )
+                        nIdx ++;
+                    else
+                        nIdx = -1;
+                }
+                else
+                    nIdx = FindNode( psWayFeaturePairs->panNodeRefs[i] );
+                if (nIdx >= 0)
+                {
+                    pasLonLatCache[nFound].nLon = pasLonLatArray[nIdx].nLon;
+                    pasLonLatCache[nFound].nLat = pasLonLatArray[nIdx].nLat;
+                    nFound ++;
+                }
             }
         }
 
@@ -1594,7 +1747,8 @@ void OGROSMDataSource::ProcessWaysBatch()
         int bFilteredOut = FALSE;
         if( !papoLayers[IDX_LYR_LINES]->AddFeature(psWayFeaturePairs->poFeature,
                                                    psWayFeaturePairs->bAttrFilterAlreadyEvaluated,
-                                                   &bFilteredOut) )
+                                                   &bFilteredOut,
+                                                   !bFeatureAdded) )
             bStopParsing = TRUE;
         else if (!bFilteredOut)
             bFeatureAdded = TRUE;
@@ -2353,7 +2507,8 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
         int bFilteredOut = FALSE;
         if( !papoLayers[iCurLayer]->AddFeature( poFeature,
                                                 bAttrFilterAlreadyEvaluated,
-                                                &bFilteredOut ) )
+                                                &bFilteredOut,
+                                                !bFeatureAdded ) )
             bStopParsing = TRUE;
         else if (!bFilteredOut)
             bFeatureAdded = TRUE;
@@ -2445,7 +2600,8 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
             int bFilteredOut = FALSE;
             if( !papoLayers[IDX_LYR_MULTIPOLYGONS]->AddFeature( poFeature,
                                                     FALSE,
-                                                    &bFilteredOut ) )
+                                                    &bFilteredOut,
+                                                    !bFeatureAdded ) )
             {
                 bStopParsing = TRUE;
                 break;
@@ -2537,19 +2693,19 @@ int OGROSMDataSource::Open( const char * pszFilename, int bUpdateIn)
     nLayers = 5;
     papoLayers = (OGROSMLayer**) CPLMalloc(nLayers * sizeof(OGROSMLayer*));
 
-    papoLayers[IDX_LYR_POINTS] = new OGROSMLayer(this, "points");
+    papoLayers[IDX_LYR_POINTS] = new OGROSMLayer(this, IDX_LYR_POINTS, "points");
     papoLayers[IDX_LYR_POINTS]->GetLayerDefn()->SetGeomType(wkbPoint);
 
-    papoLayers[IDX_LYR_LINES] = new OGROSMLayer(this, "lines");
+    papoLayers[IDX_LYR_LINES] = new OGROSMLayer(this, IDX_LYR_LINES, "lines");
     papoLayers[IDX_LYR_LINES]->GetLayerDefn()->SetGeomType(wkbLineString);
 
-    papoLayers[IDX_LYR_MULTILINESTRINGS] = new OGROSMLayer(this, "multilinestrings");
+    papoLayers[IDX_LYR_MULTILINESTRINGS] = new OGROSMLayer(this, IDX_LYR_MULTILINESTRINGS, "multilinestrings");
     papoLayers[IDX_LYR_MULTILINESTRINGS]->GetLayerDefn()->SetGeomType(wkbMultiLineString);
 
-    papoLayers[IDX_LYR_MULTIPOLYGONS] = new OGROSMLayer(this, "multipolygons");
+    papoLayers[IDX_LYR_MULTIPOLYGONS] = new OGROSMLayer(this, IDX_LYR_MULTIPOLYGONS, "multipolygons");
     papoLayers[IDX_LYR_MULTIPOLYGONS]->GetLayerDefn()->SetGeomType(wkbMultiPolygon);
 
-    papoLayers[IDX_LYR_OTHER_RELATIONS] = new OGROSMLayer(this, "other_relations");
+    papoLayers[IDX_LYR_OTHER_RELATIONS] = new OGROSMLayer(this, IDX_LYR_OTHER_RELATIONS, "other_relations");
     papoLayers[IDX_LYR_OTHER_RELATIONS]->GetLayerDefn()->SetGeomType(wkbGeometryCollection);
 
     if( !ParseConf() )
@@ -2570,6 +2726,10 @@ int OGROSMDataSource::Open( const char * pszFilename, int bUpdateIn)
     pabyWayBuffer = (GByte*)VSIMalloc(WAY_BUFFER_SIZE);
 
     panReqIds = (GIntBig*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(GIntBig));
+#ifdef ENABLE_NODE_LOOKUP_BY_HASHING
+    panHashedIndexes = (int*)VSIMalloc(HASHED_INDEXES_ARRAY_SIZE * sizeof(int));
+    psCollisionBuckets = (CollisionBucket*)VSIMalloc(COLLISION_BUCKET_ARRAY_SIZE * sizeof(CollisionBucket));
+#endif
     pasLonLatArray = (LonLat*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(LonLat));
     panUnsortedReqIds = (GIntBig*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(GIntBig));
     pasWayFeaturePairs = (WayFeaturePair*)VSIMalloc(MAX_DELAYED_FEATURES * sizeof(WayFeaturePair));
@@ -3175,6 +3335,13 @@ int OGROSMDataSource::ParseConf()
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                     papoLayers[iCurLayer]->SetHasOtherTags(TRUE);
             }
+            else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "all_tags") == 0 )
+            {
+                if( strcmp(papszTokens[1], "no") == 0 )
+                    papoLayers[iCurLayer]->SetHasAllTags(FALSE);
+                else if( strcmp(papszTokens[1], "yes") == 0 )
+                    papoLayers[iCurLayer]->SetHasAllTags(TRUE);
+            }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_id") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
@@ -3272,7 +3439,15 @@ int OGROSMDataSource::ParseConf()
 
     for(i=0;i<nLayers;i++)
     {
-        if( papoLayers[i]->HasOtherTags() )
+        if( papoLayers[i]->HasAllTags() )
+        {
+            papoLayers[i]->AddField("all_tags", OFTString);
+            if( papoLayers[i]->HasOtherTags() )
+            {
+                papoLayers[i]->SetHasOtherTags(FALSE);
+            }
+        }
+        else if( papoLayers[i]->HasOtherTags() )
             papoLayers[i]->AddField("other_tags", OFTString);
     }
 
@@ -3389,7 +3564,7 @@ int OGROSMDataSource::ResetReading()
 /*                           ParseNextChunk()                           */
 /************************************************************************/
 
-int OGROSMDataSource::ParseNextChunk()
+int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
 {
     if( bStopParsing )
         return FALSE;
@@ -3418,6 +3593,13 @@ int OGROSMDataSource::ParseNextChunk()
                 if( !bHasRowInPolygonsStandalone )
                     bStopParsing = TRUE;
 
+                if( !bInterleavedReading && !bFeatureAdded &&
+                    bHasRowInPolygonsStandalone &&
+                    nIdxLayer != IDX_LYR_MULTIPOLYGONS )
+                {
+                    return FALSE;
+                }
+
                 return bFeatureAdded || bHasRowInPolygonsStandalone;
             }
             else
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
index 98e46f6..a433855 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrosmdriver.cpp 24950 2012-09-22 13:54:36Z rouault $
+ * $Id: ogrosmdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDriver class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 
 extern "C" void CPL_DLL RegisterOGROSM();
 
-CPL_CVSID("$Id: ogrosmdriver.cpp 24950 2012-09-22 13:54:36Z rouault $");
+CPL_CVSID("$Id: ogrosmdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         ~OGROSMDriver()                           */
diff --git a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
index d0b23fc..d355a02 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrosmlayer.cpp 26051 2013-05-27 20:41:34Z rouault $
+ * $Id: ogrosmlayer.cpp 27138 2014-04-07 20:32:14Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMLayer class
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "cpl_time.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrosmlayer.cpp 26051 2013-05-27 20:41:34Z rouault $");
+CPL_CVSID("$Id: ogrosmlayer.cpp 27138 2014-04-07 20:32:14Z rouault $");
 
 #define SWITCH_THRESHOLD   10000
 #define MAX_THRESHOLD      100000
@@ -45,15 +45,18 @@ CPL_CVSID("$Id: ogrosmlayer.cpp 26051 2013-05-27 20:41:34Z rouault $");
 /************************************************************************/
 
 
-OGROSMLayer::OGROSMLayer(OGROSMDataSource* poDS, const char* pszName )
+OGROSMLayer::OGROSMLayer(OGROSMDataSource* poDS, int nIdxLayer, const char* pszName )
 {
     this->poDS = poDS;
+    this->nIdxLayer = nIdxLayer;
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
 
     poSRS = new OGRSpatialReference();
     poSRS->SetWellKnownGeogCS("WGS84");
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     nFeatureArraySize = 0;
     nFeatureArrayMaxSize = 0;
@@ -71,6 +74,9 @@ OGROSMLayer::OGROSMLayer(OGROSMDataSource* poDS, const char* pszName )
     bHasUser = FALSE;
     bHasChangeset = FALSE;
     bHasOtherTags = TRUE;
+    nIndexOtherTags = -1;
+    bHasAllTags = FALSE;
+    nIndexAllTags = -1;
 
     bResetReadingAllowed = FALSE;
     bHasWarnedTooManyFeatures = FALSE;
@@ -144,6 +150,39 @@ void OGROSMLayer::ForceResetReading()
 }
 
 /************************************************************************/
+/*                        SetAttributeFilter()                          */
+/************************************************************************/
+
+OGRErr OGROSMLayer::SetAttributeFilter( const char* pszAttrQuery )
+{
+    if( pszAttrQuery == NULL && m_pszAttrQueryString == NULL )
+        return OGRERR_NONE;
+    if( pszAttrQuery != NULL && m_pszAttrQueryString != NULL &&
+        strcmp(pszAttrQuery, m_pszAttrQueryString) == 0 )
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttrQuery);
+    if( eErr != OGRERR_NONE )
+        return eErr;
+
+    if( nFeatureArrayIndex == 0 )
+    {
+        if( !poDS->IsInterleavedReading() )
+        {
+            poDS->ResetReading();
+        }
+    }
+    else
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "The new attribute filter will "
+                 "not be taken into account immediately. It is advised to "
+                 "set attribute filters for all needed layers, before reading *any* layer");
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
@@ -197,7 +236,7 @@ OGRFeature *OGROSMLayer::GetNextFeature()
             }
 
             /* Read some more data and accumulate features */
-            poDS->ParseNextChunk();
+            poDS->ParseNextChunk(nIdxLayer);
 
             if ( nFeatureArraySize == 0 )
             {
@@ -227,7 +266,7 @@ OGRFeature *OGROSMLayer::GetNextFeature()
         {
             while(TRUE)
             {
-                int bRet = poDS->ParseNextChunk();
+                int bRet = poDS->ParseNextChunk(nIdxLayer);
                 if (nFeatureArraySize != 0)
                     break;
                 if (bRet == FALSE)
@@ -267,9 +306,9 @@ int OGROSMLayer::TestCapability( const char * pszCap )
 /*                             AddToArray()                             */
 /************************************************************************/
 
-int  OGROSMLayer::AddToArray(OGRFeature* poFeature)
+int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
 {
-    if( nFeatureArraySize > MAX_THRESHOLD)
+    if( bCheckFeatureThreshold && nFeatureArraySize > MAX_THRESHOLD)
     {
         if( !bHasWarnedTooManyFeatures )
         {
@@ -290,7 +329,9 @@ int  OGROSMLayer::AddToArray(OGRFeature* poFeature)
                                 nFeatureArrayMaxSize * sizeof(OGRFeature*));
         if (papoNewFeatures == NULL)
         {
-            delete poFeature;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "For layer %s, cannot resize feature array to %d features",
+                     GetName(), nFeatureArrayMaxSize);
             return FALSE;
         }
         papoFeatures = papoNewFeatures;
@@ -316,7 +357,8 @@ int OGROSMLayer::EvaluateAttributeFilter(OGRFeature* poFeature)
 
 int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
                              int bAttrFilterAlreadyEvaluated,
-                             int* pbFilteredOut)
+                             int* pbFilteredOut,
+                             int bCheckFeatureThreshold)
 {
     if( !bUserInterested )
     {
@@ -335,7 +377,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
         && (m_poAttrQuery == NULL || bAttrFilterAlreadyEvaluated
             || m_poAttrQuery->Evaluate( poFeature )) )
     {
-        if (!AddToArray(poFeature))
+        if (!AddToArray(poFeature, bCheckFeatureThreshold))
         {
             delete poFeature;
             return FALSE;
@@ -412,6 +454,12 @@ void OGROSMLayer::AddField(const char* pszName, OGRFieldType eFieldType)
 
     else if( strcmp(pszName, "osm_way_id") == 0 )
         nIndexOSMWayId = nIndex;
+
+    else if( strcmp(pszName, "other_tags") == 0 )
+        nIndexOtherTags = nIndex;
+
+    else if( strcmp(pszName, "all_tags") == 0 )
+        nIndexAllTags = nIndex;
 }
 
 /************************************************************************/
@@ -429,10 +477,10 @@ int OGROSMLayer::GetFieldIndex(const char* pszName)
 }
 
 /************************************************************************/
-/*                              AddInOtherTag()                         */
+/*                         AddInOtherOrAllTags()                        */
 /************************************************************************/
 
-int OGROSMLayer::AddInOtherTag(const char* pszK)
+int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
 {
     int bAddToOtherTags = FALSE;
 
@@ -565,10 +613,14 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         const char* pszV = pasTags[j].pszV;
         int nIndex = GetFieldIndex(pszK);
         if( nIndex >= 0 )
+        {
             poFeature->SetField(nIndex, pszV);
-        else if ( HasOtherTags() )
+            if( nIndexAllTags < 0 )
+                continue;
+        }
+        if ( nIndexAllTags >= 0 || nIndexOtherTags >= 0 )
         {
-            if ( AddInOtherTag(pszK) )
+            if ( AddInOtherOrAllTags(pszK) )
             {
                 int nLenK = (int)strlen(pszK);
                 int nLenV = (int)strlen(pszV);
@@ -579,7 +631,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                     1 >= ALLTAGS_LENGTH - 1 )
                 {
                     if( !bHasWarnedAllTagsTruncated )
-                        CPLDebug("OSM", "all_tags field truncated for feature " CPL_FRMT_GIB, nID);
+                        CPLDebug("OSM", "all_tags/other_tags field truncated for feature " CPL_FRMT_GIB, nID);
                     bHasWarnedAllTagsTruncated = TRUE;
                     continue;
                 }
@@ -611,7 +663,10 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
     if( nAllTagsOff )
     {
         pszAllTags[nAllTagsOff] = '\0';
-        poFeature->SetField(GetLayerDefn()->GetFieldCount() - 1, pszAllTags);
+        if( nIndexAllTags >= 0 )
+            poFeature->SetField(nIndexAllTags, pszAllTags);
+        else
+            poFeature->SetField(nIndexOtherTags, pszAllTags);
     }
 }
 
diff --git a/ogr/ogrsf_frmts/osm/osm2osm.c b/ogr/ogrsf_frmts/osm/osm2osm.c
index 889da4d..ced8032 100644
--- a/ogr/ogrsf_frmts/osm/osm2osm.c
+++ b/ogr/ogrsf_frmts/osm/osm2osm.c
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: osm2osm.c 24671 2012-07-10 18:37:55Z rouault $
+ * $Id: osm2osm.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  * Purpose:  osm2osm
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/osm/osm_parser.cpp b/ogr/ogrsf_frmts/osm/osm_parser.cpp
index b09ba99..a375119 100644
--- a/ogr/ogrsf_frmts/osm/osm_parser.cpp
+++ b/ogr/ogrsf_frmts/osm/osm_parser.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: osm_parser.cpp 25926 2013-04-18 18:33:29Z rouault $
+ * $Id: osm_parser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  * Purpose:  OSM XML and OSM PBF parser
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -45,7 +45,7 @@
 
 #define XML_BUFSIZE 64*1024
 
-CPL_CVSID("$Id: osm_parser.cpp 25926 2013-04-18 18:33:29Z rouault $");
+CPL_CVSID("$Id: osm_parser.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            INIT_INFO()                               */
@@ -804,7 +804,11 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
     OSMNode sNode;
 
     sNode.nID = 0;
+    sNode.dfLat = 0.0;
+    sNode.dfLon = 0.0;
     INIT_INFO(sNode.sInfo);
+    sNode.nTags = 0;
+    sNode.pasTags = NULL;
 
     /* printf(">ReadNode\n"); */
     while(pabyData < pabyDataLimit)
diff --git a/ogr/ogrsf_frmts/osm/osm_parser.h b/ogr/ogrsf_frmts/osm/osm_parser.h
index c32f611..bd9fea5 100644
--- a/ogr/ogrsf_frmts/osm/osm_parser.h
+++ b/ogr/ogrsf_frmts/osm/osm_parser.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: osm_parser.h 24669 2012-07-10 16:04:24Z rouault $
+ * $Id: osm_parser.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  * Purpose:  OSM XML and OSM PBF parser
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/pcidsk/ogr_pcidsk.h b/ogr/ogrsf_frmts/pcidsk/ogr_pcidsk.h
index 8776e51..3fc7720 100644
--- a/ogr/ogrsf_frmts/pcidsk/ogr_pcidsk.h
+++ b/ogr/ogrsf_frmts/pcidsk/ogr_pcidsk.h
@@ -74,7 +74,6 @@ class OGRPCIDSKLayer : public OGRLayer
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 
-    virtual OGRSpatialReference *GetSpatialRef();
     int                 GetFeatureCount( int );
     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
 };
diff --git a/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp b/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
index 6bf355a..ef5e848 100644
--- a/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
+++ b/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -46,7 +47,6 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
 
     poFeatureDefn = new OGRFeatureDefn( poSeg->GetName().c_str() );
     poFeatureDefn->Reference();
-    //poFeatureDefn->SetGeomType( wkbNone );
 
     hLastShapeId = PCIDSK::NullShapeId;
 
@@ -159,6 +159,9 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Non-PCIDSK exception trapped while initializing layer, operation likely impaired." );
     }
+    
+    if( poFeatureDefn->GetGeomFieldCount() > 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
 
 /************************************************************************/
@@ -182,16 +185,6 @@ OGRPCIDSKLayer::~OGRPCIDSKLayer()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRPCIDSKLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/pdf/ogr_pdf.h b/ogr/ogrsf_frmts/pdf/ogr_pdf.h
index d08060b..72126ed 100644
--- a/ogr/ogrsf_frmts/pdf/ogr_pdf.h
+++ b/ogr/ogrsf_frmts/pdf/ogr_pdf.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_pdf.h 25325 2012-12-16 21:25:25Z rouault $
+ * $Id: ogr_pdf.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF Translator
  * Purpose:  Definition of classes for OGR .pdf driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/pdf/ogrpdfdatasource.cpp b/ogr/ogrsf_frmts/pdf/ogrpdfdatasource.cpp
index 488ae79..01f0ed0 100644
--- a/ogr/ogrsf_frmts/pdf/ogrpdfdatasource.cpp
+++ b/ogr/ogrsf_frmts/pdf/ogrpdfdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpdfdatasource.cpp 25325 2012-12-16 21:25:25Z rouault $
+ * $Id: ogrpdfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF Translator
  * Purpose:  Implements OGRPDFDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,7 +39,7 @@
 #define SQUARE(x) ((x)*(x))
 #define EPSILON 1e-5
 
-CPL_CVSID("$Id: ogrpdfdatasource.cpp 25325 2012-12-16 21:25:25Z rouault $");
+CPL_CVSID("$Id: ogrpdfdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRPDFLayer()                             */
@@ -259,7 +259,7 @@ void OGRPDFDataSource::CleanupIntermediateResources()
 typedef struct
 {
     char        szOpName[4];
-    char        nArgs;
+    int         nArgs;
 } PDFOperator;
 
 static const PDFOperator asPDFOperators [] =
diff --git a/ogr/ogrsf_frmts/pdf/ogrpdfdriver.cpp b/ogr/ogrsf_frmts/pdf/ogrpdfdriver.cpp
index 5395250..83b6c40 100644
--- a/ogr/ogrsf_frmts/pdf/ogrpdfdriver.cpp
+++ b/ogr/ogrsf_frmts/pdf/ogrpdfdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpdfdriver.cpp 24143 2012-03-19 21:40:42Z rouault $
+ * $Id: ogrpdfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDF Translator
  * Purpose:  Implements OGRPDFDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_pdf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpdfdriver.cpp 24143 2012-03-19 21:40:42Z rouault $");
+CPL_CVSID("$Id: ogrpdfdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRPDF();
 
diff --git a/ogr/ogrsf_frmts/pds/ogr_pds.h b/ogr/ogrsf_frmts/pds/ogr_pds.h
index 2b740d2..277b00c 100644
--- a/ogr/ogrsf_frmts/pds/ogr_pds.h
+++ b/ogr/ogrsf_frmts/pds/ogr_pds.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_pds.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_pds.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Definition of classes for OGR .pdstable driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -93,8 +93,6 @@ class OGRPDSLayer : public OGRLayer
 
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
-
     virtual int                 GetFeatureCount(int bForce = TRUE );
 
     virtual OGRFeature         *GetFeature( long nFID );
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
index 0ad1bc2..cf08596 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpdsdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
+ * $Id: ogrpdsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpdsdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
+CPL_CVSID("$Id: ogrpdsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRPDSDataSource()                         */
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
index d9ac095..1e09a54 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpdsdriver.cpp 19988 2010-07-07 19:02:36Z rouault $
+ * $Id: ogrpdsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_pds.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpdsdriver.cpp 19988 2010-07-07 19:02:36Z rouault $");
+CPL_CVSID("$Id: ogrpdsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRPDS();
 
diff --git a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
index 0eb8aec..e4806b0 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpdslayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrpdslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpdslayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrpdslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRPDSLayer()                              */
@@ -44,7 +44,7 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableID,
                             CPLString osStructureFilename,
                             int nRecords,
                             int nStartBytes, int nRecordSize,
-                            GByte* pabyRecord, int bIsASCII)
+                            GByte* pabyRecordIn, int bIsASCII)
 
 {
     fpPDS = fp;
@@ -61,7 +61,7 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableID,
 
     pasFieldDesc = NULL;
 
-    this->pabyRecord = pabyRecord;
+    pabyRecord = pabyRecordIn;
 
     if (osStructureFilename.size() != 0)
     {
diff --git a/ogr/ogrsf_frmts/pg/drv_pg.html b/ogr/ogrsf_frmts/pg/drv_pg.html
index a046f0a..386ccda 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg.html
@@ -134,7 +134,7 @@ Options</a> which help control the behavior of this driver.<p>
 
 <ul>
 <li><b>PG_USE_COPY</b>: This may be "YES" for using COPY for inserting data to Postgresql.
-COPY is less robust than INSERT, but significantly faster.</li><p>
+COPY is significantly faster than INSERT.</li><p>
 <li><b>PGSQL_OGR_FID</b>: Set name of primary key instead of 'ogc_fid'. Only used when opening a layer whose primary key cannot be autodetected.
 Ignored by CreateLayer() that uses the FID creation option.</li><p>
 <!-- Little interest to advertize PG_USE_TEXT... Just to keep it mind it exists for example for debugging -->
@@ -142,6 +142,10 @@ Ignored by CreateLayer() that uses the FID creation option.</li><p>
 <li><b>PG_USE_BASE64</b>: (GDAL >= 1.8.0) If set to "YES", geometries will be fetched as BASE64 encoded EWKB instead of canonical HEX encoded EWKB.
 This reduces the amount of data to be transfered from 2 N to 1.333 N, where N is the size of EWKB data. However, it might be a
 bit slower than fetching in canonical form when the client and the server are on the same machine, so the default is NO.</li><p>
+<li><b>OGR_TRUNCATE</b>: (GDAL >= 1.11) If set to "YES", the content of the table will be first erased with the SQL TRUNCATE command before
+inserting the first feature. This is an alternative to using the -overwrite flag of ogr2ogr,
+that avoids views based on the table to be destroyed.
+Typical use case: "ogr2ogr -append PG:dbname=foo abc.shp --config OGR_TRUNCATE YES".
 </ul>
 
 <h3>Examples</h3>
diff --git a/ogr/ogrsf_frmts/pg/drv_pg_advanced.html b/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
index b8c9a25..d66e590 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
@@ -39,6 +39,21 @@ active_schema=bar_schema, 2 layers will be listed : 'foo' (implicetly within 'ba
 <h2>Multiple geometry columns</h2>
 
 Starting with GDAL 1.6.0, the PostgreSQL driver supports accessing tables with multiple PostGIS geometry columns.
+
+<h3> OGR >= 1.11 </h3>
+
+OGR 1.11 supports reading, updating, creating tables with multiple PostGIS
+geometry columns (following
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">RFC 41</a>)
+
+For such a table, a single OGR layer will be reported with as many geometry
+fields as there are geometry columns in the table.<p>
+
+For backward compatibility, it is also possible to query a layer with GetLayerByName()
+with a name formatted like 'foo(bar)' where 'foo' is a table and 'bar' a geometry column.<p>
+
+<h3> OGR < 1.11 </h3>
+
 For such a table, there will be as many layers reported as the number of geometry columns listed for that
 table in the <i>geometry_columns</i> table.
 For example, if a table 'foo' has 2 geometry columns 'bar' and 'baz', 2 layers will be reported :
diff --git a/ogr/ogrsf_frmts/pg/ogr_pg.h b/ogr/ogrsf_frmts/pg/ogr_pg.h
index a29f919..e0aefc2 100644
--- a/ogr/ogrsf_frmts/pg/ogr_pg.h
+++ b/ogr/ogrsf_frmts/pg/ogr_pg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pg.h 25366 2012-12-27 18:38:53Z rouault $
+ * $Id: ogr_pg.h 27106 2014-03-28 11:59:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -78,22 +79,85 @@ CPLString OGRPGEscapeColumnName(const char* pszColumnName);
 
 #define UNDETERMINED_SRID       -2 /* Special value when we haven't yet looked for SRID */
 
+class OGRPGDataSource;
+class OGRPGLayer;
+
+typedef enum
+{
+    GEOM_TYPE_UNKNOWN = 0,
+    GEOM_TYPE_GEOMETRY = 1,
+    GEOM_TYPE_GEOGRAPHY = 2,
+    GEOM_TYPE_WKB = 3
+} PostgisType;
+
+typedef struct
+{
+    char* pszName;
+    char* pszGeomType;
+    int   nCoordDimension;
+    int   nSRID;
+    PostgisType   ePostgisType;
+} PGGeomColumnDesc;
+
 /************************************************************************/
-/*                            OGRPGLayer                                */
+/*                         OGRPGGeomFieldDefn                           */
 /************************************************************************/
 
+class OGRPGGeomFieldDefn : public OGRGeomFieldDefn
+{
+    protected:
+        OGRPGLayer* poLayer;
 
-class OGRPGDataSource;
+    public:
+        OGRPGGeomFieldDefn( OGRPGLayer* poLayerIn,
+                                const char* pszFieldName ) :
+            OGRGeomFieldDefn(pszFieldName, wkbUnknown), poLayer(poLayerIn),
+            nSRSId(UNDETERMINED_SRID), nCoordDimension(2), ePostgisType(GEOM_TYPE_UNKNOWN)
+            {
+            }
+
+        virtual OGRSpatialReference* GetSpatialRef();
+
+        void UnsetLayer() { poLayer = NULL; }
+
+        int nSRSId;
+        int nCoordDimension;
+        PostgisType   ePostgisType;
+};
+
+/************************************************************************/
+/*                          OGRPGFeatureDefn                            */
+/************************************************************************/
+
+class OGRPGFeatureDefn : public OGRFeatureDefn
+{
+    public:
+        OGRPGFeatureDefn( const char * pszName = NULL ) :
+            OGRFeatureDefn(pszName)
+        {
+            SetGeomType(wkbNone);
+        }
+
+        virtual void UnsetLayer()
+        {
+            for(int i=0;i<nGeomFieldCount;i++)
+                ((OGRPGGeomFieldDefn*) papoGeomFieldDefn[i])->UnsetLayer();
+        }
+
+        OGRPGGeomFieldDefn* myGetGeomFieldDefn(int i)
+        {
+            return (OGRPGGeomFieldDefn*) GetGeomFieldDefn(i);
+        }
+};
+
+/************************************************************************/
+/*                            OGRPGLayer                                */
+/************************************************************************/
 
 class OGRPGLayer : public OGRLayer
 {
   protected:
-    OGRFeatureDefn     *poFeatureDefn;
-
-    // Layer spatial reference system, and srid.
-    OGRSpatialReference *poSRS;
-    int                 nSRSId;
-    int                 nCoordDimension;
+    OGRPGFeatureDefn   *poFeatureDefn;
 
     int                 iNextShapeId;
 
@@ -101,9 +165,6 @@ class OGRPGLayer : public OGRLayer
     static char        *GeometryToBYTEA( OGRGeometry * );
     static GByte       *BYTEAToGByteArray( const char *pszBytea, int* pnLength );
     static OGRGeometry *BYTEAToGeometry( const char * );
-    static OGRGeometry *HEXToGeometry( const char * );
-    static OGRGeometry *EWKBToGeometry( GByte* pabyWKB, int nLength );
-    static char        *GeometryToHex( OGRGeometry * poGeometry, int nSRSId );
     Oid                 GeometryToOID( OGRGeometry * );
     OGRGeometry        *OIDToGeometry( Oid );
 
@@ -116,28 +177,26 @@ class OGRPGLayer : public OGRLayer
 
     int                 nResultOffset;
 
-    int                 bHasWkb;
     int                 bWkbAsOid;
-    int                 bHasPostGISGeometry;
-    int                 bHasPostGISGeography;
-    char                *pszGeomColumn;
 
     int                 bHasFid;
     char                *pszFIDColumn;
 
     int                 bCanUseBinaryCursor;
     int                *panMapFieldNameToIndex;
+    int                *panMapFieldNameToGeomIndex;
 
     int                 ParsePGDate( const char *, OGRField * );
 
     void                SetInitialQueryCursor();
     void                CloseCursor();
 
+    virtual CPLString   GetFromClauseForGetExtent() = 0;
     OGRErr              RunGetExtentRequest( OGREnvelope *psExtent, int bForce,
                                              CPLString osCommand);
     void                CreateMapFromFieldNameToIndex();
 
-    OGRFeatureDefn     *ReadResultDefinition(PGresult *hInitialResultIn);
+    int                 ReadResultDefinition(PGresult *hInitialResultIn);
 
     OGRFeature         *RecordToFeature( int iRecord );
     OGRFeature         *GetNextRawFeature();
@@ -149,38 +208,32 @@ class OGRPGLayer : public OGRLayer
     virtual void        ResetReading();
 
     virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRPGFeatureDefn *  myGetLayerDefn() { return (OGRPGFeatureDefn*) GetLayerDefn(); }
+
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
 
     virtual OGRErr      StartTransaction();
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
 
     virtual OGRErr      SetNextByIndex( long nIndex );
+    
+    OGRPGDataSource    *GetDS() { return poDS; }
 
-    int                 GetSRID();
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) = 0;
 };
 
 /************************************************************************/
 /*                           OGRPGTableLayer                            */
 /************************************************************************/
 
-typedef enum
-{
-    GEOM_TYPE_UNKNOWN = 0,
-    GEOM_TYPE_GEOMETRY = 1,
-    GEOM_TYPE_GEOGRAPHY = 2
-} PostgisType;
-
 class OGRPGTableLayer : public OGRPGLayer
 {
     int                 bUpdateAccess;
 
-    OGRFeatureDefn     *ReadTableDefinition();
-
     void                BuildWhere(void);
     CPLString           BuildFields(void);
     void                BuildFullQueryStatement(void);
@@ -188,16 +241,16 @@ class OGRPGTableLayer : public OGRPGLayer
     char               *pszTableName;
     char               *pszSchemaName;
     char               *pszSqlTableName;
+    int                 bTableDefinitionValid;
 
     CPLString           osPrimaryKey;
 
     int                 bGeometryInformationSet;
-    OGRwkbGeometryType  nGeomType;
 
     /* Name of the parent table with the geometry definition if it is a derived table or NULL */
     char               *pszSqlGeomParentTableName;
 
-    CPLString           osDefnName;
+    char               *pszGeomColForced;
 
     CPLString           osQuery;
     CPLString           osWHERE;
@@ -207,6 +260,7 @@ class OGRPGTableLayer : public OGRPGLayer
     int                 bUseCopy;
     int                 bCopyActive;
     int                 bFIDColumnInCopyFields;
+    int                 bFirstInsertion;
 
     OGRErr		CreateFeatureViaCopy( OGRFeature *poFeature );
     OGRErr		CreateFeatureViaInsert( OGRFeature *poFeature );
@@ -216,40 +270,38 @@ class OGRPGTableLayer : public OGRPGLayer
                                          OGRFeature* poFeature, int i);
                   
     int                 bHasWarnedIncompatibleGeom;
-    void                CheckGeomTypeCompatibility(OGRGeometry* poGeom);
+    void                CheckGeomTypeCompatibility(int iGeomField, OGRGeometry* poGeom);
 
     int                 bRetrieveFID;
     int                 bHasWarnedAlreadySetFID;
     
     char              **papszOverrideColumnTypes;
+    int                 nForcedSRSId;
+    int                 nForcedDimension;
+    int                 bCreateSpatialIndexFlag;
+    int                 bInResetReading;
+
+    virtual CPLString   GetFromClauseForGetExtent() { return pszSqlTableName; }
 
 public:
                         OGRPGTableLayer( OGRPGDataSource *,
                                          CPLString& osCurrentSchema,
                                          const char * pszTableName,
                                          const char * pszSchemaName,
-                                         const char * pszGeomColumnIn,
-                                         int bUpdate,
-                                         int bAdvertizeGeomColumn,
-                                         int nSRSId = UNDETERMINED_SRID );
+                                         const char * pszGeomColForced,
+                                         int bUpdate );
                         ~OGRPGTableLayer();
 
-    void                SetGeometryInformation(const char* pszGeomType,
-                                               int nCoordDimension,
-                                               int nSRID,
-                                               PostgisType ePostgisType);
-
-    virtual const char  *GetName() { return osDefnName.c_str(); }
-    virtual OGRwkbGeometryType GetGeomType();
-
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    void                SetGeometryInformation(PGGeomColumnDesc* pasDesc,
+                                               int nGeomFieldCount);
 
     virtual OGRFeature *GetFeature( long nFeatureId );
     virtual void        ResetReading();
     virtual OGRFeature *GetNextFeature();
     virtual int         GetFeatureCount( int );
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -259,18 +311,21 @@ public:
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE );
     virtual OGRErr      DeleteField( int iField );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual int         TestCapability( const char * );
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
 
     const char*         GetTableName() { return pszTableName; }
     const char*         GetSchemaName() { return pszSchemaName; }
 
+    virtual const char *GetFIDColumn();
+
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
@@ -282,7 +337,17 @@ public:
     virtual OGRErr      StartCopy(int bSetFID);
     virtual OGRErr      EndCopy();
 
-    OGRFeatureDefn     *GetLayerDefnCanReturnNULL();
+    int                 ReadTableDefinition();
+    int                 HasGeometryInformation() { return bGeometryInformationSet; }
+
+    void                SetForcedSRSId( int nForcedSRSIdIn )
+                                { nForcedSRSId = nForcedSRSIdIn; }
+    void                SetForcedDimension( int nForcedDimensionIn )
+                                { nForcedDimension = nForcedDimensionIn; }
+    void                SetCreateSpatialIndexFlag( int bFlag )
+                                { bCreateSpatialIndexFlag = bFlag; }
+
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn);
 };
 
 /************************************************************************/
@@ -299,6 +364,10 @@ class OGRPGResultLayer : public OGRPGLayer
     char                *pszGeomTableSchemaName;
 
     CPLString           osWHERE;
+    
+    virtual CPLString   GetFromClauseForGetExtent()
+        { CPLString osStr("(");
+          osStr += pszRawStatement; osStr += ")"; return osStr; }
 
   public:
                         OGRPGResultLayer( OGRPGDataSource *,
@@ -309,15 +378,14 @@ class OGRPGResultLayer : public OGRPGLayer
     virtual void        ResetReading();
     virtual int         GetFeatureCount( int );
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
 
     virtual int         TestCapability( const char * );
 
     virtual OGRFeature *GetNextFeature();
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn);
 };
 
 /************************************************************************/
@@ -390,9 +458,8 @@ class OGRPGDataSource : public OGRDataSource
     OGRPGTableLayer*    OpenTable( CPLString& osCurrentSchema,
                                    const char * pszTableName,
                                    const char * pszSchemaName,
-                                   const char * pszGeomColumnIn,
-                                   int bUpdate, int bTestOpen,
-                                   int bAdvertizeGeomColumn );
+                                   const char * pszGeomColForced,
+                                   int bUpdate, int bTestOpen );
 
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 34247b8..36a8bf4 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdatasource.cpp 26100 2013-06-20 19:35:09Z warmerdam $
+ * $Id: ogrpgdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,10 +33,11 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
+#include <set>
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 26100 2013-06-20 19:35:09Z warmerdam $");
+CPL_CVSID("$Id: ogrpgdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -189,14 +191,6 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
 /*                     One entry for each PG table                      */
 /************************************************************************/
 
-typedef struct
-{
-    char* pszName;
-    char* pszGeomType;
-    int   nCoordDimension;
-    int   nSRID;
-    PostgisType   ePostgisType;
-} PGGeomColumnDesc;
 
 typedef struct
 {
@@ -235,7 +229,9 @@ static void OGRPGTableEntryAddGeomColumn(PGTableEntry* psTableEntry,
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].pszName = CPLStrdup(pszName);
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].pszGeomType = (pszGeomType) ? CPLStrdup(pszGeomType) : NULL;
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].nCoordDimension = nCoordDimension;
-    psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].nSRID = nSRID;
+    /* With PostGIS 2.0, querying geometry_columns can return 0, not only when */
+    /* the SRID is truly set to 0, but also when there's no constraint */
+    psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].nSRID = nSRID > 0 ? nSRID : UNDETERMINED_SRID;
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].ePostgisType = ePostgisType;
     psTableEntry->nGeomColumnCount ++;
 }
@@ -480,6 +476,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     int            bRet = FALSE;
     int            bListAllTables = CSLTestBoolean(CPLGetConfigOption("PG_LIST_ALL_TABLES", "NO"));
     PGresult      *hResult = NULL;
+    std::set<CPLString> osRegisteredLayers;
 
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
@@ -587,13 +584,16 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0 )
     {
+        const char* pszSpace;
         char * pszVer = PQgetvalue(hResult,0,0);
 
         CPLDebug("PG","PostgreSQL version string : '%s'", pszVer);
 
-        if (EQUALN(pszVer, "PostgreSQL ", 11))
+        /* Should work with "PostgreSQL X.Y.Z ..." or "EnterpriseDB X.Y.Z ..." */
+        pszSpace = strchr(pszVer, ' ');
+        if( pszSpace != NULL && isdigit(pszSpace[1]) )
         {
-            OGRPGDecodeVersionString(&sPostgreSQLVersion, pszVer + 11);
+            OGRPGDecodeVersionString(&sPostgreSQLVersion, pszSpace + 1);
             if (sPostgreSQLVersion.nMajor == 7 && sPostgreSQLVersion.nMinor < 4)
             {
                 /* We don't support BINARY CURSOR for PostgreSQL < 7.4. */
@@ -693,26 +693,27 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 /*      PostGIS Geometry type.  If so, disable sequential scanning      */
 /*      so we will get the value of the gist indexes.                   */
 /* -------------------------------------------------------------------- */
-    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
-
-    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
-    {
-        OGRPGClearResult( hResult );
-        CPLAssert(NULL == hResult);
-
-        hResult = OGRPG_PQexec(hPGConn,
-                         "SELECT oid FROM pg_type WHERE typname = 'geometry'" );
-    }
+    hResult = OGRPG_PQexec(hPGConn,
+                        "SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography')" );
 
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0  && CSLTestBoolean(CPLGetConfigOption("PG_USE_POSTGIS", "YES")))
     {
-        bHavePostGIS = TRUE;
-        nGeometryOID = atoi(PQgetvalue(hResult,0,0));
-    }
-    else
-    {
-        nGeometryOID = (Oid) 0;
+        for( int iRecord = 0; iRecord < PQntuples(hResult); iRecord++ )
+        {
+            const char *pszOid = PQgetvalue(hResult, iRecord, 0);
+            const char *pszTypname = PQgetvalue(hResult, iRecord, 1);
+            if( EQUAL(pszTypname, "geometry") )
+            {
+                bHavePostGIS = TRUE;
+                nGeometryOID = atoi(pszOid);
+            }
+            else if( CSLTestBoolean(CPLGetConfigOption("PG_USE_GEOGRAPHY", "YES")) )
+            {
+                bHaveGeography = TRUE;
+                nGeographyOID = atoi(pszOid);
+            }
+        }
     }
 
     OGRPGClearResult( hResult );
@@ -777,9 +778,6 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     else
         nUndefinedSRID = -1;
 
-    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
-    OGRPGClearResult( hResult );
-
 /* -------------------------------------------------------------------- */
 /*      Get a list of available tables if they have not been            */
 /*      specified through the TABLES connection string param           */
@@ -806,50 +804,23 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             /* non-PostGIS case it has only 2 columns */
             if ( bHavePostGIS && !bListAllTables )
             {
-                /* PostGIS 1.5 brings support for 'geography' type. */
-                /* Checks that the type exists */
-
-                /* Note: the PG_USE_GEOGRAPHY config option is only used for testing */
-                /* purpose, to test the ability of the driver to work with older PostGIS */
-                /* versions, even when we have a newer one. It should not be used by */
-                /* *real* OGR users */
-                if ((sPostGISVersion.nMajor > 1 ||
-                    (sPostGISVersion.nMajor == 1 && sPostGISVersion.nMinor >= 5)) &&
-                    CSLTestBoolean(CPLGetConfigOption("PG_USE_GEOGRAPHY", "YES")) )
-                {
-                    hResult = OGRPG_PQexec(hPGConn,
-                                    "SELECT oid FROM pg_type WHERE typname = 'geography'" );
-
-                    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
-                        && PQntuples(hResult) > 0)
-                    {
-                        bHaveGeography = TRUE;
-                        nGeographyOID = atoi(PQgetvalue(hResult,0,0));
-                    }
-                    else
-                    {
-                        CPLDebug("PG", "PostGIS >= 1.5 detected but cannot find 'geography' type");
-                    }
-                    
-                    OGRPGClearResult( hResult );
-                }
-                
                 osCommand.Printf("DECLARE mycursor CURSOR for "
-                                 "SELECT c.relname, n.nspname, g.f_geometry_column, g.type, g.coord_dimension, g.srid, %d FROM pg_class c, pg_namespace n, geometry_columns g "
+                                 "SELECT c.relname, n.nspname, c.relkind, g.f_geometry_column, g.type, g.coord_dimension, g.srid, %d, c.oid as oid, a.attnum as attnum FROM pg_class c, pg_namespace n, geometry_columns g, pg_attribute a "
                                  "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid "
-                                 "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema)",
+                                 "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema AND a.attname = g.f_geometry_column AND a.attrelid = c.oid) ",
                                  GEOM_TYPE_GEOMETRY, pszAllowedRelations);
 
                 if (bHaveGeography)
                     osCommand += CPLString().Printf(
-                                     "UNION SELECT c.relname, n.nspname, g.f_geography_column, g.type, g.coord_dimension, g.srid, %d FROM pg_class c, pg_namespace n, geography_columns g "
+                                     "UNION SELECT c.relname, n.nspname, c.relkind, g.f_geography_column, g.type, g.coord_dimension, g.srid, %d, c.oid as oid, a.attnum as attnum FROM pg_class c, pg_namespace n, geography_columns g, pg_attribute a "
                                      "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid "
-                                     "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema)",
+                                     "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema AND a.attname = g.f_geography_column AND a.attrelid = c.oid)",
                                      GEOM_TYPE_GEOGRAPHY, pszAllowedRelations);
+                osCommand += " ORDER BY oid, attnum";
             }
             else
                 osCommand.Printf("DECLARE mycursor CURSOR for "
-                                 "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n "
+                                 "SELECT c.relname, n.nspname, c.relkind FROM pg_class c, pg_namespace n "
                                  "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid)",
                                  pszAllowedRelations);
                                 
@@ -878,6 +849,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         {
             const char *pszTable = PQgetvalue(hResult, iRecord, 0);
             const char *pszSchemaName = PQgetvalue(hResult, iRecord, 1);
+            const char *pszRelkind = PQgetvalue(hResult, iRecord, 2);
             const char *pszGeomColumnName = NULL;
             const char *pszGeomType = NULL;
             int nGeomCoordDimension = 0;
@@ -885,11 +857,18 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             PostgisType ePostgisType = GEOM_TYPE_UNKNOWN;
             if (bHavePostGIS && !bListAllTables)
             {
-                pszGeomColumnName = PQgetvalue(hResult, iRecord, 2);
-                pszGeomType = PQgetvalue(hResult, iRecord, 3);
-                nGeomCoordDimension = atoi(PQgetvalue(hResult, iRecord, 4));
-                nSRID = atoi(PQgetvalue(hResult, iRecord, 5));
-                ePostgisType = (PostgisType) atoi(PQgetvalue(hResult, iRecord, 6));
+                pszGeomColumnName = PQgetvalue(hResult, iRecord, 3);
+                pszGeomType = PQgetvalue(hResult, iRecord, 4);
+                nGeomCoordDimension = atoi(PQgetvalue(hResult, iRecord, 5));
+                nSRID = atoi(PQgetvalue(hResult, iRecord, 6));
+                ePostgisType = (PostgisType) atoi(PQgetvalue(hResult, iRecord, 7));
+
+                /* We cannot reliably find geometry columns of a view that is */
+                /* based on a table that inherits from another one, wit that */
+                /* method, so give up, and let OGRPGTableLayer::ReadTableDefinition() */
+                /* do the job */
+                if( pszRelkind[0] == 'v' && sPostGISVersion.nMajor < 2 )
+                    pszGeomColumnName = NULL;
             }
 
             if( EQUAL(pszTable,"spatial_ref_sys")
@@ -933,7 +912,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         hResult = OGRPG_PQexec(hPGConn, "COMMIT");
         OGRPGClearResult( hResult );
 
-        if ( bHavePostGIS && !bListAllTables )
+        /* With PostGIS 2.0, we don't need to query base tables of inherited */
+        /* tables */
+        if ( bHavePostGIS && !bListAllTables && sPostGISVersion.nMajor < 2 )
         {
             hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
@@ -1046,6 +1027,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     for( int iRecord = 0; iRecord < nTableCount; iRecord++ )
     {
         PGTableEntry* psEntry;
+        CPLString osDefnName;
         psEntry = (PGTableEntry* )CPLHashSetLookup(hSetTables, papsTables[iRecord]);
 
         /* If SCHEMAS= is specified, only take into account tables inside */
@@ -1056,47 +1038,39 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             continue;
         }
 
-        /* Some heuristics to preserve backward compatibility with the way that */
-        /* layers were reported in GDAL <= 1.5.0 */
-        /* That is to say : */
-        /* - if we get only one geometry column from the request to geometry_columns */
-        /*   then use it but don't report it into layer definition */
-        /* - if we get several geometry columns, use their names and report them */
-        /*   except for the wkb_geometry column */
-        /* - if we get no geometry column, let ReadTableDefinition() parses the columns */
-        /*   and find the likely geometry column */
+        if ( papsTables[iRecord]->pszSchemaName &&
+            osCurrentSchema != papsTables[iRecord]->pszSchemaName )
+        {
+            osDefnName.Printf("%s.%s", papsTables[iRecord]->pszSchemaName,
+                              papsTables[iRecord]->pszTableName );
+        }
+        else
+        {
+            //no prefix for current_schema in layer name, for backwards compatibility
+            osDefnName = papsTables[iRecord]->pszTableName;
+        }
+        if( osRegisteredLayers.find( osDefnName ) != osRegisteredLayers.end() )
+            continue;
+        osRegisteredLayers.insert( osDefnName );
 
         OGRPGTableLayer* poLayer;
-        if (psEntry != NULL && psEntry->nGeomColumnCount <= 1)
+        poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
+            papsTables[iRecord]->pszSchemaName,
+            NULL, bUpdate, FALSE );
+        if( psEntry != NULL )
         {
-            if (psEntry->nGeomColumnCount == 1)
+            if( psEntry->nGeomColumnCount > 0 )
             {
-                poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-                           papsTables[iRecord]->pszSchemaName,
-                           psEntry->pasGeomColumns[0].pszName, bUpdate, FALSE, FALSE );
-                poLayer->SetGeometryInformation(psEntry->pasGeomColumns[0].pszGeomType,
-                                                psEntry->pasGeomColumns[0].nCoordDimension,
-                                                psEntry->pasGeomColumns[0].nSRID,
-                                                psEntry->pasGeomColumns[0].ePostgisType);
+                poLayer->SetGeometryInformation(psEntry->pasGeomColumns,
+                                                psEntry->nGeomColumnCount);
             }
-            else
-                poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-                           papsTables[iRecord]->pszSchemaName, NULL, bUpdate, FALSE, FALSE );
         }
         else
         {
-            if (papsTables[iRecord]->nGeomColumnCount == 0)
-                poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-                           papsTables[iRecord]->pszSchemaName, NULL, bUpdate, FALSE, FALSE );
-            else
+            if( papsTables[iRecord]->nGeomColumnCount > 0 )
             {
-                poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-                           papsTables[iRecord]->pszSchemaName, papsTables[iRecord]->pasGeomColumns[0].pszName,
-                           bUpdate, FALSE, !EQUAL(papsTables[iRecord]->pasGeomColumns[0].pszName, "wkb_geometry") );
-                poLayer->SetGeometryInformation(papsTables[iRecord]->pasGeomColumns[0].pszGeomType,
-                                                papsTables[iRecord]->pasGeomColumns[0].nCoordDimension,
-                                                papsTables[iRecord]->pasGeomColumns[0].nSRID,
-                                                papsTables[iRecord]->pasGeomColumns[0].ePostgisType);
+                poLayer->SetGeometryInformation(papsTables[iRecord]->pasGeomColumns,
+                                                papsTables[iRecord]->nGeomColumnCount);
             }
         }
     }
@@ -1122,10 +1096,9 @@ end:
 OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchema,
                                 const char *pszNewName,
                                 const char *pszSchemaName,
-                                const char * pszGeomColumnIn,
+                                const char * pszGeomColumnForced,
                                 int bUpdate,
-                                int bTestOpen,
-                                int bAdvertizeGeomColumn)
+                                int bTestOpen)
 
 {
 /* -------------------------------------------------------------------- */
@@ -1135,9 +1108,8 @@ OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchema,
 
     poLayer = new OGRPGTableLayer( this, osCurrentSchema,
                                    pszNewName, pszSchemaName,
-                                   pszGeomColumnIn, bUpdate,
-                                   bAdvertizeGeomColumn );
-    if( bTestOpen && poLayer->GetLayerDefnCanReturnNULL() == NULL )
+                                   pszGeomColumnForced, bUpdate );
+    if( bTestOpen && !(poLayer->ReadTableDefinition()) )
     {
         delete poLayer;
         return NULL;
@@ -1190,19 +1162,21 @@ int OGRPGDataSource::DeleteLayer( int iLayer )
     hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
 
-    if( bHavePostGIS )
+    if( bHavePostGIS  && sPostGISVersion.nMajor < 2)
     {
         /* This is unnecessary if the layer is not a geometry table, or an inherited geometry table */
         /* but it shouldn't hurt */
         osCommand.Printf(
-                 "SELECT DropGeometryColumn('%s','%s',(SELECT f_geometry_column from geometry_columns where f_table_name='%s' and f_table_schema='%s' order by f_geometry_column limit 1))",
-                 osSchemaName.c_str(), osTableName.c_str(), osTableName.c_str(), osSchemaName.c_str() );
+                 "DELETE FROM geometry_columns WHERE f_table_name='%s' and f_table_schema='%s'",
+                 osTableName.c_str(), osSchemaName.c_str() );
 
         hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
         OGRPGClearResult( hResult );
     }
 
-    osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", osSchemaName.c_str(), osTableName.c_str() );
+    osCommand.Printf("DROP TABLE %s.%s CASCADE",
+                     OGRPGEscapeColumnName(osSchemaName).c_str(),
+                     OGRPGEscapeColumnName(osTableName).c_str() );
     hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
     OGRPGClearResult( hResult );
 
@@ -1259,8 +1233,12 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     if( wkbFlatten(eType) == eType )
         nDimension = 2;
 
+    int nForcedDimension = -1;
     if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
+    {
         nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
+        nForcedDimension = nDimension;
+    }
 
     /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
     /* so they are still recorded in geometry_columns table ? (#4012) */
@@ -1309,9 +1287,9 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
     }
 
-    if ( pszSchemaName == NULL && strlen(osCurrentSchema) > 0)
+    if ( pszSchemaName == NULL )
     {
-      pszSchemaName = CPLStrdup(osCurrentSchema);
+        pszSchemaName = CPLStrdup(osCurrentSchema);
     }
 
 /* -------------------------------------------------------------------- */
@@ -1432,10 +1410,13 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     {
         CPLFree(pszSchemaName);
         pszSchemaName = CPLStrdup("pg_temp_1");
-        osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName);
+        osCreateTable.Printf("CREATE TEMPORARY TABLE %s",
+                             OGRPGEscapeColumnName(pszTableName).c_str());
     }
     else
-        osCreateTable.Printf("CREATE TABLE \"%s\".\"%s\"", pszSchemaName, pszTableName);
+        osCreateTable.Printf("CREATE TABLE %s.%s",
+                             OGRPGEscapeColumnName(pszSchemaName).c_str(), 
+                             OGRPGEscapeColumnName(pszTableName).c_str());
     
     if( eType != wkbNone && !bHavePostGIS )
     {
@@ -1459,14 +1440,16 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         if (nSRSId)
             osCommand.Printf(
                      "%s ( %s SERIAL, %s geography(%s%s,%d), PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), pszFIDColumnName,
+                     osCreateTable.c_str(),
+                     pszFIDColumnName,
                      OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
                      nDimension == 2 ? "" : "Z", nSRSId, 
                      pszFIDColumnName);
         else
             osCommand.Printf(
                      "%s ( %s SERIAL, %s geography(%s%s), PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), pszFIDColumnName,
+                     osCreateTable.c_str(),
+                     pszFIDColumnName,
                      OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
                      nDimension == 2 ? "" : "Z", 
                      pszFIDColumnName);
@@ -1475,7 +1458,9 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     {
         osCommand.Printf(
                  "%s ( %s SERIAL, PRIMARY KEY (%s) )",
-                 osCreateTable.c_str(), pszFIDColumnName, pszFIDColumnName );
+                 osCreateTable.c_str(),
+                 pszFIDColumnName,
+                 pszFIDColumnName );
     }
 
     hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
@@ -1496,6 +1481,8 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 
     CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn, pszTableName);
     const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+    CPLString osEscapedSchemaNameSingleQuote = OGRPGEscapeString(hPGConn, pszSchemaName);
+    const char* pszEscapedSchemaNameSingleQuote = osEscapedSchemaNameSingleQuote.c_str();
 
 /* -------------------------------------------------------------------- */
 /*      Eventually we should be adding this table to a table of         */
@@ -1517,16 +1504,17 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
             * Note: PostGIS 2.0 defines geometry_columns as a view (no clean up is needed)
             */
             osCommand.Printf(
-                    "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = '%s'",
-                    pszEscapedTableNameSingleQuote, pszSchemaName );
+                    "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = %s",
+                    pszEscapedTableNameSingleQuote, pszEscapedSchemaNameSingleQuote );
 
             hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
             OGRPGClearResult( hResult );
         }
 
         osCommand.Printf(
-                 "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)",
-                 pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
+                 "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
+                 pszEscapedSchemaNameSingleQuote, pszEscapedTableNameSingleQuote,
+                 OGRPGEscapeString(hPGConn, pszGFldName).c_str(),
                  nSRSId, pszGeometryType, nDimension );
 
         hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
@@ -1552,7 +1540,9 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         OGRPGClearResult( hResult );
     }
     
-    if( eType != wkbNone && bHavePostGIS )
+    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
+    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    if( eType != wkbNone && bHavePostGIS && bCreateSpatialIndex )
     {
 /* -------------------------------------------------------------------- */
 /*      Create the spatial index.                                       */
@@ -1560,36 +1550,34 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 /*      We're doing this before we add geometry and record to the table */
 /*      so this may not be exactly the best way to do it.               */
 /* -------------------------------------------------------------------- */
-        const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-        if( pszSI == NULL || CSLTestBoolean(pszSI) )
-        {
-            osCommand.Printf("CREATE INDEX \"%s_geom_idx\" "
-                             "ON \"%s\".\"%s\" "
-                             "USING GIST (%s)",
-                             pszTableName, pszSchemaName, pszTableName,
-                             OGRPGEscapeColumnName(pszGFldName).c_str());
 
-            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+        osCommand.Printf("CREATE INDEX %s ON %s.%s USING GIST (%s)",
+                         OGRPGEscapeColumnName(
+                            CPLSPrintf("%s_%s_geom_idx", pszTableName, pszGFldName)).c_str(),
+                         OGRPGEscapeColumnName(pszSchemaName).c_str(),
+                         OGRPGEscapeColumnName(pszTableName).c_str(),
+                         OGRPGEscapeColumnName(pszGFldName).c_str());
 
-            if( !hResult
-                || PQresultStatus(hResult) != PGRES_COMMAND_OK )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "'%s' failed for layer %s, index creation has failed.",
-                        osCommand.c_str(), pszLayerName );
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
-                CPLFree( pszTableName );
-                CPLFree( pszSchemaName );
+        if( !hResult
+            || PQresultStatus(hResult) != PGRES_COMMAND_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "'%s' failed for layer %s, index creation has failed.",
+                    osCommand.c_str(), pszLayerName );
 
-                OGRPGClearResult( hResult );
+            CPLFree( pszTableName );
+            CPLFree( pszSchemaName );
 
-                hResult = OGRPG_PQexec(hPGConn, "ROLLBACK");
-                OGRPGClearResult( hResult );
+            OGRPGClearResult( hResult );
 
-                return NULL;
-            }
+            hResult = OGRPG_PQexec(hPGConn, "ROLLBACK");
             OGRPGClearResult( hResult );
+
+            return NULL;
         }
+        OGRPGClearResult( hResult );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1603,8 +1591,9 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRPGTableLayer     *poLayer;
 
-    poLayer = new OGRPGTableLayer( this, osCurrentSchema, pszTableName, pszSchemaName, NULL, TRUE, FALSE, nSRSId);
-    if( poLayer->GetLayerDefnCanReturnNULL() == NULL )
+    poLayer = new OGRPGTableLayer( this, osCurrentSchema, pszTableName,
+                                   pszSchemaName, NULL, TRUE );
+    if( !(poLayer->ReadTableDefinition()) )
     {
         CPLFree( pszTableName );
         CPLFree( pszSchemaName );
@@ -1614,6 +1603,9 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    //poLayer->SetForcedSRSId(nForcedSRSId);
+    poLayer->SetForcedDimension(nForcedDimension);
+    poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
 
     /* HSTORE_COLUMNS existed at a time during GDAL 1.10dev */
     const char* pszHSTOREColumns = CSLFetchNameValue( papszOptions, "HSTORE_COLUMNS" );
@@ -1645,7 +1637,8 @@ int OGRPGDataSource::TestCapability( const char * pszCap )
 
 {
     if( EQUAL(pszCap,ODsCCreateLayer) 
-        || EQUAL(pszCap,ODsCDeleteLayer) )
+        || EQUAL(pszCap,ODsCDeleteLayer)
+        || EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
         return TRUE;
     else
         return FALSE;
@@ -1728,19 +1721,19 @@ OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszName )
     CPLFree(pszNameWithoutBracket);
     pszNameWithoutBracket = NULL;
 
-    OGRLayer* poLayer = NULL;
+    OGRPGTableLayer* poLayer = NULL;
 
     if (pszSchemaName != NULL && osCurrentSchema == pszSchemaName &&
         pszGeomColumnName == NULL )
     {
-        poLayer = GetLayerByName(pszTableName);
+        poLayer = (OGRPGTableLayer*) GetLayerByName(pszTableName);
     }
     else
     {
         poLayer = OpenTable( osCurrentSchema, pszTableName,
                              pszSchemaName,
                              pszGeomColumnName,
-                             bDSUpdate, TRUE, TRUE );
+                             bDSUpdate, TRUE );
     }
 
     CPLFree(pszTableName);
@@ -2137,6 +2130,8 @@ OGRErr OGRPGDataSource::SoftCommit()
 OGRErr OGRPGDataSource::SoftRollback()
 
 {
+    EndCopy();
+
     if( nSoftTransactionLevel <= 0 )
     {
         CPLDebug( "PG", "SoftRollback() with no transaction active." );
@@ -2205,6 +2200,9 @@ class OGRPGNoResetResultLayer : public OGRPGLayer
     virtual int         TestCapability( const char * ) { return FALSE; }
 
     virtual OGRFeature *GetNextFeature();
+    
+    virtual CPLString   GetFromClauseForGetExtent() { CPLAssert(FALSE); return ""; }
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) { poGFldDefn->nSRSId = -1; }
 };
 
 
@@ -2216,7 +2214,7 @@ OGRPGNoResetResultLayer::OGRPGNoResetResultLayer( OGRPGDataSource *poDSIn,
                                                   PGresult *hResultIn )
 {
     poDS = poDSIn;
-    poFeatureDefn = ReadResultDefinition(hResultIn);
+    ReadResultDefinition(hResultIn);
     hCursorResult = hResultIn;
     CreateMapFromFieldNameToIndex();
 }
@@ -2292,11 +2290,11 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
     /* Skip leading spaces */
     while(*pszSQLCommand == ' ')
         pszSQLCommand ++;
-    
+
 /* -------------------------------------------------------------------- */
-/*      Use generic implementation for OGRSQL dialect.                  */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand,
                                           poSpatialFilter,
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
index b35919a..4324c02 100644
--- a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpglayer.cpp 24545 2012-06-07 21:28:38Z rouault $
+ * $Id: ogrpglayer.cpp 27106 2014-03-28 11:59:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGLayer class  which implements shared handling
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -64,7 +65,7 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpglayer.cpp 24545 2012-06-07 21:28:38Z rouault $");
+CPL_CVSID("$Id: ogrpglayer.cpp 27106 2014-03-28 11:59:57Z rouault $");
 
 #define CURSOR_PAGE     500
 
@@ -75,12 +76,6 @@ CPL_CVSID("$Id: ogrpglayer.cpp 24545 2012-06-07 21:28:38Z rouault $");
 #define INV_READ                0x00040000
 #endif
 
-/* Flags for creating WKB format for PostGIS */
-#define WKBZOFFSET 0x80000000
-#define WKBMOFFSET 0x40000000
-#define WKBSRIDFLAG 0x20000000
-#define WKBBBOXFLAG 0x10000000
-
 /************************************************************************/
 /*                           OGRPGLayer()                               */
 /************************************************************************/
@@ -90,11 +85,7 @@ OGRPGLayer::OGRPGLayer()
 {
     poDS = NULL;
 
-    bHasWkb = FALSE;
     bWkbAsOid = FALSE;
-    bHasPostGISGeometry = FALSE;
-    bHasPostGISGeography = FALSE;
-    pszGeomColumn = NULL;
     pszQueryStatement = NULL;
 
     bHasFid = FALSE;
@@ -103,19 +94,15 @@ OGRPGLayer::OGRPGLayer()
     iNextShapeId = 0;
     nResultOffset = 0;
 
-    nCoordDimension = 2; // initialize in case PostGIS is not available
-
-    poSRS = NULL;
-    nSRSId = UNDETERMINED_SRID; // we haven't even queried the database for it yet.
-
     pszCursorName = CPLStrdup(CPLSPrintf("OGRPGLayerReader%p", this));
-    
+
     hCursorResult = NULL;
 
     bCanUseBinaryCursor = TRUE;
 
     poFeatureDefn = NULL;
     panMapFieldNameToIndex = NULL;
+    panMapFieldNameToGeomIndex = NULL;
 }
 
 /************************************************************************/
@@ -134,17 +121,17 @@ OGRPGLayer::~OGRPGLayer()
 
     ResetReading();
 
-    CPLFree( pszGeomColumn );
     CPLFree( pszFIDColumn );
     CPLFree( pszQueryStatement );
     CPLFree( panMapFieldNameToIndex );
+    CPLFree( panMapFieldNameToGeomIndex );
     CPLFree( pszCursorName );
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     if( poFeatureDefn )
+    {
+        poFeatureDefn->UnsetLayer();
         poFeatureDefn->Release();
+    }
 }
 
 /************************************************************************/
@@ -635,11 +622,16 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 /* -------------------------------------------------------------------- */
 /*      Handle PostGIS geometry                                         */
 /* -------------------------------------------------------------------- */
-
-        if( bHasPostGISGeometry || bHasPostGISGeography )
+        int iOGRGeomField = panMapFieldNameToGeomIndex[iField];
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( iOGRGeomField >= 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(iOGRGeomField);
+        if( iOGRGeomField >= 0 && (
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY) )
         {
             if ( !poDS->bUseBinaryCursor &&
-                 EQUAL(pszFieldName,"BinaryBase64") )
+                 EQUALN(pszFieldName,"BinaryBase64", strlen("BinaryBase64")) )
             {
                 GByte* pabyData = (GByte*)PQgetvalue( hCursorResult,
                                                         iRecord, iField);
@@ -656,14 +648,14 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 
                 if( poGeom != NULL )
                 {
-                    poGeom->assignSpatialReference( poSRS );
-                    poFeature->SetGeometryDirectly( poGeom );
+                    poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeom );
                 }
 
                 continue;
             }
-            else if ( EQUAL(pszFieldName,"ST_AsBinary") ||
-                 EQUAL(pszFieldName,"AsBinary") )
+            else if ( EQUALN(pszFieldName,"ST_AsBinary", strlen("ST_AsBinary")) ||
+                      EQUALN(pszFieldName,"AsBinary", strlen("AsBinary")) )
             {
                 GByte* pabyVal = (GByte*) PQgetvalue( hCursorResult,
                                              iRecord, iField);
@@ -689,14 +681,14 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
                 
                 if( poGeom != NULL )
                 {
-                    poGeom->assignSpatialReference( poSRS );
-                    poFeature->SetGeometryDirectly( poGeom );
+                    poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeom );
                 }
 
                 continue;
             }
             else if ( !poDS->bUseBinaryCursor &&
-                      EQUAL(pszFieldName,"EWKBBase64") )
+                      EQUALN(pszFieldName,"EWKBBase64",strlen("EWKBBase64")) )
             {
                 GByte* pabyData = (GByte*)PQgetvalue( hCursorResult,
                                                         iRecord, iField);
@@ -708,18 +700,17 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
                     continue;
 
                 nLength = CPLBase64DecodeInPlace(pabyData);
-                OGRGeometry * poGeom = EWKBToGeometry(pabyData, nLength);
+                OGRGeometry * poGeom = OGRGeometryFromEWKB(pabyData, nLength, NULL);
 
                 if( poGeom != NULL )
                 {
-                    poGeom->assignSpatialReference( poSRS );
-                    poFeature->SetGeometryDirectly( poGeom );
+                    poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeom );
                 }
 
                 continue;
             }
-            else if ( (poDS->bUseBinaryCursor &&
-                       (EQUAL(pszFieldName,pszGeomColumn))) ||
+            else if ( poDS->bUseBinaryCursor ||
                       EQUAL(pszFieldName,"ST_AsEWKB") ||
                       EQUAL(pszFieldName,"AsEWKB") )
             {
@@ -740,31 +731,30 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
                      strncmp(pabyData, "\\000",4) == 0 || strncmp(pabyData, "\\001",4) == 0) )
                 {
                     GByte* pabyEWKB = BYTEAToGByteArray(pabyData, &nLength);
-                    poGeom = EWKBToGeometry(pabyEWKB, nLength);
+                    poGeom = OGRGeometryFromEWKB(pabyEWKB, nLength, NULL);
                     CPLFree(pabyEWKB);
                 }
                 else if( nLength >= 2 && (EQUALN(pabyData,"00",2) || EQUALN(pabyData,"01",2)) )
                 {
-                    poGeom = HEXToGeometry(pabyData);
+                    poGeom = OGRGeometryFromHexEWKB(pabyData, NULL);
                 }
                 else
                 {
-                    poGeom = EWKBToGeometry((GByte*)pabyData, nLength);
+                    poGeom = OGRGeometryFromEWKB((GByte*)pabyData, nLength, NULL);
                 }
 
                 if( poGeom != NULL )
                 {
-                    poGeom->assignSpatialReference( poSRS );
-                    poFeature->SetGeometryDirectly( poGeom );
+                    poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeom );
                 }
 
                 continue;
             }
-            else if (EQUAL(pszFieldName,pszGeomColumn) ||
-                     EQUAL(pszFieldName,"asEWKT") ||
+            else /*if (EQUAL(pszFieldName,"asEWKT") ||
                      EQUAL(pszFieldName,"asText") ||
                      EQUAL(pszFieldName,"ST_AsEWKT") ||
-                     EQUAL(pszFieldName,"ST_AsText") )
+                     EQUAL(pszFieldName,"ST_AsText") )*/
             {
                 /* Handle WKT */
                 char        *pszWKT;
@@ -786,15 +776,15 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 
                 if( EQUALN(pszPostSRID,"00",2) || EQUALN(pszPostSRID,"01",2) )
                 {
-                    poGeometry = HEXToGeometry( pszWKT );
+                    poGeometry = OGRGeometryFromHexEWKB( pszWKT, NULL );
                 }
                 else
                     OGRGeometryFactory::createFromWkt( &pszPostSRID, NULL,
                                                     &poGeometry );
                 if( poGeometry != NULL )
                 {
-                    poGeometry->assignSpatialReference( poSRS );
-                    poFeature->SetGeometryDirectly( poGeometry );
+                    poGeometry->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeometry );
                 }
 
                 continue;
@@ -804,7 +794,8 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 /*      Handle raw binary geometry ... this hasn't been tested in a     */
 /*      while.                                                          */
 /* -------------------------------------------------------------------- */
-        else if( EQUAL(pszFieldName,"WKB_GEOMETRY") )
+        else if( iOGRGeomField >= 0 && 
+                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB )
         {
             OGRGeometry *poGeometry = NULL;
             GByte* pabyData = (GByte*) PQgetvalue( hCursorResult, iRecord, iField);
@@ -823,7 +814,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
                    )
                 {
                     int nLength = PQgetlength(hCursorResult, iRecord, iField);
-                    poGeometry = EWKBToGeometry(pabyData, nLength);
+                    poGeometry = OGRGeometryFromEWKB(pabyData, nLength, NULL);
                 }
                 if (poGeometry == NULL)
                 {
@@ -833,8 +824,8 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 
             if( poGeometry != NULL )
             {
-                poGeometry->assignSpatialReference( poSRS );
-                poFeature->SetGeometryDirectly( poGeometry );
+                poGeometry->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
+                poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeometry );
             }
 
             continue;
@@ -1278,6 +1269,24 @@ OGRFeature *OGRPGLayer::RecordToFeature( int iRecord )
 }
 
 /************************************************************************/
+/*                    OGRPGIsKnownGeomFuncPrefix()                      */
+/************************************************************************/
+
+static const char* papszKnownGeomFuncPrefixes[] = {
+    "ST_AsBinary", "BinaryBase64", "ST_AsEWKT", "ST_AsEWKB", "EWKBBase64",
+    "ST_AsText", "AsBinary", "asEWKT", "asEWKB", "asText" };
+static int OGRPGIsKnownGeomFuncPrefix(const char* pszFieldName)
+{
+    for(size_t i=0; i<sizeof(papszKnownGeomFuncPrefixes) / sizeof(char*); i++)
+    {
+        if( EQUALN(pszFieldName, papszKnownGeomFuncPrefixes[i],
+                   strlen(papszKnownGeomFuncPrefixes[i])) )
+            return i;
+    }
+    return -1;
+}
+
+/************************************************************************/
 /*                CreateMapFromFieldNameToIndex()                       */
 /************************************************************************/
 
@@ -1289,16 +1298,39 @@ void OGRPGLayer::CreateMapFromFieldNameToIndex()
 {
     CPLFree(panMapFieldNameToIndex);
     panMapFieldNameToIndex = NULL;
+    CPLFree(panMapFieldNameToGeomIndex);
+    panMapFieldNameToGeomIndex = NULL;
     if ( PQresultStatus(hCursorResult)  == PGRES_TUPLES_OK )
     {
         panMapFieldNameToIndex =
                 (int*)CPLMalloc(sizeof(int) * PQnfields(hCursorResult));
+        panMapFieldNameToGeomIndex =
+                (int*)CPLMalloc(sizeof(int) * PQnfields(hCursorResult));
         for( int iField = 0;
             iField < PQnfields(hCursorResult);
             iField++ )
         {
+            const char* pszName = PQfname(hCursorResult,iField);
             panMapFieldNameToIndex[iField] =
-                    poFeatureDefn->GetFieldIndex(PQfname(hCursorResult,iField));
+                    poFeatureDefn->GetFieldIndex(pszName);
+            if( panMapFieldNameToIndex[iField] < 0 )
+            {
+                panMapFieldNameToGeomIndex[iField] =
+                        poFeatureDefn->GetGeomFieldIndex(pszName);
+                if( panMapFieldNameToGeomIndex[iField] < 0 )
+                {
+                    int iKnownPrefix = OGRPGIsKnownGeomFuncPrefix(pszName);
+                    if( iKnownPrefix >= 0 &&
+                        pszName[ strlen(papszKnownGeomFuncPrefixes[iKnownPrefix]) ] == '_' )
+                    {
+                        panMapFieldNameToGeomIndex[iField] =
+                            poFeatureDefn->GetGeomFieldIndex(pszName +
+                            strlen(papszKnownGeomFuncPrefixes[iKnownPrefix]) + 1);
+                    }
+                }
+            }
+            else
+                panMapFieldNameToGeomIndex[iField] = -1;
         }
     }
 }
@@ -1477,166 +1509,6 @@ OGRErr OGRPGLayer::SetNextByIndex( long nIndex )
 }
 
 /************************************************************************/
-/*                           HEXToGeometry()                            */
-/************************************************************************/
-
-OGRGeometry *OGRPGLayer::HEXToGeometry( const char *pszBytea )
-
-{
-    GByte   *pabyWKB;
-    int     nWKBLength=0;
-    OGRGeometry *poGeometry;
-
-    if( pszBytea == NULL )
-        return NULL;
-
-    pabyWKB = CPLHexToBinary(pszBytea, &nWKBLength);
-
-    poGeometry = EWKBToGeometry(pabyWKB, nWKBLength);
-
-    CPLFree(pabyWKB);
-
-    return poGeometry;
-}
-
-
-/************************************************************************/
-/*                          EWKBToGeometry()                            */
-/************************************************************************/
-
-OGRGeometry *OGRPGLayer::EWKBToGeometry( GByte *pabyWKB, int nLength )
-
-{
-    OGRGeometry *poGeometry = NULL;
-    unsigned int ewkbFlags = 0;
-    
-    if (nLength < 5)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid EWKB content : %d bytes", nLength );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Detect XYZM variant of PostGIS EWKB                             */
-/*                                                                      */
-/*      OGR does not support parsing M coordinate,                      */
-/*      so we return NULL geometry.                                     */
-/* -------------------------------------------------------------------- */
-    memcpy(&ewkbFlags, pabyWKB+1, 4);
-    OGRwkbByteOrder eByteOrder = (pabyWKB[0] == 0 ? wkbXDR : wkbNDR);
-    if( OGR_SWAP( eByteOrder ) )
-        ewkbFlags= CPL_SWAP32(ewkbFlags);
-
-    if (ewkbFlags & 0x40000000)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Reading EWKB with 4-dimensional coordinates (XYZM) is not supported" );
-
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      PostGIS EWKB format includes an  SRID, but this won't be        */
-/*      understood by OGR, so if the SRID flag is set, we remove the    */
-/*      SRID (bytes at offset 5 to 8).                                  */
-/* -------------------------------------------------------------------- */
-    if( nLength > 9 &&
-        ((pabyWKB[0] == 0 /* big endian */ && (pabyWKB[1] & 0x20) )
-        || (pabyWKB[0] != 0 /* little endian */ && (pabyWKB[4] & 0x20))) )
-    {
-        memmove( pabyWKB+5, pabyWKB+9, nLength-9 );
-        nLength -= 4;
-        if( pabyWKB[0] == 0 )
-            pabyWKB[1] &= (~0x20);
-        else
-            pabyWKB[4] &= (~0x20);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try to ingest the geometry.                                     */
-/* -------------------------------------------------------------------- */
-    OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLength );
-
-    return poGeometry;
-}
-
-/************************************************************************/
-/*                           GeometryToHex()                            */
-/************************************************************************/
-char *OGRPGLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )
-{
-    GByte       *pabyWKB;
-    char        *pszTextBuf;
-    char        *pszTextBufCurrent;
-    char        *pszHex;
-
-    int nWkbSize = poGeometry->WkbSize();
-    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
-
-    if( poGeometry->exportToWkb( wkbNDR, pabyWKB ) != OGRERR_NONE )
-    {
-        CPLFree( pabyWKB );
-        return CPLStrdup("");
-    }
-
-    /* When converting to hex, each byte takes 2 hex characters.  In addition
-       we add in 8 characters to represent the SRID integer in hex, and
-       one for a null terminator */
-
-    int pszSize = nWkbSize*2 + 8 + 1;
-    pszTextBuf = (char *) CPLMalloc(pszSize);
-    pszTextBufCurrent = pszTextBuf;
-
-    /* Convert the 1st byte, which is the endianess flag, to hex. */
-    pszHex = CPLBinaryToHex( 1, pabyWKB );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-    pszTextBufCurrent += 2;
-
-    /* Next, get the geom type which is bytes 2 through 5 */
-    GUInt32 geomType;
-    memcpy( &geomType, pabyWKB+1, 4 );
-
-    /* Now add the SRID flag if an SRID is provided */
-    if (nSRSId > 0)
-    {
-        /* Change the flag to wkbNDR (little) endianess */
-        GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
-        /* Apply the flag */
-        geomType = geomType | nGSrsFlag;
-    }
-
-    /* Now write the geom type which is 4 bytes */
-    pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-    pszTextBufCurrent += 8;
-
-    /* Now include SRID if provided */
-    if (nSRSId > 0)
-    {
-        /* Force the srsid to wkbNDR (little) endianess */
-        GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
-        pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
-        strcpy(pszTextBufCurrent, pszHex );
-        CPLFree ( pszHex );
-        pszTextBufCurrent += 8;
-    }
-
-    /* Copy the rest of the data over - subtract
-       5 since we already copied 5 bytes above */
-    pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-
-    CPLFree( pabyWKB );
-
-    return pszTextBuf;
-}
-
-
-/************************************************************************/
 /*                        BYTEAToGByteArray()                           */
 /************************************************************************/
 
@@ -1868,37 +1740,6 @@ OGRErr OGRPGLayer::RollbackTransaction()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRPGLayer::GetSpatialRef()
-
-{
-    if (nSRSId == UNDETERMINED_SRID)
-        GetLayerDefn();
-
-    if( poSRS == NULL && nSRSId > 0 )
-    {
-        poSRS = poDS->FetchSRS( nSRSId );
-        if( poSRS != NULL )
-            poSRS->Reference();
-    }
-
-    return poSRS;
-}
-
-/************************************************************************/
-/*                             GetSRID()                                */
-/************************************************************************/
-
-int OGRPGLayer::GetSRID()
-{
-    if (nSRSId == UNDETERMINED_SRID)
-        GetSpatialRef();
-    return nSRSId;
-};
-
-/************************************************************************/
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
@@ -1914,18 +1755,62 @@ const char *OGRPGLayer::GetFIDColumn()
 }
 
 /************************************************************************/
-/*                         GetGeometryColumn()                          */
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      For PostGIS use internal Extend(geometry) function              */
+/*      in other cases we use standard OGRLayer::GetExtent()            */
 /************************************************************************/
 
-const char *OGRPGLayer::GetGeometryColumn() 
-
+OGRErr OGRPGLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
 {
-    GetLayerDefn();
+    CPLString   osCommand;
 
-    if( pszGeomColumn != NULL )
-        return pszGeomColumn;
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    OGRPGGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->myGetGeomFieldDefn(iGeomField);
+
+    const char* pszExtentFct;
+    if (poDS->sPostGISVersion.nMajor >= 2)
+        pszExtentFct = "ST_Extent";
     else
-        return "";
+        pszExtentFct = "Extent";
+
+    if ( TestCapability(OLCFastGetExtent) )
+    {
+        /* Do not take the spatial filter into account */
+        osCommand.Printf( "SELECT %s(%s) FROM %s AS ogrpgextent",
+                          pszExtentFct,
+                          OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
+                          GetFromClauseForGetExtent().c_str() );
+    }
+    else if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+    {
+        /* Probably not very efficient, but more efficient than client-side implementation */
+        osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM %s AS ogrpgextent",
+                          pszExtentFct,
+                          OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
+                          GetFromClauseForGetExtent().c_str() );
+    }
+
+    if( osCommand.size() != 0 )
+    {
+        if( RunGetExtentRequest(psExtent, bForce, osCommand) == OGRERR_NONE )
+            return OGRERR_NONE;
+    }
+    if( iGeomField == 0 )
+        return OGRLayer::GetExtent( psExtent, bForce );
+    else
+        return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
 }
 
 /************************************************************************/
@@ -1938,75 +1823,70 @@ OGRErr OGRPGLayer::RunGetExtentRequest( OGREnvelope *psExtent, int bForce,
     if ( psExtent == NULL )
         return OGRERR_FAILURE;
 
-    if ( TestCapability(OLCFastGetExtent) || bHasPostGISGeography )
-    {
-        PGconn      *hPGConn = poDS->GetPGConn();
-        PGresult    *hResult = NULL;
-
-        hResult = OGRPG_PQexec( hPGConn, osCommand );
-        if( ! hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK || PQgetisnull(hResult,0,0) )
-        {
-            OGRPGClearResult( hResult );
-            CPLDebug("PG","Unable to get extent by PostGIS. Using standard OGRLayer method.");
-            return OGRPGLayer::GetExtent( psExtent, bForce );
-        }
-
-        char * pszBox = PQgetvalue(hResult,0,0);
-        char * ptr, *ptrEndParenthesis;
-        char szVals[64*6+6];
-
-        ptr = strchr(pszBox, '(');
-        if (ptr)
-            ptr ++;
-        if (ptr == NULL ||
-            (ptrEndParenthesis = strchr(ptr, ')')) == NULL ||
-            ptrEndParenthesis - ptr > (int)(sizeof(szVals) - 1))
-        {
-            CPLError( CE_Failure, CPLE_IllegalArg,
-                      "Bad extent representation: '%s'", pszBox);
+    PGconn      *hPGConn = poDS->GetPGConn();
+    PGresult    *hResult = NULL;
 
-            OGRPGClearResult( hResult );
-            return OGRERR_FAILURE;
-        }
+    hResult = OGRPG_PQexec( hPGConn, osCommand );
+    if( ! hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK || PQgetisnull(hResult,0,0) )
+    {
+        OGRPGClearResult( hResult );
+        CPLDebug("PG","Unable to get extent by PostGIS.");
+        return OGRERR_FAILURE;
+    }
 
-        strncpy(szVals,ptr,ptrEndParenthesis - ptr);
-        szVals[ptrEndParenthesis - ptr] = '\0';
+    char * pszBox = PQgetvalue(hResult,0,0);
+    char * ptr, *ptrEndParenthesis;
+    char szVals[64*6+6];
 
-        char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);
-        int nTokenCnt = poDS->sPostGISVersion.nMajor >= 1 ? 4 : 6;
+    ptr = strchr(pszBox, '(');
+    if (ptr)
+        ptr ++;
+    if (ptr == NULL ||
+        (ptrEndParenthesis = strchr(ptr, ')')) == NULL ||
+        ptrEndParenthesis - ptr > (int)(sizeof(szVals) - 1))
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                    "Bad extent representation: '%s'", pszBox);
 
-        if ( CSLCount(papszTokens) != nTokenCnt )
-        {
-            CPLError( CE_Failure, CPLE_IllegalArg,
-                      "Bad extent representation: '%s'", pszBox);
-            CSLDestroy(papszTokens);
+        OGRPGClearResult( hResult );
+        return OGRERR_FAILURE;
+    }
 
-            OGRPGClearResult( hResult );
-            return OGRERR_FAILURE;
-        }
+    strncpy(szVals,ptr,ptrEndParenthesis - ptr);
+    szVals[ptrEndParenthesis - ptr] = '\0';
 
-        // Take X,Y coords
-        // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
-        // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
-        // =>   X2 index calculated as nTokenCnt/2
-        //      Y2 index caluclated as nTokenCnt/2+1
-        
-        psExtent->MinX = CPLAtof( papszTokens[0] );
-        psExtent->MinY = CPLAtof( papszTokens[1] );
-        psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
-        psExtent->MaxY = CPLAtof( papszTokens[nTokenCnt/2+1] );
+    char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);
+    int nTokenCnt = poDS->sPostGISVersion.nMajor >= 1 ? 4 : 6;
 
+    if ( CSLCount(papszTokens) != nTokenCnt )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                    "Bad extent representation: '%s'", pszBox);
         CSLDestroy(papszTokens);
-        OGRPGClearResult( hResult );
 
-        return OGRERR_NONE;
+        OGRPGClearResult( hResult );
+        return OGRERR_FAILURE;
     }
 
-    return OGRLayer::GetExtent( psExtent, bForce );
+    // Take X,Y coords
+    // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
+    // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
+    // =>   X2 index calculated as nTokenCnt/2
+    //      Y2 index caluclated as nTokenCnt/2+1
+    
+    psExtent->MinX = CPLAtof( papszTokens[0] );
+    psExtent->MinY = CPLAtof( papszTokens[1] );
+    psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
+    psExtent->MaxY = CPLAtof( papszTokens[nTokenCnt/2+1] );
+
+    CSLDestroy(papszTokens);
+    OGRPGClearResult( hResult );
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
-/*                         GetLayerDefn()                              */
+/*                          GetLayerDefn()                              */
 /************************************************************************/
 
 OGRFeatureDefn * OGRPGLayer::GetLayerDefn()
@@ -2020,7 +1900,7 @@ OGRFeatureDefn * OGRPGLayer::GetLayerDefn()
 /*      Build a schema from the current resultset.                      */
 /************************************************************************/
 
-OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
+int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
 
 {
     PGresult            *hResult = hInitialResultIn;
@@ -2028,10 +1908,10 @@ OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
 /* -------------------------------------------------------------------- */
 /*      Parse the returned table information.                           */
 /* -------------------------------------------------------------------- */
-    OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
+    poFeatureDefn = new OGRPGFeatureDefn( "sql_statement" );
     int            iRawField;
 
-    poDefn->Reference();
+    poFeatureDefn->Reference();
 
     for( iRawField = 0; iRawField < PQnfields(hResult); iRawField++ )
     {
@@ -2040,6 +1920,7 @@ OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
 
         nTypeOID = PQftype(hResult,iRawField);
 
+        int iGeomFuncPrefix;
         if( EQUAL(oField.GetNameRef(),"ogc_fid") )
         {
             if (bHasFid)
@@ -2052,37 +1933,38 @@ OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
             pszFIDColumn = CPLStrdup(oField.GetNameRef());
             continue;
         }
-        else if( nTypeOID == poDS->GetGeometryOID()  ||
-                 nTypeOID == poDS->GetGeographyOID()  ||
-                 EQUAL(oField.GetNameRef(),"ST_AsBinary") ||
-                 EQUAL(oField.GetNameRef(),"BinaryBase64") ||
-                 EQUAL(oField.GetNameRef(),"ST_AsEWKT") ||
-                 EQUAL(oField.GetNameRef(),"ST_AsEWKB") ||
-                 EQUAL(oField.GetNameRef(),"EWKBBase64") ||
-                 EQUAL(oField.GetNameRef(),"ST_AsText") ||
-                 EQUAL(oField.GetNameRef(),"AsBinary") ||
-                 EQUAL(oField.GetNameRef(),"asEWKT") ||
-                 EQUAL(oField.GetNameRef(),"asEWKB") ||
-                 EQUAL(oField.GetNameRef(),"asText") )
+        else if( (iGeomFuncPrefix =
+                    OGRPGIsKnownGeomFuncPrefix(oField.GetNameRef())) >= 0 ||
+                 nTypeOID == poDS->GetGeometryOID()  ||
+                 nTypeOID == poDS->GetGeographyOID()  )
         {
-            if (bHasPostGISGeometry || bHasPostGISGeography )
+            OGRPGGeomFieldDefn* poGeomFieldDefn =
+                new OGRPGGeomFieldDefn(this, oField.GetNameRef());
+            if( iGeomFuncPrefix >= 0 &&
+                oField.GetNameRef()[strlen(
+                    papszKnownGeomFuncPrefixes[iGeomFuncPrefix])] == '_' )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "More than one geometry column was found in the result of the SQL request. Only last one will be used");
+                poGeomFieldDefn->SetName( oField.GetNameRef() +
+                    strlen(papszKnownGeomFuncPrefixes[iGeomFuncPrefix]) + 1 );
             }
             if (nTypeOID == poDS->GetGeographyOID())
-                bHasPostGISGeography = TRUE;
+            {
+                poGeomFieldDefn->ePostgisType = GEOM_TYPE_GEOGRAPHY;
+                poGeomFieldDefn->nSRSId = 4326;
+            }
             else
-                bHasPostGISGeometry = TRUE;
-            CPLFree(pszGeomColumn);
-            pszGeomColumn = CPLStrdup(oField.GetNameRef());
+                poGeomFieldDefn->ePostgisType = GEOM_TYPE_GEOMETRY;
+            poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             continue;
         }
         else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
         {
-            bHasWkb = TRUE;
             if( nTypeOID == OIDOID )
                 bWkbAsOid = TRUE;
+            OGRPGGeomFieldDefn* poGeomFieldDefn =
+                new OGRPGGeomFieldDefn(this, oField.GetNameRef());
+            poGeomFieldDefn->ePostgisType = GEOM_TYPE_WKB;
+            poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             continue;
         }
 
@@ -2193,8 +2075,28 @@ OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
             oField.SetType( OFTString );
         }
 
-        poDefn->AddFieldDefn( &oField );
+        poFeatureDefn->AddFieldDefn( &oField );
     }
 
-    return poDefn;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GetSpatialRef()                             */
+/************************************************************************/
+
+OGRSpatialReference* OGRPGGeomFieldDefn::GetSpatialRef()
+{
+    if( poLayer == NULL )
+        return NULL;
+    if (nSRSId == UNDETERMINED_SRID)
+        poLayer->ResolveSRID(this);
+
+    if( poSRS == NULL && nSRSId > 0 )
+    {
+        poSRS = poLayer->GetDS()->FetchSRS( nSRSId );
+        if( poSRS != NULL )
+            poSRS->Reference();
+    }
+    return poSRS;
 }
diff --git a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
index 3d9bc12..7e2b19f 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgresultlayer.cpp 25647 2013-02-12 18:40:15Z rouault $
+ * $Id: ogrpgresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGResultLayer class, access the resultset from
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_pg.h"
 
-CPL_CVSID("$Id: ogrpgresultlayer.cpp 25647 2013-02-12 18:40:15Z rouault $");
+CPL_CVSID("$Id: ogrpgresultlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define PQexec this_is_an_error
 
@@ -53,19 +54,20 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
 
     BuildFullQueryStatement();
 
-    poFeatureDefn = ReadResultDefinition(hInitialResultIn);
+    ReadResultDefinition(hInitialResultIn);
 
     pszGeomTableName = NULL;
     pszGeomTableSchemaName = NULL;
 
     /* Find at which index the geometry column is */
     int iGeomCol = -1;
-    if (pszGeomColumn != NULL)
+    if (poFeatureDefn->GetGeomFieldCount() == 1)
     {
         int iRawField;
         for( iRawField = 0; iRawField < PQnfields(hInitialResultIn); iRawField++ )
         {
-            if( strcmp(PQfname(hInitialResultIn,iRawField), pszGeomColumn) == 0 )
+            if( strcmp(PQfname(hInitialResultIn,iRawField),
+                    poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) == 0 )
             {
                 iGeomCol = iRawField;
                 break;
@@ -96,12 +98,6 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
         }
     }
 #endif
-
-    if (bHasPostGISGeography)
-    {
-        // FIXME? But for the moment, PostGIS 1.5 only handles SRID:4326.
-        nSRSId = 4326;
-    }
 }
 
 /************************************************************************/
@@ -186,17 +182,40 @@ int OGRPGResultLayer::GetFeatureCount( int bForce )
 int OGRPGResultLayer::TestCapability( const char * pszCap )
 
 {
+    GetLayerDefn();
+    
     if( EQUAL(pszCap,OLCFastFeatureCount) ||
         EQUAL(pszCap,OLCFastSetNextByIndex) )
-        return (m_poFilterGeom == NULL || 
-                ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)) && m_poAttrQuery == NULL;
-
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+        return (m_poFilterGeom == NULL ||
+                poGeomFieldDefn == NULL ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ) 
+               && m_poAttrQuery == NULL;
+    }
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+        return (poGeomFieldDefn == NULL ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ) 
+               && m_poAttrQuery == NULL;
+    }
 
     else if( EQUAL(pszCap,OLCFastGetExtent) )
-        return (bHasPostGISGeometry && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
-        
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(0);
+        return (poGeomFieldDefn == NULL ||
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ) 
+               && m_poAttrQuery == NULL;
+    }
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
 
@@ -212,10 +231,9 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
 OGRFeature *OGRPGResultLayer::GetNextFeature()
 
 {
-    if( (bHasPostGISGeometry || bHasPostGISGeography) && nSRSId == UNDETERMINED_SRID )
-    {
-        GetSpatialRef(); /* make sure that we fetch the SRID if not already done */
-    }
+    OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
 
     for( ; TRUE; )
     {
@@ -226,8 +244,10 @@ OGRFeature *OGRPGResultLayer::GetNextFeature()
             return NULL;
 
         if( (m_poFilterGeom == NULL
-            || ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
+            || poGeomFieldDefn == NULL
+            || poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY
+            || poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
             return poFeature;
@@ -240,17 +260,27 @@ OGRFeature *OGRPGResultLayer::GetNextFeature()
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
 
-void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+void OGRPGResultLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 {
-    if( InstallFilter( poGeomIn ) )
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
     {
-        if( (bHasPostGISGeometry || bHasPostGISGeography) && nSRSId == UNDETERMINED_SRID )
+        if( iGeomField != 0 )
         {
-            GetSpatialRef(); /* make sure that we fetch the SRID if not already done */
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
         }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
 
-        if ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
+    OGRPGGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+    if( InstallFilter( poGeomIn ) )
+    {
+        if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+             poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
         {
             if( m_poFilterGeom != NULL)
             {
@@ -260,16 +290,27 @@ void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
                 OGREnvelope  sEnvelope;
 
                 m_poFilterGeom->getEnvelope( &sEnvelope );
-                snprintf(szBox3D_1, sizeof(szBox3D_1), "%.12f %.12f", sEnvelope.MinX, sEnvelope.MinY);
+                if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+                {
+                    if( sEnvelope.MinX < -180.0 )
+                        sEnvelope.MinX = -180.0;
+                    if( sEnvelope.MinY < -90.0 )
+                        sEnvelope.MinY = -90.0;
+                    if( sEnvelope.MaxX > 180.0 )
+                        sEnvelope.MaxX = 180.0;
+                    if( sEnvelope.MaxY > 90.0 )
+                        sEnvelope.MaxY = 90.0;
+                }
+                snprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
                 while((pszComma = strchr(szBox3D_1, ',')) != NULL)
                     *pszComma = '.';
-                snprintf(szBox3D_2, sizeof(szBox3D_2), "%.12f %.12f", sEnvelope.MaxX, sEnvelope.MaxY);
+                snprintf(szBox3D_2, sizeof(szBox3D_2), "%.18g %.18g", sEnvelope.MaxX, sEnvelope.MaxY);
                 while((pszComma = strchr(szBox3D_2, ',')) != NULL)
                     *pszComma = '.';
                 osWHERE.Printf("WHERE %s && %s('BOX3D(%s, %s)'::box3d,%d) ",
-                               OGRPGEscapeColumnName(pszGeomColumn).c_str(),
+                               OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
                                (poDS->sPostGISVersion.nMajor >= 2) ? "ST_SetSRID" : "SetSRID",
-                               szBox3D_1, szBox3D_2, nSRSId );
+                               szBox3D_1, szBox3D_2, poGeomFieldDefn->nSRSId );
             }
             else
             {
@@ -285,111 +326,76 @@ void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 }
 
 /************************************************************************/
-/*                             GetExtent()                              */
-/*                                                                      */
-/*      For PostGIS use internal Extend(geometry) function              */
-/*      in other cases we use standard OGRLayer::GetExtent()            */
+/*                            ResolveSRID()                             */
 /************************************************************************/
 
-OGRErr OGRPGResultLayer::GetExtent( OGREnvelope *psExtent, int bForce )
-{
-    CPLString   osCommand;
-
-    const char* pszExtentFct;
-    if (poDS->sPostGISVersion.nMajor >= 2)
-        pszExtentFct = "ST_Extent";
-    else
-        pszExtentFct = "Extent";
-
-    if( (bHasPostGISGeometry || bHasPostGISGeography) && nSRSId == UNDETERMINED_SRID )
-    {
-        GetSpatialRef(); /* make sure that we fetch the SRID if not already done */
-    }
-
-    if ( TestCapability(OLCFastGetExtent) )
-    {
-        /* Do not take the spatial filter into account */
-        osCommand.Printf( "SELECT %s(%s) FROM (%s) AS ogrpgextent",
-                          pszExtentFct, OGRPGEscapeColumnName(pszGeomColumn).c_str(),
-                          pszRawStatement );
-    }
-    else if ( bHasPostGISGeography )
-    {
-        /* Probably not very efficient, but more efficient than client-side implementation */
-        osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM (%s) AS ogrpgextent",
-                          pszExtentFct, OGRPGEscapeColumnName(pszGeomColumn).c_str(),
-                          pszRawStatement );
-    }
-    
-    return RunGetExtentRequest(psExtent, bForce, osCommand);
-}
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/*                                                                      */
-/*      We override this to try and fetch the table SRID from the       */
-/*      geometry_columns table if the srsid is UNDETERMINED_SRID        */
-/*      (meaning we haven't yet even looked for it).                    */
-/************************************************************************/
-
-OGRSpatialReference *OGRPGResultLayer::GetSpatialRef()
+void OGRPGResultLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
 
 {
-    if( nSRSId == UNDETERMINED_SRID )
+    /* We have to get the SRID of the geometry column, so to be able */
+    /* to do spatial filtering */
+    int nSRSId = UNDETERMINED_SRID;
+    if( poGFldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
     {
-        /* We have to get the SRID of the geometry column, so to be able */
-        /* to do spatial filtering */
-        if (bHasPostGISGeometry)
+        if (pszGeomTableName != NULL)
         {
-            if (pszGeomTableName != NULL)
+            CPLString osName(pszGeomTableSchemaName);
+            osName += ".";
+            osName += pszGeomTableName;
+            OGRPGLayer* poBaseLayer = (OGRPGLayer*) poDS->GetLayerByName(osName);
+            if (poBaseLayer)
             {
-                CPLString osName(pszGeomTableSchemaName);
-                osName += ".";
-                osName += pszGeomTableName;
-                OGRPGLayer* poBaseLayer = (OGRPGLayer*) poDS->GetLayerByName(osName);
-                if (poBaseLayer)
+                int iBaseIdx = poBaseLayer->GetLayerDefn()->
+                    GetGeomFieldIndex( poGFldDefn->GetNameRef() );
+                if( iBaseIdx >= 0 )
                 {
-                    nSRSId = poBaseLayer->GetSRID();
+                    OGRPGGeomFieldDefn* poBaseGFldDefn =
+                        poBaseLayer->myGetLayerDefn()->myGetGeomFieldDefn(iBaseIdx);
+                    poBaseGFldDefn->GetSpatialRef(); /* To make sure nSRSId is resolved */
+                    nSRSId = poBaseGFldDefn->nSRSId;
                 }
             }
+        }
 
-            if( nSRSId == UNDETERMINED_SRID )
-            {
-                CPLString osGetSRID;
+        if( nSRSId == UNDETERMINED_SRID )
+        {
+            CPLString osGetSRID;
 
-                const char* psGetSRIDFct;
-                if (poDS->sPostGISVersion.nMajor >= 2)
-                    psGetSRIDFct = "ST_SRID";
-                else
-                    psGetSRIDFct = "getsrid";
+            const char* psGetSRIDFct;
+            if (poDS->sPostGISVersion.nMajor >= 2)
+                psGetSRIDFct = "ST_SRID";
+            else
+                psGetSRIDFct = "getsrid";
 
-                osGetSRID += "SELECT ";
-                osGetSRID += psGetSRIDFct;
-                osGetSRID += "(";
-                osGetSRID += OGRPGEscapeColumnName(pszGeomColumn);
-                osGetSRID += ") FROM(";
-                osGetSRID += pszRawStatement;
-                osGetSRID += ") AS ogrpggetsrid LIMIT 1";
+            osGetSRID += "SELECT ";
+            osGetSRID += psGetSRIDFct;
+            osGetSRID += "(";
+            osGetSRID += OGRPGEscapeColumnName(poGFldDefn->GetNameRef());
+            osGetSRID += ") FROM(";
+            osGetSRID += pszRawStatement;
+            osGetSRID += ") AS ogrpggetsrid LIMIT 1";
 
-                PGresult* hSRSIdResult = OGRPG_PQexec(poDS->GetPGConn(), osGetSRID );
+            PGresult* hSRSIdResult = OGRPG_PQexec(poDS->GetPGConn(), osGetSRID );
 
-                nSRSId = -1;
+            nSRSId = poDS->GetUndefinedSRID();
 
-                if( hSRSIdResult && PQresultStatus(hSRSIdResult) == PGRES_TUPLES_OK)
-                {
-                    if ( PQntuples(hSRSIdResult) > 0 )
-                        nSRSId = atoi(PQgetvalue(hSRSIdResult, 0, 0));
-                }
-                else
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                                "%s", PQerrorMessage(poDS->GetPGConn()) );
-                }
-
-                OGRPGClearResult(hSRSIdResult);
+            if( hSRSIdResult && PQresultStatus(hSRSIdResult) == PGRES_TUPLES_OK)
+            {
+                if ( PQntuples(hSRSIdResult) > 0 )
+                    nSRSId = atoi(PQgetvalue(hSRSIdResult, 0, 0));
             }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                            "%s", PQerrorMessage(poDS->GetPGConn()) );
+            }
+
+            OGRPGClearResult(hSRSIdResult);
         }
     }
-
-    return OGRPGLayer::GetSpatialRef();
+    else if( poGFldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+    {
+        nSRSId = 4326;
+    }
+    poGFldDefn->nSRSId = nSRSId;
 }
diff --git a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
index e40b9f7..907bbb0 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
@@ -1,5 +1,6 @@
 /******************************************************************************
- * $Id: ogrpgtablelayer.cpp 25366 2012-12-27 18:38:53Z rouault $
+ * $Id: ogrpgtablelayer.cpp 27106 2014-03-28 11:59:57Z rouault $
+
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGTableLayer class, access to an existing table.
@@ -7,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,10 +33,12 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_error.h"
+#include "ogr_p.h"
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgtablelayer.cpp 25366 2012-12-27 18:38:53Z rouault $");
+CPL_CVSID("$Id: ogrpgtablelayer.cpp 27106 2014-03-28 11:59:57Z rouault $");
+
 
 #define USE_COPY_UNSET  -10
 static CPLString OGRPGEscapeStringList(PGconn *hPGConn,
@@ -43,6 +47,79 @@ static CPLString OGRPGEscapeStringList(PGconn *hPGConn,
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
 /************************************************************************/
+/*                        OGRPGTableFeatureDefn                         */
+/************************************************************************/
+
+class OGRPGTableFeatureDefn : public OGRPGFeatureDefn
+{
+    private:
+        OGRPGTableLayer *poLayer;
+
+        void SolveFields();
+
+    public:
+        OGRPGTableFeatureDefn( OGRPGTableLayer* poLayerIn,
+                               const char * pszName = NULL ) :
+            OGRPGFeatureDefn(pszName), poLayer(poLayerIn)
+        {
+        }
+
+        virtual void UnsetLayer()
+        {
+            poLayer = NULL;
+            OGRPGFeatureDefn::UnsetLayer();
+        }
+
+        virtual int         GetFieldCount()
+            { SolveFields(); return OGRPGFeatureDefn::GetFieldCount(); }
+        virtual OGRFieldDefn *GetFieldDefn( int i )
+            { SolveFields(); return OGRPGFeatureDefn::GetFieldDefn(i); }
+        virtual int         GetFieldIndex( const char * pszName )
+            { SolveFields(); return OGRPGFeatureDefn::GetFieldIndex(pszName); }
+
+        virtual int         GetGeomFieldCount()
+            { if (poLayer != NULL && !poLayer->HasGeometryInformation())
+                  SolveFields();
+              return OGRPGFeatureDefn::GetGeomFieldCount(); }
+        virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i )
+            { if (poLayer != NULL && !poLayer->HasGeometryInformation())
+                  SolveFields();
+              return OGRPGFeatureDefn::GetGeomFieldDefn(i); }
+        virtual int         GetGeomFieldIndex( const char * pszName)
+            { if (poLayer != NULL && !poLayer->HasGeometryInformation())
+                  SolveFields();
+              return OGRPGFeatureDefn::GetGeomFieldIndex(pszName); }
+
+};
+
+/************************************************************************/
+/*                           SolveFields()                              */
+/************************************************************************/
+
+void OGRPGTableFeatureDefn::SolveFields()
+{
+    if( poLayer == NULL )
+        return;
+
+    poLayer->ReadTableDefinition();
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char *OGRPGTableLayer::GetFIDColumn() 
+
+{
+    ReadTableDefinition();
+
+    if( pszFIDColumn != NULL )
+        return pszFIDColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
 /*                          OGRPGTableLayer()                           */
 /************************************************************************/
 
@@ -50,10 +127,8 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
                                   CPLString& osCurrentSchema,
                                   const char * pszTableNameIn,
                                   const char * pszSchemaNameIn,
-                                  const char * pszGeomColumnIn,
-                                  int bUpdate,
-                                  int bAdvertizeGeomColumn,
-                                  int nSRSIdIn )
+                                  const char * pszGeomColForced,
+                                  int bUpdate )
 
 {
     poDS = poDSIn;
@@ -64,8 +139,6 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
 
     iNextShapeId = 0;
 
-    nSRSId = nSRSIdIn;
-    nGeomType = wkbUnknown;
     bGeometryInformationSet = FALSE;
 
     bLaunderColumnNames = TRUE;
@@ -73,18 +146,20 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
     bCopyActive = FALSE;
     bUseCopy = USE_COPY_UNSET;  // unknown
     bFIDColumnInCopyFields = FALSE;
+    bFirstInsertion = TRUE;
 
     pszTableName = CPLStrdup( pszTableNameIn );
-    if (pszGeomColumnIn)
-        pszGeomColumn = CPLStrdup(pszGeomColumnIn);
     if (pszSchemaNameIn)
         pszSchemaName = CPLStrdup( pszSchemaNameIn );
     else if (strlen(osCurrentSchema))
         pszSchemaName = CPLStrdup( osCurrentSchema );
     else
         pszSchemaName = NULL;
+    this->pszGeomColForced =
+        pszGeomColForced ? CPLStrdup(pszGeomColForced) : NULL;
 
     pszSqlGeomParentTableName = NULL;
+    bTableDefinitionValid = -1;
 
     bHasWarnedIncompatibleGeom = FALSE;
     bHasWarnedAlreadySetFID = FALSE;
@@ -95,14 +170,10 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
 /* -------------------------------------------------------------------- */
 /*      Build the layer defn name.                                      */
 /* -------------------------------------------------------------------- */
+    CPLString osDefnName;
     if ( pszSchemaNameIn && osCurrentSchema != pszSchemaNameIn )
     {
-        /* For backwards compatibility, don't report the geometry column name */
-        /* if it's wkb_geometry */
-        if (bAdvertizeGeomColumn && pszGeomColumnIn)
-            osDefnName.Printf( "%s.%s(%s)", pszSchemaNameIn, pszTableName, pszGeomColumnIn );
-        else
-            osDefnName.Printf("%s.%s", pszSchemaNameIn, pszTableName );
+        osDefnName.Printf("%s.%s", pszSchemaNameIn, pszTableName );
         pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
                                OGRPGEscapeColumnName(pszSchemaNameIn).c_str(),
                                OGRPGEscapeColumnName(pszTableName).c_str() ));
@@ -110,18 +181,26 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
     else
     {
         //no prefix for current_schema in layer name, for backwards compatibility
-        /* For backwards compatibility, don't report the geometry column name */
-        /* if it's wkb_geometry */
-        if (bAdvertizeGeomColumn && pszGeomColumnIn)
-            osDefnName.Printf( "%s(%s)", pszTableName, pszGeomColumnIn );
-        else
-            osDefnName = pszTableName;
+        osDefnName = pszTableName;
         pszSqlTableName = CPLStrdup(OGRPGEscapeColumnName(pszTableName));
     }
+    if( pszGeomColForced != NULL )
+    {
+        osDefnName += "(";
+        osDefnName += pszGeomColForced;
+        osDefnName += ")";
+    }
 
     osPrimaryKey = CPLGetConfigOption( "PGSQL_OGR_FID", "ogc_fid" );
 
     papszOverrideColumnTypes = NULL;
+    nForcedSRSId = UNDETERMINED_SRID;
+    nForcedDimension = -1;
+    bCreateSpatialIndexFlag = TRUE;
+    bInResetReading = FALSE;
+
+    poFeatureDefn = new OGRPGTableFeatureDefn( this, osDefnName );
+    poFeatureDefn->Reference();
 }
 
 //************************************************************************/
@@ -136,6 +215,7 @@ OGRPGTableLayer::~OGRPGTableLayer()
     CPLFree( pszTableName );
     CPLFree( pszSqlGeomParentTableName );
     CPLFree( pszSchemaName );
+    CPLFree( pszGeomColForced );
     CSLDestroy( papszOverrideColumnTypes );
 }
 
@@ -143,47 +223,31 @@ OGRPGTableLayer::~OGRPGTableLayer()
 /*                      SetGeometryInformation()                        */
 /************************************************************************/
 
-void  OGRPGTableLayer::SetGeometryInformation(const char* pszType,
-                                               int nCoordDimension,
-                                               int nSRID,
-                                               PostgisType ePostgisType)
+void  OGRPGTableLayer::SetGeometryInformation(PGGeomColumnDesc* pasDesc,
+                                              int nGeomFieldCount)
 {
-    if (pszType == NULL || nCoordDimension == 0 || nSRID == UNDETERMINED_SRID ||
-        ePostgisType == GEOM_TYPE_UNKNOWN)
-        return;
-
+    /* flag must be set before instanciating geometry fields */
     bGeometryInformationSet = TRUE;
 
-    nGeomType = OGRFromOGCGeomType(pszType);
-
-    this->nCoordDimension = nCoordDimension;
-    this->nSRSId = nSRID;
-
-    if( nCoordDimension == 3 && nGeomType != wkbUnknown )
-        nGeomType = (OGRwkbGeometryType) (nGeomType | wkb25DBit);
-
-    if( ePostgisType == GEOM_TYPE_GEOMETRY)
-        bHasPostGISGeometry = TRUE;
-    else if( ePostgisType == GEOM_TYPE_GEOGRAPHY)
-        bHasPostGISGeography = TRUE;
-
-    CPLDebug("PG","Layer '%s' geometry type: %s:%s, Dim=%d",
-                pszTableName, pszType, OGRGeometryTypeToName(nGeomType),
-                nCoordDimension );
+    for(int i=0; i<nGeomFieldCount; i++)
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn =
+            new OGRPGGeomFieldDefn(this, pasDesc[i].pszName);
+        poGeomFieldDefn->nSRSId = pasDesc[i].nSRID;
+        poGeomFieldDefn->nCoordDimension = pasDesc[i].nCoordDimension;
+        poGeomFieldDefn->ePostgisType = pasDesc[i].ePostgisType;
+        if( pasDesc[i].pszGeomType != NULL )
+        {
+            OGRwkbGeometryType eGeomType = OGRFromOGCGeomType(pasDesc[i].pszGeomType);
+            if( poGeomFieldDefn->nCoordDimension == 3 && eGeomType != wkbUnknown )
+                eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
+            poGeomFieldDefn->SetType(eGeomType);
+        }
+        poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
+    }
 }
 
-/************************************************************************/
-/*                            GetGeomType()                             */
-/************************************************************************/
-
-OGRwkbGeometryType  OGRPGTableLayer::GetGeomType()
-{
-    if (bGeometryInformationSet)
-        return nGeomType;
 
-    return GetLayerDefn()->GetGeomType();
-}
-    
 /************************************************************************/
 /*                        ReadTableDefinition()                         */
 /*                                                                      */
@@ -191,18 +255,23 @@ OGRwkbGeometryType  OGRPGTableLayer::GetGeomType()
 /*      catalog.                                                        */
 /************************************************************************/
 
-OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
+int OGRPGTableLayer::ReadTableDefinition()
 
 {
     PGresult            *hResult;
     CPLString           osCommand;
     PGconn              *hPGConn = poDS->GetPGConn();
 
+    if( bTableDefinitionValid >= 0 )
+        return bTableDefinitionValid;
+    bTableDefinitionValid = FALSE;
+
     poDS->FlushSoftTransaction();
 
     CPLString osSchemaClause;
     if( pszSchemaName )
-        osSchemaClause.Printf("AND n.nspname='%s'", pszSchemaName);
+        osSchemaClause.Printf("AND n.nspname=%s",
+                              OGRPGEscapeString(hPGConn, pszSchemaName).c_str());
 
     const char* pszTypnameEqualsAnyClause;
     if (poDS->sPostgreSQLVersion.nMajor == 7 && poDS->sPostgreSQLVersion.nMinor <= 3)
@@ -275,7 +344,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
                  "AND a.attnum > 0 AND a.attrelid = c.oid "
                  "AND a.atttypid = t.oid "
                  "AND c.relnamespace=n.oid "
-                 "%s"
+                 "%s "
                  "ORDER BY a.attnum",
                  pszEscapedTableNameSingleQuote, osSchemaClause.c_str());
 
@@ -294,7 +363,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
 
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", PQerrorMessage(hPGConn) );
-        return NULL;
+        return bTableDefinitionValid;
     }
 
     if( PQntuples(hResult) == 0 )
@@ -310,17 +379,14 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         CPLError( CE_Failure, CPLE_AppDefined,
                   "No field definitions found for '%s', is it a table?",
                   pszTableName );
-        return NULL;
+        return bTableDefinitionValid;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Parse the returned table information.                           */
 /* -------------------------------------------------------------------- */
-    OGRFeatureDefn *poDefn = new OGRFeatureDefn( osDefnName );
     int            iRecord;
 
-    poDefn->Reference();
-
     for( iRecord = 0; iRecord < PQntuples(hResult); iRecord++ )
     {
         const char      *pszType = NULL;
@@ -337,28 +403,40 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
             CPLDebug("PG","Using column '%s' as FID for table '%s'", pszFIDColumn, pszTableName );
             continue;
         }
-        else if( EQUAL(pszType,"geometry") )
+        else if( EQUAL(pszType,"geometry") ||
+                 EQUAL(pszType,"geography") ||
+                 EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
         {
-            bHasPostGISGeometry = TRUE;
-            if (!pszGeomColumn)
-                pszGeomColumn = CPLStrdup(oField.GetNameRef());
-            continue;
-        }
-        else if( EQUAL(pszType,"geography") )
-        {
-            bHasPostGISGeography = TRUE;
-            if (!pszGeomColumn)
-                pszGeomColumn = CPLStrdup(oField.GetNameRef());
-            continue;
-        }
-        else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
-        {
-            if (!pszGeomColumn)
+            OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+            if( !bGeometryInformationSet )
+            {
+                if( pszGeomColForced == NULL ||
+                    EQUAL(pszGeomColForced, oField.GetNameRef()) )
+                    poGeomFieldDefn = new OGRPGGeomFieldDefn(this, oField.GetNameRef());
+            }
+            else
             {
-                bHasWkb = TRUE;
-                pszGeomColumn = CPLStrdup(oField.GetNameRef());
-                if( EQUAL(pszType,"OID") )
-                    bWkbAsOid = TRUE;
+                int idx = poFeatureDefn->GetGeomFieldIndex(oField.GetNameRef());
+                if( idx >= 0 )
+                    poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(idx);
+            }
+            if( poGeomFieldDefn != NULL )
+            {
+                if( EQUAL(pszType,"geometry") )
+                    poGeomFieldDefn->ePostgisType = GEOM_TYPE_GEOMETRY;
+                else if( EQUAL(pszType,"geography") )
+                {
+                    poGeomFieldDefn->ePostgisType = GEOM_TYPE_GEOGRAPHY;
+                    poGeomFieldDefn->nSRSId = 4326;
+                }
+                else
+                {
+                    poGeomFieldDefn->ePostgisType = GEOM_TYPE_WKB;
+                    if( EQUAL(pszType,"OID") )
+                        bWkbAsOid = TRUE;
+                }
+                if( !bGeometryInformationSet )
+                    poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             }
             continue;
         }
@@ -398,23 +476,28 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         else if( EQUAL(pszType,"numeric") )
         {
             const char *pszFormatName = PQgetvalue(hResult,iRecord,3);
-            const char *pszPrecision = strstr(pszFormatName,",");
-            int    nWidth, nPrecision = 0;
+            if( EQUAL(pszFormatName, "numeric") )
+                oField.SetType( OFTReal );
+            else
+            {
+                const char *pszPrecision = strstr(pszFormatName,",");
+                int    nWidth, nPrecision = 0;
 
-            nWidth = atoi(pszFormatName + 8);
-            if( pszPrecision != NULL )
-                nPrecision = atoi(pszPrecision+1);
+                nWidth = atoi(pszFormatName + 8);
+                if( pszPrecision != NULL )
+                    nPrecision = atoi(pszPrecision+1);
 
-            if( nPrecision == 0 )
-            {
-                // FIXME : If nWidth > 10, OFTInteger may not be large enough */
-                oField.SetType( OFTInteger );
-            }
-            else
-                oField.SetType( OFTReal );
+                if( nPrecision == 0 )
+                {
+                    // FIXME : If nWidth > 10, OFTInteger may not be large enough */
+                    oField.SetType( OFTInteger );
+                }
+                else
+                    oField.SetType( OFTReal );
 
-            oField.SetWidth( nWidth );
-            oField.SetPrecision( nPrecision );
+                oField.SetWidth( nWidth );
+                oField.SetPrecision( nPrecision );
+            }
         }
         else if( EQUAL(pszFormatType,"integer[]") )
         {
@@ -469,7 +552,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
                       oField.GetNameRef(), pszFormatType, pszType );
         }
 
-        poDefn->AddFieldDefn( &oField );
+        poFeatureDefn->AddFieldDefn( &oField );
     }
 
     OGRPGClearResult( hResult );
@@ -480,66 +563,81 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
     hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
+    bTableDefinitionValid = TRUE;
+
+    ResetReading();
+
     /* If geometry type, SRID, etc... have always been set by SetGeometryInformation() */
     /* no need to issue a new SQL query. Just record the geom type in the layer definition */
     if (bGeometryInformationSet)
     {
-        ;
+        return TRUE;
     }
+    bGeometryInformationSet = TRUE;
+
     // get layer geometry type (for PostGIS dataset)
-    else if ( bHasPostGISGeometry || bHasPostGISGeography )
+    for(int iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++)
     {
+      OGRPGGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->myGetGeomFieldDefn(iField);
+
       /* Get the geometry type and dimensions from the table, or */
       /* from its parents if it is a derived table, or from the parent of the parent, etc.. */
       int bGoOn = TRUE;
+      int bHasPostGISGeometry =
+        (poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY);
 
       while(bGoOn)
       {
+        CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn,
+                (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName);
+        const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+
         osCommand.Printf(
-            "SELECT type, coord_dimension%s FROM %s WHERE f_table_name='%s'",
-            (nSRSId == UNDETERMINED_SRID) ? ", srid" : "",
+            "SELECT type, coord_dimension, srid FROM %s WHERE f_table_name = %s",
             (bHasPostGISGeometry) ? "geometry_columns" : "geography_columns",
-            (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName);
-        if (pszGeomColumn)
-        {
-            osCommand += CPLString().Printf(" AND %s='%s'",
-                (bHasPostGISGeometry) ? "f_geometry_column" : "f_geography_column",
-                pszGeomColumn);
-        }
+            pszEscapedTableNameSingleQuote);
+
+        osCommand += CPLString().Printf(" AND %s=%s",
+            (bHasPostGISGeometry) ? "f_geometry_column" : "f_geography_column",
+            OGRPGEscapeString(hPGConn,poGeomFieldDefn->GetNameRef()).c_str());
+
         if (pszSchemaName)
         {
-            osCommand += CPLString().Printf(" AND f_table_schema='%s'", pszSchemaName);
+            osCommand += CPLString().Printf(" AND f_table_schema = %s",
+                                            OGRPGEscapeString(hPGConn,pszSchemaName).c_str());
         }
 
         hResult = OGRPG_PQexec(hPGConn,osCommand);
 
         if ( hResult && PQntuples(hResult) == 1 && !PQgetisnull(hResult,0,0) )
         {
-            char * pszType = PQgetvalue(hResult,0,0);
+            const char* pszType = PQgetvalue(hResult,0,0);
 
-            nCoordDimension = MAX(2,MIN(3,atoi(PQgetvalue(hResult,0,1))));
+            int nCoordDimension = MAX(2,MIN(3,atoi(PQgetvalue(hResult,0,1))));
 
-            if (nSRSId == UNDETERMINED_SRID)
-                nSRSId = atoi(PQgetvalue(hResult,0,2));
+            int nSRSId = atoi(PQgetvalue(hResult,0,2));
 
-            SetGeometryInformation(pszType, nCoordDimension, nSRSId,
-                                   (bHasPostGISGeometry) ? GEOM_TYPE_GEOMETRY : GEOM_TYPE_GEOGRAPHY);
+            poGeomFieldDefn->nCoordDimension = nCoordDimension;
+            if( nSRSId > 0 )
+                poGeomFieldDefn->nSRSId = nSRSId;
+            OGRwkbGeometryType eGeomType = OGRFromOGCGeomType(pszType);
+            if( poGeomFieldDefn->nCoordDimension == 3 && eGeomType != wkbUnknown )
+                eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
+            poGeomFieldDefn->SetType(eGeomType);
 
             bGoOn = FALSE;
         }
         else
         {
-            CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn,
-                    (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName);
-            const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
-
             /* Fetch the name of the parent table */
             if (pszSchemaName)
             {
                 osCommand.Printf("SELECT pg_class.relname FROM pg_class WHERE oid = "
                                 "(SELECT pg_inherits.inhparent FROM pg_inherits WHERE inhrelid = "
-                                "(SELECT c.oid FROM pg_class c, pg_namespace n WHERE c.relname = %s AND c.relnamespace=n.oid AND n.nspname = '%s'))",
-                                pszEscapedTableNameSingleQuote, pszSchemaName );
+                                "(SELECT c.oid FROM pg_class c, pg_namespace n WHERE c.relname = %s AND c.relnamespace=n.oid AND n.nspname = %s))",
+                                pszEscapedTableNameSingleQuote,
+                                OGRPGEscapeString(hPGConn, pszSchemaName).c_str() );
             }
             else
             {
@@ -566,28 +664,29 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
 
         OGRPGClearResult( hResult );
       }
-
-      if (nSRSId == UNDETERMINED_SRID)
-          nSRSId = poDS->GetUndefinedSRID();
-    }
-    else if (pszGeomColumn == NULL)
-    {
-        nGeomType = wkbNone;
     }
 
-    poDefn->SetGeomType( nGeomType );
-
-    return poDefn;
+    return bTableDefinitionValid;
 }
 
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
 
-void OGRPGTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+void OGRPGTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 {
-    GetLayerDefn();
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
 
     if( InstallFilter( poGeomIn ) )
     {
@@ -608,8 +707,13 @@ void OGRPGTableLayer::BuildWhere()
 
 {
     osWHERE = "";
+    OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
 
-    if( m_poFilterGeom != NULL && (bHasPostGISGeometry || bHasPostGISGeography) )
+    if( m_poFilterGeom != NULL && poGeomFieldDefn != NULL && (
+            poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+            poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY) )
     {
         char szBox3D_1[128];
         char szBox3D_2[128];
@@ -617,16 +721,27 @@ void OGRPGTableLayer::BuildWhere()
         OGREnvelope  sEnvelope;
 
         m_poFilterGeom->getEnvelope( &sEnvelope );
-        snprintf(szBox3D_1, sizeof(szBox3D_1), "%.12f %.12f", sEnvelope.MinX, sEnvelope.MinY);
+        if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+        {
+            if( sEnvelope.MinX < -180.0 )
+                sEnvelope.MinX = -180.0;
+            if( sEnvelope.MinY < -90.0 )
+                sEnvelope.MinY = -90.0;
+            if( sEnvelope.MaxX > 180.0 )
+                sEnvelope.MaxX = 180.0;
+            if( sEnvelope.MaxY > 90.0 )
+                sEnvelope.MaxY = 90.0;
+        }
+        snprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
         while((pszComma = strchr(szBox3D_1, ',')) != NULL)
             *pszComma = '.';
-        snprintf(szBox3D_2, sizeof(szBox3D_2), "%.12f %.12f", sEnvelope.MaxX, sEnvelope.MaxY);
+        snprintf(szBox3D_2, sizeof(szBox3D_2), "%.18g %.18g", sEnvelope.MaxX, sEnvelope.MaxY);
         while((pszComma = strchr(szBox3D_2, ',')) != NULL)
             *pszComma = '.';
         osWHERE.Printf("WHERE %s && %s('BOX3D(%s, %s)'::box3d,%d) ",
-                       OGRPGEscapeColumnName(pszGeomColumn).c_str(),
+                       OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()).c_str(),
                        (poDS->sPostGISVersion.nMajor >= 2) ? "ST_SetSRID" : "SetSRID",
-                       szBox3D_1, szBox3D_2, nSRSId );
+                       szBox3D_1, szBox3D_2, poGeomFieldDefn->nSRSId );
     }
 
     if( strlen(osQuery) > 0 )
@@ -651,14 +766,12 @@ void OGRPGTableLayer::BuildWhere()
 void OGRPGTableLayer::BuildFullQueryStatement()
 
 {
+    CPLString osFields = BuildFields();
     if( pszQueryStatement != NULL )
     {
         CPLFree( pszQueryStatement );
         pszQueryStatement = NULL;
     }
-
-    CPLString osFields = BuildFields();
-
     pszQueryStatement = (char *)
         CPLMalloc(strlen(osFields)+strlen(osWHERE)
                   +strlen(pszSqlTableName) + 40);
@@ -674,13 +787,17 @@ void OGRPGTableLayer::BuildFullQueryStatement()
 void OGRPGTableLayer::ResetReading()
 
 {
-    GetLayerDefn();
+    if( bInResetReading )
+        return;
+    bInResetReading = TRUE;
 
     bUseCopy = USE_COPY_UNSET;
 
     BuildFullQueryStatement();
 
     OGRPGLayer::ResetReading();
+
+    bInResetReading = FALSE;
 }
 
 /************************************************************************/
@@ -690,7 +807,10 @@ void OGRPGTableLayer::ResetReading()
 OGRFeature *OGRPGTableLayer::GetNextFeature()
 
 {
-    GetLayerDefn();
+    OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+        poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+    poFeatureDefn->GetFieldCount();
 
     for( ; TRUE; )
     {
@@ -705,9 +825,10 @@ OGRFeature *OGRPGTableLayer::GetNextFeature()
         /* is already taken into account in the select request */
         /* The attribute filter is always taken into account by the select request */
         if( m_poFilterGeom == NULL
-            || bHasPostGISGeometry
-            || bHasPostGISGeography
-            || FilterGeometry( poFeature->GetGeometryRef() )  )
+            || poGeomFieldDefn == NULL
+            || poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY
+            || poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) )  )
             return poFeature;
 
         delete poFeature;
@@ -727,40 +848,49 @@ CPLString OGRPGTableLayer::BuildFields()
     int     i = 0;
     CPLString osFieldList;
 
+    poFeatureDefn->GetFieldCount();
+
     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
     {
         osFieldList += OGRPGEscapeColumnName(pszFIDColumn);
     }
 
-    if( pszGeomColumn )
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        if( strlen(osFieldList) > 0 )
+        OGRPGGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        CPLString osEscapedGeom =
+            OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
+
+        if( osFieldList.size() > 0 )
             osFieldList += ", ";
 
-        if( bHasPostGISGeometry )
+        if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
         {
             if ( poDS->bUseBinaryCursor )
             {
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += osEscapedGeom;
             }
             else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")) &&
-                     nCoordDimension != 4 /* we don't know how to decode 4-dim EWKB for now */)
+                     poGeomFieldDefn->nCoordDimension != 4 /* we don't know how to decode 4-dim EWKB for now */)
             {
                 if (poDS->sPostGISVersion.nMajor >= 2)
                     osFieldList += "encode(ST_AsEWKB(";
                 else
                     osFieldList += "encode(AsEWKB(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += "), 'base64') AS EWKBBase64";
+                osFieldList += osEscapedGeom;
+                osFieldList += "), 'base64') AS ";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("EWKBBase64_%s", poGeomFieldDefn->GetNameRef()));
             }
             else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) &&
-                     nCoordDimension != 4 && /* we don't know how to decode 4-dim EWKB for now */
+                     poGeomFieldDefn->nCoordDimension != 4 && /* we don't know how to decode 4-dim EWKB for now */
                       /* perhaps works also for older version, but I didn't check */
                       (poDS->sPostGISVersion.nMajor > 1 ||
                       (poDS->sPostGISVersion.nMajor == 1 && poDS->sPostGISVersion.nMinor >= 1)) )
             {
                 /* This will return EWKB in an hex encoded form */
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += osEscapedGeom;
             }
             else if ( poDS->sPostGISVersion.nMajor >= 1 )
             {
@@ -768,44 +898,55 @@ CPLString OGRPGTableLayer::BuildFields()
                     osFieldList += "ST_AsEWKT(";
                 else
                     osFieldList += "AsEWKT(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += ")";
+                osFieldList += osEscapedGeom;
+                osFieldList += ") AS ";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("AsEWKT_%s", poGeomFieldDefn->GetNameRef()));
+
             }
             else
             {
                 osFieldList += "AsText(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += ")";
+                osFieldList += osEscapedGeom;
+                osFieldList += ") AS ";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("AsText_%s", poGeomFieldDefn->GetNameRef()));
             }
         }
-        else if ( bHasPostGISGeography )
+        else if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
         {
             if ( poDS->bUseBinaryCursor )
             {
                 osFieldList += "ST_AsBinary(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += ")";
+                osFieldList += osEscapedGeom;
+                osFieldList += ") AS";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("AsBinary_%s", poGeomFieldDefn->GetNameRef()));
             }
             else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")))
             {
                 osFieldList += "encode(ST_AsBinary(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += "), 'base64') AS BinaryBase64";
+                osFieldList += osEscapedGeom;
+                osFieldList += "), 'base64') AS ";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("BinaryBase64_%s", poGeomFieldDefn->GetNameRef()));
             }
             else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += osEscapedGeom;
             }
             else
             {
                 osFieldList += "ST_AsText(";
-                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
-                osFieldList += ")";
+                osFieldList += osEscapedGeom;
+                osFieldList += ") AS ";
+                osFieldList += OGRPGEscapeColumnName(
+                    CPLSPrintf("AsText_%s", poGeomFieldDefn->GetNameRef()));
             }
         }
         else
         {
-            osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+            osFieldList += osEscapedGeom;
         }
     }
 
@@ -813,7 +954,7 @@ CPLString OGRPGTableLayer::BuildFields()
     {
         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
-        if( strlen(osFieldList) > 0 )
+        if( osFieldList.size() > 0 )
             osFieldList += ", ";
 
         /* With a binary cursor, it is not possible to get the time zone */
@@ -841,7 +982,8 @@ CPLString OGRPGTableLayer::BuildFields()
 OGRErr OGRPGTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
-    GetLayerDefn();
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
 
     if( pszQuery == NULL )
         osQuery = "";
@@ -866,7 +1008,7 @@ OGRErr OGRPGTableLayer::DeleteFeature( long nFID )
     PGresult    *hResult = NULL;
     CPLString   osCommand;
 
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -1088,7 +1230,7 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
     int                 bNeedComma = FALSE;
     OGRErr              eErr = OGRERR_FAILURE;
 
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -1133,97 +1275,110 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
     osCommand.Printf( "UPDATE %s SET ", pszSqlTableName );
 
     /* Set the geometry */
-    if( bHasWkb )
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        osCommand += "WKB_GEOMETRY = ";
-        if ( poFeature->GetGeometryRef() != NULL )
+        OGRPGGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB )
         {
-            if( !bWkbAsOid  )
-            {
-                char    *pszBytea = GeometryToBYTEA( poFeature->GetGeometryRef() );
+            if( bNeedComma )
+                osCommand += ", ";
+            else
+                bNeedComma = TRUE;
 
-                if( pszBytea != NULL )
+            osCommand += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
+            osCommand += " = ";
+            if ( poGeom != NULL )
+            {
+                if( !bWkbAsOid  )
                 {
-                    if (poDS->bUseEscapeStringSyntax)
-                        osCommand += "E";
-                    osCommand = osCommand + "'" + pszBytea + "'";
-                    CPLFree( pszBytea );
+                    char    *pszBytea = GeometryToBYTEA( poGeom );
+
+                    if( pszBytea != NULL )
+                    {
+                        if (poDS->bUseEscapeStringSyntax)
+                            osCommand += "E";
+                        osCommand = osCommand + "'" + pszBytea + "'";
+                        CPLFree( pszBytea );
+                    }
+                    else
+                        osCommand += "NULL";
                 }
                 else
-                    osCommand += "NULL";
-            }
-            else
-            {
-                Oid     oid = GeometryToOID( poFeature->GetGeometryRef() );
-
-                if( oid != 0 )
                 {
-                    osCommand += CPLString().Printf( "'%d' ", oid );
+                    Oid     oid = GeometryToOID( poGeom );
+
+                    if( oid != 0 )
+                    {
+                        osCommand += CPLString().Printf( "'%d' ", oid );
+                    }
+                    else
+                        osCommand += "NULL";
                 }
-                else
-                    osCommand += "NULL";
             }
+            else
+                osCommand += "NULL";
         }
-        else
-            osCommand += "NULL";
-        bNeedComma = TRUE;
-    }
-    else if( bHasPostGISGeometry || bHasPostGISGeography )
-    {
-        osCommand = osCommand + OGRPGEscapeColumnName(pszGeomColumn) + " = ";
-        OGRGeometry *poGeom = NULL;
-        
-        if( poFeature->GetGeometryRef() != NULL )
+        else if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ||
+                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
         {
-            poGeom = (OGRGeometry *) poFeature->GetGeometryRef();
-
-            poGeom->closeRings();
-            poGeom->setCoordinateDimension( nCoordDimension );
-
-        }
+            if( bNeedComma )
+                osCommand += ", ";
+            else
+                bNeedComma = TRUE;
 
-        if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
-        {
-            if ( poGeom != NULL )
+            osCommand += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
+            osCommand += " = ";
+            if( poGeom != NULL )
             {
-                char* pszHexEWKB = GeometryToHex( poGeom, nSRSId );
-                if ( bHasPostGISGeography )
-                    osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
-                else
-                    osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
-                OGRFree( pszHexEWKB );
+                poGeom->closeRings();
+                poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
             }
-            else
-                osCommand += "NULL";    
-        }
-        else
-        {
-            char    *pszWKT = NULL;
-    
-            if (poGeom != NULL)
-                poGeom->exportToWkt( &pszWKT );
 
-            if( pszWKT != NULL )
+            if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
-                if( bHasPostGISGeography )
-                    osCommand +=
-                        CPLString().Printf(
-                            "ST_GeographyFromText('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
-                else if( poDS->sPostGISVersion.nMajor >= 1 )
-                    osCommand +=
-                        CPLString().Printf(
-                            "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
+                if ( poGeom != NULL )
+                {
+                    char* pszHexEWKB = OGRGeometryToHexEWKB( poGeom, poGeomFieldDefn->nSRSId );
+                    if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+                        osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
+                    else
+                        osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
+                    OGRFree( pszHexEWKB );
+                }
                 else
-                    osCommand += 
-                        CPLString().Printf(
-                            "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
-                OGRFree( pszWKT );
+                    osCommand += "NULL";    
             }
             else
-                osCommand += "NULL";
+            {
+                char    *pszWKT = NULL;
+        
+                if (poGeom != NULL)
+                    poGeom->exportToWkt( &pszWKT );
 
+                int nSRSId = poGeomFieldDefn->nSRSId;
+                if( pszWKT != NULL )
+                {
+                    if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+                        osCommand +=
+                            CPLString().Printf(
+                                "ST_GeographyFromText('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
+                    else if( poDS->sPostGISVersion.nMajor >= 1 )
+                        osCommand +=
+                            CPLString().Printf(
+                                "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
+                    else
+                        osCommand += 
+                            CPLString().Printf(
+                                "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
+                    OGRFree( pszWKT );
+                }
+                else
+                    osCommand += "NULL";
+
+            }
         }
-        bNeedComma = TRUE;
     }
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
@@ -1279,7 +1434,7 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
 
 OGRErr OGRPGTableLayer::CreateFeature( OGRFeature *poFeature )
 {
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -1296,6 +1451,21 @@ OGRErr OGRPGTableLayer::CreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
+    if( bFirstInsertion )
+    {
+        bFirstInsertion = FALSE;
+        if( CSLTestBoolean(CPLGetConfigOption("OGR_TRUNCATE", "NO")) )
+        {
+            PGconn              *hPGConn = poDS->GetPGConn();
+            PGresult            *hResult;
+            CPLString            osCommand;
+
+            osCommand.Printf("TRUNCATE TABLE %s", pszSqlTableName );
+            hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
+            OGRPGClearResult( hResult );
+        }
+    }
+
     // We avoid testing the config option too often. 
     if( bUseCopy == USE_COPY_UNSET )
         bUseCopy = CSLTestBoolean( CPLGetConfigOption( "PG_USE_COPY", "NO") );
@@ -1356,13 +1526,17 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
     /* We need to quote and escape string fields. */
     osCommand += "'";
 
+
     int nSrcLen = strlen(pszStrValue);
-    if (nMaxLength > 0 && nSrcLen > nMaxLength)
+    int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
+
+    if (nMaxLength > 0 && nSrcLenUTF > nMaxLength)
     {
         CPLDebug( "PG",
                   "Truncated %s.%s field value '%s' to %d characters.",
                   pszTableName, pszFieldName, pszStrValue, nMaxLength );
-        nSrcLen = nMaxLength;
+        nSrcLen = nSrcLen * nMaxLength / nSrcLenUTF;
+
         
         while( nSrcLen > 0 && ((unsigned char *) pszStrValue)[nSrcLen-1] > 127 )
         {
@@ -1484,19 +1658,20 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );
 
-    OGRGeometry *poGeom = poFeature->GetGeometryRef();
-
-    if( bHasWkb && poGeom != NULL )
-    {
-        osCommand += "WKB_GEOMETRY ";
-        bNeedComma = TRUE;
-    }
-    else if( (bHasPostGISGeometry || bHasPostGISGeography) && poGeom != NULL )
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        osCommand = osCommand + OGRPGEscapeColumnName(pszGeomColumn) + " ";
-        bNeedComma = TRUE;
+        OGRGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom == NULL )
+            continue;
+        if( !bNeedComma )
+            bNeedComma = TRUE;
+        else
+            osCommand += ", ";
+        osCommand += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()) + " ";
     }
-
+    
     /* Use case of ogr_pg_60 test */
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
@@ -1529,77 +1704,89 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
     /* Set the geometry */
     bNeedComma = FALSE;
-    if( (bHasPostGISGeometry || bHasPostGISGeography) && poGeom != NULL)
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        CheckGeomTypeCompatibility(poGeom);
-
-        poGeom->closeRings();
-        poGeom->setCoordinateDimension( nCoordDimension );
+        OGRPGGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom == NULL )
+            continue;
+        if( bNeedComma )
+            osCommand += ", ";
+        else
+            bNeedComma = TRUE;
 
-        if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
+        if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ||
+            poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
         {
-            char    *pszHexEWKB = GeometryToHex( poGeom, nSRSId );
-            if ( bHasPostGISGeography )
-                osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
+            CheckGeomTypeCompatibility(i, poGeom);
+
+            poGeom->closeRings();
+            poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
+
+            int nSRSId = poGeomFieldDefn->nSRSId;
+
+            if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
+            {
+                char    *pszHexEWKB = OGRGeometryToHexEWKB( poGeom, nSRSId );
+                if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+                    osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
+                else
+                    osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
+                OGRFree( pszHexEWKB );
+            }
             else
-                osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
-            OGRFree( pszHexEWKB );
+            { 
+                char    *pszWKT = NULL;
+                poGeom->exportToWkt( &pszWKT );
+
+                if( pszWKT != NULL )
+                {
+                    if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
+                        osCommand +=
+                            CPLString().Printf(
+                                "ST_GeographyFromText('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
+                    else if( poDS->sPostGISVersion.nMajor >= 1 )
+                        osCommand +=
+                            CPLString().Printf(
+                                "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
+                    else
+                        osCommand += 
+                            CPLString().Printf(
+                                "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
+                    OGRFree( pszWKT );
+                }
+                else
+                    osCommand += "''";
+                
+            }
         }
-        else
-        { 
-            char    *pszWKT = NULL;
-            poGeom->exportToWkt( &pszWKT );
+        else if( !bWkbAsOid )
+        {
+            char    *pszBytea = GeometryToBYTEA( poGeom );
 
-            if( pszWKT != NULL )
+            if( pszBytea != NULL )
             {
-                if( bHasPostGISGeography )
-                    osCommand +=
-                        CPLString().Printf(
-                            "ST_GeographyFromText('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
-                else if( poDS->sPostGISVersion.nMajor >= 1 )
-                    osCommand +=
-                        CPLString().Printf(
-                            "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
-                else
-                    osCommand += 
-                        CPLString().Printf(
-                            "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
-                OGRFree( pszWKT );
+                if (poDS->bUseEscapeStringSyntax)
+                    osCommand += "E";
+                osCommand = osCommand + "'" + pszBytea + "'";
+                CPLFree( pszBytea );
             }
             else
                 osCommand += "''";
-            
         }
-        bNeedComma = TRUE;
-    }
-    else if( bHasWkb && !bWkbAsOid && poGeom != NULL )
-    {
-        char    *pszBytea = GeometryToBYTEA( poGeom );
-
-        if( pszBytea != NULL )
+        else if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB &&
+                 bWkbAsOid && poGeom != NULL )
         {
-            if (poDS->bUseEscapeStringSyntax)
-                osCommand += "E";
-            osCommand = osCommand + "'" + pszBytea + "'";
-            CPLFree( pszBytea );
-        }
-        else
-            osCommand += "''";
-            
-        bNeedComma = TRUE;
-    }
-    else if( bHasWkb && bWkbAsOid && poGeom != NULL )
-    {
-        Oid     oid = GeometryToOID( poGeom );
+            Oid     oid = GeometryToOID( poGeom );
 
-        if( oid != 0 )
-        {
-            osCommand += CPLString().Printf( "'%d' ", oid );
+            if( oid != 0 )
+            {
+                osCommand += CPLString().Printf( "'%d' ", oid );
+            }
+            else
+                osCommand += "''";
         }
-        else
-            osCommand += "''";
-            
-        bNeedComma = TRUE;
     }
 
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
@@ -1690,34 +1877,43 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
 {
     PGconn              *hPGConn = poDS->GetPGConn();
     CPLString            osCommand;
+    int                  i;
 
     /* First process geometry */
-    OGRGeometry *poGeometry = (OGRGeometry *) poFeature->GetGeometryRef();
-    
-    char *pszGeom = NULL;
-    if ( NULL != poGeometry && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography))
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        CheckGeomTypeCompatibility(poGeometry);
+        OGRPGGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
 
-        poGeometry->closeRings();
-        poGeometry->setCoordinateDimension( nCoordDimension );
+        char *pszGeom = NULL;
+        if ( NULL != poGeom )
+        {
+            CheckGeomTypeCompatibility(i, poGeom);
 
-        if (bHasWkb)
-            pszGeom = GeometryToBYTEA( poGeometry );
-        else
-            pszGeom = GeometryToHex( poGeometry, nSRSId );
-    }
+            poGeom->closeRings();
+            poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
 
-    if ( pszGeom )
-    {
-        osCommand += pszGeom,
-        CPLFree( pszGeom );
-    }
-    else if (nGeomType != wkbNone)
-    {
-        osCommand = "\\N";
-    }
+            if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB )
+                pszGeom = GeometryToBYTEA( poGeom );
+            else
+                pszGeom = OGRGeometryToHexEWKB( poGeom, poGeomFieldDefn->nSRSId );
+        }
 
+        if (osCommand.size() > 0)
+            osCommand += "\t";
+
+        if ( pszGeom )
+        {
+            osCommand += pszGeom;
+            CPLFree( pszGeom );
+        }
+        else
+        {
+            osCommand += "\\N";
+        }
+    }
+    
     /* Next process the field id column */
     int nFIDIndex = -1;
     if( bFIDColumnInCopyFields )
@@ -1744,7 +1940,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     int nFieldCount = poFeatureDefn->GetFieldCount();
     int bAddTab = osCommand.size() > 0;
 
-    for( int i = 0; i < nFieldCount;  i++ )
+    for( i = 0; i < nFieldCount;  i++ )
     {
         if (i == nFIDIndex)
             continue;
@@ -1855,11 +2051,13 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
             nOGRFieldType != OFTBinary )
         {
             int         iChar;
+            int         iUTFChar = 0;
 
             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
             {
+
                 if( poFeatureDefn->GetFieldDefn(i)->GetWidth() > 0
-                    && iChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() )
+                    && iUTFChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() )
                 {
                     CPLDebug( "PG",
                               "Truncated %s.%s field value '%s' to %d characters.",
@@ -1870,6 +2068,10 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
                     break;
                 }
 
+                //count of utf chars
+                if ((pszStrValue[iChar] & 0xc0) != 0x80) 
+                    iUTFChar++;
+
                 /* Escape embedded \, \t, \n, \r since they will cause COPY
                    to misinterpret a line of text and thus abort */
                 if( pszStrValue[iChar] == '\\' || 
@@ -1939,36 +2141,63 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
 int OGRPGTableLayer::TestCapability( const char * pszCap )
 
 {
-    GetLayerDefn();
-
     if ( bUpdateAccess )
     {
         if( EQUAL(pszCap,OLCSequentialWrite) ||
             EQUAL(pszCap,OLCCreateField) ||
+            EQUAL(pszCap,OLCCreateGeomField) ||
             EQUAL(pszCap,OLCDeleteField) ||
             EQUAL(pszCap,OLCAlterFieldDefn) )
             return TRUE;
 
         else if( EQUAL(pszCap,OLCRandomWrite) ||
                  EQUAL(pszCap,OLCDeleteFeature) )
+        {
+            GetLayerDefn()->GetFieldCount();
             return bHasFid;
+        }
     }
 
     if( EQUAL(pszCap,OLCRandomRead) )
+    {
+        GetLayerDefn()->GetFieldCount();
         return bHasFid;
+    }
 
     else if( EQUAL(pszCap,OLCFastFeatureCount) ||
              EQUAL(pszCap,OLCFastSetNextByIndex) )
-        return m_poFilterGeom == NULL || bHasPostGISGeometry || bHasPostGISGeography;
+    {
+        if( m_poFilterGeom == NULL )
+            return TRUE;
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+        return poGeomFieldDefn == NULL ||
+               poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+               poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY;
+    }
 
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return bHasPostGISGeometry || bHasPostGISGeography;
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
+        return poGeomFieldDefn == NULL ||
+               poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
+               poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY;
+    }
 
     else if( EQUAL(pszCap,OLCTransactions) )
         return TRUE;
 
     else if( EQUAL(pszCap,OLCFastGetExtent) )
-        return bHasPostGISGeometry;
+    {
+        OGRPGGeomFieldDefn* poGeomFieldDefn = NULL;
+        if( poFeatureDefn->GetGeomFieldCount() > 0 )
+            poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(0);
+        return poGeomFieldDefn != NULL &&
+               poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY;
+    }
 
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
@@ -2074,7 +2303,7 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     CPLString           osFieldType;
     OGRFieldDefn        oField( poFieldIn );
 
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -2151,6 +2380,120 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 }
 
 /************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRPGTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
+                                         int bApproxOK )
+{
+    PGconn              *hPGConn = poDS->GetPGConn();
+    PGresult            *hResult;
+    OGRwkbGeometryType eType = poGeomFieldIn->GetType();
+    if( eType == wkbNone )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create geometry field of type wkbNone");
+        return OGRERR_FAILURE;
+    }
+    
+    CPLString               osCommand;
+    OGRPGGeomFieldDefn *poGeomField =
+        new OGRPGGeomFieldDefn( this, poGeomFieldIn->GetNameRef() );
+    poGeomField->SetSpatialRef(poGeomFieldIn->GetSpatialRef());
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to "launder" the column names into Postgres          */
+/*      friendly format?                                                */
+/* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char    *pszSafeName = poDS->LaunderName( poGeomField->GetNameRef() );
+
+        poGeomField->SetName( pszSafeName );
+        CPLFree( pszSafeName );
+    }
+    
+    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
+    int nSRSId = poDS->GetUndefinedSRID();
+    if( nForcedSRSId != UNDETERMINED_SRID )
+        nSRSId = nForcedSRSId;
+    else if( poSRS != NULL )
+        nSRSId = poDS->FetchSRSId( poSRS );
+
+    int nDimension = 3;
+    if( wkbFlatten(eType) == eType )
+        nDimension = 2;
+    if( nForcedDimension > 0 )
+    {
+        nDimension = nForcedDimension;
+        if( nDimension == 2 )
+            eType = (OGRwkbGeometryType)( eType & ~wkb25DBit );
+        else
+            eType = (OGRwkbGeometryType)( eType | wkb25DBit );
+    }
+    poGeomField->SetType(eType);
+    poGeomField->nSRSId = nSRSId;
+    poGeomField->nCoordDimension = nDimension;
+    poGeomField->ePostgisType = GEOM_TYPE_GEOMETRY;
+
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+    poDS->FlushSoftTransaction();
+    
+    const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
+    osCommand.Printf(
+            "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
+            OGRPGEscapeString(hPGConn, pszSchemaName).c_str(),
+            OGRPGEscapeString(hPGConn, poFeatureDefn->GetName()).c_str(),
+            OGRPGEscapeString(hPGConn, poGeomField->GetNameRef()).c_str(),
+            nSRSId, pszGeometryType, nDimension );
+
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+
+    if( !hResult
+        || PQresultStatus(hResult) != PGRES_TUPLES_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "AddGeometryColumn failed." );
+
+        OGRPGClearResult( hResult );
+        delete poGeomField;
+
+        return OGRERR_FAILURE;
+    }
+
+    OGRPGClearResult( hResult );
+
+    if( bCreateSpatialIndexFlag )
+    {
+        osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)",
+                        OGRPGEscapeColumnName(
+                            CPLSPrintf("%s_%s_geom_idx", GetName(), poGeomField->GetNameRef())).c_str(),
+                        pszSqlTableName,
+                        OGRPGEscapeColumnName(poGeomField->GetNameRef()).c_str());
+
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+
+        if( !hResult
+            || PQresultStatus(hResult) != PGRES_COMMAND_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "CREATE INDEX failed." );
+
+            OGRPGClearResult( hResult );
+            delete poGeomField;
+
+            return OGRERR_FAILURE;
+        }
+        
+        OGRPGClearResult( hResult );
+    }
+
+    poFeatureDefn->AddGeomFieldDefn( poGeomField, FALSE );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                            DeleteField()                             */
 /************************************************************************/
 
@@ -2160,7 +2503,7 @@ OGRErr OGRPGTableLayer::DeleteField( int iField )
     PGresult            *hResult = NULL;
     CPLString           osCommand;
 
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -2219,7 +2562,7 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
     PGresult            *hResult = NULL;
     CPLString           osCommand;
 
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( !bUpdateAccess )
     {
@@ -2355,7 +2698,7 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
 OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId )
 
 {
-    GetLayerDefn();
+    GetLayerDefn()->GetFieldCount();
 
     if( pszFIDColumn == NULL )
         return OGRLayer::GetFeature( nFeatureId );
@@ -2442,8 +2785,6 @@ OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId )
 int OGRPGTableLayer::GetFeatureCount( int bForce )
 
 {
-    GetLayerDefn();
-
     if( TestCapability(OLCFastFeatureCount) == FALSE )
         return OGRPGLayer::GetFeatureCount( bForce );
 
@@ -2473,43 +2814,64 @@ int OGRPGTableLayer::GetFeatureCount( int bForce )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/*                                                                      */
-/*      We override this to try and fetch the table SRID from the       */
-/*      geometry_columns table if the srsid is UNDETERMINED_SRID        */
-/*      (meaning we haven't yet even looked for it).                    */
+/*                             ResolveSRID()                            */
 /************************************************************************/
 
-OGRSpatialReference *OGRPGTableLayer::GetSpatialRef()
+void OGRPGTableLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
 
 {
-    if( nSRSId == UNDETERMINED_SRID )
+    PGconn      *hPGConn = poDS->GetPGConn();
+    PGresult    *hResult = NULL;
+    CPLString    osCommand;
+
+    int nSRSId = poDS->GetUndefinedSRID();
+
+    osCommand.Printf(
+                "SELECT srid FROM geometry_columns "
+                "WHERE f_table_name = %s AND "
+                "f_geometry_column = %s",
+                OGRPGEscapeString(hPGConn, pszTableName).c_str(),
+                OGRPGEscapeString(hPGConn, poGFldDefn->GetNameRef()).c_str());
+
+    if (pszSchemaName)
     {
-        PGconn      *hPGConn = poDS->GetPGConn();
-        PGresult    *hResult = NULL;
-        CPLString    osCommand;
+        osCommand += CPLString().Printf(" AND f_table_schema = %s",
+                                        OGRPGEscapeString(hPGConn, pszSchemaName).c_str());
+    }
 
-        nSRSId = poDS->GetUndefinedSRID();
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
-        poDS->SoftStartTransaction();
+    if( hResult
+        && PQresultStatus(hResult) == PGRES_TUPLES_OK
+        && PQntuples(hResult) == 1 )
+    {
+        nSRSId = atoi(PQgetvalue(hResult,0,0));
+    }
 
-        osCommand.Printf(
-                    "SELECT srid FROM geometry_columns "
-                    "WHERE f_table_name = '%s'",
-                    pszTableName);
+    OGRPGClearResult( hResult );
 
-        if (pszGeomColumn)
-        {
-            osCommand += CPLString().Printf(" AND f_geometry_column = '%s'", pszGeomColumn);
-        }
+    /* With PostGIS 2.0, SRID = 0 can also mean that there's no constraint */
+    /* so we need to fetch from values */
+    /* We assume that all geometry of this column have identical SRID */
+    if( nSRSId <= 0 && poGFldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
+    {
+        CPLString osGetSRID;
 
-        if (pszSchemaName)
-        {
-            osCommand += CPLString().Printf(" AND f_table_schema = '%s'", pszSchemaName);
-        }
+        const char* psGetSRIDFct;
+        if (poDS->sPostGISVersion.nMajor >= 2)
+            psGetSRIDFct = "ST_SRID";
+        else
+            psGetSRIDFct = "getsrid";
 
-        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
+        osGetSRID += "SELECT ";
+        osGetSRID += psGetSRIDFct;
+        osGetSRID += "(";
+        osGetSRID += OGRPGEscapeColumnName(poGFldDefn->GetNameRef());
+        osGetSRID += ") FROM ";
+        osGetSRID += pszSqlTableName;
+        osGetSRID += " LIMIT 1";
 
+        hResult = OGRPG_PQexec(poDS->GetPGConn(), osGetSRID );
         if( hResult
             && PQresultStatus(hResult) == PGRES_TUPLES_OK
             && PQntuples(hResult) == 1 )
@@ -2518,46 +2880,9 @@ OGRSpatialReference *OGRPGTableLayer::GetSpatialRef()
         }
 
         OGRPGClearResult( hResult );
-
-        poDS->SoftCommit();
-    }
-
-    return OGRPGLayer::GetSpatialRef();
-}
-
-/************************************************************************/
-/*                             GetExtent()                              */
-/*                                                                      */
-/*      For PostGIS use internal Extend(geometry) function              */
-/*      in other cases we use standard OGRLayer::GetExtent()            */
-/************************************************************************/
-
-OGRErr OGRPGTableLayer::GetExtent( OGREnvelope *psExtent, int bForce )
-{
-    CPLString   osCommand;
-
-    GetLayerDefn();
-
-    const char* pszExtentFct;
-    if (poDS->sPostGISVersion.nMajor >= 2)
-        pszExtentFct = "ST_Extent";
-    else
-        pszExtentFct = "Extent";
-
-    if ( TestCapability(OLCFastGetExtent) )
-    {
-        osCommand.Printf( "SELECT %s(%s) FROM %s", pszExtentFct,
-                          OGRPGEscapeColumnName(pszGeomColumn).c_str(), pszSqlTableName );
-    }
-    else if ( bHasPostGISGeography )
-    {
-        /* Probably not very efficient, but more efficient than client-side implementation */
-        osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM %s",
-                          pszExtentFct,
-                          OGRPGEscapeColumnName(pszGeomColumn).c_str(), pszSqlTableName );
     }
 
-    return RunGetExtentRequest(psExtent, bForce, osCommand);
+    poGFldDefn->nSRSId = nSRSId;
 }
 
 /************************************************************************/
@@ -2671,9 +2996,13 @@ CPLString OGRPGTableLayer::BuildCopyFields(int bSetFID)
     int     nFIDIndex = -1;
     CPLString osFieldList;
 
-    if( pszGeomColumn != NULL )
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        osFieldList = OGRPGEscapeColumnName(pszGeomColumn);
+        OGRGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        if( osFieldList.size() > 0 )
+            osFieldList += ", ";
+        osFieldList += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
     }
 
     bFIDColumnInCopyFields = (pszFIDColumn != NULL && bSetFID);
@@ -2707,12 +3036,15 @@ CPLString OGRPGTableLayer::BuildCopyFields(int bSetFID)
 /*                    CheckGeomTypeCompatibility()                      */
 /************************************************************************/
 
-void OGRPGTableLayer::CheckGeomTypeCompatibility(OGRGeometry* poGeom)
+void OGRPGTableLayer::CheckGeomTypeCompatibility(int iGeomField,
+                                                 OGRGeometry* poGeom)
 {
     if (bHasWarnedIncompatibleGeom)
         return;
-        
-    OGRwkbGeometryType eFlatLayerGeomType = wkbFlatten(poFeatureDefn->GetGeomType());
+
+    OGRwkbGeometryType eExpectedGeomType =
+        poFeatureDefn->GetGeomFieldDefn(iGeomField)->GetType();
+    OGRwkbGeometryType eFlatLayerGeomType = wkbFlatten(eExpectedGeomType);
     OGRwkbGeometryType eFlatGeomType = wkbFlatten(poGeom->getGeometryType());
     if (eFlatLayerGeomType == wkbUnknown)
         return;
@@ -2731,45 +3063,8 @@ void OGRPGTableLayer::CheckGeomTypeCompatibility(OGRGeometry* poGeom)
                  "Geometry to be inserted is of type %s, whereas the layer geometry type is %s.\n"
                  "Insertion is likely to fail",
                  OGRGeometryTypeToName(poGeom->getGeometryType()), 
-                 OGRGeometryTypeToName(poFeatureDefn->GetGeomType()));
-    }
-}
-
-/************************************************************************/
-/*                  GetLayerDefnCanReturnNULL()                         */
-/************************************************************************/
-
-OGRFeatureDefn * OGRPGTableLayer::GetLayerDefnCanReturnNULL()
-{
-    if (poFeatureDefn)
-        return poFeatureDefn;
-
-    poFeatureDefn = ReadTableDefinition();
-
-    if( poFeatureDefn )
-    {
-        ResetReading();
-    }
-
-    return poFeatureDefn;
-}
-
-/************************************************************************/
-/*                         GetLayerDefn()                              */
-/************************************************************************/
-
-OGRFeatureDefn * OGRPGTableLayer::GetLayerDefn()
-{
-    if (poFeatureDefn)
-        return poFeatureDefn;
-
-    GetLayerDefnCanReturnNULL();
-    if (poFeatureDefn == NULL)
-    {
-        poFeatureDefn = new OGRFeatureDefn(pszTableName);
-        poFeatureDefn->Reference();
+                 OGRGeometryTypeToName(eExpectedGeomType));
     }
-    return poFeatureDefn;
 }
 
 /************************************************************************/
@@ -2815,3 +3110,59 @@ void OGRPGTableLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes
     if( osCur.size() )
         papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
 }
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      For PostGIS use internal ST_EstimatedExtent(geometry) function  */
+/*      if bForce == 0                                                  */
+/************************************************************************/
+
+OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
+{
+    CPLString   osCommand;
+
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    OGRPGGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->myGetGeomFieldDefn(iGeomField);
+
+    const char* pszExtentFct;
+    // if bForce is 0 and ePostgisType is not GEOM_TYPE_GEOGRAPHY we can use 
+    // the ST_EstimatedExtent function which is quicker
+    // ST_EstimatedExtent was called ST_Estimated_Extent up to PostGIS 2.0.x
+    // ST_EstimatedExtent returns NULL in absence of statistics (an exception before 
+    //   PostGIS 1.5.4)
+    if ( bForce == 0 && TestCapability(OLCFastGetExtent) )
+    {
+        PGconn              *hPGConn = poDS->GetPGConn();
+
+        if ( poDS->sPostGISVersion.nMajor > 2 ||
+             ( poDS->sPostGISVersion.nMajor == 2 && poDS->sPostGISVersion.nMinor >= 1 ) )
+            pszExtentFct = "ST_EstimatedExtent";
+        else
+            pszExtentFct = "ST_Estimated_Extent";
+
+        osCommand.Printf( "SELECT %s(%s, %s, %s)",
+                        pszExtentFct,
+                        OGRPGEscapeString(hPGConn, pszSchemaName).c_str(),
+                        OGRPGEscapeString(hPGConn, pszTableName).c_str(),
+                        OGRPGEscapeString(hPGConn, poGeomFieldDefn->GetNameRef()).c_str() );
+
+        if( RunGetExtentRequest(psExtent, bForce, osCommand) == OGRERR_NONE )
+            return OGRERR_NONE;
+
+        CPLDebug("PG","Unable to get extimated extent by PostGIS. Trying real extent.");
+    }
+
+    return OGRPGLayer::GetExtent( iGeomField, psExtent, bForce );
+}
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
index ebfac7e..d228491 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpgutility.cpp 22919 2011-08-10 18:12:05Z rouault $
+ * $Id: ogrpgutility.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility methods
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2009, Even Rouault
+ * Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgutility.cpp 22919 2011-08-10 18:12:05Z rouault $");
+CPL_CVSID("$Id: ogrpgutility.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRPG_PQexec()                               */
diff --git a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
index 86d1d66..b2e7d13 100644
--- a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
+++ b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
@@ -18,6 +18,10 @@ This driver is very similar to the PostGIS shp2pgsql utility.<p>
 
 Most creation options are shared with the regular PostgreSQL driver.<p>
 
+Starting with OGR 1.11, the PGDump driver supports creating tables with multiple PostGIS
+geometry columns (following
+<a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">RFC 41</a>)<p>
+
 <h2>Creation options</h2>
 
 <h3>Dataset Creation Options</h3>
@@ -82,7 +86,7 @@ critical to set it. Its effect is just to avoid a few warnings.<p>
 
 <ul>
 <li><b>PG_USE_COPY</b>: This may be "YES" for using COPY for inserting data to Postgresql.
-COPY is less robust than INSERT, but significantly faster.</li><p>
+COPY is significantly faster than INSERT.</li><p>
 </ul>
 
 <h3>VSI Virtual File System API support</h3>
diff --git a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
index 6a8fd1a..11849f0 100644
--- a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
+++ b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_pgdump.h 25366 2012-12-27 18:38:53Z rouault $
+ * $Id: ogr_pgdump.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL dump driver.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,8 +34,25 @@
 #include "cpl_string.h"
 
 CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName);
-CPLString OGRPGDumpEscapeString(   const char* pszStrValue, int nMaxLength,
-                                   const char* pszFieldName);
+CPLString OGRPGDumpEscapeString(   const char* pszStrValue, int nMaxLength = -1,
+                                   const char* pszFieldName = "");
+
+
+/************************************************************************/
+/*                        OGRPGDumpGeomFieldDefn                        */
+/************************************************************************/
+
+class OGRPGDumpGeomFieldDefn : public OGRGeomFieldDefn
+{
+    public:
+        OGRPGDumpGeomFieldDefn( OGRGeomFieldDefn *poGeomField ) :
+            OGRGeomFieldDefn(poGeomField), nSRSId(-1), nCoordDimension(2)
+            {
+            }
+            
+        int nSRSId;
+        int nCoordDimension;
+};
 
 /************************************************************************/
 /*                          OGRPGDumpLayer                              */
@@ -46,11 +63,9 @@ class OGRPGDumpDataSource;
 
 class OGRPGDumpLayer : public OGRLayer
 {
+    char                *pszSchemaName;
     char                *pszSqlTableName;
-    char                *pszGeomColumn;
     char                *pszFIDColumn;
-    int                  nCoordDimension;
-    int                  nSRSId;
     OGRFeatureDefn      *poFeatureDefn;
     OGRPGDumpDataSource *poDS;
     int                 nFeatures;
@@ -61,14 +76,16 @@ class OGRPGDumpLayer : public OGRLayer
     int                 bCopyActive;
     int                 bFIDColumnInCopyFields;
     int                 bCreateTable;
+    int                 nUnknownSRSId;
+    int                 nForcedSRSId;
+    int                 bCreateSpatialIndexFlag;
 
     char              **papszOverrideColumnTypes;
 
     void                AppendFieldValue(CPLString& osCommand,
                                        OGRFeature* poFeature, int i);
     char*               GByteArrayToBYTEA( const GByte* pabyData, int nLen);
-    char*               GeometryToHex( OGRGeometry * poGeometry, int nSRSId );
-    
+
     OGRErr              StartCopy(int bSetFID);
     CPLString           BuildCopyFields(int bSetFID);
 
@@ -76,10 +93,7 @@ class OGRPGDumpLayer : public OGRLayer
                         OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
                                        const char* pszSchemaName,
                                        const char* pszLayerName,
-                                       const char* pszGeomColumn,
                                        const char *pszFIDColumn,
-                                       int         nCoordDimension,
-                                       int         nSRSId,
                                        int         bWriteAsHexIn,
                                        int         bCreateTable);
     virtual             ~OGRPGDumpLayer();
@@ -95,7 +109,9 @@ class OGRPGDumpLayer : public OGRLayer
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
-                                     
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE );
+
     virtual OGRFeature *GetNextFeature();
 
     // follow methods are not base class overrides
@@ -105,7 +121,12 @@ class OGRPGDumpLayer : public OGRLayer
                                 { bPreservePrecision = bFlag; }
 
     void                SetOverrideColumnTypes( const char* pszOverrideColumnTypes );
-
+    void                SetUnknownSRSId( int nUnknownSRSIdIn )
+                                { nUnknownSRSId = nUnknownSRSIdIn; }
+    void                SetForcedSRSId( int nForcedSRSIdIn )
+                                { nForcedSRSId = nForcedSRSIdIn; }
+    void                SetCreateSpatialIndexFlag( int bFlag )
+                                { bCreateSpatialIndexFlag = bFlag; }
     OGRErr              EndCopy();
 };
 
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
index e776efb..542b3d5 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpgdumpdatasource.cpp 26197 2013-07-23 22:16:13Z rouault $
+ * $Id: ogrpgdumpdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDataSource class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 26197 2013-07-23 22:16:13Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                      OGRPGDumpDataSource()                           */
@@ -321,13 +321,18 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
 /*      Try to get the SRS Id of this spatial reference system,         */
 /*      adding tot the srs table if needed.                             */
 /* -------------------------------------------------------------------- */
-    int nSRSId = -1;
+    int nUnknownSRSId = -1;
     const char* pszPostgisVersion = CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" );
     if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 )
-        nSRSId = 0;
+        nUnknownSRSId = 0;
 
+    int nSRSId = nUnknownSRSId;
+    int nForcedSRSId = -2;
     if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
+    {
         nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
+        nForcedSRSId = nSRSId;
+    }
     else
     {
         if (poSRS)
@@ -347,7 +352,7 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
         }
     }
 
-    CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName, -1, "");
+    CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName);
     const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
 
     const char *pszGeometryType = OGRToOGCGeomType(eType);
@@ -451,7 +456,9 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
         Log(osCommand);
     }
 
-    if( bCreateTable && bHavePostGIS )
+    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
+    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
     {
 /* -------------------------------------------------------------------- */
 /*      Create the spatial index.                                       */
@@ -459,16 +466,12 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
 /*      We're doing this before we add geometry and record to the table */
 /*      so this may not be exactly the best way to do it.               */
 /* -------------------------------------------------------------------- */
-        const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-        if( pszSI == NULL || CSLTestBoolean(pszSI) )
-        {
-            osCommand.Printf("CREATE INDEX \"%s_geom_idx\" "
-                            "ON \"%s\".\"%s\" "
-                            "USING GIST (\"%s\")",
-                    pszTableName, pszSchemaName, pszTableName, pszGFldName);
+        osCommand.Printf("CREATE INDEX \"%s_%s_geom_idx\" "
+                        "ON \"%s\".\"%s\" "
+                        "USING GIST (\"%s\")",
+                pszTableName, pszGFldName, pszSchemaName, pszTableName, pszGFldName);
 
-            Log(osCommand);
-        }
+        Log(osCommand);
     }
 
 /* -------------------------------------------------------------------- */
@@ -478,13 +481,26 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
 
     int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE);
 
-    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName, pszGFldName,
-                                  pszFIDColumnName, nDimension, nSRSId, bWriteAsHex, bCreateTable );
+    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName,
+                                  pszFIDColumnName, bWriteAsHex, bCreateTable );
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
 
     const char* pszOverrideColumnTypes = CSLFetchNameValue( papszOptions, "COLUMN_TYPES" );
     poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
+    poLayer->SetUnknownSRSId(nUnknownSRSId);
+    poLayer->SetForcedSRSId(nForcedSRSId);
+    poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
+
+    if( bHavePostGIS )
+    {
+        OGRGeomFieldDefn oTmp( pszGFldName, eType );
+        OGRPGDumpGeomFieldDefn *poGeomField =
+            new OGRPGDumpGeomFieldDefn(&oTmp);
+        poGeomField->nSRSId = nSRSId;
+        poGeomField->nCoordDimension = nDimension;
+        poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -509,6 +525,8 @@ int OGRPGDumpDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
index 92e9d8d..bbd6bdd 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpgdumpdriver.cpp 24950 2012-09-22 13:54:36Z rouault $
+ * $Id: ogrpgdumpdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDriver class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_pgdump.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgdumpdriver.cpp 24950 2012-09-22 13:54:36Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         ~OGRPGDumpDriver()                           */
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
index d10a9ec..9cbefbd 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrpgdumplayer.cpp 26197 2013-07-23 22:16:13Z rouault $
+ * $Id: ogrpgdumplayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpLayer class
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,17 +30,12 @@
 #include "ogr_pgdump.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpgdumplayer.cpp 26197 2013-07-23 22:16:13Z rouault $");
+CPL_CVSID("$Id: ogrpgdumplayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define USE_COPY_UNSET -1
 
-/* Flags for creating WKB format for PostGIS */
-#define WKBZOFFSET 0x80000000
-#define WKBMOFFSET 0x40000000
-#define WKBSRIDFLAG 0x20000000
-#define WKBBBOXFLAG 0x10000000
-
 static CPLString OGRPGDumpEscapeStringList(
                                        char** papszItems, int bForInsertOrUpdate);
 
@@ -51,24 +46,20 @@ static CPLString OGRPGDumpEscapeStringList(
 OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
                                const char* pszSchemaName,
                                const char* pszTableName,
-                               const char* pszGeomColumn,
                                const char *pszFIDColumn,
-                               int         nCoordDimension,
-                               int         nSRSId,
                                int         bWriteAsHexIn,
                                int         bCreateTable)
 {
     this->poDS = poDS;
     poFeatureDefn = new OGRFeatureDefn( pszTableName );
+    poFeatureDefn->SetGeomType(wkbNone);
     poFeatureDefn->Reference();
     nFeatures = 0;
     pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
                                OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
                                OGRPGDumpEscapeColumnName(pszTableName).c_str() ));
-    this->pszGeomColumn = (pszGeomColumn) ? CPLStrdup(pszGeomColumn) : NULL;
+    this->pszSchemaName = CPLStrdup(pszSchemaName);
     this->pszFIDColumn = CPLStrdup(pszFIDColumn);
-    this->nCoordDimension = nCoordDimension;
-    this->nSRSId = nSRSId;
     this->bCreateTable = bCreateTable;
     bLaunderColumnNames = TRUE;
     bPreservePrecision = TRUE;
@@ -77,6 +68,9 @@ OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
     bWriteAsHex = bWriteAsHexIn;
     bCopyActive = FALSE;
     papszOverrideColumnTypes = NULL;
+    nUnknownSRSId = -1;
+    nForcedSRSId = -2;
+    bCreateSpatialIndexFlag = TRUE;
 }
 
 /************************************************************************/
@@ -88,8 +82,8 @@ OGRPGDumpLayer::~OGRPGDumpLayer()
     EndCopy();
 
     poFeatureDefn->Release();
+    CPLFree(pszSchemaName);
     CPLFree(pszSqlTableName);
-    CPLFree(pszGeomColumn);
     CPLFree(pszFIDColumn);
     CSLDestroy(papszOverrideColumnTypes);
 }
@@ -111,88 +105,14 @@ OGRFeature *OGRPGDumpLayer::GetNextFeature()
 int OGRPGDumpLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCSequentialWrite) ||
-        EQUAL(pszCap,OLCCreateField) )
+        EQUAL(pszCap,OLCCreateField) ||
+        EQUAL(pszCap,OLCCreateGeomField) )
         return TRUE;
     else
         return FALSE;
 }
 
 /************************************************************************/
-/*                           GeometryToHex()                            */
-/************************************************************************/
-
-char *OGRPGDumpLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )
-{
-    GByte       *pabyWKB;
-    char        *pszTextBuf;
-    char        *pszTextBufCurrent;
-    char        *pszHex;
-
-    int nWkbSize = poGeometry->WkbSize();
-    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
-
-    if( poGeometry->exportToWkb( wkbNDR, pabyWKB ) != OGRERR_NONE )
-    {
-        CPLFree( pabyWKB );
-        return CPLStrdup("");
-    }
-
-    /* When converting to hex, each byte takes 2 hex characters.  In addition
-       we add in 8 characters to represent the SRID integer in hex, and
-       one for a null terminator */
-
-    int pszSize = nWkbSize*2 + 8 + 1;
-    pszTextBuf = (char *) CPLMalloc(pszSize);
-    pszTextBufCurrent = pszTextBuf;
-
-    /* Convert the 1st byte, which is the endianess flag, to hex. */
-    pszHex = CPLBinaryToHex( 1, pabyWKB );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-    pszTextBufCurrent += 2;
-
-    /* Next, get the geom type which is bytes 2 through 5 */
-    GUInt32 geomType;
-    memcpy( &geomType, pabyWKB+1, 4 );
-
-    /* Now add the SRID flag if an SRID is provided */
-    if (nSRSId > 0)
-    {
-        /* Change the flag to wkbNDR (little) endianess */
-        GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
-        /* Apply the flag */
-        geomType = geomType | nGSrsFlag;
-    }
-
-    /* Now write the geom type which is 4 bytes */
-    pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-    pszTextBufCurrent += 8;
-
-    /* Now include SRID if provided */
-    if (nSRSId > 0)
-    {
-        /* Force the srsid to wkbNDR (little) endianess */
-        GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
-        pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
-        strcpy(pszTextBufCurrent, pszHex );
-        CPLFree ( pszHex );
-        pszTextBufCurrent += 8;
-    }
-
-    /* Copy the rest of the data over - subtract
-       5 since we already copied 5 bytes above */
-    pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
-    strcpy(pszTextBufCurrent, pszHex );
-    CPLFree ( pszHex );
-
-    CPLFree( pabyWKB );
-
-    return pszTextBuf;
-}
-
-/************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
@@ -255,11 +175,18 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );
 
-    OGRGeometry *poGeom = poFeature->GetGeometryRef();
-    if( poGeom != NULL && pszGeomColumn != NULL )
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        osCommand = osCommand + OGRPGDumpEscapeColumnName(pszGeomColumn) + " ";
-        bNeedComma = TRUE;
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom != NULL )
+        {
+            if( bNeedComma )
+                osCommand += ", ";
+
+            OGRGeomFieldDefn* poGFldDefn = poFeature->GetGeomFieldDefnRef(i);
+            osCommand = osCommand + OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef()) + " ";
+            bNeedComma = TRUE;
+        }
     }
 
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
@@ -292,38 +219,48 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
     /* Set the geometry */
     bNeedComma = FALSE;
-    if( poGeom != NULL && pszGeomColumn != NULL )
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        char    *pszWKT = NULL;
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom != NULL )
+        {
+            char    *pszWKT = NULL;
+            
+            OGRPGDumpGeomFieldDefn* poGFldDefn =
+                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
 
-        poGeom->closeRings();
-        poGeom->setCoordinateDimension( nCoordDimension );
+            poGeom->closeRings();
+            poGeom->setCoordinateDimension( poGFldDefn->nCoordDimension );
 
-        if( bWriteAsHex )
-        {
-            char* pszHex = GeometryToHex( poGeom, nSRSId );
-            osCommand += "'";
-            if (pszHex)
-                osCommand += pszHex;
-            osCommand += "'";
-            CPLFree(pszHex);
-        }
-        else
-        {
-            poGeom->exportToWkt( &pszWKT );
+            if( bNeedComma )
+                osCommand += ", ";
 
-            if( pszWKT != NULL )
+            if( bWriteAsHex )
             {
-                osCommand +=
-                    CPLString().Printf(
-                        "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
-                OGRFree( pszWKT );
+                char* pszHex = OGRGeometryToHexEWKB( poGeom, poGFldDefn->nSRSId );
+                osCommand += "'";
+                if (pszHex)
+                    osCommand += pszHex;
+                osCommand += "'";
+                CPLFree(pszHex);
             }
             else
-                osCommand += "''";
-        }
+            {
+                poGeom->exportToWkt( &pszWKT );
 
-        bNeedComma = TRUE;
+                if( pszWKT != NULL )
+                {
+                    osCommand +=
+                        CPLString().Printf(
+                            "GeomFromEWKT('SRID=%d;%s'::TEXT) ", poGFldDefn->nSRSId, pszWKT );
+                    OGRFree( pszWKT );
+                }
+                else
+                    osCommand += "''";
+            }
+
+            bNeedComma = TRUE;
+        }
     }
 
     /* Set the FID */
@@ -369,27 +306,32 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
 OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
 {
+    int                  i;
     CPLString            osCommand;
 
     /* First process geometry */
-    OGRGeometry *poGeometry = (OGRGeometry *) poFeature->GetGeometryRef();
-    
-    if (pszGeomColumn)
+    for( i = 0; i < poFeature->GetGeomFieldCount(); i++ )
     {
+        OGRGeometry *poGeometry = poFeature->GetGeomFieldRef(i);
         char *pszGeom = NULL;
         if ( NULL != poGeometry /* && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography) */)
         {
+            OGRPGDumpGeomFieldDefn* poGFldDefn =
+                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
+
             poGeometry->closeRings();
-            poGeometry->setCoordinateDimension( nCoordDimension );
-            
+            poGeometry->setCoordinateDimension( poGFldDefn->nCoordDimension );
+
             //CheckGeomTypeCompatibility(poGeometry);
     
             /*if (bHasWkb)
                 pszGeom = GeometryToBYTEA( poGeometry );
             else*/
-                pszGeom = GeometryToHex( poGeometry, nSRSId );
+                pszGeom = OGRGeometryToHexEWKB( poGeometry, poGFldDefn->nSRSId );
         }
     
+        if (osCommand.size() > 0)
+            osCommand += "\t";
         if ( pszGeom )
         {
             osCommand += pszGeom,
@@ -397,7 +339,7 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
         }
         else
         {
-            osCommand = "\\N";
+            osCommand += "\\N";
         }
     }
 
@@ -427,7 +369,7 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     int nFieldCount = poFeatureDefn->GetFieldCount();
     int bAddTab = osCommand.size() > 0; 
 
-    for( int i = 0; i < nFieldCount;  i++ )
+    for( i = 0; i < nFieldCount;  i++ )
     {
         if (i == nFIDIndex)
             continue;
@@ -641,9 +583,14 @@ CPLString OGRPGDumpLayer::BuildCopyFields(int bSetFID)
     int     nFIDIndex = -1; 
     CPLString osFieldList;
 
-    if( pszGeomColumn != NULL )
+    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        osFieldList = OGRPGDumpEscapeColumnName(pszGeomColumn);
+        if( osFieldList.size() > 0 )
+            osFieldList += ", ";
+        
+        OGRGeomFieldDefn* poGFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
+        
+        osFieldList += OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef());
     }
 
     bFIDColumnInCopyFields = (pszFIDColumn != NULL && bSetFID);
@@ -802,7 +749,7 @@ static CPLString OGRPGDumpEscapeStringList(
         if (*pszStr != '\0')
         {
             if (bForInsertOrUpdate)
-                osStr += OGRPGDumpEscapeString(pszStr, -1, "");
+                osStr += OGRPGDumpEscapeString(pszStr);
             else
             {
                 osStr += '"';
@@ -1089,13 +1036,6 @@ static CPLString OGRPGTableLayerGetType(OGRFieldDefn& oField,
 OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
                                      int bApproxOK )
 {
-    if (nFeatures != 0)
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot create field after first feature has been written");
-        return OGRERR_FAILURE;
-    }
-    
     CPLString           osCommand;
     CPLString           osFieldType;
     OGRFieldDefn        oField( poFieldIn );
@@ -1144,6 +1084,95 @@ OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
 }
 
 /************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
+                                        int bApproxOK )
+{
+    OGRwkbGeometryType eType = poGeomFieldIn->GetType();
+    if( eType == wkbNone )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create geometry field of type wkbNone");
+        return OGRERR_FAILURE;
+    }
+    
+    CPLString               osCommand;
+    OGRPGDumpGeomFieldDefn *poGeomField =
+        new OGRPGDumpGeomFieldDefn( poGeomFieldIn );
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to "launder" the column names into Postgres          */
+/*      friendly format?                                                */
+/* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char    *pszSafeName = poDS->LaunderName( poGeomField->GetNameRef() );
+
+        poGeomField->SetName( pszSafeName );
+        CPLFree( pszSafeName );
+    }
+    
+    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
+    int nSRSId = nUnknownSRSId;
+    if( nForcedSRSId != -2 )
+        nSRSId = nForcedSRSId;
+    else if( poSRS != NULL )
+    {
+        const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
+        if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+        {
+            /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
+            nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
+        }
+        else
+        {
+            const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
+            if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984"))
+                nSRSId = 4326;
+        }
+    }
+    
+    int nDimension = 3;
+    if( wkbFlatten(eType) == eType )
+        nDimension = 2;
+    poGeomField->nSRSId = nSRSId;
+    poGeomField->nCoordDimension = nDimension;
+
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+    if (bCreateTable)
+    {
+        const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
+        osCommand.Printf(
+                "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
+                OGRPGDumpEscapeString(pszSchemaName).c_str(),
+                OGRPGDumpEscapeString(poFeatureDefn->GetName()).c_str(),
+                OGRPGDumpEscapeString(poGeomField->GetNameRef()).c_str(),
+                nSRSId, pszGeometryType, nDimension );
+        
+        poDS->Log(osCommand);
+
+        if( bCreateSpatialIndexFlag )
+        {
+            osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)",
+                            OGRPGDumpEscapeColumnName(
+                                CPLSPrintf("%s_%s_geom_idx", GetName(), poGeomField->GetNameRef())).c_str(),
+                            pszSqlTableName,
+                            OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str());
+
+            poDS->Log(osCommand);
+        }
+    }
+
+    poFeatureDefn->AddGeomFieldDefn( poGeomField, FALSE );
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                        SetOverrideColumnTypes()                      */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
index 4b3e77a..9d16339 100644
--- a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
+++ b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pgeo.h 21550 2011-01-22 18:01:57Z rouault $
+ * $Id: ogr_pgeo.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Personal Geodatabase driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -79,8 +80,6 @@ class OGRPGeoLayer : public OGRLayer
     
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual int         TestCapability( const char * );
 
     virtual const char *GetFIDColumn();
@@ -194,18 +193,30 @@ class OGRPGeoDataSource : public OGRDataSource
 };
 
 /************************************************************************/
-/*                             OGRPGeoDriver                            */
+/*                           OGRODBCMDBDriver                           */
 /************************************************************************/
 
-class OGRPGeoDriver : public OGRSFDriver
+class OGRODBCMDBDriver : public OGRSFDriver
 {
+#ifndef WIN32
     CPLString   osDriverFile;
-
-    bool        InstallMdbDriver();
     bool        LibraryExists( const char* pszLibPath );
     bool        FindDriverLib();
     CPLString   FindDefaultLib(const char* pszLibName);
+#endif
+
+protected:
+#ifndef WIN32
+    bool        InstallMdbDriver();
+#endif
+};
+
+/************************************************************************/
+/*                             OGRPGeoDriver                            */
+/************************************************************************/
 
+class OGRPGeoDriver : public OGRODBCMDBDriver
+{
   public:
                 ~OGRPGeoDriver();
                 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
index 1b771ee..e80fe9b 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeodatasource.cpp 20440 2010-08-25 17:35:49Z rouault $
+ * $Id: ogrpgeodatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrpgeodatasource.cpp 20440 2010-08-25 17:35:49Z rouault $");
+CPL_CVSID("$Id: ogrpgeodatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRPGeoDataSource()                          */
@@ -245,9 +246,9 @@ OGRLayer * OGRPGeoDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic imlplementation for OGRSQL dialect.                 */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+    if( IsGenericSQLDialect(pszDialect) )
         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
                                           poSpatialFilter, 
                                           pszDialect );
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
index 45e98bf..cdbd60e 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeodriver.cpp 23931 2012-02-09 13:41:13Z rouault $
+ * $Id: ogrpgeodriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_pgeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgeodriver.cpp 23931 2012-02-09 13:41:13Z rouault $");
+CPL_CVSID("$Id: ogrpgeodriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -61,6 +62,12 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
 {
     OGRPGeoDataSource     *poDS;
 
+    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+        return NULL;
+
     if( !EQUALN(pszFilename,"PGEO:",5) 
         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
@@ -153,7 +160,7 @@ int OGRPGeoDriver::TestCapability( const char * pszCap )
 /*                           InstallMdbDriver()                         */
 /************************************************************************/
 
-bool OGRPGeoDriver::InstallMdbDriver()
+bool OGRODBCMDBDriver::InstallMdbDriver()
 {
     if ( !FindDriverLib() )
     {
@@ -162,7 +169,7 @@ bool OGRPGeoDriver::InstallMdbDriver()
     else
     {
         CPLAssert( !osDriverFile.empty() );
-        CPLDebug( "PGeo", "MDB Tools driver: %s", osDriverFile.c_str() );
+        CPLDebug( GetName(), "MDB Tools driver: %s", osDriverFile.c_str() );
 
         CPLString driverName("Microsoft Access Driver (*.mdb)");
         CPLString driver(driverName);
@@ -192,7 +199,7 @@ bool OGRPGeoDriver::InstallMdbDriver()
 /*                           FindDriverLib()                            */
 /************************************************************************/
 
-bool OGRPGeoDriver::FindDriverLib()
+bool OGRODBCMDBDriver::FindDriverLib()
 {
     // Default name and path of driver library
     const char* aszDefaultLibName[] = {
@@ -250,7 +257,7 @@ bool OGRPGeoDriver::FindDriverLib()
         }
     }
 
-    CPLError(CE_Failure, CPLE_AppDefined, "PGeo: MDB Tools driver not found!\n");
+    CPLError(CE_Failure, CPLE_AppDefined, "%s: MDB Tools driver not found!\n", GetName());
     // Driver not found!
     return false;
 }
@@ -259,7 +266,7 @@ bool OGRPGeoDriver::FindDriverLib()
 /*                           LibraryExists()                            */
 /************************************************************************/
 
-bool OGRPGeoDriver::LibraryExists(const char* pszLibPath)
+bool OGRODBCMDBDriver::LibraryExists(const char* pszLibPath)
 {
     CPLAssert( 0 != pszLibPath );
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
index cd7e8b8..0194913 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $
+ * $Id: ogrpgeolayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoLayer class, code shared between 
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $");
+CPL_CVSID("$Id: ogrpgeolayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRPGeoLayer()                            */
@@ -107,6 +108,7 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
     int    nRawColumns = poStmt->GetColCount();
 
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
@@ -174,6 +176,9 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
             /* leave it as OFTString */;
         }
 
+        if( pszGeomColumn != NULL )
+            poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
+
         poFeatureDefn->AddFieldDefn( &oField );
         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
     }
@@ -326,16 +331,6 @@ int OGRPGeoLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRPGeoLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
index 7df5024..08cda7e 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeoselectlayer.cpp 20194 2010-08-06 18:28:05Z rouault $
+ * $Id: ogrpgeoselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoSelectLayer class, layer access to the results
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_pgeo.h"
 
-CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 20194 2010-08-06 18:28:05Z rouault $");
+CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRPGeoSelectLayer()                        */
@@ -49,6 +50,21 @@ OGRPGeoSelectLayer::OGRPGeoSelectLayer( OGRPGeoDataSource *poDSIn,
 
     poStmt = poStmtIn;
     pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
+    
+    /* Just to make test_ogrsf happy, but would/could need be extended to */
+    /* other cases */
+    if( EQUALN(pszBaseStatement, "SELECT * FROM ", strlen("SELECT * FROM ")) )
+    {
+        
+        OGRLayer* poBaseLayer =
+            poDSIn->GetLayerByName(pszBaseStatement + strlen("SELECT * FROM "));
+        if( poBaseLayer != NULL )
+        {
+            poSRS = poBaseLayer->GetSpatialRef();
+            if( poSRS != NULL )
+                poSRS->Reference();
+        }
+    }
 
     BuildFeatureDefn( "SELECT", poStmt );
 }
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
index b1a01db..eb9111c 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $
+ * $Id: ogrpgeotablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoTableLayer class, access to an existing table.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogr_pgeo.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $");
+CPL_CVSID("$Id: ogrpgeotablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRPGeoTableLayer()                         */
@@ -299,6 +300,9 @@ OGRFeature *OGRPGeoTableLayer::GetFeature( long nFeatureId )
 OGRErr OGRPGeoTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( (pszQuery == NULL && this->pszQuery == NULL)
         || (pszQuery != NULL && this->pszQuery != NULL 
             && EQUAL(pszQuery,this->pszQuery)) )
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
index 34c20ca..3febb84 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrrecdatasource.cpp 13025 2007-11-25 18:03:46Z rouault $
+ * $Id: ogrrecdatasource.cpp 26243 2013-07-29 20:45:59Z rouault $
  *
  * Project:  Epiinfo .REC Translator
  * Purpose:  Implements OGRRECDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrrecdatasource.cpp 13025 2007-11-25 18:03:46Z rouault $");
+CPL_CVSID("$Id: ogrrecdatasource.cpp 26243 2013-07-29 20:45:59Z rouault $");
 
 /************************************************************************/
 /*                          OGRRECDataSource()                          */
@@ -103,7 +103,7 @@ int OGRRECDataSource::Open( const char * pszFilename )
     const char * pszLine;
     FILE       * fp;
 
-    fp = VSIFOpen( pszFilename, "r" );
+    fp = VSIFOpen( pszFilename, "rb" );
     if( fp == NULL )
         return FALSE;
     
diff --git a/ogr/ogrsf_frmts/s57/GNUmakefile b/ogr/ogrsf_frmts/s57/GNUmakefile
index 8c9fd36..7eec819 100644
--- a/ogr/ogrsf_frmts/s57/GNUmakefile
+++ b/ogr/ogrsf_frmts/s57/GNUmakefile
@@ -15,9 +15,11 @@ CPPFLAGS	:=	-I.. -I../.. -I$(ISODIR) $(GDAL_INCLUDE) $(CPPFLAGS)
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
-	rm -f *.o s57dump$(EXE) mks57$(EXE) $(O_OBJ)
+	rm -f *.o s57dump$(EXE) $(O_OBJ)
 
-all:	default s57dump$(EXE) mks57$(EXE)
+all:	default s57dump$(EXE)
+
+$(O_OBJ):	s57.h ogr_s57.h
 
 s57dump$(EXE):	s57dump.$(OBJ_EXT)
 	$(LD) $(LDFLAGS) s57dump.$(OBJ_EXT) $(CONFIG_LIBS) -o s57dump$(EXE)
diff --git a/ogr/ogrsf_frmts/s57/ogr_s57.h b/ogr/ogrsf_frmts/s57/ogr_s57.h
index 08fe149..3f79d7e 100644
--- a/ogr/ogrsf_frmts/s57/ogr_s57.h
+++ b/ogr/ogrsf_frmts/s57/ogr_s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_s57.h 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogr_s57.h 26465 2013-09-13 21:18:16Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for classes binding S57 support onto OGRLayer,
@@ -72,8 +72,6 @@ class OGRS57Layer : public OGRLayer
 
     virtual OGRErr      CreateFeature( OGRFeature *poFeature );
     int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef();
 };
 
 /************************************************************************/
@@ -96,6 +94,8 @@ class OGRS57DataSource : public OGRDataSource
 
     S57Writer           *poWriter;
 
+    S57ClassContentExplorer* poClassContentExplorer;
+
     int                 bExtentsSet;
     OGREnvelope         oExtents;
     
diff --git a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
index cc2d364..eeb08f5 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57datasource.cpp 25905 2013-04-13 20:46:53Z rouault $
+ * $Id: ogrs57datasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57DataSource class
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrs57datasource.cpp 25905 2013-04-13 20:46:53Z rouault $");
+CPL_CVSID("$Id: ogrs57datasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRS57DataSource()                          */
@@ -45,6 +46,7 @@ OGRS57DataSource::OGRS57DataSource()
 
     nModules = 0;
     papoModules = NULL;
+    poClassContentExplorer = NULL;
     poWriter = NULL;
 
     pszName = NULL;
@@ -107,6 +109,7 @@ OGRS57DataSource::~OGRS57DataSource()
         poWriter->Close();
         delete poWriter;
     }
+    delete poClassContentExplorer;
 }
 
 /************************************************************************/
@@ -318,33 +321,36 @@ int OGRS57DataSource::Open( const char * pszFilename, int bTestOpen )
     else
     {
         OGRFeatureDefn  *poDefn;
-        int             *panClassCount;
-        int             iClass, bGeneric = FALSE;
+        std::vector<int> anClassCount;
+        int              bGeneric = FALSE;
+        unsigned int     iClass;
+        
+        poClassContentExplorer =
+            new S57ClassContentExplorer( OGRS57Driver::GetS57Registrar() );
 
         for( iModule = 0; iModule < nModules; iModule++ )
-            papoModules[iModule]->SetClassBased( OGRS57Driver::GetS57Registrar() );
+            papoModules[iModule]->SetClassBased( OGRS57Driver::GetS57Registrar(),
+                                                 poClassContentExplorer );
         
-        panClassCount = (int *) CPLCalloc(sizeof(int),MAX_CLASSES);
-
         for( iModule = 0; iModule < nModules; iModule++ )
         {
             bSuccess &= 
-                papoModules[iModule]->CollectClassList(panClassCount,
-                                                       MAX_CLASSES);
+                papoModules[iModule]->CollectClassList(anClassCount);
         }
 
-        for( iClass = 0; iClass < MAX_CLASSES; iClass++ )
+        for( iClass = 0; iClass < anClassCount.size(); iClass++ )
         {
-            if( panClassCount[iClass] > 0 )
+            if( anClassCount[iClass] > 0 )
             {
                 poDefn = 
-                    S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(), 
+                    S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(),
+                                                poClassContentExplorer,
                                                 iClass, 
                                                 poModule->GetOptionFlags() );
 
                 if( poDefn != NULL )
                     AddLayer( new OGRS57Layer( this, poDefn, 
-                                               panClassCount[iClass] ) );
+                                               anClassCount[iClass] ) );
                 else
                 {
                     bGeneric = TRUE;
@@ -361,8 +367,6 @@ int OGRS57DataSource::Open( const char * pszFilename, int bTestOpen )
                                                  poModule->GetOptionFlags() );
             AddLayer( new OGRS57Layer( this, poDefn ) );
         }
-            
-        CPLFree( panClassCount );
     }
 
 /* -------------------------------------------------------------------- */
@@ -494,7 +498,11 @@ int OGRS57DataSource::Create( const char *pszFilename, char **papszOptions )
     if( !poWriter->CreateS57File( pszFilename ) )
         return FALSE;
 
-    poWriter->SetClassBased( OGRS57Driver::GetS57Registrar() );
+    poClassContentExplorer =
+        new S57ClassContentExplorer( OGRS57Driver::GetS57Registrar() );
+
+    poWriter->SetClassBased( OGRS57Driver::GetS57Registrar(),
+                             poClassContentExplorer );
     pszName = CPLStrdup( pszFilename );
 
 /* -------------------------------------------------------------------- */
@@ -518,16 +526,17 @@ int OGRS57DataSource::Create( const char *pszFilename, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Initialize a feature definition for each object class.          */
 /* -------------------------------------------------------------------- */
-    for( int iClass = 0; iClass < MAX_CLASSES; iClass++ )
+    poClassContentExplorer->Rewind();
+    while( poClassContentExplorer->NextClass() )
     {
         poDefn = 
             S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(), 
-                                        iClass, nOptionFlags );
+                                        poClassContentExplorer,
+                                        poClassContentExplorer->GetOBJL(),
+                                        nOptionFlags );
         
-        if( poDefn == NULL )
-            continue;
-
-        AddLayer( new OGRS57Layer( this, poDefn, 0, iClass ) );
+        AddLayer( new OGRS57Layer( this, poDefn, 0, 
+                                   poClassContentExplorer->GetOBJL() ) );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
index 50c4f75..0a2244a 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57driver.cpp 25823 2013-03-31 15:38:35Z rouault $
+ * $Id: ogrs57driver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Driver
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrs57driver.cpp 25823 2013-03-31 15:38:35Z rouault $");
+CPL_CVSID("$Id: ogrs57driver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 S57ClassRegistrar *OGRS57Driver::poRegistrar = NULL;
 static void* hS57RegistrarMutex = NULL;
diff --git a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
index 5253f23..e00edd3 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57layer.cpp 17953 2009-11-02 21:13:56Z rouault $
+ * $Id: ogrs57layer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Layer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrs57layer.cpp 17953 2009-11-02 21:13:56Z rouault $");
+CPL_CVSID("$Id: ogrs57layer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRS57Layer()                             */
@@ -51,6 +52,8 @@ OGRS57Layer::OGRS57Layer( OGRS57DataSource *poDSIn,
     nFeatureCount = nFeatureCountIn;
 
     poFeatureDefn = poDefnIn;
+    if( poFeatureDefn->GetGeomFieldCount() > 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
 
     nOBJL = nOBJLIn;
 
@@ -222,22 +225,15 @@ int OGRS57Layer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRS57Layer::GetSpatialRef()
-
-{
-    return poDS->GetSpatialRef();
-}
-
-/************************************************************************/
 /*                             GetExtent()                              */
 /************************************************************************/
 
 OGRErr OGRS57Layer::GetExtent( OGREnvelope *psExtent, int bForce )
 
 {
+    if( GetGeomType() == wkbNone )
+        return OGRERR_FAILURE;
+
     return poDS->GetDSExtent( psExtent, bForce );
 }
 
diff --git a/ogr/ogrsf_frmts/s57/s57.h b/ogr/ogrsf_frmts/s57/s57.h
index 11e44bf..dcfe372 100644
--- a/ogr/ogrsf_frmts/s57/s57.h
+++ b/ogr/ogrsf_frmts/s57/s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57.h 25905 2013-04-13 20:46:53Z rouault $
+ * $Id: s57.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for S-57 translator not including the
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,6 +33,7 @@
 #ifndef _S57_H_INCLUDED
 #define _S57_H_INCLUDED
 
+#include <vector>
 #include "ogr_feature.h"
 #include "iso8211.h"
 
@@ -94,31 +96,29 @@ char **S57FileCollector( const char * pszDataset );
 /*                          S57ClassRegistrar                           */
 /************************************************************************/
 
-#define MAX_CLASSES 23000
-#define MAX_ATTRIBUTES 65535
+class S57ClassContentExplorer;
+
+class CPL_DLL S57AttrInfo 
+{
+  public:
+    CPLString    osName;
+    CPLString    osAcronym;
+    char         chType;
+    char         chClass;
+};
 
 class CPL_DLL S57ClassRegistrar
 {
+    friend class S57ClassContentExplorer;
+
     // Class information:
     int         nClasses;
-    char      **papszClassesInfo;
-    char     ***papapszClassesFields;
-
-    int         iCurrentClass;
-
-    char      **papszCurrentFields;
-
-    char      **papszTempResult;
+    CPLStringList apszClassesInfo;
 
     // Attribute Information:
-    int         nAttrMax;
     int         nAttrCount;
-    char      **papszAttrNames;
-    char      **papszAttrAcronym;
-    char     ***papapszAttrValues;
-    char       *pachAttrType;
-    char       *pachAttrClass;
-    GUInt16    *panAttrIndex; // sorted by acronym.
+    std::vector<S57AttrInfo*> aoAttrInfos;
+    std::vector<int> anAttrIndex; // sorted by acronym.
 
     int         FindFile( const char *pszTarget, const char *pszDirectory,
                           int bReportErr, VSILFILE **fp );
@@ -132,7 +132,48 @@ public:
 
     int         LoadInfo( const char *, const char *, int );
 
-    // class table methods.
+    // attribute table methods.
+    //int         GetMaxAttrIndex() { return nAttrMax; }
+    const S57AttrInfo *GetAttrInfo(int i);
+    const char *GetAttrName( int i ) 
+    { return GetAttrInfo(i) == NULL ? NULL : aoAttrInfos[i]->osName.c_str(); }
+    const char *GetAttrAcronym( int i )
+    { return GetAttrInfo(i) == NULL ? NULL : aoAttrInfos[i]->osAcronym.c_str(); }
+    char        GetAttrType( int i )
+    { return GetAttrInfo(i) == NULL ? '\0' : aoAttrInfos[i]->chType; }
+#define SAT_ENUM        'E'
+#define SAT_LIST        'L'
+#define SAT_FLOAT       'F'
+#define SAT_INT         'I'
+#define SAT_CODE_STRING 'A'
+#define SAT_FREE_TEXT   'S'
+
+    char        GetAttrClass( int i )
+    { return GetAttrInfo(i) == NULL ? '\0' : aoAttrInfos[i]->chClass; }
+    int         FindAttrByAcronym( const char * );
+
+};
+
+/************************************************************************/
+/*                       S57ClassContentExplorer                        */
+/************************************************************************/
+
+class S57ClassContentExplorer
+{
+    S57ClassRegistrar* poRegistrar;
+
+    char     ***papapszClassesFields;
+
+    int         iCurrentClass;
+
+    char      **papszCurrentFields;
+
+    char      **papszTempResult;
+
+    public:
+        S57ClassContentExplorer(S57ClassRegistrar* poRegistrar);
+       ~S57ClassContentExplorer();
+
     int         SelectClassByIndex( int );
     int         SelectClass( int );
     int         SelectClass( const char * );
@@ -148,23 +189,6 @@ public:
 
     char        GetClassCode();
     char      **GetPrimitives();
-
-    // attribute table methods.
-    int         GetMaxAttrIndex() { return nAttrMax; }
-    const char *GetAttrName( int i ) { return papszAttrNames[i]; }
-    const char *GetAttrAcronym( int i ) { return papszAttrAcronym[i]; }
-    char      **GetAttrValues( int i ) { return papapszAttrValues[i]; }
-    char        GetAttrType( int i ) { return pachAttrType[i]; }
-#define SAT_ENUM        'E'
-#define SAT_LIST        'L'
-#define SAT_FLOAT       'F'
-#define SAT_INT         'I'
-#define SAT_CODE_STRING 'A'
-#define SAT_FREE_TEXT   'S'
-
-    char        GetAttrClass( int i ) { return pachAttrClass[i]; }
-    int         FindAttrByAcronym( const char * );
-
 };
 
 /************************************************************************/
@@ -221,11 +245,12 @@ public:
 class CPL_DLL S57Reader
 {
     S57ClassRegistrar  *poRegistrar;
+    S57ClassContentExplorer* poClassContentExplorer;
 
     int                 nFDefnCount;
     OGRFeatureDefn      **papoFDefnList;
 
-    OGRFeatureDefn      *apoFDefnByOBJL[MAX_CLASSES];
+    std::vector<OGRFeatureDefn*> apoFDefnByOBJL;
 
     char                *pszModuleName;
     char                *pszDSNM;
@@ -295,7 +320,7 @@ class CPL_DLL S57Reader
                         S57Reader( const char * );
                        ~S57Reader();
 
-    void                SetClassBased( S57ClassRegistrar * );
+    void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
     void                SetOptions( char ** );
     int                 GetOptionFlags() { return nOptionFlags; }
 
@@ -319,7 +344,7 @@ class CPL_DLL S57Reader
 
     void                AddFeatureDefn( OGRFeatureDefn * );
 
-    int                 CollectClassList( int *, int);
+    int                 CollectClassList(std::vector<int> &anClassCount);
 
     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
 
@@ -337,7 +362,7 @@ public:
                         S57Writer();
                         ~S57Writer();
 
-    void                SetClassBased( S57ClassRegistrar * );
+    void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
     int                 CreateS57File( const char *pszFilename );
     int                 Close();
 
@@ -360,6 +385,7 @@ public:
 private:
     int                 nNext0001Index;
     S57ClassRegistrar   *poRegistrar;
+    S57ClassContentExplorer* poClassContentExplorer;
 
     int                 nCOMF;  /* Coordinate multiplier */
     int                 nSOMF;  /* Vertical (sounding) multiplier */
@@ -371,6 +397,7 @@ private:
 void           CPL_DLL  S57GenerateStandardAttributes( OGRFeatureDefn *, int );
 OGRFeatureDefn CPL_DLL *S57GenerateGeomFeatureDefn( OGRwkbGeometryType, int );
 OGRFeatureDefn CPL_DLL *S57GenerateObjectClassDefn( S57ClassRegistrar *, 
+                                                    S57ClassContentExplorer* poClassContentExplorer,
                                                     int, int );
 OGRFeatureDefn CPL_DLL  *S57GenerateVectorPrimitiveFeatureDefn( int, int );
 OGRFeatureDefn CPL_DLL  *S57GenerateDSIDFeatureDefn( void );
diff --git a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
index dfa53aa..6343e43 100644
--- a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
+++ b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57classregistrar.cpp 25822 2013-03-31 15:29:55Z rouault $
+ * $Id: s57classregistrar.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57ClassRegistrar class for keeping track of
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57classregistrar.cpp 25822 2013-03-31 15:29:55Z rouault $");
+CPL_CVSID("$Id: s57classregistrar.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 #ifdef S57_BUILTIN_CLASSES
@@ -46,54 +47,48 @@ CPL_CVSID("$Id: s57classregistrar.cpp 25822 2013-03-31 15:29:55Z rouault $");
 S57ClassRegistrar::S57ClassRegistrar()
 
 {
+    papszNextLine = NULL;
+}
+
+/************************************************************************/
+/*                         ~S57ClassRegistrar()                         */
+/************************************************************************/
+
+S57ClassRegistrar::~S57ClassRegistrar()
+
+{
     nClasses = 0;
-    papszClassesInfo = NULL;
+}
+
+/************************************************************************/
+/*                        S57ClassContentExplorer()                     */
+/************************************************************************/
+
+S57ClassContentExplorer::S57ClassContentExplorer(S57ClassRegistrar* poRegistrar):
+    poRegistrar(poRegistrar)
+{
     
     iCurrentClass = -1;
 
     papszCurrentFields = NULL;
-    papszTempResult = NULL;
-    papszNextLine = NULL;
     papapszClassesFields = NULL;
-    pachAttrClass = NULL;
-    pachAttrType = NULL;
-    panAttrIndex = NULL;
-    papszAttrNames = NULL;
-    papszAttrAcronym = NULL;
-    papapszAttrValues = NULL;
+    papszTempResult = NULL;
 }
 
 /************************************************************************/
-/*                         ~S57ClassRegistrar()                         */
+/*                        ~S57ClassContentExplorer()                    */
 /************************************************************************/
 
-S57ClassRegistrar::~S57ClassRegistrar()
-
+S57ClassContentExplorer::~S57ClassContentExplorer()
 {
-    int i;
-
-    CSLDestroy( papszClassesInfo );
     CSLDestroy( papszTempResult );
     
     if( papapszClassesFields != NULL )
     {
-        for( i = 0; i < nClasses; i++ )
+        for( int i = 0; i < poRegistrar->nClasses; i++ )
             CSLDestroy( papapszClassesFields[i] );
         CPLFree( papapszClassesFields );
     }
-    if( papszAttrNames )
-    {
-        for( i = 0; i < MAX_ATTRIBUTES; i++ )
-        {
-            CPLFree( papszAttrNames[i] );
-            CPLFree( papszAttrAcronym[i] );
-        }
-        CPLFree( papszAttrNames );
-        CPLFree( papszAttrAcronym );
-    }
-    CPLFree( pachAttrType );
-    CPLFree( pachAttrClass );
-    CPLFree( panAttrIndex );
 }
 
 /************************************************************************/
@@ -228,33 +223,19 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 /* -------------------------------------------------------------------- */
 /*      Read and form string list.                                      */
 /* -------------------------------------------------------------------- */
-    
-    CSLDestroy( papszClassesInfo );
-    papszClassesInfo = (char **) CPLCalloc(sizeof(char *),MAX_CLASSES);
-
-    nClasses = 0;
-
-    while( nClasses < MAX_CLASSES
-           && (pszLine = ReadLine(fp)) != NULL )
+    apszClassesInfo.Clear();
+    while( (pszLine = ReadLine(fp)) != NULL )
     {
-        papszClassesInfo[nClasses] = CPLStrdup(pszLine);
-        if( papszClassesInfo[nClasses] == NULL )
-            break;
-
-        nClasses++;
+        apszClassesInfo.AddString(pszLine);
     }
 
-    if( nClasses == MAX_CLASSES )
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "MAX_CLASSES exceeded in S57ClassRegistrar::LoadInfo().\n" );
-
 /* -------------------------------------------------------------------- */
 /*      Cleanup, and establish state.                                   */
 /* -------------------------------------------------------------------- */
     if( fp != NULL )
         VSIFCloseL( fp );
-    iCurrentClass = -1;
 
+    nClasses = apszClassesInfo.size();
     if( nClasses == 0 )
         return FALSE;
 
@@ -298,21 +279,10 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     }
     
 /* -------------------------------------------------------------------- */
-/*      Prepare arrays for the per-attribute information.               */
-/* -------------------------------------------------------------------- */
-    nAttrMax = MAX_ATTRIBUTES-1;
-    papszAttrNames = (char **) CPLCalloc(sizeof(char *),MAX_ATTRIBUTES);
-    papszAttrAcronym = (char **) CPLCalloc(sizeof(char *),MAX_ATTRIBUTES);
-    //papapszAttrValues = (char ***) CPLCalloc(sizeof(char **),MAX_ATTRIBUTES);
-    pachAttrType = (char *) CPLCalloc(sizeof(char),MAX_ATTRIBUTES);
-    pachAttrClass = (char *) CPLCalloc(sizeof(char),MAX_ATTRIBUTES);
-    panAttrIndex = (GUInt16 *) CPLCalloc(sizeof(GUInt16),MAX_ATTRIBUTES);
-    
-/* -------------------------------------------------------------------- */
 /*      Read and form string list.                                      */
 /* -------------------------------------------------------------------- */
-    GUInt16         iAttr;
-    
+    int        iAttr;
+
     while( (pszLine = ReadLine(fp)) != NULL )
     {
         char    **papszTokens = CSLTokenizeStringComplex( pszLine, ",",
@@ -324,55 +294,49 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
             continue;
         }
         
-        iAttr = (GUInt16) atoi(papszTokens[0]);
-        if( iAttr < 0 || iAttr >= nAttrMax
-            || papszAttrNames[iAttr] != NULL )
+        iAttr = atoi(papszTokens[0]);
+        if( iAttr >= (int) aoAttrInfos.size() )
+            aoAttrInfos.resize(iAttr+1);
+
+        if( iAttr < 0 || aoAttrInfos[iAttr] != NULL )
         {
-            CPLDebug( "S57", "Duplicate definition for attribute %d:%s", 
+            CPLDebug( "S57", 
+                      "Duplicate/corrupt definition for attribute %d:%s", 
                       iAttr, papszTokens[2] );
             continue;
         }
-        
-        papszAttrNames[iAttr] = CPLStrdup(papszTokens[1]);
-        papszAttrAcronym[iAttr] = CPLStrdup(papszTokens[2]);
-        pachAttrType[iAttr] = papszTokens[3][0];
-        pachAttrClass[iAttr] = papszTokens[4][0];
 
+        aoAttrInfos[iAttr] = new S57AttrInfo();
+        aoAttrInfos[iAttr]->osName = papszTokens[1];
+        aoAttrInfos[iAttr]->osAcronym = papszTokens[2];
+        aoAttrInfos[iAttr]->chType = papszTokens[3][0];
+        aoAttrInfos[iAttr]->chClass = papszTokens[4][0];
+        anAttrIndex.push_back(iAttr);
         CSLDestroy( papszTokens );
     }
 
     if( fp != NULL )
         VSIFCloseL( fp );
-    
-/* -------------------------------------------------------------------- */
-/*      Build unsorted index of attributes.                             */
-/* -------------------------------------------------------------------- */
-    nAttrCount = 0;
-    for( iAttr = 0; iAttr < nAttrMax; iAttr++ )
-    {
-        if( papszAttrAcronym[iAttr] != NULL )
-            panAttrIndex[nAttrCount++] = iAttr;
-    }
 
+    nAttrCount = anAttrIndex.size();
+    
 /* -------------------------------------------------------------------- */
 /*      Sort index by acronym.                                          */
 /* -------------------------------------------------------------------- */
     int         bModified;
-
     do
     {
         bModified = FALSE;
         for( iAttr = 0; iAttr < nAttrCount-1; iAttr++ )
         {
-            if( strcmp(papszAttrAcronym[panAttrIndex[iAttr]],
-                       papszAttrAcronym[panAttrIndex[iAttr+1]]) > 0 )
+            if( strcmp(aoAttrInfos[anAttrIndex[iAttr]]->osAcronym,
+                       aoAttrInfos[anAttrIndex[iAttr+1]]->osAcronym) > 0 )
             {
-                GInt16     nTemp;
-
-                nTemp = panAttrIndex[iAttr];
-                panAttrIndex[iAttr] = panAttrIndex[iAttr+1];
-                panAttrIndex[iAttr+1] = nTemp;
+                int     nTemp;
 
+                nTemp = anAttrIndex[iAttr];
+                anAttrIndex[iAttr] = anAttrIndex[iAttr+1];
+                anAttrIndex[iAttr+1] = nTemp;
                 bModified = TRUE;
             }
         }
@@ -385,10 +349,10 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 /*                         SelectClassByIndex()                         */
 /************************************************************************/
 
-int S57ClassRegistrar::SelectClassByIndex( int nNewIndex )
+int S57ClassContentExplorer::SelectClassByIndex( int nNewIndex )
 
 {
-    if( nNewIndex < 0 || nNewIndex >= nClasses )
+    if( nNewIndex < 0 || nNewIndex >= poRegistrar->nClasses )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -396,7 +360,7 @@ int S57ClassRegistrar::SelectClassByIndex( int nNewIndex )
 /* -------------------------------------------------------------------- */
     if( papapszClassesFields == NULL )
     {
-        papapszClassesFields = (char ***) CPLCalloc(sizeof(void*),nClasses);
+        papapszClassesFields = (char ***) CPLCalloc(sizeof(void*),poRegistrar->nClasses);
     }
 
 /* -------------------------------------------------------------------- */
@@ -404,7 +368,7 @@ int S57ClassRegistrar::SelectClassByIndex( int nNewIndex )
 /* -------------------------------------------------------------------- */
     if( papapszClassesFields[nNewIndex] == NULL )
         papapszClassesFields[nNewIndex] = 
-            CSLTokenizeStringComplex( papszClassesInfo[nNewIndex],
+            CSLTokenizeStringComplex( poRegistrar->apszClassesInfo[nNewIndex],
                                       ",", TRUE, TRUE );
 
     papszCurrentFields = papapszClassesFields[nNewIndex];
@@ -418,12 +382,12 @@ int S57ClassRegistrar::SelectClassByIndex( int nNewIndex )
 /*                             SelectClass()                            */
 /************************************************************************/
 
-int S57ClassRegistrar::SelectClass( int nOBJL )
+int S57ClassContentExplorer::SelectClass( int nOBJL )
 
 {
-    for( int i = 0; i < nClasses; i++ )
+    for( int i = 0; i < poRegistrar->nClasses; i++ )
     {
-        if( atoi(papszClassesInfo[i]) == nOBJL )
+        if( atoi(poRegistrar->apszClassesInfo[i]) == nOBJL )
             return SelectClassByIndex( i );
     }
 
@@ -434,10 +398,10 @@ int S57ClassRegistrar::SelectClass( int nOBJL )
 /*                            SelectClass()                             */
 /************************************************************************/
 
-int S57ClassRegistrar::SelectClass( const char *pszAcronym )
+int S57ClassContentExplorer::SelectClass( const char *pszAcronym )
 
 {
-    for( int i = 0; i < nClasses; i++ )
+    for( int i = 0; i < poRegistrar->nClasses; i++ )
     {
         if( !SelectClassByIndex( i ) )
             continue;
@@ -453,11 +417,11 @@ int S57ClassRegistrar::SelectClass( const char *pszAcronym )
 /*                              GetOBJL()                               */
 /************************************************************************/
 
-int S57ClassRegistrar::GetOBJL()
+int S57ClassContentExplorer::GetOBJL()
 
 {
     if( iCurrentClass >= 0 )
-        return atoi(papszClassesInfo[iCurrentClass]);
+        return atoi(poRegistrar->apszClassesInfo[iCurrentClass]);
     else
         return -1;
 }
@@ -466,7 +430,7 @@ int S57ClassRegistrar::GetOBJL()
 /*                           GetDescription()                           */
 /************************************************************************/
 
-const char * S57ClassRegistrar::GetDescription()
+const char * S57ClassContentExplorer::GetDescription()
 
 {
     if( iCurrentClass >= 0 && papszCurrentFields[0] != NULL )
@@ -479,7 +443,7 @@ const char * S57ClassRegistrar::GetDescription()
 /*                             GetAcronym()                             */
 /************************************************************************/
 
-const char * S57ClassRegistrar::GetAcronym()
+const char * S57ClassContentExplorer::GetAcronym()
 
 {
     if( iCurrentClass >= 0 
@@ -497,7 +461,7 @@ const char * S57ClassRegistrar::GetAcronym()
 /*      returned list remained owned by this object, not the caller.    */
 /************************************************************************/
 
-char **S57ClassRegistrar::GetAttributeList( const char * pszType )
+char **S57ClassContentExplorer::GetAttributeList( const char * pszType )
 
 {
     if( iCurrentClass < 0 )
@@ -505,7 +469,7 @@ char **S57ClassRegistrar::GetAttributeList( const char * pszType )
     
     CSLDestroy( papszTempResult );
     papszTempResult = NULL;
-    
+
     for( int iColumn = 3; iColumn < 6; iColumn++ )
     {
         if( pszType != NULL && iColumn == 3 && !EQUAL(pszType,"a") )
@@ -536,7 +500,7 @@ char **S57ClassRegistrar::GetAttributeList( const char * pszType )
 /*                            GetClassCode()                            */
 /************************************************************************/
 
-char S57ClassRegistrar::GetClassCode()
+char S57ClassContentExplorer::GetClassCode()
 
 {
     if( iCurrentClass >= 0
@@ -556,7 +520,7 @@ char S57ClassRegistrar::GetClassCode()
 /*                           GetPrimitives()                            */
 /************************************************************************/
 
-char **S57ClassRegistrar::GetPrimitives()
+char **S57ClassContentExplorer::GetPrimitives()
 
 {
     if( iCurrentClass >= 0
@@ -573,6 +537,18 @@ char **S57ClassRegistrar::GetPrimitives()
 }
 
 /************************************************************************/
+/*                            GetAttrInfo()                             */
+/************************************************************************/
+
+const S57AttrInfo *S57ClassRegistrar::GetAttrInfo(int iAttr)
+{
+    if( iAttr < 0 || iAttr >= (int) aoAttrInfos.size() )
+        return NULL;
+    else 
+        return aoAttrInfos[iAttr];
+}
+
+/************************************************************************/
 /*                         FindAttrByAcronym()                          */
 /************************************************************************/
 
@@ -590,7 +566,7 @@ int    S57ClassRegistrar::FindAttrByAcronym( const char * pszName )
         
         iCandidate = (iStart + iEnd)/2;
         nCompareValue =
-            strcmp( pszName, papszAttrAcronym[panAttrIndex[iCandidate]] );
+            strcmp(pszName, aoAttrInfos[anAttrIndex[iCandidate]]->osAcronym);
 
         if( nCompareValue < 0 )
         {
@@ -601,7 +577,7 @@ int    S57ClassRegistrar::FindAttrByAcronym( const char * pszName )
             iStart = iCandidate+1;
         }
         else
-            return panAttrIndex[iCandidate];
+            return anAttrIndex[iCandidate];
     }
 
     return -1;
diff --git a/ogr/ogrsf_frmts/s57/s57dump.cpp b/ogr/ogrsf_frmts/s57/s57dump.cpp
index 9673d67..814a291 100644
--- a/ogr/ogrsf_frmts/s57/s57dump.cpp
+++ b/ogr/ogrsf_frmts/s57/s57dump.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57dump.cpp 15650 2008-10-30 14:08:37Z warmerdam $
+ * $Id: s57dump.cpp 26388 2013-09-02 18:04:16Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing S57 driver data.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57dump.cpp 15650 2008-10-30 14:08:37Z warmerdam $");
+CPL_CVSID("$Id: s57dump.cpp 26388 2013-09-02 18:04:16Z warmerdam $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -91,6 +91,10 @@ int main( int nArgc, char ** papszArgv )
 
     bRegistrarLoaded = oRegistrar.LoadInfo( pszDataPath, NULL, TRUE );
 
+    S57ClassContentExplorer *poClassContentExplorer = NULL;
+    if (bRegistrarLoaded)
+        poClassContentExplorer = new S57ClassContentExplorer(&oRegistrar);
+            
 /* -------------------------------------------------------------------- */
 /*      Get a list of candidate files.                                  */
 /* -------------------------------------------------------------------- */
@@ -120,31 +124,30 @@ int main( int nArgc, char ** papszArgv )
 
         if( bRegistrarLoaded )
         {
-            int i, anClassList[MAX_CLASSES], bGeneric = FALSE;
-            
-            for( i = 0; i < MAX_CLASSES; i++ )
-                anClassList[i] = 0;
-        
-            oReader.CollectClassList(anClassList, MAX_CLASSES);
+            int bGeneric = FALSE;
+            std::vector<int> anClassList;
+            unsigned int i;
+            oReader.CollectClassList(anClassList);
 
-            oReader.SetClassBased( &oRegistrar );
+            oReader.SetClassBased( &oRegistrar, poClassContentExplorer );
 
             printf( "Classes found:\n" );
-            for( i = 0; i < MAX_CLASSES; i++ )
+            for( i = 0; i < anClassList.size(); i++ )
             {
                 if( anClassList[i] == 0 )
                     continue;
                 
-                if( oRegistrar.SelectClass( i ) )
+                if( poClassContentExplorer->SelectClass( i ) )
                 {
                     printf( "%d: %s/%s\n",
                             i,
-                            oRegistrar.GetAcronym(),
-                            oRegistrar.GetDescription() );
+                            poClassContentExplorer->GetAcronym(),
+                            poClassContentExplorer->GetDescription() );
                     
                     oReader.AddFeatureDefn(
-                        S57GenerateObjectClassDefn( &oRegistrar, i, 
-                                                    nOptionFlags ) );
+                        S57GenerateObjectClassDefn( &oRegistrar, 
+                                                    poClassContentExplorer,
+                                                    i, nOptionFlags ) );
                 }
                 else
                 {
diff --git a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
index 869f30c..42d0cf9 100644
--- a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
+++ b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57featuredefns.cpp 21268 2010-12-14 23:33:34Z warmerdam $
+ * $Id: s57featuredefns.cpp 26333 2013-08-15 21:40:50Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements methods to create OGRFeatureDefns for various
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57featuredefns.cpp 21268 2010-12-14 23:33:34Z warmerdam $");
+CPL_CVSID("$Id: s57featuredefns.cpp 26333 2013-08-15 21:40:50Z rouault $");
 
 
 /************************************************************************/
@@ -318,27 +318,28 @@ S57GenerateVectorPrimitiveFeatureDefn( int nRCNM, int nOptionFlags )
 /************************************************************************/
 
 OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
+                                            S57ClassContentExplorer* poClassContentExplorer,
                                             int nOBJL, int nOptionFlags )
 
 {
     OGRFeatureDefn      *poFDefn = NULL;
     char               **papszGeomPrim;
 
-    if( !poCR->SelectClass( nOBJL ) )
+    if( !poClassContentExplorer->SelectClass( nOBJL ) )
         return NULL;
     
 /* -------------------------------------------------------------------- */
 /*      Create the feature definition based on the object class         */
 /*      acronym.                                                        */
 /* -------------------------------------------------------------------- */
-    poFDefn = new OGRFeatureDefn( poCR->GetAcronym() );
+    poFDefn = new OGRFeatureDefn( poClassContentExplorer->GetAcronym() );
     poFDefn->Reference();
 
 /* -------------------------------------------------------------------- */
 /*      Try and establish the geometry type.  If more than one          */
 /*      geometry type is allowed we just fall back to wkbUnknown.       */
 /* -------------------------------------------------------------------- */
-    papszGeomPrim = poCR->GetPrimitives();
+    papszGeomPrim = poClassContentExplorer->GetPrimitives();
     if( CSLCount(papszGeomPrim) == 0 )
     {
         poFDefn->SetGeomType( wkbNone );
@@ -349,7 +350,7 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
     }
     else if( papszGeomPrim[0][0] == 'P' )
     {
-        if( EQUAL(poCR->GetAcronym(),"SOUNDG") )
+        if( EQUAL(poClassContentExplorer->GetAcronym(),"SOUNDG") )
         {
             if( nOptionFlags & S57M_SPLIT_MULTIPOINT )
                 poFDefn->SetGeomType( wkbPoint25D );
@@ -377,7 +378,7 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
 /* -------------------------------------------------------------------- */
 /*      Add the attributes specific to this object class.               */
 /* -------------------------------------------------------------------- */
-    char        **papszAttrList = poCR->GetAttributeList();
+    char        **papszAttrList = poClassContentExplorer->GetAttributeList();
 
     for( int iAttr = 0;
          papszAttrList != NULL && papszAttrList[iAttr] != NULL;
@@ -389,8 +390,8 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
         {
             CPLDebug( "S57", "Can't find attribute %s from class %s:%s.",
                       papszAttrList[iAttr],
-                      poCR->GetAcronym(),
-                      poCR->GetDescription() );
+                      poClassContentExplorer->GetAcronym(),
+                      poClassContentExplorer->GetDescription() );
             continue;
         }
 
@@ -424,7 +425,7 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
 /* -------------------------------------------------------------------- */
 /*      Do we need to add DEPTH attributes to soundings?                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poCR->GetAcronym(),"SOUNDG") 
+    if( EQUAL(poClassContentExplorer->GetAcronym(),"SOUNDG") 
         && (nOptionFlags & S57M_ADD_SOUNDG_DEPTH) )
     {
         OGRFieldDefn    oField( "DEPTH", OFTReal );
diff --git a/ogr/ogrsf_frmts/s57/s57reader.cpp b/ogr/ogrsf_frmts/s57/s57reader.cpp
index 4f28cc9..0b4bef8 100644
--- a/ogr/ogrsf_frmts/s57/s57reader.cpp
+++ b/ogr/ogrsf_frmts/s57/s57reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57reader.cpp 25905 2013-04-13 20:46:53Z rouault $
+ * $Id: s57reader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Reader class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, 2001, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 #include <string>
 #include <fstream>
 
-CPL_CVSID("$Id: s57reader.cpp 25905 2013-04-13 20:46:53Z rouault $");
+CPL_CVSID("$Id: s57reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -157,6 +158,7 @@ S57Reader::S57Reader( const char * pszFilename )
     nSOMF = 10;
 
     poRegistrar = NULL;
+    poClassContentExplorer = NULL;
     bFileIngested = FALSE;
 
     nNextFEIndex = 0;
@@ -180,8 +182,6 @@ S57Reader::S57Reader( const char * pszFilename )
     bMissingWarningIssued = FALSE;
     bAttrWarningIssued = FALSE;
 
-    memset( apoFDefnByOBJL, 0, sizeof(apoFDefnByOBJL) );
-    
     Aall=0;                 // see RecodeByDSSI() function
     Nall=0;                 // see RecodeByDSSI() function
     needAallNallSetup=true; // see RecodeByDSSI() function
@@ -422,10 +422,12 @@ void S57Reader::SetOptions( char ** papszOptionsIn )
 /*                           SetClassBased()                            */
 /************************************************************************/
 
-void S57Reader::SetClassBased( S57ClassRegistrar * poReg )
+void S57Reader::SetClassBased( S57ClassRegistrar * poReg,
+                               S57ClassContentExplorer* poClassContentExplorerIn )
 
 {
     poRegistrar = poReg;
+    poClassContentExplorer = poClassContentExplorerIn;
 }
 
 /************************************************************************/
@@ -763,8 +765,17 @@ OGRFeature *S57Reader::ReadFeature( int nFeatureId, OGRFeatureDefn *poTarget )
     if( nFeatureId < 0 || nFeatureId >= oFE_Index.GetCount() )
         return NULL;
 
-    poFeature = AssembleFeature( oFE_Index.GetByIndex(nFeatureId),
-                                 poTarget );
+    if( (nOptionFlags & S57M_RETURN_DSID) 
+        && nFeatureId == 0 
+        && (poTarget == NULL || EQUAL(poTarget->GetName(),"DSID")) )
+    {
+        poFeature = ReadDSID();
+    }
+    else
+    {
+        poFeature = AssembleFeature( oFE_Index.GetByIndex(nFeatureId),
+                                    poTarget );
+    }
     if( poFeature != NULL )
         poFeature->SetFID( nFeatureId );
 
@@ -895,10 +906,8 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
     for( iAttr = 0; iAttr < nAttrCount; iAttr++ )
     {
         int     nAttrId = poRecord->GetIntSubfield("ATTF",0,"ATTL",iAttr);
-        const char *pszAcronym;
         
-        if( nAttrId < 1 || nAttrId > poRegistrar->GetMaxAttrIndex() 
-            || (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL )
+        if( poRegistrar->GetAttrInfo(nAttrId) == NULL )
         {
             if( !bAttrWarningIssued )
             {
@@ -930,6 +939,7 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         int iField;
         OGRFieldDefn *poFldDefn;
 
+        const char *pszAcronym = poRegistrar->GetAttrAcronym(nAttrId);
         iField = poFeature->GetDefnRef()->GetFieldIndex(pszAcronym);
         if( iField < 0 )
         {
@@ -977,10 +987,9 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
     for( iAttr = 0; iAttr < nAttrCount; iAttr++ )
     {
         int     nAttrId = poRecord->GetIntSubfield("NATF",0,"ATTL",iAttr);
-        const char *pszAcronym;
+        const char *pszAcronym = poRegistrar->GetAttrAcronym(nAttrId);
 
-        if( nAttrId < 1 || nAttrId >= poRegistrar->GetMaxAttrIndex()
-            || (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL )
+        if( pszAcronym == NULL )
         {
             static int bAttrWarningIssued = FALSE;
 
@@ -2419,10 +2428,11 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
     {
         int     nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
 
-        if( apoFDefnByOBJL[nOBJL] != NULL )
+        if( nOBJL < (int)apoFDefnByOBJL.size() 
+            && apoFDefnByOBJL[nOBJL] != NULL )
             return apoFDefnByOBJL[nOBJL];
 
-        if( !poRegistrar->SelectClass( nOBJL ) )
+        if( !poClassContentExplorer->SelectClass( nOBJL ) )
         {
             for( int i = 0; i < nFDefnCount; i++ )
             {
@@ -2435,7 +2445,7 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
         for( int i = 0; i < nFDefnCount; i++ )
         {
             if( EQUAL(papoFDefnList[i]->GetName(),
-                      poRegistrar->GetAcronym()) )
+                      poClassContentExplorer->GetAcronym()) )
                 return papoFDefnList[i];
         }
 
@@ -2519,8 +2529,13 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
 
     if( poRegistrar != NULL )
     {
-        if( poRegistrar->SelectClass( poFDefn->GetName() ) )
-            apoFDefnByOBJL[poRegistrar->GetOBJL()] = poFDefn;
+        if( poClassContentExplorer->SelectClass( poFDefn->GetName() ) )
+        {
+            int nOBJL = poClassContentExplorer->GetOBJL();
+            if( nOBJL >= (int) apoFDefnByOBJL.size() )
+                apoFDefnByOBJL.resize(nOBJL+1);
+            apoFDefnByOBJL[nOBJL] = poFDefn;
+        }
     }
 }
 
@@ -2531,7 +2546,7 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
 /*      occur in this dataset.                                          */
 /************************************************************************/
 
-int S57Reader::CollectClassList(int *panClassCount, int nMaxClass )
+int S57Reader::CollectClassList(std::vector<int> &anClassCount)
 
 {
     int         bSuccess = TRUE;
@@ -2544,10 +2559,14 @@ int S57Reader::CollectClassList(int *panClassCount, int nMaxClass )
         DDFRecord *poRecord = oFE_Index.GetByIndex( iFEIndex );
         int     nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
 
-        if( nOBJL < 0 || nOBJL >= nMaxClass )
+        if( nOBJL < 0 )
             bSuccess = FALSE;
         else
-            panClassCount[nOBJL]++;
+        {
+            if( nOBJL >= (int) anClassCount.size() )
+                anClassCount.resize(nOBJL+1);
+            anClassCount[nOBJL]++;
+        }
 
     }
 
diff --git a/ogr/ogrsf_frmts/s57/s57writer.cpp b/ogr/ogrsf_frmts/s57/s57writer.cpp
index 5f45b24..6ee0c9c 100644
--- a/ogr/ogrsf_frmts/s57/s57writer.cpp
+++ b/ogr/ogrsf_frmts/s57/s57writer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57writer.cpp 25501 2013-01-14 19:05:28Z rouault $
+ * $Id: s57writer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Writer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57writer.cpp 25501 2013-01-14 19:05:28Z rouault $");
+CPL_CVSID("$Id: s57writer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                             S57Writer()                              */
@@ -43,6 +44,7 @@ S57Writer::S57Writer()
 {
     poModule = NULL;
     poRegistrar = NULL;
+    poClassContentExplorer = NULL;
 
     nCOMF = 10000000;
     nSOMF = 10;
@@ -864,7 +866,7 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     
     if( poRegistrar != NULL 
-        && poRegistrar->SelectClass( poFeature->GetDefnRef()->GetName() )
+        && poClassContentExplorer->SelectClass( poFeature->GetDefnRef()->GetName() )
         && !WriteATTF( poRec, poFeature ) )
         return FALSE;
 
@@ -963,10 +965,12 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 /*                           SetClassBased()                            */
 /************************************************************************/
 
-void S57Writer::SetClassBased( S57ClassRegistrar * poReg )
+void S57Writer::SetClassBased( S57ClassRegistrar * poReg,
+                               S57ClassContentExplorer* poClassContentExplorerIn )
 
 {
     poRegistrar = poReg;
+    poClassContentExplorer = poClassContentExplorerIn;
 }
 
 /************************************************************************/
@@ -984,7 +988,7 @@ int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Loop over all attributes.                                       */
 /* -------------------------------------------------------------------- */
-    papszAttrList = poRegistrar->GetAttributeList(NULL); 
+    papszAttrList = poClassContentExplorer->GetAttributeList(NULL); 
     
     for( int iAttr = 0; papszAttrList[iAttr] != NULL; iAttr++ )
     {
diff --git a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
index 96d0ff2..954f5da 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdelayer.cpp 24943 2012-09-20 12:03:38Z tamas $
+ * $Id: ogrsdelayer.cpp 26688 2013-12-02 19:07:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDELayer class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdelayer.cpp 24943 2012-09-20 12:03:38Z tamas $");
+CPL_CVSID("$Id: ogrsdelayer.cpp 26688 2013-12-02 19:07:41Z rouault $");
 
 /************************************************************************/
 /*                            OGRSDELayer()                             */
@@ -717,6 +717,9 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
 OGRErr OGRSDELayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( pszQuery == NULL )
         osAttributeFilter = "";
     else
diff --git a/ogr/ogrsf_frmts/sdts/ogr_sdts.h b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
index 1549ba6..90a0ef2 100644
--- a/ogr/ogrsf_frmts/sdts/ogr_sdts.h
+++ b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sdts.h 15583 2008-10-23 00:04:33Z warmerdam $
+ * $Id: ogr_sdts.h 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  STS Translator
  * Purpose:  Definition of classes finding SDTS support into OGRDriver
@@ -67,8 +67,6 @@ class OGRSDTSLayer : public OGRLayer
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
 //    int                 GetFeatureCount( int );
-
-    OGRSpatialReference *GetSpatialRef();
     
     int                 TestCapability( const char * );
 };
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
index 49776dc..4d05e7a 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdtslayer.cpp 25839 2013-04-02 18:54:20Z rouault $
+ * $Id: ogrsdtslayer.cpp 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  SDTSReader
  * Purpose:  Implements OGRSDTSLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdtslayer.cpp 25839 2013-04-02 18:54:20Z rouault $");
+CPL_CVSID("$Id: ogrsdtslayer.cpp 26466 2013-09-14 09:07:46Z rouault $");
 
 /************************************************************************/
 /*                            OGRSDTSLayer()                            */
@@ -59,6 +59,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
     poFeatureDefn =
         new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
     poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
 
     OGRFieldDefn oRecId( "RCID", OFTInteger );
     poFeatureDefn->AddFieldDefn( &oRecId );
@@ -473,14 +474,3 @@ int OGRSDTSLayer::TestCapability( const char * pszCap )
     else 
         return FALSE;
 }
-
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference * OGRSDTSLayer::GetSpatialRef()
-
-{
-    return poDS->GetSpatialRef();
-}
diff --git a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
index 6542518..99ec92e 100644
--- a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
+++ b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_segukooa.h 23220 2011-10-11 21:50:55Z rouault $
+ * $Id: ogr_segukooa.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Definition of classes for OGR SEG-P1 / UKOOA P1-90 driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -77,9 +77,6 @@ class OGRUKOOAP190Layer : public OGRSEGUKOOABaseLayer
 
 
     virtual void                ResetReading();
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 };
 
 /************************************************************************/
@@ -100,8 +97,6 @@ class OGRSEGUKOOALineLayer : public OGRSEGUKOOABaseLayer
                         ~OGRSEGUKOOALineLayer();
 
     virtual void                ResetReading();
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poBaseLayer->GetSpatialRef(); }
 };
 
 
@@ -129,8 +124,6 @@ class OGRSEGP1Layer: public OGRSEGUKOOABaseLayer
 
     virtual void                ResetReading();
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 public:
     static char* ExpandTabs(const char* pszLine);
     static int   DetectLatitudeColumn(const char* pzLine);
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
index a419035..fd470f8 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegukooadatasource.cpp 23259 2011-10-20 21:11:42Z rouault $
+ * $Id: ogrsegukooadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsegukooadatasource.cpp 23259 2011-10-20 21:11:42Z rouault $");
+CPL_CVSID("$Id: ogrsegukooadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRSEGUKOOADataSource()                       */
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
index b0f3cd9..6059419 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegukooadriver.cpp 23220 2011-10-11 21:50:55Z rouault $
+ * $Id: ogrsegukooadriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_segukooa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegukooadriver.cpp 23220 2011-10-11 21:50:55Z rouault $");
+CPL_CVSID("$Id: ogrsegukooadriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRSEGUKOOA();
 
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
index 7a4dedb..175279f 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $
+ * $Id: ogrsegukooalayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRUKOOAP190Layer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $");
+CPL_CVSID("$Id: ogrsegukooalayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ExtractField()                            */
@@ -137,6 +137,8 @@ OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
         CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
 
     ParseHeaders();
+
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
 
 /************************************************************************/
@@ -724,6 +726,7 @@ OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
                                                    CPLGetBasename(pszFilename)) );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbLineString );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poBaseLayer->GetSpatialRef());
 
     OGRFieldDefn    oField( "LINENAME", OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
diff --git a/ogr/ogrsf_frmts/segy/ogr_segy.h b/ogr/ogrsf_frmts/segy/ogr_segy.h
index d7fb72c..5613c1a 100644
--- a/ogr/ogrsf_frmts/segy/ogr_segy.h
+++ b/ogr/ogrsf_frmts/segy/ogr_segy.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_segy.h 23268 2011-10-22 09:50:46Z rouault $
+ * $Id: ogr_segy.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Definition of classes for OGR SEG-Y driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -76,7 +76,6 @@ typedef struct
 
 class OGRSEGYLayer: public OGRLayer
 {
-    OGRSpatialReference* poSRS;
     OGRFeatureDefn*    poFeatureDefn;
     int                bEOF;
     int                nNextFID;
@@ -97,8 +96,6 @@ class OGRSEGYLayer: public OGRLayer
 
     virtual void                ResetReading();
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * ) { return FALSE; }
@@ -128,8 +125,6 @@ class OGRSEGYHeaderLayer: public OGRLayer
 
     virtual void                ResetReading();
 
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
-
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * ) { return FALSE; }
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
index 9aa8f5c..65c5cac 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegydatasource.cpp 25280 2012-12-02 18:55:32Z rouault $
+ * $Id: ogrsegydatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYDataSource class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsegydatasource.cpp 25280 2012-12-02 18:55:32Z rouault $");
+CPL_CVSID("$Id: ogrsegydatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRSEGYDataSource()                       */
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
index ed7368d..8e58be4 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegydriver.cpp 23268 2011-10-22 09:50:46Z rouault $
+ * $Id: ogrsegydriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYDriver class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_segy.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegydriver.cpp 23268 2011-10-22 09:50:46Z rouault $");
+CPL_CVSID("$Id: ogrsegydriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRSEGYDriver()                           */
diff --git a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
index df7a5fc..297ecbf 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsegylayer.cpp 23292 2011-10-30 09:16:40Z rouault $
+ * $Id: ogrsegylayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegylayer.cpp 23292 2011-10-30 09:16:40Z rouault $");
+CPL_CVSID("$Id: ogrsegylayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define DT_IBM_4BYTES_FP         1
 #define DT_4BYTES_INT            2
@@ -233,7 +233,6 @@ OGRSEGYLayer::OGRSEGYLayer( const char* pszFilename,
     this->fp = fp;
     nNextFID = 0;
     bEOF = FALSE;
-    poSRS = NULL;
     memcpy(&sBFH, psBFH, sizeof(sBFH));
 
     nDataSize = 0;
@@ -286,9 +285,6 @@ OGRSEGYLayer::~OGRSEGYLayer()
     poFeatureDefn->Release();
 
     VSIFCloseL( fp );
-
-    if (poSRS)
-        poSRS->Release();
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/shape/dbfopen.c b/ogr/ogrsf_frmts/shape/dbfopen.c
index 69d8098..5ceda6d 100644
--- a/ogr/ogrsf_frmts/shape/dbfopen.c
+++ b/ogr/ogrsf_frmts/shape/dbfopen.c
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
@@ -996,7 +997,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 /* -------------------------------------------------------------------- */
 /*	Extract the requested field.					*/
 /* -------------------------------------------------------------------- */
-    strncpy( psDBF->pszWorkField,
+    memcpy( psDBF->pszWorkField,
 	     ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
 	     psDBF->panFieldSize[iField] );
     psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
@@ -1006,11 +1007,17 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 /* -------------------------------------------------------------------- */
 /*      Decode the field.                                               */
 /* -------------------------------------------------------------------- */
-    if( chReqType == 'N' )
+    if( chReqType == 'I' )
     {
-        psDBF->dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
+        psDBF->fieldValue.nIntField = atoi(psDBF->pszWorkField);
 
-	pReturnField = &(psDBF->dfDoubleField);
+        pReturnField = &(psDBF->fieldValue.nIntField);
+    }
+    else if( chReqType == 'N' )
+    {
+        psDBF->fieldValue.dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
+
+        pReturnField = &(psDBF->fieldValue.dfDoubleField);
     }
 
 /* -------------------------------------------------------------------- */
@@ -1047,14 +1054,14 @@ int SHPAPI_CALL
 DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
-    double	*pdValue;
+    int	*pnValue;
 
-    pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+    pnValue = (int *) DBFReadAttribute( psDBF, iRecord, iField, 'I' );
 
-    if( pdValue == NULL )
+    if( pnValue == NULL )
         return 0;
     else
-        return( (int) *pdValue );
+        return( *pnValue );
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/shape/drv_shapefile.html b/ogr/ogrsf_frmts/shape/drv_shapefile.html
index fad5a77..90d0151 100644
--- a/ogr/ogrsf_frmts/shape/drv_shapefile.html
+++ b/ogr/ogrsf_frmts/shape/drv_shapefile.html
@@ -56,11 +56,13 @@ any recoding. (Recoding support is new for GDAL/OGR 1.9.0)</p>
 attribute indexing.</p>
 
 <p>The spatial indexing uses the same .qix quadtree spatial index files that
-are used by UMN MapServer. Starting with OGR 1.10, it can also use the ESRI spatial index
-files (.sbn / .sbx).  Spatial indexing can accelerate spatially filtered
+are used by UMN MapServer. Spatial indexing can accelerate spatially filtered
 passes through large datasets to pick out a small area quite dramatically.</p>
 
-<p>To create a spatial index, issue a SQL command of the form</p>
+<p>Starting with OGR 1.10, it can also use the ESRI spatial index
+files (.sbn / .sbx), but writing them is not supported currently.</p> 
+
+<p>To create a spatial index (in .qix format), issue a SQL command of the form</p>
 <pre>CREATE SPATIAL INDEX ON tablename [DEPTH N]</pre>
 <p>where optional DEPTH specifier can be used to control number of index tree levels
 generated. If DEPTH is omitted, tree depth is estimated on basis of number of features
@@ -178,12 +180,20 @@ same applies for the deletion of a shape.</p>
 <h2>Size Issues</h2>
 
 <p>Geometry: The Shapefile format explicitly uses 32bit offsets and so cannot
-go over 8GB (it actually uses 32bit offsets to 16bit words).
-Hence, it is is not recommended to use a file size over 4GB.</p>
+go over 8GB (it actually uses 32bit offsets to 16bit words), but the OGR shapefile
+implementation has a limitation to 4GB.</p>
 
 <p>Attributes: The dbf format does not have any offsets in it, so it can be
 arbitrarily large.</p>
 
+<p>However, for compatibility with other software implementation, it is is not
+recommended to use a file size over 2GB for both .SHP and .DBF files.</p>
+
+<p>Starting with OGR 1.11, the 2GB_LIMIT=YES layer creation option can be used
+to strictly enforce that limit. For update mode, the SHAPE_2GB_LIMIT configuration option
+can be set to YES for similar effect. If nothing is set, a warning will be
+emitted when the 2GB limit is reached.</p>
+
 <h3>Dataset Creation Options</h3>
 
 <p>None</p>
@@ -202,8 +212,12 @@ values are not supported, nor are MULTIPATCH files.</li>
 default value is "LDID/87".  It is not clear what other values may be
 appropriate.</li>
 
-<li> <b>RESIZE=</b><i>yes/no</i>: (OGR >= 1.10.0) set the yes to resize fields to their optimal
-size. See above "Field sizes" section. Defaults to no.</li>
+<li> <b>RESIZE=</b><i>YES/NO</i>: (OGR >= 1.10.0) set the YES to resize fields to their optimal
+size. See above "Field sizes" section. Defaults to NO.</li>
+
+<li> <b>2GB_LIMIT=</b><i>YES/NO</i>: (OGR >= 1.11) set the YES to enforce the 2GB file size
+for .SHP or .DBF files. Defaults to NO.</li>
+
 </ul>
 
 <h3>VSI Virtual File System API support</h3>
diff --git a/ogr/ogrsf_frmts/shape/ogrshape.h b/ogr/ogrsf_frmts/shape/ogrshape.h
index c0bb408..299b696 100644
--- a/ogr/ogrsf_frmts/shape/ogrshape.h
+++ b/ogr/ogrsf_frmts/shape/ogrshape.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshape.h 25900 2013-04-11 20:24:31Z rouault $
+ * $Id: ogrshape.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the Shapefile driver to implement
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,6 +34,7 @@
 
 #include "ogrsf_frmts.h"
 #include "shapefil.h"
+#include "shp_vsi.h"
 #include "ogrlayerpool.h"
 #include <vector>
 
@@ -66,8 +68,7 @@ class OGRShapeDataSource;
 class OGRShapeLayer : public OGRAbstractProxiedLayer
 {
     OGRShapeDataSource  *poDS;
-    OGRSpatialReference *poSRS; /* lazy loaded --> use GetSpatialRef() */
-    int                 bSRSSet;
+
     OGRFeatureDefn     *poFeatureDefn;
     int                 iNextShapeId;
     int                 nTotalShapeCount;
@@ -120,7 +121,6 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
 
     void                TruncateDBF();
 
-
   protected:
 
     virtual void        CloseUnderlyingLayer();
@@ -173,8 +173,6 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-    
     virtual int         TestCapability( const char * );
     virtual void        SetSpatialFilter( OGRGeometry * );
     virtual OGRErr      SetAttributeFilter( const char * );
@@ -200,6 +198,8 @@ class OGRShapeDataSource : public OGRDataSource
     void                AddLayer(OGRShapeLayer* poLayer);
 
     std::vector<CPLString> oVectorLayerName;
+    
+    int                 b2GBLimit;
 
   public:
                         OGRShapeDataSource();
@@ -231,6 +231,9 @@ class OGRShapeDataSource : public OGRDataSource
 
     void                 SetLastUsedLayer( OGRShapeLayer* poLayer );
     void                 UnchainLayer( OGRShapeLayer* poLayer );
+
+    SHPHandle            DS_SHPOpen( const char * pszShapeFile, const char * pszAccess );
+    DBFHandle            DS_DBFOpen( const char * pszDBFFile, const char * pszAccess );
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
index 337aae0..1e62ff2 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapedatasource.cpp 25863 2013-04-05 20:19:51Z rouault $
+ * $Id: ogrshapedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,30 @@
 
 //#define IMMEDIATE_OPENING 1
 
-CPL_CVSID("$Id: ogrshapedatasource.cpp 25863 2013-04-05 20:19:51Z rouault $");
+CPL_CVSID("$Id: ogrshapedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+
+/************************************************************************/
+/*                          DS_SHPOpen()                                */
+/************************************************************************/
+
+SHPHandle OGRShapeDataSource::DS_SHPOpen( const char * pszShapeFile, const char * pszAccess )
+{
+    SHPHandle hSHP = SHPOpenLL( pszShapeFile, pszAccess, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
+    if( hSHP != NULL )
+        SHPSetFastModeReadObject( hSHP, TRUE );
+    return hSHP;
+}
+
+/************************************************************************/
+/*                           DS_DBFOpen()                               */
+/************************************************************************/
+
+DBFHandle OGRShapeDataSource::DS_DBFOpen( const char * pszDBFFile, const char * pszAccess )
+{
+    DBFHandle hDBF = DBFOpenLL( pszDBFFile, pszAccess, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
+    return hDBF;
+}
 
 /************************************************************************/
 /*                         OGRShapeDataSource()                         */
@@ -48,6 +72,7 @@ OGRShapeDataSource::OGRShapeDataSource()
     nLayers = 0;
     bSingleFileDataSource = FALSE;
     poPool = new OGRLayerPool();
+    b2GBLimit = CSLTestBoolean(CPLGetConfigOption("SHAPE_2GB_LIMIT", "FALSE"));
 }
 
 /************************************************************************/
@@ -288,9 +313,9 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
     CPLPushErrorHandler( CPLQuietErrorHandler );
     if( bUpdate )
-        hSHP = SHPOpen( pszNewName, "r+" );
+        hSHP = DS_SHPOpen( pszNewName, "r+" );
     else
-        hSHP = SHPOpen( pszNewName, "r" );
+        hSHP = DS_SHPOpen( pszNewName, "r" );
     CPLPopErrorHandler();
 
     if( hSHP == NULL 
@@ -314,26 +339,15 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     {
         if( bUpdate )
         {
-            hDBF = DBFOpen( pszNewName, "r+" );
+            hDBF = DS_DBFOpen( pszNewName, "r+" );
             if( hSHP != NULL && hDBF == NULL )
             {
-                VSIStatBufL sStat;
-                const char* pszDBFName = CPLResetExtension(pszNewName, "dbf");
-                VSILFILE* fp = NULL;
-                if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+                for(int i=0;i<2;i++)
                 {
-                    fp = VSIFOpenL(pszDBFName, "r+");
-                    if (fp == NULL)
-                    {
-                        CPLError( CE_Failure, CPLE_OpenFailed,
-                                "%s exists, but cannot be opened in update mode",
-                                pszDBFName );
-                        return FALSE;
-                    }
-                }
-                else
-                {
-                    pszDBFName = CPLResetExtension(pszNewName, "DBF");
+                    VSIStatBufL sStat;
+                    const char* pszDBFName = CPLResetExtension(pszNewName,
+                                                    (i == 0 ) ? "dbf" : "DBF");
+                    VSILFILE* fp = NULL;
                     if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
                     {
                         fp = VSIFOpenL(pszDBFName, "r+");
@@ -342,16 +356,17 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
                             CPLError( CE_Failure, CPLE_OpenFailed,
                                     "%s exists, but cannot be opened in update mode",
                                     pszDBFName );
+                            SHPClose(hSHP);
                             return FALSE;
                         }
+                        VSIFCloseL(fp);
+                        break;
                     }
                 }
-                if (fp != NULL)
-                    VSIFCloseL(fp);
             }
         }
         else
-            hDBF = DBFOpen( pszNewName, "r" );
+            hDBF = DS_DBFOpen( pszNewName, "r" );
     }
     else
         hDBF = NULL;
@@ -579,11 +594,13 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     char        *pszFilename;
 
+    int b2GBLimit = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" ));
+
     if( nShapeType != SHPT_NULL )
     {
         pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
 
-        hSHP = SHPCreate( pszFilename, nShapeType );
+        hSHP = SHPCreateLL( pszFilename, nShapeType, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
         
         if( hSHP == NULL )
         {
@@ -594,6 +611,9 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
             CPLFree( pszFilenameWithoutExt );
             return NULL;
         }
+        
+        SHPSetFastModeReadObject( hSHP, TRUE );
+
         CPLFree( pszFilename );
     }
     else
@@ -610,9 +630,9 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
     pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "dbf" ));
 
     if( pszLDID != NULL )
-        hDBF = DBFCreateEx( pszFilename, pszLDID );
+        hDBF = DBFCreateLL( pszFilename, pszLDID, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
     else
-        hDBF = DBFCreate( pszFilename );
+        hDBF = DBFCreateLL( pszFilename, "LDID/87",(SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
 
     if( hDBF == NULL )
     {
@@ -833,7 +853,14 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
             GetLayerByName( pszStatement + 7 );
 
         if( poLayer != NULL )
-            poLayer->Repack();
+        {
+            if( poLayer->Repack() != OGRERR_NONE )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "REPACK of layer '%s' failed.",
+                          pszStatement + 7 );
+            }
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined, 
diff --git a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
index abdb383..71bfd4e 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapelayer.cpp 25900 2013-04-11 20:24:31Z rouault $
+ * $Id: ogrshapelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,28 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrshapelayer.cpp 25900 2013-04-11 20:24:31Z rouault $");
+CPL_CVSID("$Id: ogrshapelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+
+class OGRShapeGeomFieldDefn: public OGRGeomFieldDefn
+{
+    char* pszFullName;
+    int   bSRSSet;
+
+    public:
+        OGRShapeGeomFieldDefn(const char* pszFullNameIn, OGRwkbGeometryType eType,
+                              int bSRSSetIn, OGRSpatialReference *poSRSIn) :
+            OGRGeomFieldDefn("", eType),
+            pszFullName(CPLStrdup(pszFullNameIn)),
+            bSRSSet(bSRSSetIn)
+        {
+            poSRS = poSRSIn;
+        }
+
+        virtual ~OGRShapeGeomFieldDefn() { CPLFree(pszFullName); }
+
+        virtual OGRSpatialReference* GetSpatialRef();
+};
 
 /************************************************************************/
 /*                           OGRShapeLayer()                            */
@@ -58,8 +80,6 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
 
 {
     poDS = poDSIn;
-    poSRS = poSRSIn;
-    bSRSSet = bSRSSetIn;
 
     pszFullName = CPLStrdup(pszFullNameIn);
     
@@ -132,6 +152,18 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
 
     poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszFullName),
                                            hSHP, hDBF, osEncoding );
+
+    /* To make sure that GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef() == GetSpatialRef() */
+    OGRwkbGeometryType eGeomType = poFeatureDefn->GetGeomType();
+    if( eGeomType != wkbNone )
+    {
+        OGRShapeGeomFieldDefn* poGeomFieldDefn =
+            new OGRShapeGeomFieldDefn(pszFullName, eGeomType, bSRSSetIn, poSRSIn);
+        poFeatureDefn->SetGeomType(wkbNone);
+        poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
+    }
+    else if( bSRSSetIn && poSRSIn != NULL )
+        poSRSIn->Release();
 }
 
 /************************************************************************/
@@ -161,9 +193,6 @@ OGRShapeLayer::~OGRShapeLayer()
     if( poFeatureDefn != NULL )
         poFeatureDefn->Release();
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     if( hDBF != NULL )
         DBFClose( hDBF );
 
@@ -716,7 +745,7 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
             {
                 if (DBFIsRecordDeleted( hDBF, iNextShapeId ))
                     poFeature = NULL;
-                else if( VSIFEofL((VSILFILE*)hDBF->fp) )
+                else if( VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)) )
                     return NULL; /* There's an I/O error */
                 else
                     poFeature = FetchShape(iNextShapeId /*, &oShapeExtent */);
@@ -892,6 +921,12 @@ OGRErr OGRShapeLayer::CreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
+    if( hDBF != NULL &&
+        !VSI_SHP_WriteMoreDataOK(hDBF->fp, hDBF->nRecordLength) )
+    {
+        return OGRERR_FAILURE;
+    }
+
     bHeaderDirty = TRUE;
     if( CheckForQIX() || CheckForSBN() )
         DropSpatialIndex();
@@ -1008,8 +1043,6 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
     SHPObject sShape;
     memset(&sShape, 0, sizeof(sShape));
 
-    VSILFILE* fpSHP = (VSILFILE*) hSHP->fpSHP;
-
     while( TRUE )
     {
         SHPObject* psShape = NULL;
@@ -1033,7 +1066,7 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
                 if (DBFIsRecordDeleted( hDBF, iShape ))
                     continue;
 
-                if (VSIFEofL((VSILFILE*)hDBF->fp))
+                if (VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)))
                     break;
             }
         }
@@ -1051,8 +1084,8 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
                     hSHP->panRecSize[iShape] > 4 + 8 * 4 )
         {
             GByte abyBuf[4 + 8 * 4];
-            if( VSIFSeekL( fpSHP, hSHP->panRecOffset[iShape] + 8, 0 ) == 0 &&
-                VSIFReadL( abyBuf, sizeof(abyBuf), 1, fpSHP ) == 1 )
+            if( hSHP->sHooks.FSeek( hSHP->fpSHP, hSHP->panRecOffset[iShape] + 8, 0 ) == 0 &&
+                hSHP->sHooks.FRead( abyBuf, sizeof(abyBuf), 1, hSHP->fpSHP ) == 1 )
             {
                 memcpy(&(sShape.nSHPType), abyBuf, 4);
                 CPL_LSBPTR32(&(sShape.nSHPType));
@@ -1779,7 +1812,7 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
 /*                           GetSpatialRef()                            */
 /************************************************************************/
 
-OGRSpatialReference *OGRShapeLayer::GetSpatialRef()
+OGRSpatialReference *OGRShapeGeomFieldDefn::GetSpatialRef()
 
 {
     if (bSRSSet)
@@ -2115,7 +2148,7 @@ OGRErr OGRShapeLayer::Repack()
             }
             panRecordsToDelete[nDeleteCount++] = iShape;
         }
-        if( VSIFEofL((VSILFILE*)hDBF->fp) )
+        if( VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)) )
         {
             CPLFree( panRecordsToDelete );
             return OGRERR_FAILURE; /* There's an I/O error */
@@ -2222,6 +2255,18 @@ OGRErr OGRShapeLayer::Repack()
         return OGRERR_FAILURE;
     }
 
+    /* Delete temporary .cpg file if existing */
+    if( osCPGName.size() )
+    {
+        CPLString oCPGTempFile = CPLFormFilename(osDirname, osBasename, NULL);
+        oCPGTempFile += "_packed.cpg";
+        if( VSIUnlink( oCPGTempFile ) != 0 )
+        {
+            CPLDebug( "Shape", "Did not manage to remove temporary .cpg file: %s",
+                      VSIStrerror( errno ) );
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Copy over all records that are not deleted.                     */
 /* -------------------------------------------------------------------- */
@@ -2248,6 +2293,7 @@ OGRErr OGRShapeLayer::Repack()
     {
         CPLFree( panRecordsToDelete );
         VSIUnlink( oTempFile );
+        DBFClose( hNewDBF );
         return eErr;
     }
 
@@ -2257,8 +2303,18 @@ OGRErr OGRShapeLayer::Repack()
     DBFClose( hDBF );
     DBFClose( hNewDBF );
     hDBF = hNewDBF = NULL;
-    
-    VSIUnlink( osDBFName );
+
+    if( VSIUnlink( osDBFName ) != 0 )
+    {
+        CPLDebug( "Shape", "Failed to delete DBF file: %s", VSIStrerror( errno ) );
+        CPLFree( panRecordsToDelete );
+
+        hDBF = poDS->DS_DBFOpen ( osDBFName, bUpdateAccess ? "r+" : "r" );
+
+        VSIUnlink( oTempFile );
+
+        return OGRERR_FAILURE;
+    }
         
     if( VSIRename( oTempFile, osDBFName ) != 0 )
     {
@@ -2267,18 +2323,6 @@ OGRErr OGRShapeLayer::Repack()
         return OGRERR_FAILURE;
     }
 
-    /* Delete temporary .cpg file if existing */
-    if( osCPGName.size() )
-    {
-        oTempFile = CPLFormFilename(osDirname, osBasename, NULL);
-        oTempFile += "_packed.cpg";
-        if( VSIUnlink( oTempFile ) != 0 )
-        {
-            CPLDebug( "Shape", "Did not manage to remove temporary .cpg file: %s",
-                      VSIStrerror( errno ) );
-        }
-    }
-
 /* -------------------------------------------------------------------- */
 /*      Now create a shapefile matching the old one.                    */
 /* -------------------------------------------------------------------- */
@@ -2329,6 +2373,7 @@ OGRErr OGRShapeLayer::Repack()
             CPLFree( panRecordsToDelete );
             VSIUnlink( CPLResetExtension( oTempFile, "shp" ) );
             VSIUnlink( CPLResetExtension( oTempFile, "shx" ) );
+            SHPClose( hNewSHP );
             return eErr;
         }
 
@@ -2380,8 +2425,8 @@ OGRErr OGRShapeLayer::Repack()
         pszAccess = "r";
     
     if( bMustReopenSHP )
-        hSHP = SHPOpen ( osSHPName , pszAccess );
-    hDBF = DBFOpen ( osDBFName , pszAccess );
+        hSHP = poDS->DS_SHPOpen ( osSHPName , pszAccess );
+    hDBF = poDS->DS_DBFOpen ( osDBFName , pszAccess );
 
     if( (bMustReopenSHP && NULL == hSHP) || NULL == hDBF )
         return OGRERR_FAILURE;
@@ -2528,9 +2573,8 @@ void OGRShapeLayer::TruncateDBF()
     if (hDBF == NULL)
         return;
 
-    VSILFILE* fp = (VSILFILE*)(hDBF->fp);
-    VSIFSeekL(fp, 0, SEEK_END);
-    vsi_l_offset nOldSize = VSIFTellL(fp);
+    hDBF->sHooks.FSeek(hDBF->fp, 0, SEEK_END);
+    vsi_l_offset nOldSize = hDBF->sHooks.FTell(hDBF->fp);
     vsi_l_offset nNewSize = hDBF->nRecordLength * (SAOffset) hDBF->nRecords
                             + hDBF->nHeaderLength;
     if (nNewSize < nOldSize)
@@ -2538,9 +2582,9 @@ void OGRShapeLayer::TruncateDBF()
         CPLDebug("SHAPE",
                  "Truncating DBF file from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB " bytes",
                  nOldSize, nNewSize);
-        VSIFTruncateL(fp, nNewSize);
+        VSIFTruncateL(VSI_SHP_GetVSIL(hDBF->fp), nNewSize);
     }
-    VSIFSeekL(fp, 0, SEEK_SET);
+    hDBF->sHooks.FSeek(hDBF->fp, 0, SEEK_SET);
 }
 
 /************************************************************************/
@@ -2590,20 +2634,28 @@ OGRErr OGRShapeLayer::RecomputeExtent()
                     bHasBeenInit = TRUE;
                     adBoundsMin[0] = adBoundsMax[0] = psObject->padfX[0];
                     adBoundsMin[1] = adBoundsMax[1] = psObject->padfY[0];
-                    adBoundsMin[2] = adBoundsMax[2] = psObject->padfZ[0];
-                    adBoundsMin[3] = adBoundsMax[3] = psObject->padfM[0];
+                    if( psObject->padfZ )
+                        adBoundsMin[2] = adBoundsMax[2] = psObject->padfZ[0];
+                    if( psObject->padfM )
+                        adBoundsMin[3] = adBoundsMax[3] = psObject->padfM[0];
                 }
 
                 for( int i = 0; i < psObject->nVertices; i++ )
                 {
                     adBoundsMin[0] = MIN(adBoundsMin[0],psObject->padfX[i]);
                     adBoundsMin[1] = MIN(adBoundsMin[1],psObject->padfY[i]);
-                    adBoundsMin[2] = MIN(adBoundsMin[2],psObject->padfZ[i]);
-                    adBoundsMin[3] = MIN(adBoundsMin[3],psObject->padfM[i]);
                     adBoundsMax[0] = MAX(adBoundsMax[0],psObject->padfX[i]);
                     adBoundsMax[1] = MAX(adBoundsMax[1],psObject->padfY[i]);
-                    adBoundsMax[2] = MAX(adBoundsMax[2],psObject->padfZ[i]);
-                    adBoundsMax[3] = MAX(adBoundsMax[3],psObject->padfM[i]);
+                    if( psObject->padfZ )
+                    {
+                        adBoundsMin[2] = MIN(adBoundsMin[2],psObject->padfZ[i]);
+                        adBoundsMax[2] = MAX(adBoundsMax[2],psObject->padfZ[i]);
+                    }
+                    if( psObject->padfM )
+                    {
+                        adBoundsMax[3] = MAX(adBoundsMax[3],psObject->padfM[i]);
+                        adBoundsMin[3] = MIN(adBoundsMin[3],psObject->padfM[i]);
+                    }
                 }
             }
             SHPDestroyObject(psObject);
@@ -2650,9 +2702,9 @@ int OGRShapeLayer::ReopenFileDescriptors()
     if( bHSHPWasNonNULL )
     {
         if( bUpdateAccess )
-            hSHP = SHPOpen( pszFullName, "r+" );
+            hSHP = poDS->DS_SHPOpen( pszFullName, "r+" );
         else
-            hSHP = SHPOpen( pszFullName, "r" );
+            hSHP = poDS->DS_SHPOpen( pszFullName, "r" );
 
         if (hSHP == NULL)
         {
@@ -2664,9 +2716,9 @@ int OGRShapeLayer::ReopenFileDescriptors()
     if( bHDBFWasNonNULL )
     {
         if( bUpdateAccess )
-            hDBF = DBFOpen( pszFullName, "r+" );
+            hDBF = poDS->DS_DBFOpen( pszFullName, "r+" );
         else
-            hDBF = DBFOpen( pszFullName, "r" );
+            hDBF = poDS->DS_DBFOpen( pszFullName, "r" );
 
         if (hDBF == NULL)
         {
diff --git a/ogr/ogrsf_frmts/shape/sbnsearch.c b/ogr/ogrsf_frmts/shape/sbnsearch.c
index cea8206..8592c06 100644
--- a/ogr/ogrsf_frmts/shape/sbnsearch.c
+++ b/ogr/ogrsf_frmts/shape/sbnsearch.c
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: sbnsearch.c 25862 2013-04-05 10:06:06Z rouault $
+ * $Id: sbnsearch.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of search in ESRI SBN spatial index.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
@@ -40,7 +40,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-SHP_CVSID("$Id: sbnsearch.c 25862 2013-04-05 10:06:06Z rouault $")
+SHP_CVSID("$Id: sbnsearch.c 27044 2014-03-16 23:41:27Z rouault $")
 
 #ifndef TRUE
 #  define TRUE 1
@@ -245,10 +245,10 @@ SBNSearchHandle SBNOpenDiskTree( const char* pszSBNFilename,
 /* -------------------------------------------------------------------- */
 /*      Compute tree depth.                                             */
 /*      It is computed such as in average there are not more than 8     */
-/*      shapes per node. With a minimum depth of 2, and a maximum of 15 */
+/*      shapes per node. With a minimum depth of 2, and a maximum of 24 */
 /* -------------------------------------------------------------------- */
     nMaxDepth = 2;
-    while( nMaxDepth < 15 && nShapeCount > ((1 << nMaxDepth) - 1) * 8 )
+    while( nMaxDepth < 24 && nShapeCount > ((1 << nMaxDepth) - 1) * 8 )
         nMaxDepth ++;
     hSBN->nMaxDepth = nMaxDepth;
     nMaxNodes = (1 << nMaxDepth) - 1;
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index bbdac86..fb58ea9 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shape2ogr.cpp 26116 2013-06-29 18:57:36Z rouault $
+ * $Id: shape2ogr.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements translation of Shapefile shapes into OGR
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "ogrshape.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: shape2ogr.cpp 26116 2013-06-29 18:57:36Z rouault $");
+CPL_CVSID("$Id: shape2ogr.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
diff --git a/ogr/ogrsf_frmts/shape/shapefil.h b/ogr/ogrsf_frmts/shape/shapefil.h
index a16bee2..3232f14 100644
--- a/ogr/ogrsf_frmts/shape/shapefil.h
+++ b/ogr/ogrsf_frmts/shape/shapefil.h
@@ -2,7 +2,7 @@
 #define SHAPEFILE_H_INCLUDED
 
 /******************************************************************************
- * $Id: shapefil.h 24607 2012-06-24 19:18:48Z rouault $
+ * $Id: shapefil.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
@@ -273,7 +274,9 @@ void SHPAPI_CALL SASetupUtf8Hooks( SAHooks *psHooks );
 /************************************************************************/
 /*                             SHP Support.                             */
 /************************************************************************/
-typedef	struct
+typedef struct tagSHPObject SHPObject;
+
+typedef struct
 {
     SAHooks sHooks;
 
@@ -296,6 +299,11 @@ typedef	struct
 
     unsigned char *pabyRec;
     int         nBufSize;
+    
+    int            bFastModeReadObject;
+    unsigned char *pabyObjectBuf;
+    int            nObjectBufSize;
+    SHPObject*     psCachedObject;
 } SHPInfo;
 
 typedef SHPInfo * SHPHandle;
@@ -335,7 +343,7 @@ typedef SHPInfo * SHPHandle;
 /*      SHPObject - represents on shape (without attributes) read       */
 /*      from the .shp file.                                             */
 /* -------------------------------------------------------------------- */
-typedef struct
+struct tagSHPObject
 {
     int		nSHPType;
 
@@ -362,7 +370,8 @@ typedef struct
     double	dfMMax;
 
     int		bMeasureIsUsed;
-} SHPObject;
+    int     bFastModeReadObject;
+};
 
 /* -------------------------------------------------------------------- */
 /*      SHP API Prototypes                                              */
@@ -375,6 +384,13 @@ SHPHandle SHPAPI_CALL
 SHPHandle SHPAPI_CALL
       SHPOpenLL( const char *pszShapeFile, const char *pszAccess, 
                  SAHooks *psHooks );
+
+/* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
+/* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
+/* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
+/* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
+void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode );
+
 SHPHandle SHPAPI_CALL
       SHPCreate( const char * pszShapeFile, int nShapeType );
 SHPHandle SHPAPI_CALL
@@ -559,7 +575,11 @@ typedef	struct
     int		bNoHeader;
     int		bUpdated;
 
-    double      dfDoubleField;
+    union
+    {
+        double      dfDoubleField;
+        int         nIntField;
+    } fieldValue;
 
     int         iLanguageDriver;
     char        *pszCodePage;
diff --git a/ogr/ogrsf_frmts/shape/shp_vsi.c b/ogr/ogrsf_frmts/shape/shp_vsi.c
index e1827e6..a6f0ab1 100644
--- a/ogr/ogrsf_frmts/shape/shp_vsi.c
+++ b/ogr/ogrsf_frmts/shape/shp_vsi.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shp_vsi.c 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: shp_vsi.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  IO Redirection via VSI services for shp/dbf io.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007,  Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,89 +28,195 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "shapefil.h"
-#include "cpl_vsi.h"
+#include "shp_vsi.h"
 #include "cpl_error.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: shp_vsi.c 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: shp_vsi.c 27044 2014-03-16 23:41:27Z rouault $");
+
+typedef struct
+{
+    VSILFILE *fp;
+    char     *pszFilename;
+    int       bEnforce2GBLimit;
+    int       bHasWarned2GB;
+    SAOffset  nCurOffset;
+} OGRSHPDBFFile;
+
+/************************************************************************/
+/*                         VSI_SHP_GetVSIL()                            */
+/************************************************************************/
+
+VSILFILE* VSI_SHP_GetVSIL( SAFile file )
+{
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    return pFile->fp;
+}
+
+/************************************************************************/
+/*                         VSI_SHP_OpenInternal()                       */
+/************************************************************************/
+
+static
+SAFile VSI_SHP_OpenInternal( const char *pszFilename, const char *pszAccess,
+                             int bEnforce2GBLimit )
+
+{
+    OGRSHPDBFFile* pFile;
+    VSILFILE* fp = VSIFOpenL( pszFilename, pszAccess );
+    if( fp == NULL )
+        return NULL;
+    pFile = (OGRSHPDBFFile* )CPLCalloc(1,sizeof(OGRSHPDBFFile));
+    pFile->fp = fp;
+    pFile->pszFilename = CPLStrdup(pszFilename);
+    pFile->bEnforce2GBLimit = bEnforce2GBLimit;
+    pFile->nCurOffset = 0;
+    return (SAFile) pFile;
+}
 
 /************************************************************************/
 /*                            VSI_SHP_Open()                            */
 /************************************************************************/
 
+static
 SAFile VSI_SHP_Open( const char *pszFilename, const char *pszAccess )
 
 {
-    return (SAFile) VSIFOpenL( pszFilename, pszAccess );
+    return VSI_SHP_OpenInternal(pszFilename, pszAccess, FALSE);
+}
+
+/************************************************************************/
+/*                        VSI_SHP_Open2GBLimit()                        */
+/************************************************************************/
+
+static
+SAFile VSI_SHP_Open2GBLimit( const char *pszFilename, const char *pszAccess )
+
+{
+    return VSI_SHP_OpenInternal(pszFilename, pszAccess, TRUE);
 }
 
 /************************************************************************/
 /*                            VSI_SHP_Read()                            */
 /************************************************************************/
 
+static
 SAOffset VSI_SHP_Read( void *p, SAOffset size, SAOffset nmemb, SAFile file )
 
 {
-    return (SAOffset) VSIFReadL( p, (size_t) size, (size_t) nmemb, 
-                                 (VSILFILE *) file );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    SAOffset ret = (SAOffset) VSIFReadL( p, (size_t) size, (size_t) nmemb, 
+                                 pFile->fp );
+    pFile->nCurOffset += ret * size;
+    return ret;
+}
+
+/************************************************************************/
+/*                      VSI_SHP_WriteMoreDataOK()                       */
+/************************************************************************/
+
+int VSI_SHP_WriteMoreDataOK( SAFile file, SAOffset nExtraBytes )
+{
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    if( pFile->nCurOffset + nExtraBytes > 0x7FFFFFFF )
+    {
+        if( pFile->bEnforce2GBLimit )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "2GB file size limit reached for %s",
+                      pFile->pszFilename );
+            return FALSE;
+        }
+        else if( !pFile->bHasWarned2GB )
+        {
+            pFile->bHasWarned2GB = TRUE;
+            CPLError( CE_Warning, CPLE_AppDefined, "2GB file size limit reached for %s. "
+                      "Going on, but might cause compatibility issues with third party software",
+                      pFile->pszFilename );
+        }
+    }
+
+    return TRUE;
 }
 
 /************************************************************************/
 /*                           VSI_SHP_Write()                            */
 /************************************************************************/
 
+static
 SAOffset VSI_SHP_Write( void *p, SAOffset size, SAOffset nmemb, SAFile file )
 
 {
-    return (SAOffset) VSIFWriteL( p, (size_t) size, (size_t) nmemb, 
-                                  (VSILFILE *) file );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    SAOffset ret;
+    if( !VSI_SHP_WriteMoreDataOK( file, size * nmemb ) )
+        return 0;
+    ret = (SAOffset) VSIFWriteL( p, (size_t) size, (size_t) nmemb, 
+                                  pFile->fp );
+    pFile->nCurOffset += ret * size;
+    return ret;
 }
 
 /************************************************************************/
 /*                            VSI_SHP_Seek()                            */
 /************************************************************************/
 
+static
 SAOffset VSI_SHP_Seek( SAFile file, SAOffset offset, int whence )
 
 {
-    return (SAOffset) VSIFSeekL( (VSILFILE *) file, (vsi_l_offset) offset, whence );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    SAOffset ret = (SAOffset) VSIFSeekL( pFile->fp, (vsi_l_offset) offset, whence );
+    if( whence == 0 && ret == 0)
+        pFile->nCurOffset = offset;
+    else
+        pFile->nCurOffset = (SAOffset) VSIFTellL( pFile->fp );
+    return ret;
 }
 
 /************************************************************************/
 /*                            VSI_SHP_Tell()                            */
 /************************************************************************/
 
+static
 SAOffset VSI_SHP_Tell( SAFile file )
 
 {
-    return (SAOffset) VSIFTellL( (VSILFILE *) file );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    return (SAOffset) pFile->nCurOffset;
 }
 
 /************************************************************************/
 /*                           VSI_SHP_Flush()                            */
 /************************************************************************/
 
+static
 int VSI_SHP_Flush( SAFile file )
 
 {
-    return VSIFFlushL( (VSILFILE *) file );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    return VSIFFlushL( pFile->fp );
 }
 
 /************************************************************************/
 /*                           VSI_SHP_Close()                            */
 /************************************************************************/
 
+static
 int VSI_SHP_Close( SAFile file )
 
 {
-    return VSIFCloseL( (VSILFILE *) file );
+    OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
+    int ret = VSIFCloseL( pFile->fp );
+    CPLFree(pFile->pszFilename);
+    CPLFree(pFile);
+    return ret;
 }
 
 /************************************************************************/
 /*                              SADError()                              */
 /************************************************************************/
 
+static
 void VSI_SHP_Error( const char *message )
 
 {
@@ -120,6 +227,7 @@ void VSI_SHP_Error( const char *message )
 /*                           VSI_SHP_Remove()                           */
 /************************************************************************/
 
+static
 int VSI_SHP_Remove( const char *pszFilename )
 
 {
@@ -140,9 +248,45 @@ void SASetupDefaultHooks( SAHooks *psHooks )
     psHooks->FTell   = VSI_SHP_Tell;
     psHooks->FFlush  = VSI_SHP_Flush;
     psHooks->FClose  = VSI_SHP_Close;
-
     psHooks->Remove  = VSI_SHP_Remove;
-    psHooks->Atof    = CPLAtof;
 
     psHooks->Error   = VSI_SHP_Error;
+    psHooks->Atof    = CPLAtof;
+}
+
+/************************************************************************/
+/*                         VSI_SHP_GetHook()                            */
+/************************************************************************/
+
+static const SAHooks sOGRHook =
+{
+    VSI_SHP_Open,
+    VSI_SHP_Read,
+    VSI_SHP_Write,
+    VSI_SHP_Seek,
+    VSI_SHP_Tell,
+    VSI_SHP_Flush,
+    VSI_SHP_Close,
+    VSI_SHP_Remove,
+    VSI_SHP_Error,
+    CPLAtof
+};
+
+static const SAHooks sOGRHook2GBLimit =
+{
+    VSI_SHP_Open2GBLimit,
+    VSI_SHP_Read,
+    VSI_SHP_Write,
+    VSI_SHP_Seek,
+    VSI_SHP_Tell,
+    VSI_SHP_Flush,
+    VSI_SHP_Close,
+    VSI_SHP_Remove,
+    VSI_SHP_Error,
+    CPLAtof
+};
+
+const SAHooks* VSI_SHP_GetHook(int b2GBLimit)
+{
+    return (b2GBLimit) ? &sOGRHook2GBLimit : &sOGRHook;
 }
diff --git a/ogr/ogrsf_frmts/shape/shp_vsi.h b/ogr/ogrsf_frmts/shape/shp_vsi.h
new file mode 100644
index 0000000..5cec121
--- /dev/null
+++ b/ogr/ogrsf_frmts/shape/shp_vsi.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * $Id: shp_vsi.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  IO Redirection via VSI services for shp/dbf io.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2007,  Frank Warmerdam
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef SHP_VSI_H_INCLUDED
+#define SHP_VSI_H_INCLUDED
+
+#include "cpl_vsi.h"
+#include "shapefil.h"
+
+CPL_C_START
+
+const SAHooks* VSI_SHP_GetHook(int b2GBLimit);
+
+VSILFILE* VSI_SHP_GetVSIL( SAFile file );
+int VSI_SHP_WriteMoreDataOK( SAFile file, SAOffset nExtraBytes );
+
+CPL_C_END
+
+#endif /* SHP_VSI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/shape/shpopen.c b/ogr/ogrsf_frmts/shape/shpopen.c
index ee9fce5..ec1b0dd 100644
--- a/ogr/ogrsf_frmts/shape/shpopen.c
+++ b/ogr/ogrsf_frmts/shape/shpopen.c
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, 2001, Frank Warmerdam
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
@@ -300,8 +301,13 @@ typedef unsigned int	      int32;
 #  endif
 #endif
 
+#if defined(CPL_LSB)
+#define bBigEndian FALSE
+#elif defined(CPL_MSB)
+#define bBigEndian TRUE
+#else
 static int 	bBigEndian;
-
+#endif
 
 /************************************************************************/
 /*                              SwapWord()                              */
@@ -513,11 +519,13 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*	Establish the byte order on this machine.			*/
 /* -------------------------------------------------------------------- */
+#if !defined(bBigEndian)
     i = 1;
     if( *((uchar *) &i) == 1 )
         bBigEndian = FALSE;
     else
         bBigEndian = TRUE;
+#endif
 
 /* -------------------------------------------------------------------- */
 /*	Initialize the info structure.					*/
@@ -795,10 +803,41 @@ SHPClose(SHPHandle psSHP )
         free( psSHP->pabyRec );
     }
     
+    if( psSHP->pabyObjectBuf != NULL )
+    {
+        free( psSHP->pabyObjectBuf );
+    }
+    if( psSHP->psCachedObject != NULL )
+    {
+        free( psSHP->psCachedObject );
+    }
+    
     free( psSHP );
 }
 
 /************************************************************************/
+/*                    SHPSetFastModeReadObject()                        */
+/************************************************************************/
+
+/* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
+/* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
+/* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
+/* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
+void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode )
+{
+    if( bFastMode )
+    {
+        if( hSHP->psCachedObject == NULL )
+        {
+            hSHP->psCachedObject = (SHPObject*) calloc(1, sizeof(SHPObject));
+            assert( hSHP->psCachedObject != NULL );
+        }
+    }
+
+    hSHP->bFastModeReadObject = bFastMode;
+}
+
+/************************************************************************/
 /*                             SHPGetInfo()                             */
 /*                                                                      */
 /*      Fetch general information about the shape file.                 */
@@ -868,11 +907,13 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*      Establish the byte order on this system.                        */
 /* -------------------------------------------------------------------- */
+#if !defined(bBigEndian)
     i = 1;
     if( *((uchar *) &i) == 1 )
         bBigEndian = FALSE;
     else
         bBigEndian = TRUE;
+#endif
 
 /* -------------------------------------------------------------------- */
 /*	Compute the base (layer) name.  If there is any extension	*/
@@ -1186,6 +1227,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     int i;
     uchar	*pabyRec;
     int32	i32;
+    int     bExtendFile = FALSE;
 
     psSHP->bUpdated = TRUE;
 
@@ -1479,23 +1521,18 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
             return -1;
         }
 
-        if( nShapeId == -1 )
-            nShapeId = psSHP->nRecords++;
-
-        psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
-        psSHP->panRecSize[nShapeId] = nRecordSize-8;
-        psSHP->nFileSize += nRecordSize;
+        bExtendFile = TRUE;
+        nRecordOffset = psSHP->nFileSize;
     }
     else
     {
         nRecordOffset = psSHP->panRecOffset[nShapeId];
-        psSHP->panRecSize[nShapeId] = nRecordSize-8;
     }
     
 /* -------------------------------------------------------------------- */
 /*      Set the shape type, record number, and record size.             */
 /* -------------------------------------------------------------------- */
-    i32 = nShapeId+1;					/* record # */
+    i32 = (nShapeId < 0) ? psSHP->nRecords+1 : nShapeId+1;					/* record # */
     if( !bBigEndian ) SwapWord( 4, &i32 );
     ByteCopy( &i32, pabyRec, 4 );
 
@@ -1525,6 +1562,16 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     
     free( pabyRec );
 
+    if( bExtendFile )
+    {
+        if( nShapeId == -1 )
+            nShapeId = psSHP->nRecords++;
+
+        psSHP->panRecOffset[nShapeId] = psSHP->nFileSize;
+        psSHP->nFileSize += nRecordSize;
+    }
+    psSHP->panRecSize[nShapeId] = nRecordSize-8;
+
 /* -------------------------------------------------------------------- */
 /*	Expand file wide bounds based on this shape.			*/
 /* -------------------------------------------------------------------- */
@@ -1544,8 +1591,8 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         {
             psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
             psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
-            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
-            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ ? psObject->padfZ[0] : 0.0;
+            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM ? psObject->padfM[0] : 0.0;
         }
     }
 
@@ -1553,18 +1600,69 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     {
         psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
         psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
-        psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
-        psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
         psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
         psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
-        psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
-        psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+        if( psObject->padfZ )
+        {
+            psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
+            psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+        }
+        if( psObject->padfM )
+        {
+            psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
+            psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+        }
     }
 
     return( nShapeId  );
 }
 
 /************************************************************************/
+/*                         SHPAllocBuffer()                             */
+/************************************************************************/
+
+static void* SHPAllocBuffer(unsigned char** pBuffer, int nSize)
+{
+    unsigned char* pRet;
+
+    if( pBuffer == NULL )
+        return calloc(1, nSize);
+
+    pRet = *pBuffer;
+    if( pRet == NULL )
+        return NULL;
+
+    (*pBuffer) += nSize;
+    return pRet;
+}
+
+/************************************************************************/
+/*                    SHPReallocObjectBufIfNecessary()                  */
+/************************************************************************/
+
+static unsigned char* SHPReallocObjectBufIfNecessary ( SHPHandle psSHP,
+                                                       int nObjectBufSize )
+{
+    unsigned char* pBuffer;
+    if( nObjectBufSize == 0 )
+    {
+        nObjectBufSize = 4 * sizeof(double);
+    }
+    if( nObjectBufSize > psSHP->nObjectBufSize )
+    {
+        pBuffer = (unsigned char*) realloc( psSHP->pabyObjectBuf, nObjectBufSize );
+        if( pBuffer != NULL )
+        {
+            psSHP->pabyObjectBuf = pBuffer;
+            psSHP->nObjectBufSize = nObjectBufSize;
+        }
+    }
+    else
+        pBuffer = psSHP->pabyObjectBuf;
+    return pBuffer;
+}
+
+/************************************************************************/
 /*                          SHPReadObject()                             */
 /*                                                                      */
 /*      Read the vertices, parts, and other non-attribute information	*/
@@ -1578,6 +1676,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     int                  nEntitySize, nRequiredSize;
     SHPObject           *psShape;
     char                 szErrorMsg[128];
+    int                  nSHPType;
 
 /* -------------------------------------------------------------------- */
 /*      Validate the record/entity number.                              */
@@ -1649,25 +1748,39 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*	Allocate and minimally initialize the object.			*/
-/* -------------------------------------------------------------------- */
-    psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
-    psShape->nShapeId = hEntity;
-    psShape->bMeasureIsUsed = FALSE;
-
     if ( 8 + 4 > nEntitySize )
     {
         snprintf(szErrorMsg, sizeof(szErrorMsg),
                  "Corrupted .shp file : shape %d : nEntitySize = %d",
                  hEntity, nEntitySize); 
         psSHP->sHooks.Error( szErrorMsg );
-        SHPDestroyObject(psShape);
         return NULL;
     }
-    memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+    memcpy( &nSHPType, psSHP->pabyRec + 8, 4 );
+
+    if( bBigEndian ) SwapWord( 4, &(nSHPType) );
+
+/* -------------------------------------------------------------------- */
+/*	Allocate and minimally initialize the object.			*/
+/* -------------------------------------------------------------------- */
+    if( psSHP->bFastModeReadObject )
+    {
+        if( psSHP->psCachedObject->bFastModeReadObject )
+        {
+            psSHP->sHooks.Error( "Invalid read pattern in fast read mode. "
+                                 "SHPDestroyObject() should be called." );
+            return NULL;
+        }
 
-    if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
+        psShape = psSHP->psCachedObject;
+        memset(psShape, 0, sizeof(SHPObject));
+    }
+    else
+        psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
+    psShape->nShapeId = hEntity;
+    psShape->nSHPType = nSHPType;
+    psShape->bMeasureIsUsed = FALSE;
+    psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
 
 /* ==================================================================== */
 /*  Extract vertices for a Polygon or Arc.				*/
@@ -1681,6 +1794,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         int32		nPoints, nParts;
         int    		i, nOffset;
+        unsigned char* pBuffer = NULL;
+        unsigned char** ppBuffer = NULL;
 
         if ( 40 + 8 + 4 > nEntitySize )
         {
@@ -1749,16 +1864,23 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             return NULL;
         }
 
+        if( psShape->bFastModeReadObject )
+        {
+            int nObjectBufSize = 4 * sizeof(double) * nPoints + 2 * sizeof(int) * nParts;
+            pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
+            ppBuffer = &pBuffer;
+        }
+
         psShape->nVertices = nPoints;
-        psShape->padfX = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfY = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+        psShape->padfX = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfY = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfZ = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfM = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
 
         psShape->nParts = nParts;
-        psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
-        psShape->panPartType = (int *) calloc(nParts,sizeof(int));
-        
+        psShape->panPartStart = (int *) SHPAllocBuffer(ppBuffer, nParts * sizeof(int));
+        psShape->panPartType = (int *) SHPAllocBuffer(ppBuffer, nParts * sizeof(int));
+
         if (psShape->padfX == NULL ||
             psShape->padfY == NULL ||
             psShape->padfZ == NULL ||
@@ -1767,8 +1889,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->panPartType == NULL)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
-                     "Probably broken SHP file", hEntity, nPoints, nParts );
+                    "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
+                    "Probably broken SHP file", hEntity, nPoints, nParts );
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -1865,6 +1987,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
             nOffset += 16 + 8*nPoints;
         }
+        else if( psShape->bFastModeReadObject )
+        {
+            psShape->padfZ = NULL;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If we have a M measure value, then read it now.  We assume      */
@@ -1888,6 +2014,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             }
             psShape->bMeasureIsUsed = TRUE;
         }
+        else if( psShape->bFastModeReadObject )
+        {
+            psShape->padfM = NULL;
+        }
     }
 
 /* ==================================================================== */
@@ -1899,6 +2029,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         int32		nPoints;
         int    		i, nOffset;
+        unsigned char* pBuffer = NULL;
+        unsigned char** ppBuffer = NULL;
 
         if ( 44 + 4 > nEntitySize )
         {
@@ -1938,11 +2070,19 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             return NULL;
         }
         
+        if( psShape->bFastModeReadObject )
+        {
+            int nObjectBufSize = 4 * sizeof(double) * nPoints;
+            pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
+            ppBuffer = &pBuffer;
+        }
+
         psShape->nVertices = nPoints;
-        psShape->padfX = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfY = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
-        psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+
+        psShape->padfX = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfY = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfZ = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
+        psShape->padfM = (double *) SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints);
 
         if (psShape->padfX == NULL ||
             psShape->padfY == NULL ||
@@ -2001,6 +2141,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
             nOffset += 16 + 8*nPoints;
         }
+        else if( psShape->bFastModeReadObject )
+            psShape->padfZ = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      If we have a M measure value, then read it now.  We assume      */
@@ -2024,6 +2166,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             }
             psShape->bMeasureIsUsed = TRUE;
         }
+        else if( psShape->bFastModeReadObject )
+            psShape->padfM = NULL;
     }
 
 /* ==================================================================== */
@@ -2036,10 +2180,22 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         int	nOffset;
         
         psShape->nVertices = 1;
-        psShape->padfX = (double *) calloc(1,sizeof(double));
-        psShape->padfY = (double *) calloc(1,sizeof(double));
-        psShape->padfZ = (double *) calloc(1,sizeof(double));
-        psShape->padfM = (double *) calloc(1,sizeof(double));
+        if( psShape->bFastModeReadObject )
+        {
+            psShape->padfX = &(psShape->dfXMin);
+            psShape->padfY = &(psShape->dfYMin);
+            psShape->padfZ = &(psShape->dfZMin);
+            psShape->padfM = &(psShape->dfMMin);
+            psShape->padfZ[0] = 0.0;
+            psShape->padfM[0] = 0.0;
+        }
+        else
+        {
+            psShape->padfX = (double *) calloc(1,sizeof(double));
+            psShape->padfY = (double *) calloc(1,sizeof(double));
+            psShape->padfZ = (double *) calloc(1,sizeof(double));
+            psShape->padfM = (double *) calloc(1,sizeof(double));
+        }
 
         if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
         {
@@ -2197,6 +2353,12 @@ SHPDestroyObject( SHPObject * psShape )
 {
     if( psShape == NULL )
         return;
+
+    if( psShape->bFastModeReadObject )
+    {
+        psShape->bFastModeReadObject = FALSE;
+        return;
+    }
     
     if( psShape->padfX != NULL )
         free( psShape->padfX );
diff --git a/ogr/ogrsf_frmts/shape/shptree.c b/ogr/ogrsf_frmts/shape/shptree.c
index 00673aa..a6d4300 100644
--- a/ogr/ogrsf_frmts/shape/shptree.c
+++ b/ogr/ogrsf_frmts/shape/shptree.c
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
diff --git a/ogr/ogrsf_frmts/sosi/GNUmakefile b/ogr/ogrsf_frmts/sosi/GNUmakefile
new file mode 100644
index 0000000..29f8dc0
--- /dev/null
+++ b/ogr/ogrsf_frmts/sosi/GNUmakefile
@@ -0,0 +1,16 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrsosidriver.o ogrsosidatasource.o ogrsosilayer.o
+# ogrsosidatatypes.o 
+
+CPPFLAGS	:=-DLINUX -DUNIX -I.. -I../.. $(GDAL_INCLUDE) $(SOSI_INC) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_sosi.h
+
diff --git a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
index b076262..4048ca3 100644
--- a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
+++ b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fyba_melding.cpp 20487 2010-08-29 21:42:53Z rouault $
+ * $Id: fyba_melding.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  FYBA Callbacks
  * Purpose:  Needed by FYBA - however we do not want to display most messages
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sosi/makefile.vc b/ogr/ogrsf_frmts/sosi/makefile.vc
index b267a8f..665d85d 100644
--- a/ogr/ogrsf_frmts/sosi/makefile.vc
+++ b/ogr/ogrsf_frmts/sosi/makefile.vc
@@ -1,15 +1,30 @@
 
-OBJ	=	ogrsosidriver.obj ogrsosidatasource.obj ogrsosilayer.obj fyba_melding.obj \
+OBJ	=	ogrsosidriver.obj ogrsosidatasource.obj \
+        ogrsosilayer.obj fyba_melding.obj
 
-EXTRAFLAGS =	-I.. -I..\.. -I$(SOSI_INC_DIR)
+PLUGIN_DLL = ogr_SOSI.dll
 
 GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+EXTRAFLAGS = -I.. -I..\.. -I$(SOSI_INC_DIR)
+
 default:	$(OBJ)
 
-clean:
-	-del *.obj *.pdb
+plugin: $(PLUGIN_DLL)
 
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(SOSI_LIBS)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb *.exp
+	-del *.dll
+	-del *.manifest
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
 
diff --git a/ogr/ogrsf_frmts/sosi/ogr_sosi.h b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
index d6b8000..7583869 100644
--- a/ogr/ogrsf_frmts/sosi/ogr_sosi.h
+++ b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sosi.h 21065 2010-11-05 18:47:30Z rouault $
+ * $Id: ogr_sosi.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -68,7 +69,6 @@ public:
  ************************************************************************/
 
 class OGRSOSILayer : public OGRLayer {
-    FILE               *fp;
     int                 nNextFID;
 
     OGRSOSIDataSource  *poParent;   /* used to call methods from data source */
@@ -90,7 +90,6 @@ public:
     OGRErr              CreateField(OGRFieldDefn *poField, int bApproxOK=TRUE);
     OGRErr              CreateFeature(OGRFeature *poFeature);
     int                 TestCapability( const char * );
-    OGRSpatialReference  *GetSpatialRef();
 };
 
 /************************************************************************
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
index e5fbf49..d10e338 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosidatasource.cpp 21065 2010-11-05 18:47:30Z rouault $
+ * $Id: ogrsosidatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SOSI Data Source
  * Purpose:  Provide SOSI Data to OGR.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -148,6 +149,7 @@ OGRSOSIDataSource::OGRSOSIDataSource() {
     poCurveHeaders = NULL;
     
     pszEncoding = CPL_ENC_UTF8;
+    nMode = MODE_READING;
 }
 
 /************************************************************************/
@@ -192,7 +194,8 @@ OGRSOSIDataSource::~OGRSOSIDataSource() {
     if (pszName != NULL) CPLFree(pszName);
 }
 
-OGRFeatureDefn *defineLayer(char *szName, OGRwkbGeometryType szType, S2I *poHeaders) {
+static
+OGRFeatureDefn *defineLayer(const char *szName, OGRwkbGeometryType szType, S2I *poHeaders) {
     OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn( szName );
     poFeatureDefn->SetGeomType( szType );
     
@@ -223,6 +226,11 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
         return FALSE;
     }
 
+    /* Check that the file exists otherwise HO_TestSOSI() emits an error */
+    VSIStatBuf sStat;
+    if( VSIStat(pszFilename, &sStat) != 0 )
+        return FALSE;
+
     pszName = CPLStrdup( pszFilename );
     /* We ignore any layer parameters for now. */
     pszPos = strchr(pszName, ',');
@@ -305,11 +313,12 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
             if (pszLine[0] == '!') continue;  /* If we have a comment line, skip it. */
             
             char *pszUTFLine = CPLRecode(pszLine, pszEncoding, CPL_ENC_UTF8); /* switch to UTF encoding here, if it is known. */
+            char *pszUTFLineIter = pszUTFLine;
 			
-            while (pszUTFLine[0] == '.') pszUTFLine++; /* Skipping the dots at the beginning of a SOSI line */
-            char *pszPos = strstr(pszUTFLine, " "); /* Split header and value */
+            while (pszUTFLineIter[0] == '.') pszUTFLineIter++; /* Skipping the dots at the beginning of a SOSI line */
+            char *pszPos = strstr(pszUTFLineIter, " "); /* Split header and value */
             if (pszPos != NULL) {
-                CPLString osKey = CPLString(std::string(pszUTFLine,pszPos)); /* FIXME: clean instantiation of CPLString? */
+                CPLString osKey = CPLString(std::string(pszUTFLineIter,pszPos)); /* FIXME: clean instantiation of CPLString? */
                 CPLString osValue = CPLString(pszPos+1);
                 
                 oHeaders[osKey]=osValue;          /* Add to header map */
@@ -344,7 +353,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
                 }
                 }
             }
-            //CPLFree(pszUTFLine);
+            CPLFree(pszUTFLine);
         }
 
         /* Feature-specific tasks */
@@ -384,7 +393,6 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
                 return NULL;
             }
             poSRS = new OGRSpatialReference();
-            poSRS->Reference();
 
             /* Get coordinate system from SOSI header. */
             int nEPSG = sosi2epsg(oTrans.sKoordsys);
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
index 41e4fc5..4d5536a 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosidriver.cpp 25330 2012-12-18 11:12:05Z mloskot $
+ * $Id: ogrsosidriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
index 78afe29..4d9f8f5 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosilayer.cpp 21826 2011-02-24 15:25:13Z warmerdam $
+ * $Id: ogrsosilayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSILayer.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,6 +41,12 @@ OGRSOSILayer::OGRSOSILayer( OGRSOSIDataSource *poPar, OGRFeatureDefn *poFeatDefn
     poFeatureDefn = poFeatDefn;
     poHeaderDefn  = poHeadDefn;
     nNextFID      = 0;
+    poNextSerial  = NULL;
+    
+    if( poFeatureDefn->GetGeomFieldCount() > 0 )
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poParent->poSRS);
+
+    ResetReading();
 }
 
 /************************************************************************/
@@ -57,16 +64,6 @@ OGRFeatureDefn *OGRSOSILayer::GetLayerDefn() {
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-OGRSpatialReference *OGRSOSILayer::GetSpatialRef() {
-    if (poParent->poSRS == NULL) {
-        CPLDebug( "[GetSpatialRef]", "Called, but parent spatial ref is unknown yet.");
-    }
-    return poParent->poSRS; /* The same for all layers */
-}
-
-/************************************************************************/
 /*                           CreateField()                              */
 /************************************************************************/
 OGRErr OGRSOSILayer::CreateField (OGRFieldDefn *poField, int bApproxOK) {
@@ -267,6 +264,9 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                 poFeature->SetField( iHNr, pszLine);
             }
         }
+        
+        if( poGeom != NULL )
+            poGeom->assignSpatialReference(poParent->poSRS);
 
         poFeature->SetGeometryDirectly( poGeom );
         poFeature->SetFID( nNextFID++ );
@@ -298,6 +298,8 @@ int OGRSOSILayer::TestCapability( const char * pszCap ) {
 
     if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
+    if( EQUAL(pszCap,OLCCreateField) )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/GNUmakefile b/ogr/ogrsf_frmts/sqlite/GNUmakefile
index 8c8513a..bd6c393 100644
--- a/ogr/ogrsf_frmts/sqlite/GNUmakefile
+++ b/ogr/ogrsf_frmts/sqlite/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrsqlitedatasource.o ogrsqlitelayer.o ogrsqlitedriver.o \
 		ogrsqlitetablelayer.o ogrsqliteviewlayer.o ogrsqliteselectlayer.o ogrsqlitesinglefeaturelayer.o \
-		ogrsqlitevfs.o ogrsqlitevirtualogr.o ogrsqliteexecutesql.o
+		ogrsqlitevfs.o ogrsqlitevirtualogr.o ogrsqliteexecutesql.o ogrsqliteapiroutines.o
 
 ifeq ($(HAVE_SPATIALITE),yes)
 CPPFLAGS +=  -DHAVE_SPATIALITE
@@ -14,6 +14,10 @@ ifeq ($(SPATIALITE_AMALGAMATION),yes)
 CPPFLAGS +=  -DSPATIALITE_AMALGAMATION
 endif
 
+ifeq ($(SPATIALITE_412_OR_LATER),yes)
+CPPFLAGS +=  -DSPATIALITE_412_OR_LATER
+endif
+
 ifeq ($(HAVE_PCRE),yes)
 CPPFLAGS +=  -DHAVE_PCRE
 endif
diff --git a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
index 9dfc330..f66ce79 100644
--- a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
+++ b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
@@ -39,6 +39,10 @@ at the expense of data safety w.r.t system/OS crashes. So use it carefully in
 production environments and read the SQLite
 <a href="http://www.sqlite.org/pragma.html#pragma_synchronous">related documentation</a>.</p>
 
+<p>Starting with OGR 1.11, any SQLite <a href="http://www.sqlite.org/pragma.html">pragma</a> can be
+specified with the OGR_SQLITE_PRAGMA configuration option. The syntax is
+OGR_SQLITE_PRAGMA = "pragma_name=pragma_value[,pragma_name2=pragma_value2]*".</p>
+
 <h2>"Regular" SQLite databases</h2>
 
 <p>The driver looks for a geometry_columns table layed out as defined
@@ -260,6 +264,8 @@ Note: in table definition, such columns have the "VARCHAR_deflate" declaration t
 
 </ul>
 
+<h2>Other Configuration Options</h2>
+See other configure options <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions#SQLITE_LIST_ALL_TABLES">here</a>.
 <h2>Performance hints</h2>
 SQLite is a Transactional DBMS; while many INSERT statements are executed in close
 sequence, BEGIN TRANSACTION and COMMIT TRANSACTION statements have to be invoked
@@ -288,6 +294,25 @@ Setting the <b>OGR_SQLITE_SYNCHRONOUS</b> configuration option to <i>OFF</i> mig
 increase performance when creating SQLite databases (altough at the expense of integrity in case of
 interruption/crash ).<p>
 
+If many source files will be collected into the same Spatialite table, it
+can be much faster to initialize the table without a spatial index by using
+-lco SPATIAL_INDEX=NO and to create spatial index with a separate command
+after all the data are appended. Spatial index can be created with ogrinfo
+command
+<pre>
+ogr2ogr -f SQLite -dsco SPATIALITE=YES db.sqlite first.shp -nln the_table -lco SPATIAL_INDEX=NO
+ogr2ogr -append db.sqlite second.shp -nln the_table
+...
+ogr2ogr -append db.sqlite last.shp -nln the_table
+ogrinfo db.sqlite -sql "SELECT CreateSpatialIndex('the_table','GEOMETRY')"
+</pre>
+<p>
+
+If a database has gone through editing operations, it might be usefull to run a
+<a href="https://sqlite.org/lang_vacuum.html">VACUUM</a> query to compact and optimize it.
+<pre>ogrinfo db.sqlite -sql "VACUUM"</pre>
+<p>
+
 <h2>Credits</h2>
 <ul>
 <li>Development of the OGR SQLite driver was supported by 
diff --git a/ogr/ogrsf_frmts/sqlite/makefile.vc b/ogr/ogrsf_frmts/sqlite/makefile.vc
index e1d3d90..4b5d5f2 100644
--- a/ogr/ogrsf_frmts/sqlite/makefile.vc
+++ b/ogr/ogrsf_frmts/sqlite/makefile.vc
@@ -8,7 +8,7 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = -I.. -I..\.. $(SQLITE_INC) $(PCRE_EXTRAFLAGS) $(SQLITE_HAS_COLUMN_METADATA_EXTRAFLAGS)
+EXTRAFLAGS = -I.. -I..\.. $(SQLITE_INC) $(PCRE_EXTRAFLAGS) $(SQLITE_HAS_COLUMN_METADATA_EXTRAFLAGS) $(SPATIALITE_412_OR_LATER_EXTRAFLAGS)
 
 !IFDEF PCRE_INC
 PCRE_EXTRAFLAGS = $(PCRE_INC)
@@ -18,6 +18,10 @@ PCRE_EXTRAFLAGS = $(PCRE_INC)
 SQLITE_HAS_COLUMN_METADATA_EXTRAFLAGS = -DSQLITE_HAS_COLUMN_METADATA
 !ENDIF
 
+!IFDEF SPATIALITE_412_OR_LATER
+SPATIALITE_412_OR_LATER_EXTRAFLAGS = -DSPATIALITE_412_OR_LATER
+!ENDIF
+
 default:	$(OBJ)
 
 clean:
diff --git a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index 6d71d4d..83391be 100644
--- a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
+++ b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sqlite.h 25694 2013-03-01 17:26:40Z rouault $
+ * $Id: ogr_sqlite.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/SQLite driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -65,9 +66,6 @@
 
 #define UNINITIALIZED_SRID  -2
 
-int OGRSQLiteIsSpatialiteLoaded();
-int OGRSQLiteGetSpatialiteVersionNumber();
-
 /************************************************************************/
 /*      Format used to store geometry data in the database.             */
 /************************************************************************/
@@ -150,6 +148,44 @@ enum OGRSpatialiteGeomType
 };
 
 /************************************************************************/
+/*                        OGRSQLiteGeomFieldDefn                        */
+/************************************************************************/
+
+class OGRSQLiteGeomFieldDefn : public OGRGeomFieldDefn
+{
+    public:
+        OGRSQLiteGeomFieldDefn( const char* pszName, int iGeomColIn ) :
+            OGRGeomFieldDefn(pszName, wkbUnknown), nSRSId(UNINITIALIZED_SRID),
+            iCol(iGeomColIn), bTriedAsSpatiaLite(FALSE), eGeomFormat(OSGF_None)
+            {
+            }
+
+        int nSRSId;
+        int iCol; /* ordinal of geometry field in SQL statement */
+        int bTriedAsSpatiaLite;
+        OGRSQLiteGeomFormat eGeomFormat;
+};
+
+/************************************************************************/
+/*                        OGRSQLiteFeatureDefn                          */
+/************************************************************************/
+
+class OGRSQLiteFeatureDefn : public OGRFeatureDefn
+{
+    public:
+        OGRSQLiteFeatureDefn( const char * pszName = NULL ) :
+            OGRFeatureDefn(pszName)
+        {
+            SetGeomType(wkbNone);
+        }
+            
+        OGRSQLiteGeomFieldDefn* myGetGeomFieldDefn(int i)
+        {
+            return (OGRSQLiteGeomFieldDefn*) GetGeomFieldDefn(i);
+        }
+};
+
+/************************************************************************/
 /*                            OGRSQLiteLayer                            */
 /************************************************************************/
 
@@ -183,11 +219,7 @@ class OGRSQLiteLayer : public OGRLayer
                                                         GByte* pabyData );
 
   protected:
-    OGRFeatureDefn     *poFeatureDefn;
-
-    // Layer spatial reference system, and srid.
-    OGRSpatialReference *poSRS;
-    int                 nSRSId;
+    OGRSQLiteFeatureDefn *poFeatureDefn;
 
     int                 iNextShapeId;
 
@@ -196,15 +228,10 @@ class OGRSQLiteLayer : public OGRLayer
 
     OGRSQLiteDataSource *poDS;
 
-    int                 bTriedAsSpatiaLite;
-    CPLString           osGeomColumn;
-    OGRSQLiteGeomFormat eGeomFormat;
-
     char                *pszFIDColumn;
 
     int                *panFieldOrdinals;
     int                 iFIDCol;
-    int                 iGeomCol;
 
     int                 bHasSpatialIndex;
     int                 bHasM;
@@ -213,6 +240,7 @@ class OGRSQLiteLayer : public OGRLayer
 
     void                BuildFeatureDefn( const char *pszLayerName,
                                           sqlite3_stmt *hStmt,
+                                          const char *pszExpectedGeomCol,
                                           const std::set<CPLString>& aosGeomCols);
 
     void                ClearStatement();
@@ -222,6 +250,8 @@ class OGRSQLiteLayer : public OGRLayer
 
     char              **papszCompressedColumns;
 
+    int                 bAllowMultipleGeomFields;
+
   public:
                         OGRSQLiteLayer();
     virtual             ~OGRSQLiteLayer();
@@ -235,11 +265,9 @@ class OGRSQLiteLayer : public OGRLayer
     virtual OGRFeature *GetFeature( long nFeatureId );
     
     virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSQLiteFeatureDefn *myGetLayerDefn() { return poFeatureDefn; }
 
     virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
 
     virtual int         TestCapability( const char * );
 
@@ -253,7 +281,8 @@ class OGRSQLiteLayer : public OGRLayer
 
     virtual int          HasSpatialIndex() { return bHasSpatialIndex; }
 
-    virtual CPLString     GetSpatialWhere(OGRGeometry* poFilterGeom) { return ""; }
+    virtual CPLString     GetSpatialWhere(int iGeomCol,
+                                          OGRGeometry* poFilterGeom) { return ""; }
 
     static OGRErr       ImportSpatiaLiteGeometry( const GByte *, int,
                                                   OGRGeometry ** );
@@ -290,12 +319,19 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     sqlite3_stmt       *hInsertStmt;
     CPLString           osLastInsertStmt;
 
+    OGRSQLiteGeomFormat eGeomFormat;
+    char                *pszGeomCol;
+    int                 nSRSId;
+    OGRSpatialReference *poSRS;
+
     void                ClearInsertStmt();
 
     void                BuildWhere(void);
 
     virtual OGRErr      ResetStatement();
 
+    OGRErr              RecomputeOrdinals();
+
     OGRErr              AddColumnAncientMethod( OGRFieldDefn& oField);
 
     void                InitFieldListForRecrerate(char* & pszNewFieldList,
@@ -388,7 +424,8 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
 
     virtual int          HasSpatialIndex();
 
-    virtual CPLString    GetSpatialWhere(OGRGeometry* poFilterGeom);
+    virtual CPLString    GetSpatialWhere(int iGeomCol,
+                                         OGRGeometry* poFilterGeom);
 };
 
 /************************************************************************/
@@ -401,6 +438,9 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
     CPLString           osQuery;
     int                 bHasCheckedSpatialIndexTable;
 
+    OGRSQLiteGeomFormat eGeomFormat;
+    CPLString           osGeomColumn;
+    
     char               *pszViewName;
     char               *pszEscapedTableName;
     char               *pszEscapedUnderlyingTableName;
@@ -445,9 +485,8 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
-    virtual CPLString    GetSpatialWhere(OGRGeometry* poFilterGeom);
+    virtual CPLString    GetSpatialWhere(int iGeomCol,
+                                         OGRGeometry* poFilterGeom);
 };
 
 /************************************************************************/
@@ -465,7 +504,7 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer
     virtual OGRErr      ResetStatement();
 
     OGRSQLiteLayer     *GetBaseLayer(size_t& i);
-    int                 RebuildSQLWithSpatialClause();
+    int                 BuildSQL();
 
     int                 bAllowResetReadingEvenIfIndexAtZero;
  
@@ -474,18 +513,22 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer
                                               CPLString osSQL,
                                               sqlite3_stmt *,
                                               int bUseStatementForGetNextFeature,
-                                              int bEmptyLayer );
+                                              int bEmptyLayer,
+                                              int bAllowMultipleGeomFields );
 
     virtual void        ResetReading();
 
     virtual OGRFeature *GetNextFeature();
     virtual int         GetFeatureCount( int );
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual OGRErr      SetAttributeFilter( const char * );
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
 };
 
 /************************************************************************/
@@ -540,6 +583,12 @@ class OGRSQLiteDataSource : public OGRDataSource
     int                 bIsSpatiaLiteDB;
     int                 bSpatialite4Layout;
 
+#ifdef SPATIALITE_412_OR_LATER
+    void               *hSpatialiteCtxt;
+    int                 InitNewSpatialite();
+    void                FinishNewSpatialite();
+#endif
+
     int                 nUndefinedSRID;
 
     virtual void        DeleteLayer( const char *pszLayer );
@@ -636,7 +685,10 @@ class OGRSQLiteDataSource : public OGRDataSource
             { return aoMapTableToSetOfGeomCols[pszTableName]; }
 
     GIntBig             GetFileTimestamp() const { return nFileTimestamp; }
-    
+
+    int                 IsSpatialiteLoaded();
+    int                 GetSpatialiteVersionNumber();
+
     int                 IsSpatialiteDB() const { return bIsSpatiaLiteDB; }
     int                 HasSpatialite4Layout() const { return bSpatialite4Layout; }
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
index 97f20fe..3e7a40c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlite3ext.h 24824 2012-08-22 11:43:07Z rouault $
+ * $Id: ogrsqlite3ext.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Custom version of sqlite3ext.h to workaround issues with Spatialite amalgamation
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -223,6 +223,7 @@
 #undef sqlite3_vtab_config
 #undef sqlite3_vtab_on_conflict
 
+typedef struct sqlite3_backup ogr_sqlite3_backup;
 
 /*
 ** 2006 June 7
@@ -436,11 +437,11 @@ struct sqlite3_api_routines {
   sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
   const char *(*sql)(sqlite3_stmt*);
   int (*status)(int,int*,int*,int);
-  int (*backup_finish)(sqlite3_backup*);
-  sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
-  int (*backup_pagecount)(sqlite3_backup*);
-  int (*backup_remaining)(sqlite3_backup*);
-  int (*backup_step)(sqlite3_backup*,int);
+  int (*backup_finish)(ogr_sqlite3_backup*);
+  ogr_sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
+  int (*backup_pagecount)(ogr_sqlite3_backup*);
+  int (*backup_remaining)(ogr_sqlite3_backup*);
+  int (*backup_step)(ogr_sqlite3_backup*,int);
   const char *(*compileoption_get)(int);
   int (*compileoption_used)(const char*);
   int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
new file mode 100644
index 0000000..c9ac266
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
@@ -0,0 +1,275 @@
+/******************************************************************************
+ * $Id: ogrsqliteapiroutines.c 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Static registration of sqlite3 entry points
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+
+#ifndef WIN32
+
+#ifdef HAVE_SPATIALITE
+  #ifdef SPATIALITE_AMALGAMATION
+    /*
+    / using an AMALGAMATED version of SpatiaLite
+    / a private internal copy of SQLite is included:
+    / so we are required including the SpatiaLite's 
+    / own header 
+    /
+    / IMPORTANT NOTICE: using AMALAGATION is only
+    / useful on Windows (to skip DLL hell related oddities)
+    */
+    #include <spatialite/sqlite3.h>
+  #else
+    /*
+    / You MUST NOT use AMALGAMATION on Linux or any
+    / other "sane" operating system !!!!
+    */
+    #include "sqlite3.h"
+  #endif
+#else
+#include "sqlite3.h"
+#endif
+
+#if SQLITE_VERSION_NUMBER >= 3006000
+#define HAVE_SQLITE_VFS
+#define HAVE_SQLITE3_PREPARE_V2
+#endif
+
+#define DONT_UNDEF_SQLITE3_MACROS
+#ifndef SQLITE_CORE
+#define SQLITE_CORE
+#endif
+#include "ogrsqlite3ext.h"
+
+const struct sqlite3_api_routines OGRSQLITE_static_routines =
+{
+  NULL, /*sqlite3_aggregate_context, */
+  NULL, /*sqlite3_aggregate_count, */
+  sqlite3_bind_blob, /* YES */
+  sqlite3_bind_double, /* YES */
+  sqlite3_bind_int, /* YES */
+  sqlite3_bind_int64, /* YES */
+  sqlite3_bind_null, /* YES */
+  NULL, /*sqlite3_bind_parameter_count,*/
+  NULL, /*sqlite3_bind_parameter_index,*/
+  NULL, /*sqlite3_bind_parameter_name,*/
+  sqlite3_bind_text, /* YES */
+  NULL, /*sqlite3_bind_text16,*/
+  NULL, /*sqlite3_bind_value,*/
+  NULL, /*sqlite3_busy_handler,*/
+  NULL, /*sqlite3_busy_timeout,*/
+  sqlite3_changes, /* YES */
+  sqlite3_close, /* YES */
+  NULL, /*sqlite3_collation_needed,*/
+  NULL, /*sqlite3_collation_needed16,*/
+  sqlite3_column_blob, /* YES */
+  sqlite3_column_bytes, /* YES */
+  NULL, /*sqlite3_column_bytes16,*/
+  sqlite3_column_count, /* YES */
+  NULL, /*sqlite3_column_database_name,*/
+  NULL, /*sqlite3_column_database_name16,*/
+  sqlite3_column_decltype, /* YES */
+  NULL, /*sqlite3_column_decltype16,*/
+  sqlite3_column_double, /* YES */
+  sqlite3_column_int, /* YES */
+  sqlite3_column_int64, /* YES */
+  sqlite3_column_name, /* YES */
+  NULL, /*sqlite3_column_name16,*/
+  NULL, /*sqlite3_column_origin_name,*/
+  NULL, /*sqlite3_column_origin_name16,*/
+#ifdef SQLITE_HAS_COLUMN_METADATA
+  sqlite3_column_table_name, /* YES */
+#else
+  NULL,
+#endif
+  NULL, /*sqlite3_column_table_name16,*/
+  sqlite3_column_text, /* YES */
+  NULL, /*sqlite3_column_text16,*/
+  sqlite3_column_type, /* YES */
+  NULL, /*sqlite3_column_value,*/
+  NULL, /*sqlite3_commit_hook,*/
+  NULL, /*sqlite3_complete,*/
+  NULL, /*sqlite3_complete16,*/
+  NULL, /*sqlite3_create_collation,*/
+  NULL, /*sqlite3_create_collation16,*/
+  sqlite3_create_function,
+  NULL, /*sqlite3_create_function16,*/
+  sqlite3_create_module,
+  NULL, /*sqlite3_data_count,*/
+  NULL, /*sqlite3_db_handle,*/
+  sqlite3_declare_vtab,
+  NULL, /*sqlite3_enable_shared_cache,*/
+  sqlite3_errcode,
+  sqlite3_errmsg, /* YES */
+  NULL, /*sqlite3_errmsg16,*/
+  sqlite3_exec, /* YES */
+  NULL, /*sqlite3_expired,*/
+  sqlite3_finalize, /* YES */
+  sqlite3_free, /* YES */
+  sqlite3_free_table, /* YES */
+  NULL, /*sqlite3_get_autocommit,*/
+  NULL, /*sqlite3_get_auxdata,*/
+  sqlite3_get_table, /* YES */
+  NULL, /*sqlite3_global_recover,*/
+  NULL, /*sqlite3_interrupt,*/
+  sqlite3_last_insert_rowid, /* YES */
+  NULL, /*sqlite3_libversion,*/
+  sqlite3_libversion_number, /* YES */
+  sqlite3_malloc,
+  sqlite3_mprintf,
+  sqlite3_open, /* YES */
+  NULL, /*sqlite3_open16,*/
+  sqlite3_prepare, /* YES */
+  NULL, /*sqlite3_prepare16,*/
+  NULL, /*sqlite3_profile,*/
+  NULL, /*sqlite3_progress_handler,*/
+  sqlite3_realloc,
+  sqlite3_reset, /* YES */
+  sqlite3_result_blob,
+  sqlite3_result_double,
+  sqlite3_result_error,
+  NULL, /*sqlite3_result_error16,*/
+  sqlite3_result_int,
+  sqlite3_result_int64,
+  sqlite3_result_null,
+  sqlite3_result_text,
+  NULL, /*sqlite3_result_text16,*/
+  NULL, /*sqlite3_result_text16be,*/
+  NULL, /*sqlite3_result_text16le,*/
+  sqlite3_result_value,
+  NULL, /*sqlite3_rollback_hook,*/
+  NULL, /*sqlite3_set_authorizer,*/
+  NULL, /*sqlite3_set_auxdata,*/
+  sqlite3_snprintf,
+  sqlite3_step, /* YES */
+  NULL, /*sqlite3_table_column_metadata,*/
+  NULL, /*sqlite3_thread_cleanup,*/
+  sqlite3_total_changes,
+  NULL, /*sqlite3_trace,*/
+  NULL, /*sqlite3_transfer_bindings,*/
+  NULL, /*sqlite3_update_hook,*/
+  sqlite3_user_data,
+  sqlite3_value_blob,
+  sqlite3_value_bytes,
+  NULL, /*sqlite3_value_bytes16,*/
+  sqlite3_value_double,
+  sqlite3_value_int,
+  sqlite3_value_int64,
+  sqlite3_value_numeric_type,
+  sqlite3_value_text,
+  NULL, /*sqlite3_value_text16,*/
+  NULL, /*sqlite3_value_text16be,*/
+  NULL, /*sqlite3_value_text16le,*/
+  sqlite3_value_type,
+  sqlite3_vmprintf,
+  /* Added ??? */
+ NULL, /*sqlite3_overload_function,*/
+  /* Added by 3.3.13 */
+#ifdef HAVE_SQLITE3_PREPARE_V2
+ sqlite3_prepare_v2, /* YES */
+#else
+ NULL,
+#endif
+ NULL, /*sqlite3_prepare16_v2,*/
+ NULL, /*sqlite3_clear_bindings,*/
+  /* Added by 3.4.1 */
+#ifdef HAVE_SQLITE_VFS
+ sqlite3_create_module_v2,
+#endif
+  /* Added by 3.5.0 */
+ NULL, /*sqlite3_bind_zeroblob,*/
+ NULL, /*sqlite3_blob_bytes,*/
+ NULL, /*sqlite3_blob_close,*/
+ NULL, /*sqlite3_blob_open,*/
+ NULL, /*sqlite3_blob_read,*/
+ NULL, /*sqlite3_blob_write,*/
+ NULL, /*sqlite3_create_collation_v2,*/
+ NULL, /*sqlite3_file_control,*/
+  NULL, /*sqlite3_memory_highwater,*/
+  NULL, /*sqlite3_memory_used,*/
+  NULL, /*sqlite3_mutex_alloc,*/
+  NULL, /*sqlite3_mutex_enter,*/
+  NULL, /*sqlite3_mutex_free,*/
+  NULL, /*sqlite3_mutex_leave,*/
+ NULL, /*sqlite3_mutex_try,*/
+#ifdef HAVE_SQLITE_VFS
+ sqlite3_open_v2, /* YES */
+#else
+ NULL,
+#endif
+ NULL, /*sqlite3_release_memory,*/
+  NULL, /*sqlite3_result_error_nomem,*/
+  NULL, /*sqlite3_result_error_toobig,*/
+ NULL, /*sqlite3_sleep,*/
+  NULL, /*sqlite3_soft_heap_limit,*/
+#ifdef HAVE_SQLITE_VFS
+  sqlite3_vfs_find, /* YES */
+ sqlite3_vfs_register, /* YES */
+ sqlite3_vfs_unregister, /* YES */
+#else
+ NULL,
+ NULL,
+ NULL,
+#endif
+ NULL, /*sqlite3_threadsafe,*/
+  NULL, /*sqlite3_result_zeroblob,*/
+  NULL, /*sqlite3_result_error_code,*/
+ NULL, /*sqlite3_test_control,*/
+  NULL, /*sqlite3_randomness,*/
+  NULL, /*sqlite3_context_db_handle,*/
+ NULL, /*sqlite3_extended_result_codes,*/
+ NULL, /*sqlite3_limit,*/
+  NULL, /*sqlite3_next_stmt,*/
+  NULL, /*sqlite3_sql,*/
+ NULL, /*sqlite3_status,*/
+ NULL, /*sqlite3_backup_finish,*/
+  NULL, /*sqlite3_backup_init,*/
+ NULL, /*sqlite3_backup_pagecount,*/
+ NULL, /*sqlite3_backup_remaining,*/
+ NULL, /*sqlite3_backup_step,*/
+  NULL,/*sqlite3_compileoption_get,*/
+ NULL,/*sqlite3_compileoption_used,*/
+ NULL,/*sqlite3_create_function_v2,*/
+ NULL, /*sqlite3_db_config,*/
+  NULL, /*sqlite3_db_mutex,*/
+ NULL, /*sqlite3_db_status,*/
+ NULL, /*sqlite3_extended_errcode,*/
+  NULL, /*sqlite3_log,*/
+  NULL, /*sqlite3_soft_heap_limit64,*/
+  NULL, /*sqlite3_sourceid,*/
+ NULL, /*sqlite3_stmt_status,*/
+ NULL, /*sqlite3_strnicmp,*/
+ NULL, /*sqlite3_unlock_notify,*/
+ NULL, /*sqlite3_wal_autocheckpoint,*/
+ NULL, /*sqlite3_wal_checkpoint,*/
+  NULL, /*sqlite3_wal_hook,*/
+ NULL, /*sqlite3_blob_reopen,*/
+ NULL, /*sqlite3_vtab_config,*/
+ NULL, /*sqlite3_vtab_on_conflict,*/
+};
+
+#endif // WIN32
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 06efbc3..14e6f4c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 26252 2013-07-30 21:07:00Z rouault $
+ * $Id: ogrsqlitedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
@@ -14,6 +14,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -45,47 +46,89 @@
 #include "spatialite.h"
 #endif
 
-static int bSpatialiteLoaded = FALSE;
+#ifndef SPATIALITE_412_OR_LATER
+static int bSpatialiteGlobalLoaded = FALSE;
+#endif
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 26252 2013-07-30 21:07:00Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
-/*                      OGRSQLiteInitSpatialite()                       */
+/*                      OGRSQLiteInitOldSpatialite()                    */
 /************************************************************************/
 
-static int OGRSQLiteInitSpatialite()
+#ifndef SPATIALITE_412_OR_LATER
+
+static int OGRSQLiteInitOldSpatialite()
 {
 /* -------------------------------------------------------------------- */
 /*      Try loading SpatiaLite.                                         */
 /* -------------------------------------------------------------------- */
 #ifdef HAVE_SPATIALITE
-    if (!bSpatialiteLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
+    if (!bSpatialiteGlobalLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
     {
-        bSpatialiteLoaded = TRUE;
+        bSpatialiteGlobalLoaded = TRUE;
         spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
     }
 #endif
-    return bSpatialiteLoaded;
+    return bSpatialiteGlobalLoaded;
 }
 
+#else
+
 /************************************************************************/
-/*                     OGRSQLiteIsSpatialiteLoaded()                    */
+/*                          InitNewSpatialite()                         */
 /************************************************************************/
 
-int OGRSQLiteIsSpatialiteLoaded()
+int OGRSQLiteDataSource::InitNewSpatialite()
 {
-    return bSpatialiteLoaded;
+    if( CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")) )
+    {
+        hSpatialiteCtxt = spatialite_alloc_connection();
+        if( hSpatialiteCtxt != NULL )
+        {
+            spatialite_init_ex(hDB, hSpatialiteCtxt,
+                CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
+        }
+    }
+    return hSpatialiteCtxt != NULL;
 }
 
 /************************************************************************/
-/*               OGRSQLiteGetSpatialiteVersionNumber()                  */
+/*                         FinishNewSpatialite()                        */
 /************************************************************************/
 
-int OGRSQLiteGetSpatialiteVersionNumber()
+void OGRSQLiteDataSource::FinishNewSpatialite()
+{
+    if( hSpatialiteCtxt != NULL )
+    {
+        spatialite_cleanup_ex(hSpatialiteCtxt);
+    }
+}
+
+#endif
+
+/************************************************************************/
+/*                          IsSpatialiteLoaded()                        */
+/************************************************************************/
+
+int OGRSQLiteDataSource::IsSpatialiteLoaded()
+{
+#ifdef SPATIALITE_412_OR_LATER
+    return hSpatialiteCtxt != NULL;
+#else
+    return bSpatialiteGlobalLoaded;
+#endif
+}
+
+/************************************************************************/
+/*                     GetSpatialiteVersionNumber()                     */
+/************************************************************************/
+
+int OGRSQLiteDataSource::GetSpatialiteVersionNumber()
 {
     int v = 0;
 #ifdef HAVE_SPATIALITE
-    if( bSpatialiteLoaded )
+    if( IsSpatialiteLoaded() )
     {
         v = (int)(( atof( spatialite_version() ) + 0.001 )  * 10.0);
     }
@@ -115,6 +158,10 @@ OGRSQLiteDataSource::OGRSQLiteDataSource()
     bSpatialite4Layout = FALSE;
     bUpdate = FALSE;
 
+#ifdef SPATIALITE_412_OR_LATER
+    hSpatialiteCtxt = NULL;
+#endif
+
     nUndefinedSRID = -1; /* will be changed to 0 if Spatialite >= 4.0 detected */
 
     hDB = NULL;
@@ -163,6 +210,10 @@ OGRSQLiteDataSource::~OGRSQLiteDataSource()
     CPLFree( panSRID );
     CPLFree( papoSRS );
 
+#ifdef SPATIALITE_412_OR_LATER
+    FinishNewSpatialite();
+#endif
+
     if( hDB != NULL )
         sqlite3_close( hDB );
 
@@ -185,7 +236,7 @@ void OGRSQLiteDataSource::SaveStatistics()
     int i;
     int nSavedAllLayersCacheData = -1;
 
-    if( !bIsSpatiaLiteDB || !OGRSQLiteIsSpatialiteLoaded() || bLastSQLCommandIsUpdateLayerStatistics )
+    if( !bIsSpatiaLiteDB || !IsSpatialiteLoaded() || bLastSQLCommandIsUpdateLayerStatistics )
         return;
 
     for( i = 0; i < nLayers; i++ )
@@ -474,6 +525,33 @@ int OGRSQLiteDataSource::OpenOrCreateDB(int flags)
         }
     }
 
+    const char* pszSqlitePragma = CPLGetConfigOption("OGR_SQLITE_PRAGMA", NULL);
+    if (pszSqlitePragma != NULL)
+    {
+        char** papszTokens = CSLTokenizeString2( pszSqlitePragma, ",", CSLT_HONOURSTRINGS );
+        for(int i=0; papszTokens[i] != NULL; i++ )
+        {
+            char* pszErrMsg = NULL;
+            char **papszResult;
+            int nRowCount, nColCount;
+
+            const char* pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
+
+            rc = sqlite3_get_table( hDB, pszSQL,
+                                    &papszResult, &nRowCount, &nColCount,
+                                    &pszErrMsg );
+            if( rc == SQLITE_OK )
+            {
+                sqlite3_free_table(papszResult);
+            }
+            else
+            {
+                sqlite3_free( pszErrMsg );
+            }
+        }
+        CSLDestroy(papszTokens);
+    }
+
     if (!SetCacheSize())
         return FALSE;
 
@@ -505,13 +583,15 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
     if (bSpatialite == TRUE)
     {
 #ifdef HAVE_SPATIALITE
-        OGRSQLiteInitSpatialite();
-        if (!OGRSQLiteIsSpatialiteLoaded())
+#ifndef SPATIALITE_412_OR_LATER
+        OGRSQLiteInitOldSpatialite();
+        if (!IsSpatialiteLoaded())
         {
             CPLError( CE_Failure, CPLE_NotSupported,
                     "Creating a Spatialite database, but Spatialite extensions are not loaded." );
             return FALSE;
         }
+#endif
 #else
         CPLError( CE_Failure, CPLE_NotSupported,
             "OGR was built without libspatialite support\n"
@@ -538,6 +618,15 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
 /* -------------------------------------------------------------------- */
     if ( bSpatialite )
     {
+#ifdef SPATIALITE_412_OR_LATER
+        if (!InitNewSpatialite())
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "Creating a Spatialite database, but Spatialite extensions are not loaded." );
+            return FALSE;
+        }
+#endif
+
         /*
         / SpatiaLite full support: calling InitSpatialMetadata()
         /
@@ -549,10 +638,19 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
         
         const char* pszVal = CSLFetchNameValue( papszOptions, "INIT_WITH_EPSG" );
         if( pszVal != NULL && !CSLTestBoolean(pszVal) &&
-            OGRSQLiteGetSpatialiteVersionNumber() >= 40 )
+            GetSpatialiteVersionNumber() >= 40 )
             osCommand =  "SELECT InitSpatialMetadata('NONE')";
         else
-            osCommand =  "SELECT InitSpatialMetadata()";
+        {
+            /* Since spatialite 4.1, InitSpatialMetadata() is no longer run */
+            /* into a transaction, which makes population of spatial_ref_sys */
+            /* from EPSG awfully slow. We have to use InitSpatialMetadata(1) */
+            /* to run within a transaction */
+            if( GetSpatialiteVersionNumber() >= 41 )
+                osCommand =  "SELECT InitSpatialMetadata(1)";
+            else
+                osCommand =  "SELECT InitSpatialMetadata()";
+        }
         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
@@ -633,7 +731,7 @@ int OGRSQLiteDataSource::InitWithEPSG()
         / if v.2.4.0 (or any subsequent) InitWithEPSG make no sense at all
         / because the EPSG dataset is already self-initialized at DB creation
         */
-        int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+        int iSpatialiteVersion = GetSpatialiteVersionNumber();
         if ( iSpatialiteVersion >= 24 )
             return TRUE;
     }
@@ -887,7 +985,9 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
 /* -------------------------------------------------------------------- */
     if (hDB == NULL)
     {
-        OGRSQLiteInitSpatialite();
+#ifndef SPATIALITE_412_OR_LATER
+        OGRSQLiteInitOldSpatialite();
+#endif
 
 #ifdef HAVE_SQLITE_VFS
         if (!OpenOrCreateDB((bUpdateIn) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY) )
@@ -895,6 +995,10 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
         if (!OpenOrCreateDB(0))
 #endif
             return FALSE;
+
+#ifdef SPATIALITE_412_OR_LATER
+        InitNewSpatialite();
+#endif
     }
 
 /* -------------------------------------------------------------------- */
@@ -1048,9 +1152,9 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
         int iSpatialiteVersion = -1;
 
         /* Only enables write-mode if linked against SpatiaLite */
-        if( OGRSQLiteIsSpatialiteLoaded() )
+        if( IsSpatialiteLoaded() )
         {
-            iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+            iSpatialiteVersion = GetSpatialiteVersionNumber();
         }
         else if( bUpdate )
         {
@@ -1170,7 +1274,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
                 if( pszName == NULL || pszSQL == NULL )
                     continue;
 
-                if( (OGRSQLiteIsSpatialiteLoaded() &&
+                if( (IsSpatialiteLoaded() &&
                         (strstr(pszSQL, "VirtualShape") || strstr(pszSQL, "VirtualXL"))) ||
                     (bListVirtualOGRLayers && strstr(pszSQL, "VirtualOGR")) )
                 {
@@ -1685,10 +1789,10 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         
     CPLString osSQL = pszSQLCommand;
     poLayer = new OGRSQLiteSelectLayer( this, osSQL, hSQLStmt,
-                                        bUseStatementForGetNextFeature, bEmptyLayer );
+                                        bUseStatementForGetNextFeature, bEmptyLayer, TRUE );
 
     if( poSpatialFilter != NULL )
-        poLayer->SetSpatialFilter( poSpatialFilter );
+        poLayer->SetSpatialFilter( 0, poSpatialFilter );
     
     return poLayer;
 }
@@ -1771,7 +1875,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
 
     /* Shouldn't happen since a spatialite DB should be opened in read-only mode */
     /* if libspatialite isn't loaded */
-    if (bIsSpatiaLiteDB && !OGRSQLiteIsSpatialiteLoaded())
+    if (bIsSpatiaLiteDB && !IsSpatialiteLoaded())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Creating layers on a SpatiaLite enabled database, "
@@ -1954,7 +2058,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
             / to support 2.5D: if an obsolete version of the library
             / is found we'll unconditionally activate 2D casting mode
             */
-            int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+            int iSpatialiteVersion = GetSpatialiteVersionNumber();
             if ( iSpatialiteVersion < 24 && nCoordDim == 3 )
             {
                 CPLDebug("SQLITE", "Spatialite < 2.4.0 --> 2.5D geometry not supported. Casting to 2D");
@@ -2016,7 +2120,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
 
         const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
         if ( pszSI != NULL && CSLTestBoolean(pszSI) &&
-             (bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) && !OGRSQLiteIsSpatialiteLoaded() )
+             (bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) && !IsSpatialiteLoaded() )
         {
             CPLError( CE_Warning, CPLE_OpenFailed,
                     "Cannot create a spatial index when Spatialite extensions are not loaded." );
@@ -2024,7 +2128,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
 
 #ifdef HAVE_SPATIALITE
         /* Only if linked against SpatiaLite and the datasource was created as a SpatiaLite DB */
-        if ( bIsSpatiaLiteDB && OGRSQLiteIsSpatialiteLoaded() )
+        if ( bIsSpatiaLiteDB && IsSpatialiteLoaded() )
 #else
         if ( 0 )
 #endif
@@ -2769,7 +2873,18 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      If there is no SRS ID with such auth_srid, use it as SRS ID.    */
 /* -------------------------------------------------------------------- */
         if ( nRowCount < 1 )
+        {
             nSRSId = atoi(pszAuthorityCode);
+            /* The authority code might be non numeric, e.g. IGNF:LAMB93 */
+            /* in which case we might fallback to the fake OGR authority */
+            /* for spatialite, since its auth_srid is INTEGER */
+            if( nSRSId == 0 )
+            {
+                nSRSId = nUndefinedSRID;
+                if( bIsSpatiaLiteDB )
+                    pszAuthorityName = NULL;
+            }
+        }
         sqlite3_free_table(papszResult);
     }
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
index c7c8608..bc14ee1 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedriver.cpp 25409 2012-12-31 11:51:10Z rouault $
+ * $Id: ogrsqlitedriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDriver class.
@@ -14,6 +14,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,11 @@
 #include "ogr_sqlite.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsqlitedriver.cpp 25409 2012-12-31 11:51:10Z rouault $");
+#ifdef HAVE_SPATIALITE
+#include "spatialite.h"
+#endif
+
+CPL_CVSID("$Id: ogrsqlitedriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSQLiteDriver()                        */
@@ -46,6 +51,9 @@ CPL_CVSID("$Id: ogrsqlitedriver.cpp 25409 2012-12-31 11:51:10Z rouault $");
 OGRSQLiteDriver::~OGRSQLiteDriver()
 
 {
+#ifdef SPATIALITE_412_OR_LATER
+    spatialite_shutdown();
+#endif
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
index 58e4955..8a2c12a 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.cpp 25435 2013-01-02 20:40:56Z rouault $
+ * $Id: ogrsqliteexecutesql.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -66,7 +66,7 @@ OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(char* pszTmpDBName,
 
                                OGRSQLiteSelectLayer(poDS, osSQL, hStmt,
                                                     bUseStatementForGetNextFeature,
-                                                    bEmptyLayer)
+                                                    bEmptyLayer, TRUE)
 {
     this->pszTmpDBName = pszTmpDBName;
 }
@@ -482,6 +482,226 @@ void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer* poLayer)
     CSLDestroy(papszIgnored);
 }
 
+
+/************************************************************************/
+/*                  OGR2SQLITEDealWithSpatialColumn()                   */
+/************************************************************************/
+static
+int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
+                                    int iGeomCol,
+                                    const LayerDesc& oLayerDesc,
+                                    const CPLString& osTableName,
+                                    OGRSQLiteDataSource* poSQLiteDS,
+                                    sqlite3* hDB,
+                                    int bSpatialiteDB,
+                                    const std::set<LayerDesc>& oSetLayers,
+                                    const std::set<CPLString>& oSetSpatialIndex
+                                   )
+{
+    int rc;
+
+    OGRGeomFieldDefn* poGeomField =
+        poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol);
+    CPLString osGeomColRaw;
+    if( iGeomCol == 0 )
+        osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer);
+    else
+        osGeomColRaw = poGeomField->GetNameRef();
+    const char* pszGeomColRaw = osGeomColRaw.c_str();
+
+    CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
+    const char* pszGeomColEscaped = osGeomColEscaped.c_str();
+
+    CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
+    const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();
+
+    CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
+                    oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
+    CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));
+
+    /* Make sure that the SRS is injected in spatial_ref_sys */
+    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
+    if( iGeomCol == 0 && poSRS == NULL )
+        poSRS = poLayer->GetSpatialRef();
+    int nSRSId = poSQLiteDS->GetUndefinedSRID();
+    if( poSRS != NULL )
+        nSRSId = poSQLiteDS->FetchSRSId(poSRS);
+
+    CPLString osSQL;
+    int bCreateSpatialIndex = FALSE;
+    if( !bSpatialiteDB )
+    {
+        osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
+                    "f_geometry_column, geometry_format, geometry_type, "
+                    "coord_dimension, srid) "
+                    "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
+                    pszLayerNameEscaped,
+                    pszGeomColEscaped,
+                        (int) wkbFlatten(poLayer->GetGeomType()),
+                    ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2,
+                    nSRSId);
+    }
+#ifdef HAVE_SPATIALITE
+    else
+    {
+        /* We detect the need for creating a spatial index by 2 means : */
+
+        /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
+        /*   table in the SQL --> old/traditionnal way of requesting spatial indices */
+        /*   with spatialite. */
+
+        std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin();
+        for(; oIter2 != oSetLayers.end(); ++oIter2)
+        {
+            const LayerDesc& oLayerDescIter = *oIter2;
+            if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
+            {
+                    bCreateSpatialIndex = TRUE;
+                    break;
+            }
+        }
+
+        /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */
+        if( !bCreateSpatialIndex )
+        {
+            std::set<CPLString>::const_iterator oIter3 = oSetSpatialIndex.begin();
+            for(; oIter3 != oSetSpatialIndex.end(); ++oIter3)
+            {
+                const CPLString& osNameIter = *oIter3;
+                if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
+                {
+                    bCreateSpatialIndex = TRUE;
+                    break;
+                }
+            }
+        }
+
+        if( poSQLiteDS->HasSpatialite4Layout() )
+        {
+            int nGeomType = poLayer->GetGeomType();
+            int nCoordDimension = 2;
+            if( nGeomType & wkb25DBit )
+            {
+                nGeomType += 1000;
+                nCoordDimension = 3;
+            }
+
+            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
+                        "f_geometry_column, geometry_type, coord_dimension, "
+                        "srid, spatial_index_enabled) "
+                        "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)",
+                        pszLayerNameEscaped,
+                        pszGeomColEscaped, nGeomType,
+                        nCoordDimension,
+                        nSRSId, bCreateSpatialIndex );
+        }
+        else
+        {
+            const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType());
+            if (pszGeometryType[0] == '\0')
+                pszGeometryType = "GEOMETRY";
+
+            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
+                        "f_geometry_column, type, coord_dimension, "
+                        "srid, spatial_index_enabled) "
+                        "VALUES ('%s','%s','%s','%s',%d, %d)",
+                        pszLayerNameEscaped,
+                        pszGeomColEscaped, pszGeometryType,
+                        ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY",
+                        nSRSId, bCreateSpatialIndex );
+        }
+    }
+#endif // HAVE_SPATIALITE
+    rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
+
+#ifdef HAVE_SPATIALITE
+/* -------------------------------------------------------------------- */
+/*      Should we create a spatial index ?.                             */
+/* -------------------------------------------------------------------- */
+    if( !bSpatialiteDB || !bCreateSpatialIndex )
+        return rc == SQLITE_OK;
+
+    CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());
+
+    /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
+#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
+    osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING "
+                    "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
+                    osIdxNameEscaped.c_str(),
+                    nExtraDS,
+                    OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());
+
+    rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLDebug("SQLITE",
+                    "Error occured during spatial index creation : %s",
+                    sqlite3_errmsg(hDB));
+    }
+#else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
+    rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );
+
+    osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
+                    "USING rtree(pkid, xmin, xmax, ymin, ymax)",
+                    osIdxNameEscaped.c_str());
+
+    if( rc == SQLITE_OK )
+        rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
+
+    sqlite3_stmt *hStmt = NULL;
+    if( rc == SQLITE_OK )
+    {
+        const char* pszInsertInto = CPLSPrintf(
+            "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
+            "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
+        rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
+    }
+
+    OGRFeature* poFeature;
+    OGREnvelope sEnvelope;
+    OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
+    poLayer->ResetReading();
+
+    while( rc == SQLITE_OK &&
+            (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        if( poGeom != NULL && !poGeom->IsEmpty() )
+        {
+            poGeom->getEnvelope(&sEnvelope);
+            sqlite3_bind_int64(hStmt, 1,
+                                (sqlite3_int64) poFeature->GetFID() );
+            sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
+            sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
+            sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
+            sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
+            rc = sqlite3_step(hStmt);
+            if( rc == SQLITE_OK || rc == SQLITE_DONE )
+                rc = sqlite3_reset(hStmt);
+        }
+        delete poFeature;
+    }
+
+    poLayer->SetIgnoredFields(NULL);
+
+    sqlite3_finalize(hStmt);
+
+    if( rc == SQLITE_OK )
+        rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
+    else
+    {
+        CPLDebug("SQLITE",
+                    "Error occured during spatial index creation : %s",
+                    sqlite3_errmsg(hDB));
+        rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
+    }
+#endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
+
+#endif // HAVE_SPATIALITE
+
+    return rc == SQLITE_OK;
+}
+
 /************************************************************************/
 /*                          OGRSQLiteExecuteSQL()                       */
 /************************************************************************/
@@ -654,12 +874,6 @@ OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
             osTableName = oLayerDesc.osLayerName;
 
             nExtraDS = -1;
-
-            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
-                         OGRSQLiteEscapeName(osTableName).c_str(),
-                         nExtraDS,
-                         OGRSQLiteEscape(osTableName).c_str(),
-                         bFoundOGRStyle);
         }
         else
         {
@@ -693,14 +907,14 @@ OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
             osTableName = oLayerDesc.osSubstitutedName;
 
             nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS);
-
-            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
-                         OGRSQLiteEscapeName(osTableName).c_str(),
-                         nExtraDS,
-                         OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
-                         bFoundOGRStyle);
         }
 
+        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
+                OGRSQLiteEscapeName(osTableName).c_str(),
+                nExtraDS,
+                OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
+                bFoundOGRStyle);
+
         char* pszErrMsg = NULL;
         int rc = sqlite3_exec( hDB, osSQL.c_str(),
                                NULL, NULL, &pszErrMsg );
@@ -713,199 +927,13 @@ OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
             continue;
         }
 
-        if( poLayer->GetGeomType() == wkbNone )
-            continue;
-
-        CPLString osGeomColRaw(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
-        const char* pszGeomColRaw = osGeomColRaw.c_str();
-
-        CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
-        const char* pszGeomColEscaped = osGeomColEscaped.c_str();
-
-        CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
-        const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();
-
-        CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
-                        oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
-        CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));
-
-        /* Make sure that the SRS is injected in spatial_ref_sys */
-        OGRSpatialReference* poSRS = poLayer->GetSpatialRef();
-        int nSRSId = poSQLiteDS->GetUndefinedSRID();
-        if( poSRS != NULL )
-            nSRSId = poSQLiteDS->FetchSRSId(poSRS);
-
-        int bCreateSpatialIndex = FALSE;
-        if( !bSpatialiteDB )
+        for(int i=0; i<poLayer->GetLayerDefn()->GetGeomFieldCount(); i++)
         {
-            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
-                        "f_geometry_column, geometry_format, geometry_type, "
-                        "coord_dimension, srid) "
-                        "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
-                        pszLayerNameEscaped,
-                        pszGeomColEscaped,
-                         (int) wkbFlatten(poLayer->GetGeomType()),
-                        ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2,
-                        nSRSId);
+            OGR2SQLITEDealWithSpatialColumn(poLayer, i, oLayerDesc,
+                                            osTableName, poSQLiteDS, hDB,
+                                            bSpatialiteDB, oSetLayers,
+                                            oSetSpatialIndex);
         }
-#ifdef HAVE_SPATIALITE
-        else
-        {
-            /* We detect the need for creating a spatial index by 2 means : */
-
-            /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
-            /*   table in the SQL --> old/traditionnal way of requesting spatial indices */
-            /*   with spatialite. */
-
-            std::set<LayerDesc>::iterator oIter2 = oSetLayers.begin();
-            for(; oIter2 != oSetLayers.end(); ++oIter2)
-            {
-                const LayerDesc& oLayerDescIter = *oIter2;
-                if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
-                {
-                     bCreateSpatialIndex = TRUE;
-                     break;
-                }
-            }
-
-            /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */
-            if( !bCreateSpatialIndex )
-            {
-                std::set<CPLString>::iterator oIter3 = oSetSpatialIndex.begin();
-                for(; oIter3 != oSetSpatialIndex.end(); ++oIter3)
-                {
-                    const CPLString& osNameIter = *oIter3;
-                    if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
-                    {
-                        bCreateSpatialIndex = TRUE;
-                        break;
-                    }
-                }
-            }
-
-            if( poSQLiteDS->HasSpatialite4Layout() )
-            {
-                int nGeomType = poLayer->GetGeomType();
-                int nCoordDimension = 2;
-                if( nGeomType & wkb25DBit )
-                {
-                    nGeomType += 1000;
-                    nCoordDimension = 3;
-                }
-
-                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
-                            "f_geometry_column, geometry_type, coord_dimension, "
-                            "srid, spatial_index_enabled) "
-                            "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)",
-                            pszLayerNameEscaped,
-                            pszGeomColEscaped, nGeomType,
-                            nCoordDimension,
-                            nSRSId, bCreateSpatialIndex );
-            }
-            else
-            {
-                const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType());
-                if (pszGeometryType[0] == '\0')
-                    pszGeometryType = "GEOMETRY";
-
-                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
-                            "f_geometry_column, type, coord_dimension, "
-                            "srid, spatial_index_enabled) "
-                            "VALUES ('%s','%s','%s','%s',%d, %d)",
-                            pszLayerNameEscaped,
-                            pszGeomColEscaped, pszGeometryType,
-                            ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY",
-                            nSRSId, bCreateSpatialIndex );
-            }
-        }
-#endif // HAVE_SPATIALITE
-        sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
-
-#ifdef HAVE_SPATIALITE
-/* -------------------------------------------------------------------- */
-/*      Should we create a spatial index ?.                             */
-/* -------------------------------------------------------------------- */
-        if( !bSpatialiteDB || !bCreateSpatialIndex )
-            continue;
-
-        CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());
-
-        /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
-#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
-        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING "
-                     "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
-                     osIdxNameEscaped.c_str(),
-                     nExtraDS,
-                     OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());
-
-        rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
-        if( rc != SQLITE_OK )
-        {
-            CPLDebug("SQLITE",
-                     "Error occured during spatial index creation : %s",
-                     sqlite3_errmsg(hDB));
-        }
-#else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
-        rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );
-
-        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
-                     "USING rtree(pkid, xmin, xmax, ymin, ymax)",
-                      osIdxNameEscaped.c_str());
-
-        if( rc == SQLITE_OK )
-            rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
-
-        sqlite3_stmt *hStmt = NULL;
-        if( rc == SQLITE_OK )
-        {
-            const char* pszInsertInto = CPLSPrintf(
-                "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
-                "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
-            rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
-        }
-
-        OGRFeature* poFeature;
-        OGREnvelope sEnvelope;
-        OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
-        poLayer->ResetReading();
-
-        while( rc == SQLITE_OK &&
-               (poFeature = poLayer->GetNextFeature()) != NULL )
-        {
-            OGRGeometry* poGeom = poFeature->GetGeometryRef();
-            if( poGeom != NULL && !poGeom->IsEmpty() )
-            {
-                poGeom->getEnvelope(&sEnvelope);
-                sqlite3_bind_int64(hStmt, 1,
-                                   (sqlite3_int64) poFeature->GetFID() );
-                sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
-                sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
-                sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
-                sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
-                rc = sqlite3_step(hStmt);
-                if( rc == SQLITE_OK || rc == SQLITE_DONE )
-                    rc = sqlite3_reset(hStmt);
-            }
-            delete poFeature;
-        }
-
-        poLayer->SetIgnoredFields(NULL);
-
-        sqlite3_finalize(hStmt);
-
-        if( rc == SQLITE_OK )
-            rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
-        else
-        {
-            CPLDebug("SQLITE",
-                     "Error occured during spatial index creation : %s",
-                     sqlite3_errmsg(hDB));
-            rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
-        }
-#endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
-
-#endif // HAVE_SPATIALITE
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -992,7 +1020,7 @@ OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
                                             bUseStatementForGetNextFeature, bEmptyLayer );
 
     if( poSpatialFilter != NULL )
-        poLayer->SetSpatialFilter( poSpatialFilter );
+        poLayer->SetSpatialFilter( 0, poSpatialFilter );
 
     return poLayer;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
index 1f7548b..45f5a29 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.h 24972 2012-09-25 05:53:19Z rouault $
+ * $Id: ogrsqliteexecutesql.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
index a28fd3f..a5b5bcb 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitelayer.cpp 25454 2013-01-05 14:18:12Z rouault $
+ * $Id: ogrsqlitelayer.cpp 27102 2014-03-28 09:03:37Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteLayer class, code shared between 
@@ -16,6 +16,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,7 +42,7 @@
 #include "ogr_sqlite.h"
 #include <cassert>
 
-CPL_CVSID("$Id: ogrsqlitelayer.cpp 25454 2013-01-05 14:18:12Z rouault $");
+CPL_CVSID("$Id: ogrsqlitelayer.cpp 27102 2014-03-28 09:03:37Z rouault $");
 
 /************************************************************************/
 /*                           OGRSQLiteLayer()                           */
@@ -54,21 +55,14 @@ OGRSQLiteLayer::OGRSQLiteLayer()
 
     pszFIDColumn = NULL;
 
-    eGeomFormat = OSGF_None;
-
     hStmt = NULL;
     bDoStep = TRUE;
 
     iNextShapeId = 0;
 
-    poSRS = NULL;
-    nSRSId = UNINITIALIZED_SRID; // we haven't even queried the database for it yet. 
-
     panFieldOrdinals = NULL;
     iFIDCol = -1;
-    iGeomCol = -1;
 
-    bTriedAsSpatiaLite = FALSE;
     bHasSpatialIndex = FALSE;
     bHasM = FALSE;
 
@@ -77,6 +71,8 @@ OGRSQLiteLayer::OGRSQLiteLayer()
     bUseComprGeom = CSLTestBoolean(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
 
     papszCompressedColumns = NULL;
+
+    bAllowMultipleGeomFields = FALSE;
 }
 
 /************************************************************************/
@@ -118,12 +114,6 @@ void OGRSQLiteLayer::Finalize()
         poFeatureDefn = NULL;
     }
 
-    if( poSRS != NULL )
-    {
-        poSRS->Release();
-        poSRS = NULL;
-    }
-
     CPLFree( pszFIDColumn );
     pszFIDColumn = NULL;
     CPLFree( panFieldOrdinals );
@@ -140,8 +130,7 @@ void OGRSQLiteLayer::Finalize()
 static
 int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt, int iCol,
                         OGRFieldDefn& oField,
-                        OGRSQLiteGeomFormat& eGeomFormat,
-                        CPLString& osGeomColumn )
+                        OGRSQLiteGeomFormat& eGeomFormat )
 {
     OGRGeometry* poGeometry = NULL;
     const int nBytes = sqlite3_column_bytes( hStmt, iCol );
@@ -171,7 +160,6 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt, int iCol,
     delete poGeometry;
     if( eGeomFormat != OSGF_None )
     {
-        osGeomColumn = oField.GetNameRef();
         return TRUE;
     }
     return FALSE;
@@ -186,14 +174,16 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt, int iCol,
 
 void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                                        sqlite3_stmt *hStmt,
+                                       const char* pszExpectedGeomCol,
                                        const std::set<CPLString>& aosGeomCols )
 
 {
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
-    int    nRawColumns = sqlite3_column_count( hStmt );
-
+    poFeatureDefn = new OGRSQLiteFeatureDefn( pszLayerName );
+    poFeatureDefn->SetGeomType(wkbNone);
     poFeatureDefn->Reference();
 
+    int    nRawColumns = sqlite3_column_count( hStmt );
+
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
     int iCol;
@@ -221,9 +211,14 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
         //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
 
-        if( osGeomColumn.size()
-            && EQUAL(oField.GetNameRef(),osGeomColumn) )
+        if( pszExpectedGeomCol != NULL
+            && EQUAL(oField.GetNameRef(),pszExpectedGeomCol) )
+        {
+            OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+            poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             continue;
+        }
         if( aosGeomCols.find( oField.GetNameRef() ) != aosGeomCols.end() )
             continue;
 
@@ -239,8 +234,49 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             else if (EQUAL(pszDeclType, "FLOAT") ||
                      EQUAL(pszDeclType, "DECIMAL"))
                 nColType = SQLITE_FLOAT;
-            else if (EQUAL(pszDeclType, "BLOB"))
+            else if (EQUALN(pszDeclType, "BLOB", 4))
+            {
                 nColType = SQLITE_BLOB;
+                /* Parse format like BLOB_POINT_25D_4326 created by */
+                /* OGRSQLiteExecuteSQL() */
+                if( pszDeclType[4] == '_' )
+                {
+                    char* pszDeclTypeDup = CPLStrdup(pszDeclType);
+                    char* pszNextUnderscore = strchr(pszDeclTypeDup + 5, '_');
+                    const char* pszGeomType = pszDeclTypeDup + 5;
+                    if( pszNextUnderscore != NULL )
+                    {
+                        *pszNextUnderscore = '\0';
+                        pszNextUnderscore ++;
+                        int nSRID = -1;
+                        const char* pszCoordDimension = pszNextUnderscore;
+                        pszNextUnderscore = strchr(pszNextUnderscore, '_');
+                        if( pszNextUnderscore != NULL )
+                        {
+                            *pszNextUnderscore = '\0';
+                            pszNextUnderscore ++;
+                            const char* pszSRID = pszNextUnderscore;
+                            nSRID = atoi(pszSRID);
+                        }
+
+                        OGRwkbGeometryType eGeomType =
+                            OGRFromOGCGeomType(pszGeomType);
+                        if( EQUAL(pszCoordDimension, "25D") )
+                            eGeomType = (OGRwkbGeometryType)
+                                (eGeomType | wkb25DBit);
+                        OGRSpatialReference* poSRS = poDS->FetchSRS(nSRID);
+                        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                            new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                        poGeomFieldDefn->eGeomFormat = OSGF_SpatiaLite;
+                        poGeomFieldDefn->SetSpatialRef(poSRS);
+                        poGeomFieldDefn->SetType(eGeomType);
+                        poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
+                        CPLFree(pszDeclTypeDup);
+                        continue;
+                    }
+                    CPLFree(pszDeclTypeDup);
+                }
+            }
             else if (EQUAL(pszDeclType, "TEXT") ||
                      EQUALN(pszDeclType, "VARCHAR", 7))
             {
@@ -257,13 +293,26 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 }
             }
             else if ((EQUAL(pszDeclType, "TIMESTAMP") ||
-                      EQUAL(pszDeclType, "DATETIME")) && nColType == SQLITE_TEXT)
+                      EQUAL(pszDeclType, "DATETIME")) &&
+                     (nColType == SQLITE_TEXT || nColType == SQLITE_NULL))
                 eFieldType = OFTDateTime;
-            else if (EQUAL(pszDeclType, "DATE") && nColType == SQLITE_TEXT)
+            else if (EQUAL(pszDeclType, "DATE") &&
+                     (nColType == SQLITE_TEXT || nColType == SQLITE_NULL))
                 eFieldType = OFTDate;
-            else if (EQUAL(pszDeclType, "TIME") && nColType == SQLITE_TEXT)
+            else if (EQUAL(pszDeclType, "TIME") &&
+                     (nColType == SQLITE_TEXT || nColType == SQLITE_NULL))
                 eFieldType = OFTTime;
         }
+        else if( nColType == SQLITE_TEXT &&
+                 (EQUALN(oField.GetNameRef(), "MIN(", 4) ||
+                  EQUALN(oField.GetNameRef(), "MAX(", 4)) &&
+                 sqlite3_column_text( hStmt, iCol ) != NULL )
+        {
+            int nRet = OGRSQLITEStringToDateTimeField(NULL, 0,
+                              (const char*)sqlite3_column_text( hStmt, iCol ));
+            if( nRet > 0 )
+                eFieldType = (OGRFieldType) nRet;
+        }
 
         // Recognise some common geometry column names.
         if( (EQUAL(oField.GetNameRef(),"wkt_geometry") 
@@ -271,24 +320,32 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
              || EQUALN(oField.GetNameRef(), "asbinary(", 9)
              || EQUALN(oField.GetNameRef(), "astext(", 7)
              || (EQUALN(oField.GetNameRef(), "st_", 3) && nColType == SQLITE_BLOB ) )
-            && osGeomColumn.size() == 0 )
+            && (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             if( nColType == SQLITE_BLOB )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, iCol );
                 if( nBytes > 0 )
                 {
-                    if( OGRIsBinaryGeomCol( hStmt, iCol, oField,
-                                    eGeomFormat, osGeomColumn ) )
+                    OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
+                    if( OGRIsBinaryGeomCol( hStmt, iCol, oField, eGeomFormat ) )
+                    {
+                        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                            new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                        poGeomFieldDefn->eGeomFormat = eGeomFormat;
+                        poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
                         continue;
+                    }
                 }
                 else
                 {
                     /* This could also be a SpatialLite geometry, so */
                     /* we'll also try to decode as SpatialLite if */
                     /* bTriedAsSpatiaLite is not FALSE */
-                    osGeomColumn = oField.GetNameRef();
-                    eGeomFormat = OSGF_WKB;
+                    OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                        new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                    poGeomFieldDefn->eGeomFormat = OSGF_WKB;
+                    poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
                     continue;
                 }
             }
@@ -297,13 +354,17 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 char* pszText = (char*) sqlite3_column_text( hStmt, iCol );
                 if( pszText != NULL )
                 {
+                    OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
                     CPLPushErrorHandler(CPLQuietErrorHandler);
                     OGRGeometry* poGeometry = NULL;
                     if( OGRGeometryFactory::createFromWkt( 
                         &pszText, NULL, &poGeometry ) == OGRERR_NONE )
                     {
-                        osGeomColumn = oField.GetNameRef();
                         eGeomFormat = OSGF_WKT;
+                        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                            new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                        poGeomFieldDefn->eGeomFormat = eGeomFormat;
+                        poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
                     }
                     CPLPopErrorHandler();
                     CPLErrorReset();
@@ -313,8 +374,10 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 }
                 else
                 {
-                    osGeomColumn = oField.GetNameRef();
-                    eGeomFormat = OSGF_WKT;
+                    OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                        new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                    poGeomFieldDefn->eGeomFormat = OSGF_WKT;
+                    poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
                     continue;
                 }
             }
@@ -322,21 +385,31 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
         // SpatialLite / Gaia
         if( EQUAL(oField.GetNameRef(),"GaiaGeometry") 
-            && osGeomColumn.size() == 0 )
+            && (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
-            osGeomColumn = oField.GetNameRef();
-            eGeomFormat = OSGF_SpatiaLite;
+            OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+            poGeomFieldDefn->eGeomFormat = OSGF_SpatiaLite;
+            poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             continue;
         }
 
         // Recognize a geometry column from trying to build the geometry
         // Usefull for OGRSQLiteSelectLayer
-        if( nColType == SQLITE_BLOB && osGeomColumn.size() == 0 )
+        if( nColType == SQLITE_BLOB && 
+            (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             const int nBytes = sqlite3_column_bytes( hStmt, iCol );
+            OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
             if( nBytes > 0 && OGRIsBinaryGeomCol( hStmt, iCol, oField,
-                                                  eGeomFormat, osGeomColumn ) )
+                                                  eGeomFormat ) )
+            {
+                OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                    new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
+                poGeomFieldDefn->eGeomFormat = eGeomFormat;
+                poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
                 continue;
+            }
         }
 
         // The rowid is for internal use, not a real column.
@@ -375,7 +448,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         }
 
         poFeatureDefn->AddFieldDefn( &oField );
-        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
+        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
     }
 
     if( pszFIDColumn != NULL )
@@ -390,25 +463,6 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             }
         }
     }
-
-/* -------------------------------------------------------------------- */
-/*      If we have no geometry source, we know our geometry type is     */
-/*      none.                                                           */
-/* -------------------------------------------------------------------- */
-    if( osGeomColumn.size() == 0 )
-        poFeatureDefn->SetGeomType( wkbNone );
-    else
-    {
-        for( iCol = 0; iCol < nRawColumns; iCol++ )
-        {
-            if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
-                      osGeomColumn) )
-            {
-                iGeomCol = iCol;
-                break;
-            }
-        }
-    }
 }
 
 /************************************************************************/
@@ -425,19 +479,6 @@ const char *OGRSQLiteLayer::GetFIDColumn()
 }
 
 /************************************************************************/
-/*                         GetGeometryColumn()                          */
-/************************************************************************/
-
-const char *OGRSQLiteLayer::GetGeometryColumn() 
-
-{
-    if( osGeomColumn.size() != 0 )
-        return osGeomColumn.c_str();
-    else
-        return "";
-}
-
-/************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
 
@@ -464,7 +505,7 @@ OGRFeature *OGRSQLiteLayer::GetNextFeature()
             return NULL;
 
         if( (m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
             return poFeature;
@@ -534,67 +575,79 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Process Geometry if we have a column.                           */
 /* -------------------------------------------------------------------- */
-    if( iGeomCol >= 0 && !poFeatureDefn->IsGeometryIgnored() )
+    for( iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
     {
-        OGRGeometry *poGeometry = NULL;
-        if ( eGeomFormat == OSGF_WKT )
-        {
-            char *pszWKTCopy, *pszWKT = NULL;
-
-            pszWKT = (char *) sqlite3_column_text( hStmt, iGeomCol );
-            pszWKTCopy = pszWKT;
-            if( OGRGeometryFactory::createFromWkt( 
-                    &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
-                poFeature->SetGeometryDirectly( poGeometry );
-        }
-        else if ( eGeomFormat == OSGF_WKB )
+        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(iField);
+        if( !poGeomFieldDefn->IsIgnored() )
         {
-            const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
-
-            /* Try as spatialite first since createFromWkb() can sometimes */
-            /* interpret spatialite blobs as WKB for certain SRID values */
-            if (!bTriedAsSpatiaLite)
+            OGRGeometry *poGeometry = NULL;
+            if ( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
             {
-                /* If the layer is the result of a sql select, we cannot be sure if it is */
-                /* WKB or SpatialLite format */
-                if( ImportSpatiaLiteGeometry( 
-                    (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
-                    &poGeometry ) == OGRERR_NONE )
+                char *pszWKTCopy, *pszWKT = NULL;
+
+                pszWKT = (char *) sqlite3_column_text( hStmt, poGeomFieldDefn->iCol );
+                pszWKTCopy = pszWKT;
+                if( OGRGeometryFactory::createFromWkt( 
+                        &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
                 {
-                    poFeature->SetGeometryDirectly( poGeometry );
-                    eGeomFormat = OSGF_SpatiaLite;
+                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
                 }
-                bTriedAsSpatiaLite = TRUE;
             }
+            else if ( poGeomFieldDefn->eGeomFormat == OSGF_WKB )
+            {
+                const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
+
+                /* Try as spatialite first since createFromWkb() can sometimes */
+                /* interpret spatialite blobs as WKB for certain SRID values */
+                if (!poGeomFieldDefn->bTriedAsSpatiaLite)
+                {
+                    /* If the layer is the result of a sql select, we cannot be sure if it is */
+                    /* WKB or SpatialLite format */
+                    if( ImportSpatiaLiteGeometry( 
+                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
+                        &poGeometry ) == OGRERR_NONE )
+                    {
+                        poFeature->SetGeomFieldDirectly( iField, poGeometry );
+                        poGeomFieldDefn->eGeomFormat = OSGF_SpatiaLite;
+                    }
+                    poGeomFieldDefn->bTriedAsSpatiaLite = TRUE;
+                }
 
-            if( eGeomFormat == OSGF_WKB && OGRGeometryFactory::createFromWkb( 
-                    (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
-                    NULL, &poGeometry, nBytes ) == OGRERR_NONE )
+                if( poGeomFieldDefn->eGeomFormat == OSGF_WKB &&
+                    OGRGeometryFactory::createFromWkb( 
+                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
+                        NULL, &poGeometry, nBytes ) == OGRERR_NONE )
+                {
+                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
+                }
+            }
+            else if ( poGeomFieldDefn->eGeomFormat == OSGF_FGF )
             {
-                poFeature->SetGeometryDirectly( poGeometry );
+                const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
+
+                if( OGRGeometryFactory::createFromFgf( 
+                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
+                        NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
+                {
+                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
+                }
             }
-        }
-        else if ( eGeomFormat == OSGF_FGF )
-        {
-            const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
+            else if ( poGeomFieldDefn->eGeomFormat == OSGF_SpatiaLite )
+            {
+                const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
 
-            if( OGRGeometryFactory::createFromFgf( 
-                    (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
-                    NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
-                poFeature->SetGeometryDirectly( poGeometry );
-        }
-        else if ( eGeomFormat == OSGF_SpatiaLite )
-        {
-            const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
+                if( ImportSpatiaLiteGeometry( 
+                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
+                        &poGeometry ) == OGRERR_NONE )
+                {
+                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
+                }
+            }
 
-            if( ImportSpatiaLiteGeometry( 
-                    (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
-                    &poGeometry ) == OGRERR_NONE )
-                poFeature->SetGeometryDirectly( poGeometry );
+            if (poGeometry != NULL && poGeomFieldDefn->GetSpatialRef() != NULL)
+                poGeometry->assignSpatialReference(poGeomFieldDefn->GetSpatialRef());
         }
-
-        if (poGeometry != NULL && poSRS != NULL)
-            poGeometry->assignSpatialReference(poSRS);
     }
 
 /* -------------------------------------------------------------------- */
@@ -606,7 +659,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         if ( poFieldDefn->IsIgnored() )
             continue;
 
-        int iRawField = panFieldOrdinals[iField] - 1;
+        int iRawField = panFieldOrdinals[iField];
 
         if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
             continue;
@@ -883,18 +936,20 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         poGeom = poLS = new OGRLineString();
-        poLS->setNumPoints( nPointCount );
-
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        if( !NEED_SWAP_SPATIALITE() )
         {
-            memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
-            if (NEED_SWAP_SPATIALITE())
+            poLS->setPoints( nPointCount, (OGRRawPoint*)(pabyData + 8), NULL );
+        }
+        else
+        {
+            poLS->setNumPoints( nPointCount, FALSE );
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
                 CPL_SWAP64PTR( adfTuple );
                 CPL_SWAP64PTR( adfTuple + 1 );
+                poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
             }
-
-            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
         }
 
         if( pnBytesConsumed )
@@ -1372,35 +1427,46 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             nNextByte += 4;
 
             if( nBytes - nNextByte < 2 * 8 * nPointCount )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
-            
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            if( !NEED_SWAP_SPATIALITE() )
             {
-                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
-                nNextByte += 2 * 8;
-
-                if (NEED_SWAP_SPATIALITE())
+                poLR->setPoints( nPointCount, (OGRRawPoint*)(pabyData + nNextByte), NULL );
+                nNextByte += 2 * 8 * nPointCount;
+            }
+            else
+            {
+                poLR->setNumPoints( nPointCount, FALSE );
+                for( iPoint = 0; iPoint < nPointCount; iPoint++ )
                 {
+                    memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                    nNextByte += 2 * 8;
                     CPL_SWAP64PTR( adfTuple );
                     CPL_SWAP64PTR( adfTuple + 1 );
+                    poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
                 }
-
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
             }
 
             poPoly->addRingDirectly( poLR );
@@ -1444,22 +1510,31 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             nNextByte += 4;
 
             if( nBytes - nNextByte < 3 * 8 * nPointCount )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1517,22 +1592,31 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             nNextByte += 4;
 
             if( nBytes - nNextByte < 3 * 8 * nPointCount )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1590,22 +1674,31 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             nNextByte += 4;
 
             if( nBytes - nNextByte < 4 * 8 * nPointCount )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1666,14 +1759,20 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             compressedSize = 16 * 2;                  // first and last Points
             compressedSize += 8 * (nPointCount - 2);  // intermediate Points
@@ -1683,10 +1782,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             adfTupleBase[1] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1765,14 +1867,20 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             compressedSize = 24 * 2;                  	// first and last Points
             compressedSize += 12 * (nPointCount - 2);  // intermediate Points
@@ -1783,10 +1891,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             adfTupleBase[2] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1869,7 +1980,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
@@ -1877,7 +1991,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
 
             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             compressedSize = 24 * 2;                   // first and last Points
             compressedSize += 16 * (nPointCount - 2);  // intermediate Points
@@ -1887,10 +2004,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 			adfTupleBase[1] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -1969,14 +2089,20 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         for( iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
+            {
+                delete poPoly;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             compressedSize = 32 * 2;                   // first and last Points
             /* Note 20 is not an error : x,y,z are float and the m is a double */
@@ -1988,10 +2114,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             adfTupleBase[2] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
+            {
+                delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
+            poLR->setNumPoints( nPointCount, FALSE );
             
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
@@ -2127,10 +2256,16 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             OGRGeometry *poThisGeom = NULL;
 
             if (nBytes - nBytesUsed < 5)
+            {
+                delete poGC;
                 return OGRERR_NOT_ENOUGH_DATA;
+            }
 
             if (pabyData[nBytesUsed] != 0x69)
+            {
+                delete poGC;
                 return OGRERR_CORRUPT_DATA;
+            }
 
             nBytesUsed ++;
 
@@ -2877,16 +3012,6 @@ int OGRSQLiteLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRSQLiteLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                          StartTransaction()                          */
 /************************************************************************/
 
@@ -2948,9 +3073,10 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d:%f",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
     {
-        poFeature->SetField( iField, nYear, nMonth,
+        if( poFeature )
+            poFeature->SetField( iField, nYear, nMonth,
                                 nDay, nHour, nMinute, (int)(fSecond + 0.5), 0 );
-        return TRUE;
+        return OFTDateTime;
     }
 
     /* YYYY-MM-DD HH:MM */
@@ -2959,9 +3085,10 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
     {
-        poFeature->SetField( iField, nYear, nMonth,
+        if( poFeature )
+            poFeature->SetField( iField, nYear, nMonth,
                                 nDay, nHour, nMinute, 0, 0 );
-        return TRUE;
+        return OFTDateTime;
     }
 
     /*  YYYY-MM-DDTHH:MM:SS or YYYY-MM-DDTHH:MM:SS.SSS */
@@ -2970,9 +3097,10 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d:%f",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
     {
-        poFeature->SetField( iField, nYear, nMonth, nDay,
+        if( poFeature )
+            poFeature->SetField( iField, nYear, nMonth, nDay,
                                 nHour, nMinute, (int)(fSecond + 0.5), 0 );
-        return TRUE;
+        return OFTDateTime;
     }
 
     /* YYYY-MM-DDTHH:MM */
@@ -2981,9 +3109,10 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
     {
-        poFeature->SetField( iField, nYear, nMonth, nDay,
+        if( poFeature )
+            poFeature->SetField( iField, nYear, nMonth, nDay,
                                 nHour, nMinute, 0, 0 );
-        return TRUE;
+        return OFTDateTime;
     }
 
     /* YYYY-MM-DD */
@@ -2991,9 +3120,10 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%04d-%02d-%02d",
                 &nYear, &nMonth, &nDay) == 3 )
     {
-        poFeature->SetField( iField, nYear, nMonth, nDay,
+        if( poFeature )
+            poFeature->SetField( iField, nYear, nMonth, nDay,
                                 0, 0, 0, 0 );
-        return TRUE;
+        return OFTDate;
     }
 
     /*  HH:MM:SS or HH:MM:SS.SSS */
@@ -3001,18 +3131,20 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     if( sscanf(pszValue, "%02d:%02d:%f",
         &nHour, &nMinute, &fSecond) == 3 )
     {
-        poFeature->SetField( iField, 0, 0, 0,
+        if( poFeature )
+            poFeature->SetField( iField, 0, 0, 0,
                                 nHour, nMinute, (int)(fSecond + 0.5), 0 );
-        return TRUE;
+        return OFTTime;
     }
 
     /*  HH:MM */
     nHour = 0; nMinute = 0;
     if( sscanf(pszValue, "%02d:%02d", &nHour, &nMinute) == 2 )
     {
-        poFeature->SetField( iField, 0, 0, 0,
+        if( poFeature )
+            poFeature->SetField( iField, 0, 0, 0,
                                 nHour, nMinute, 0, 0 );
-        return TRUE;
+        return OFTTime;
     }
 
     return FALSE;
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
index 1e268e1..efa78d3 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqliteregexp.cpp 25406 2012-12-30 20:07:19Z rouault $
+ * $Id: ogrsqliteregexp.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite REGEXP function
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
index 8426693..585e10b 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqliteregexp.h 25406 2012-12-30 20:07:19Z rouault $
+ * $Id: ogrsqliteregexp.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite REGEXP function
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
index ee76d77..5a8d36a 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteselectlayer.cpp 25694 2013-03-01 17:26:40Z rouault $
+ * $Id: ogrsqliteselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSelectLayer class, layer access to the results
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +31,10 @@
 
 #include "cpl_conv.h"
 #include "ogr_sqlite.h"
+#include "swq.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 25694 2013-03-01 17:26:40Z rouault $");
+CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /************************************************************************/
 /*                        OGRSQLiteSelectLayer()                        */
 /************************************************************************/
@@ -40,7 +43,8 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
                                             CPLString osSQLIn,
                                             sqlite3_stmt *hStmtIn,
                                             int bUseStatementForGetNextFeature,
-                                            int bEmptyLayer )
+                                            int bEmptyLayer,
+                                            int bAllowMultipleGeomFields )
 
 {
     poDS = poDSIn;
@@ -48,9 +52,10 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
     iNextShapeId = 0;
     poFeatureDefn = NULL;
     bAllowResetReadingEvenIfIndexAtZero = FALSE;
+    this->bAllowMultipleGeomFields = bAllowMultipleGeomFields;
 
     std::set<CPLString> aosEmpty;
-    BuildFeatureDefn( "SELECT", hStmtIn, aosEmpty );
+    BuildFeatureDefn( "SELECT", hStmtIn, NULL, aosEmpty );
 
     if( bUseStatementForGetNextFeature )
     {
@@ -58,56 +63,63 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
         bDoStep = FALSE;
 
         // Try to extract SRS from first geometry
-        if( !bEmptyLayer && osGeomColumn.size() != 0 )
+        for( int iField = 0;
+             !bEmptyLayer && iField < poFeatureDefn->GetGeomFieldCount();
+             iField ++)
         {
-            int    nRawColumns = sqlite3_column_count( hStmt );
-            for( int iCol = 0; iCol < nRawColumns; iCol++ )
+            OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                poFeatureDefn->myGetGeomFieldDefn(iField);
+            if( wkbFlatten(poGeomFieldDefn->GetType()) != wkbUnknown )
+                continue;
+
+            int nBytes;
+            if( sqlite3_column_type( hStmt, poGeomFieldDefn->iCol ) == SQLITE_BLOB &&
+                (nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol )) > 39 )
             {
-                int nBytes;
-                if( sqlite3_column_type( hStmt, iCol ) == SQLITE_BLOB &&
-                    strcmp(OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )).c_str(), osGeomColumn.c_str()) == 0 &&
-                    (nBytes = sqlite3_column_bytes( hStmt, iCol )) > 39 )
+                const GByte* pabyBlob = (const GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
+                int eByteOrder = pabyBlob[1];
+                if( pabyBlob[0] == 0x00 &&
+                    (eByteOrder == wkbNDR || eByteOrder == wkbXDR) &&
+                    pabyBlob[38] == 0x7C )
                 {
-                    const GByte* pabyBlob = (const GByte*)sqlite3_column_blob( hStmt, iCol );
-                    int eByteOrder = pabyBlob[1];
-                    if( pabyBlob[0] == 0x00 &&
-                        (eByteOrder == wkbNDR || eByteOrder == wkbXDR) &&
-                        pabyBlob[38] == 0x7C )
-                    {
-                        memcpy(&nSRSId, pabyBlob + 2, 4);
+                    int nSRSId;
+                    memcpy(&nSRSId, pabyBlob + 2, 4);
 #ifdef CPL_LSB
-                        if( eByteOrder != wkbNDR)
-                            CPL_SWAP32PTR(&nSRSId);
+                    if( eByteOrder != wkbNDR)
+                        CPL_SWAP32PTR(&nSRSId);
 #else
-                        if( eByteOrder == wkbNDR)
-                            CPL_SWAP32PTR(&nSRSId);
+                    if( eByteOrder == wkbNDR)
+                        CPL_SWAP32PTR(&nSRSId);
 #endif
-                        CPLPushErrorHandler(CPLQuietErrorHandler);
-                        poSRS = poDS->FetchSRS( nSRSId );
-                        CPLPopErrorHandler();
-                        if( poSRS != NULL )
-                            poSRS->Reference();
-                        else
-                            CPLErrorReset();
+                    CPLPushErrorHandler(CPLQuietErrorHandler);
+                    OGRSpatialReference* poSRS = poDS->FetchSRS( nSRSId );
+                    CPLPopErrorHandler();
+                    if( poSRS != NULL )
+                    {
+                        poGeomFieldDefn->nSRSId = nSRSId;
+                        poGeomFieldDefn->SetSpatialRef(poSRS);
                     }
-#ifdef SQLITE_HAS_COLUMN_METADATA
                     else
+                        CPLErrorReset();
+                }
+#ifdef SQLITE_HAS_COLUMN_METADATA
+                else if( iField == 0 )
+                {
+                    const char* pszTableName = sqlite3_column_table_name( hStmt, poGeomFieldDefn->iCol );
+                    if( pszTableName != NULL )
                     {
-                        const char* pszTableName = sqlite3_column_table_name( hStmt, iCol );
-                        if( pszTableName != NULL )
+                        OGRSQLiteLayer* poLayer = (OGRSQLiteLayer*)
+                                        poDS->GetLayerByName(pszTableName);
+                        if( poLayer != NULL &&  poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
                         {
-                            OGRLayer* poLayer = poDS->GetLayerByName(pszTableName);
-                            if( poLayer != NULL )
-                            {
-                                poSRS = poLayer->GetSpatialRef();
-                                if( poSRS != NULL )
-                                    poSRS->Reference();
-                            }
+                            OGRSQLiteGeomFieldDefn* poSrcGFldDefn =
+                                poLayer->myGetLayerDefn()->myGetGeomFieldDefn(0);
+                            poGeomFieldDefn->nSRSId = poSrcGFldDefn->nSRSId;
+                            poGeomFieldDefn->SetSpatialRef(poSrcGFldDefn->GetSpatialRef());
                         }
                     }
-#endif
-                    break;
                 }
+#endif
             }
         }
     }
@@ -147,6 +159,65 @@ OGRFeature *OGRSQLiteSelectLayer::GetNextFeature()
 }
 
 /************************************************************************/
+/*               OGRGenSQLResultsLayerHasSpecialField()                 */
+/************************************************************************/
+
+static
+int HasSpecialFields(swq_expr_node* expr, int nMinIndexForSpecialField)
+{
+    if (expr->eNodeType == SNT_COLUMN)
+    {
+        if (expr->table_index == 0)
+        {
+            return expr->field_index >= nMinIndexForSpecialField &&
+                   expr->field_index < nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
+        }
+    }
+    else if (expr->eNodeType == SNT_OPERATION)
+    {
+        for( int i = 0; i < expr->nSubExprCount; i++ )
+        {
+            if (HasSpecialFields(expr->papoSubExpr[i], nMinIndexForSpecialField))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRSQLiteSelectLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    if( m_pszAttrQueryString == NULL && pszQuery == NULL )
+        return OGRERR_NONE;
+
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
+    bAllowResetReadingEvenIfIndexAtZero = TRUE;
+
+    OGRFeatureQuery oQuery;
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    int bHasSpecialFields = (pszQuery != NULL && pszQuery[0] != '\0' &&
+        oQuery.Compile( GetLayerDefn(), pszQuery ) == OGRERR_NONE &&
+        HasSpecialFields((swq_expr_node*)oQuery.GetSWGExpr(), GetLayerDefn()->GetFieldCount()) );
+    CPLPopErrorHandler();
+
+    if( bHasSpecialFields || !BuildSQL() )
+    {
+        return OGRSQLiteLayer::SetAttributeFilter(pszQuery);
+    }
+
+    ResetReading();
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
@@ -237,14 +308,26 @@ OGRErr OGRSQLiteSelectLayer::ResetStatement()
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
 
-void OGRSQLiteSelectLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+void OGRSQLiteSelectLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 {
+    if( iGeomField == 0 && poGeomIn == NULL && GetLayerDefn()->GetGeomFieldCount() == 0 )
+    {
+        /* do nothing */
+    }
+    else if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Invalid geometry field index : %d", iGeomField);
+        return;
+    }
+
     bAllowResetReadingEvenIfIndexAtZero = TRUE;
 
+    m_iGeomFieldFilter = iGeomField;
     if( InstallFilter( poGeomIn ) )
     {
-        bSpatialFilterInSQL = RebuildSQLWithSpatialClause();
+        BuildSQL();
 
         ResetReading();
     }
@@ -257,7 +340,7 @@ void OGRSQLiteSelectLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i)
 {
     char** papszTokens = CSLTokenizeString(osSQLBase.c_str());
-    int bCanInsertSpatialFilter = TRUE;
+    int bCanInsertFilter = TRUE;
     int nCountSelect = 0, nCountFrom = 0, nCountWhere = 0;
 
     for(int iToken = 0; papszTokens[iToken] != NULL; iToken++)
@@ -273,12 +356,12 @@ OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i)
                  EQUAL(papszTokens[iToken], "INTERSECT") ||
                  EQUAL(papszTokens[iToken], "EXCEPT"))
         {
-            bCanInsertSpatialFilter = FALSE;
+            bCanInsertFilter = FALSE;
         }
     }
     CSLDestroy(papszTokens);
 
-    if (!(bCanInsertSpatialFilter && nCountSelect == 1 && nCountFrom == 1 && nCountWhere <= 1))
+    if (!(bCanInsertFilter && nCountSelect == 1 && nCountFrom == 1 && nCountWhere <= 1))
     {
         CPLDebug("SQLITE", "SQL expression too complex to analyse");
         return NULL;
@@ -290,23 +373,24 @@ OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i)
         return NULL;
     }
 
-    int bInSingleQuotes = (osSQLBase[nFromPos + 6] == '\'');
+    char chQuote = osSQLBase[nFromPos + 6];
+    int bInQuotes = (chQuote == '\'' || chQuote == '"' );
     CPLString osBaseLayerName;
-    for( i = nFromPos + 6 + (bInSingleQuotes ? 1 : 0);
+    for( i = nFromPos + 6 + (bInQuotes ? 1 : 0);
          i < osSQLBase.size(); i++ )
     {
-        if (osSQLBase[i] == '\'' && i + 1 < osSQLBase.size() &&
-            osSQLBase[i + 1] == '\'' )
+        if (osSQLBase[i] == chQuote && i + 1 < osSQLBase.size() &&
+            osSQLBase[i + 1] == chQuote )
         {
             osBaseLayerName += osSQLBase[i];
             i++;
         }
-        else if (osSQLBase[i] == '\'' && bInSingleQuotes)
+        else if (osSQLBase[i] == chQuote && bInQuotes)
         {
             i++;
             break;
         }
-        else if (osSQLBase[i] == ' ' && !bInSingleQuotes)
+        else if (osSQLBase[i] == ' ' && !bInQuotes)
             break;
         else
             osBaseLayerName += osSQLBase[i];
@@ -314,22 +398,22 @@ OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i)
 
     OGRSQLiteLayer* poUnderlyingLayer = NULL;
     if( strchr(osBaseLayerName, '(') == NULL &&
-        osGeomColumn.size() != 0 )
+        poFeatureDefn->GetGeomFieldCount() != 0 )
     {
         CPLString osNewUnderlyingTableName;
         osNewUnderlyingTableName.Printf("%s(%s)",
                                         osBaseLayerName.c_str(),
-                                        osGeomColumn.c_str());
+                                        poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
         poUnderlyingLayer =
             (OGRSQLiteLayer*) poDS->GetLayerByName(osNewUnderlyingTableName);
     }
     if( poUnderlyingLayer == NULL )
         poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(osBaseLayerName);
 
-    if( poUnderlyingLayer != NULL && poSRS != NULL &&
+    if( poUnderlyingLayer != NULL && GetSpatialRef() != NULL &&
         poUnderlyingLayer->GetSpatialRef() != NULL &&
-        poSRS != poUnderlyingLayer->GetSpatialRef() &&
-        !poSRS->IsSame(poUnderlyingLayer->GetSpatialRef()) )
+        GetSpatialRef() != poUnderlyingLayer->GetSpatialRef() &&
+        !GetSpatialRef()->IsSame(poUnderlyingLayer->GetSpatialRef()) )
     {
         CPLDebug("SQLITE", "Result layer and base layer don't have the same SRS.");
         return NULL;
@@ -339,41 +423,71 @@ OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i)
 }
 
 /************************************************************************/
-/*                    RebuildSQLWithSpatialClause()                     */
+/*                             BuildSQL()                               */
 /************************************************************************/
 
-int OGRSQLiteSelectLayer::RebuildSQLWithSpatialClause()
+int OGRSQLiteSelectLayer::BuildSQL()
 
 {
     osSQLCurrent = osSQLBase;
-
-    if (m_poFilterGeom == NULL)
-    {
-        return TRUE;
-    }
+    bSpatialFilterInSQL = TRUE;
 
     size_t i = 0;
     OGRSQLiteLayer* poBaseLayer = GetBaseLayer(i);
     if (poBaseLayer == NULL)
     {
         CPLDebug("SQLITE", "Cannot find base layer");
+        bSpatialFilterInSQL = FALSE;
         return FALSE;
     }
 
-    CPLString    osSpatialWhere = poBaseLayer->GetSpatialWhere(m_poFilterGeom);
-    if (osSpatialWhere.size() == 0)
+    CPLString osSpatialWhere;
+    if (m_poFilterGeom != NULL)
     {
-        CPLDebug("SQLITE", "Cannot get spatial where clause");
-        return FALSE;
+        const char* pszGeomCol =
+            poFeatureDefn->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef();
+        int nIdx = poBaseLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomCol);
+        if( nIdx < 0 )
+        {
+            CPLDebug("SQLITE", "Cannot find field %s in base layer", pszGeomCol);
+            bSpatialFilterInSQL = FALSE;
+        }
+        else
+        {
+            osSpatialWhere = poBaseLayer->GetSpatialWhere(nIdx, m_poFilterGeom);
+            if (osSpatialWhere.size() == 0)
+            {
+                CPLDebug("SQLITE", "Cannot get spatial where clause");
+                bSpatialFilterInSQL = FALSE;
+            }
+        }
     }
 
+    CPLString osCustomWhere;
+    if( osSpatialWhere.size() != 0 )
+    {
+        osCustomWhere = osSpatialWhere;
+    }
+    if( m_pszAttrQueryString != NULL && m_pszAttrQueryString[0] != '\0' )
+    {
+        if( osSpatialWhere.size() != 0)
+            osCustomWhere += " AND (";
+        osCustomWhere += m_pszAttrQueryString;
+        if( osSpatialWhere.size() != 0)
+            osCustomWhere += ")";
+    }
+
+    /* Nothing to do */
+    if( osCustomWhere.size() == 0 )
+        return TRUE;
+
     while (i < osSQLBase.size() && osSQLBase[i] == ' ')
         i ++;
 
     if (i < osSQLBase.size() && EQUALN(osSQLBase.c_str() + i, "WHERE ", 6))
     {
         osSQLCurrent = osSQLBase.substr(0, i + 6);
-        osSQLCurrent += osSpatialWhere;
+        osSQLCurrent += osCustomWhere;
         osSQLCurrent += " AND (";
 
         size_t nEndOfWhere = osSQLBase.ifind(" GROUP ");
@@ -401,7 +515,7 @@ int OGRSQLiteSelectLayer::RebuildSQLWithSpatialClause()
     {
         osSQLCurrent = osSQLBase.substr(0, i);
         osSQLCurrent += " WHERE ";
-        osSQLCurrent += osSpatialWhere;
+        osSQLCurrent += osCustomWhere;
         osSQLCurrent += " ";
         osSQLCurrent += osSQLBase.substr(i);
     }
@@ -409,11 +523,12 @@ int OGRSQLiteSelectLayer::RebuildSQLWithSpatialClause()
     {
         osSQLCurrent = osSQLBase.substr(0, i);
         osSQLCurrent += " WHERE ";
-        osSQLCurrent += osSpatialWhere;
+        osSQLCurrent += osCustomWhere;
     }
     else
     {
-        CPLDebug("SQLITE", "SQL expression too complex for the driver to insert spatial filter in it");
+        CPLDebug("SQLITE", "SQL expression too complex for the driver to insert attribute and/or spatial filter in it");
+        bSpatialFilterInSQL = FALSE;
         return FALSE;
     }
 
@@ -443,7 +558,7 @@ int OGRSQLiteSelectLayer::TestCapability( const char * pszCap )
         OGRPolygon oFakePoly;
         const char* pszWKT = "POLYGON((0 0,0 1,1 1,1 0,0 0))";
         oFakePoly.importFromWkt((char**) &pszWKT);
-        CPLString    osSpatialWhere = poBaseLayer->GetSpatialWhere(&oFakePoly);
+        CPLString    osSpatialWhere = poBaseLayer->GetSpatialWhere(0, &oFakePoly);
 
         return osSpatialWhere.size() != 0;
     }
@@ -455,19 +570,30 @@ int OGRSQLiteSelectLayer::TestCapability( const char * pszCap )
 /*                             GetExtent()                              */
 /************************************************************************/
 
-OGRErr OGRSQLiteSelectLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+OGRErr OGRSQLiteSelectLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
 {
-    if (GetGeomType() == wkbNone)
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
         return OGRERR_FAILURE;
+    }
 
     /* Caching of extent by SQL string is interesting to speed-up the */
     /* establishment of the WFS GetCapabilities document for a MapServer mapfile */
     /* which has several layers, only differing by scale rules */
-    const OGREnvelope* psCachedExtent = poDS->GetEnvelopeFromSQL(osSQLBase);
-    if (psCachedExtent)
+    if( iGeomField == 0 )
     {
-        memcpy(psExtent, psCachedExtent, sizeof(*psCachedExtent));
-        return OGRERR_NONE;
+        const OGREnvelope* psCachedExtent = poDS->GetEnvelopeFromSQL(osSQLBase);
+        if (psCachedExtent)
+        {
+            memcpy(psExtent, psCachedExtent, sizeof(*psCachedExtent));
+            return OGRERR_NONE;
+        }
     }
 
     CPLString osSQLCommand = osSQLBase;
@@ -487,14 +613,18 @@ OGRErr OGRSQLiteSelectLayer::GetExtent(OGREnvelope *psExtent, int bForce)
         OGRLayer* poTmpLayer = poDS->ExecuteSQL(osSQLCommand.c_str(), NULL, NULL);
         if (poTmpLayer)
         {
-            OGRErr eErr = poTmpLayer->GetExtent(psExtent, bForce);
+            OGRErr eErr = poTmpLayer->GetExtent(iGeomField, psExtent, bForce);
             poDS->ReleaseResultSet(poTmpLayer);
             return eErr;
         }
     }
 
-    OGRErr eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce);
-    if (eErr == OGRERR_NONE && poDS->GetUpdate() == FALSE)
+    OGRErr eErr;
+    if( iGeomField == 0 )
+        eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce);
+    else
+        eErr = OGRSQLiteLayer::GetExtent(iGeomField, psExtent, bForce);
+    if (iGeomField == 0 && eErr == OGRERR_NONE && poDS->GetUpdate() == FALSE)
         poDS->SetEnvelopeForSQL(osSQLBase, *psExtent);
     return eErr;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
index 6c74f4b..008c092 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitesinglefeaturelayer.cpp 23736 2012-01-09 19:05:02Z rouault $
+ * $Id: ogrsqlitesinglefeaturelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSingleFeatureLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 23736 2012-01-09 19:05:02Z rouault $");
+CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                    OGRSQLiteSingleFeatureLayer()                     */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
index 959135c..a34b5a0 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitesqlfunctions.cpp 25462 2013-01-06 02:10:38Z rouault $
+ * $Id: ogrsqlitesqlfunctions.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Extension SQL functions
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
index a42c72f..da04f76 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitesqlfunctions.h 25406 2012-12-30 20:07:19Z rouault $
+ * $Id: ogrsqlitesqlfunctions.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Extension SQL functions
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index e96a4c5..5bb4f66 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 25394 2012-12-29 22:01:36Z rouault $
+ * $Id: ogrsqlitetablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 25394 2012-12-29 22:01:36Z rouault $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
@@ -53,7 +54,7 @@ OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
        to support 2.5D: if an obsolete version of the library
        is found we'll unconditionally activate 2D casting mode.
     */
-    bSpatialite2D = OGRSQLiteGetSpatialiteVersionNumber() < 24;
+    bSpatialite2D = poDS->GetSpatialiteVersionNumber() < 24;
 
     iNextShapeId = 0;
 
@@ -72,6 +73,11 @@ OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
     bStatisticsNeedsToBeFlushed = FALSE;
     bCachedExtentIsValid = FALSE;
     nFeatureCount = -1;
+
+    eGeomFormat = OSGF_None;
+    pszGeomCol = NULL;
+    nSRSId = UNINITIALIZED_SRID;
+    poSRS = NULL;
 }
 
 /************************************************************************/
@@ -84,6 +90,13 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
     ClearStatement();
     ClearInsertStmt();
 
+    CPLFree(pszGeomCol);
+    if( poSRS != NULL )
+    {
+        poSRS->Release();
+        poSRS = NULL;
+    }
+
     CPLFree(pszTableName);
     CPLFree(pszEscapedTableName);
 }
@@ -133,11 +146,6 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
     int rc;
     sqlite3 *hDB = poDS->GetDB();
 
-    if( pszGeomCol == NULL )
-        osGeomColumn = "";
-    else
-        osGeomColumn = pszGeomCol;
-
     if( pszGeomFormat )
     {
         if ( EQUAL(pszGeomFormat, "WKT") )
@@ -162,10 +170,11 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
     this->bHasM = bHasM;
     this->bIsVirtualShape = bIsVirtualShapeIn;
     this->pszTableName = CPLStrdup(pszTableName);
+    this->pszGeomCol = (pszGeomCol) ? CPLStrdup(pszGeomCol) : NULL;
     this->eGeomType = eGeomType;
 
     if( bMustIncludeGeomColName )
-        osLayerName.Printf("%s(%s)", pszTableName, osGeomColumn.c_str());
+        osLayerName.Printf("%s(%s)", pszTableName, pszGeomCol);
     else
         osLayerName = pszTableName;
 
@@ -175,8 +184,8 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
     const char *pszSQL;
 
     if ( eGeomFormat == OSGF_SpatiaLite &&
-         OGRSQLiteIsSpatialiteLoaded() && 
-         OGRSQLiteGetSpatialiteVersionNumber() < 24 && poDS->GetUpdate() )
+         poDS->IsSpatialiteLoaded() && 
+         poDS->GetSpatialiteVersionNumber() < 24 && poDS->GetUpdate() )
     {
     // we need to test version required by Spatialite TRIGGERs 
         hColStmt = NULL;
@@ -264,24 +273,114 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn()
 /*      name if the rowid corresponds to another primary key            */
 /*      column.                                                         */
 /* -------------------------------------------------------------------- */
+    CPLFree( pszFIDColumn );
     pszFIDColumn = CPLStrdup(OGRSQLiteParamsUnquote(sqlite3_column_name( hColStmt, 0 )));
 
 /* -------------------------------------------------------------------- */
 /*      Collect the rest of the fields.                                 */
 /* -------------------------------------------------------------------- */
-    BuildFeatureDefn( osLayerName, hColStmt, poDS->GetGeomColsForTable(pszTableName) );
+    BuildFeatureDefn( osLayerName, hColStmt, pszGeomCol, poDS->GetGeomColsForTable(pszTableName) );
     sqlite3_finalize( hColStmt );
 
 /* -------------------------------------------------------------------- */
-/*      Set the geometry type if we know it.                            */
+/*      Set the properties of the geometry column.                      */
 /* -------------------------------------------------------------------- */
-    if( eGeomType != wkbUnknown )
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+    {
         poFeatureDefn->SetGeomType( eGeomType );
+        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(0);
+        if( pszGeomCol == NULL )
+            pszGeomCol = CPLStrdup( poGeomFieldDefn->GetNameRef() );
+        poGeomFieldDefn->nSRSId = nSRSId;
+        if( eGeomFormat != OSGF_None )
+            poGeomFieldDefn->eGeomFormat = eGeomFormat;
+        poGeomFieldDefn->SetSpatialRef(poSRS);
+    }
 
     return CE_None;
 }
 
 /************************************************************************/
+/*                         RecomputeOrdinals()                          */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
+{
+    sqlite3 *hDB = poDS->GetDB();
+    int rc;
+    const char *pszSQL;
+    sqlite3_stmt *hColStmt = NULL;
+/* -------------------------------------------------------------------- */
+/*      Get the column definitions for this table.                      */
+/* -------------------------------------------------------------------- */
+
+    pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
+                                     pszEscapedTableName );
+
+    rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to query table %s for column definitions : %s.",
+                  pszTableName, sqlite3_errmsg(hDB) );
+        
+        return CE_Failure;
+    }
+
+    rc = sqlite3_step( hColStmt );
+    if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "In Initialize(): sqlite3_step(%s):\n  %s", 
+                  pszSQL, sqlite3_errmsg(hDB) );
+        sqlite3_finalize( hColStmt );
+        return CE_Failure;
+    }
+
+    int    nRawColumns = sqlite3_column_count( hColStmt );
+
+    CPLFree(panFieldOrdinals);
+    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * poFeatureDefn->GetFieldCount() );
+    int nCountFieldOrdinals = 0;
+    int nCountGeomFieldOrdinals = 0;
+    iFIDCol = -1;
+
+    int iCol;
+    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        CPLString osName =
+            OGRSQLiteParamsUnquote(sqlite3_column_name( hColStmt, iCol ));
+        int nIdx = poFeatureDefn->GetFieldIndex(osName);
+        if( nIdx >= 0 )
+        {
+            panFieldOrdinals[nIdx] = iCol;
+            nCountFieldOrdinals ++;
+        }
+        else
+        {
+            nIdx = poFeatureDefn->GetGeomFieldIndex(osName);
+            if( nIdx >= 0 )
+            {
+                OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+                    poFeatureDefn->myGetGeomFieldDefn(nIdx);
+                poGeomFieldDefn->iCol = iCol;
+                nCountGeomFieldOrdinals ++;
+            }
+            else if( pszFIDColumn != NULL && strcmp(osName, pszFIDColumn) == 0 )
+                iFIDCol = iCol;
+        }
+    }
+    CPLAssert(nCountFieldOrdinals == poFeatureDefn->GetFieldCount() );
+    CPLAssert(nCountGeomFieldOrdinals == poFeatureDefn->GetGeomFieldCount() );
+    CPLAssert(pszFIDColumn == NULL || iFIDCol > 0 );
+
+    sqlite3_finalize( hColStmt );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                           GetLayerDefn()                             */
 /************************************************************************/
 
@@ -296,7 +395,7 @@ OGRFeatureDefn* OGRSQLiteTableLayer::GetLayerDefn()
     {
         bLayerDefnError = TRUE;
 
-        poFeatureDefn = new OGRFeatureDefn( osLayerName );
+        poFeatureDefn = new OGRSQLiteFeatureDefn( osLayerName );
         poFeatureDefn->Reference();
     }
 
@@ -419,6 +518,9 @@ OGRFeature *OGRSQLiteTableLayer::GetFeature( long nFeatureId )
 OGRErr OGRSQLiteTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
     if( pszQuery == NULL )
         osQuery = "";
     else
@@ -464,7 +566,7 @@ int OGRSQLiteTableLayer::CheckSpatialIndexTable()
 
         /* This will ensure that RTree support is available */
         osSQL.Printf("SELECT pkid FROM 'idx_%s_%s' WHERE xmax > 0 AND xmin < 0 AND ymax > 0 AND ymin < 0",
-                     pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                     pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
         int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
                                     &papszResult, &nRowCount,
@@ -473,7 +575,7 @@ int OGRSQLiteTableLayer::CheckSpatialIndexTable()
         if( rc != SQLITE_OK )
         {
             CPLDebug("SQLITE", "Count not find or use idx_%s_%s layer (%s). Disabling spatial index",
-                        pszEscapedTableName, osGeomColumn.c_str(), pszErrMsg);
+                        pszEscapedTableName, pszGeomCol, pszErrMsg);
             sqlite3_free( pszErrMsg );
             bHasSpatialIndex = FALSE;
         }
@@ -490,11 +592,13 @@ int OGRSQLiteTableLayer::CheckSpatialIndexTable()
 /*                           GetSpatialWhere()                          */
 /************************************************************************/
 
-CPLString OGRSQLiteTableLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
+CPLString OGRSQLiteTableLayer::GetSpatialWhere(int iGeomCol,
+                                               OGRGeometry* poFilterGeom)
 {
     CPLString osSpatialWHERE;
 
-    if( !poDS->IsSpatialiteDB() )
+    if( !poDS->IsSpatialiteDB() || poFeatureDefn == NULL ||
+        iGeomCol < 0 || iGeomCol >= poFeatureDefn->GetGeomFieldCount() )
         return osSpatialWHERE;
 
     if( poFilterGeom != NULL && CheckSpatialIndexTable() )
@@ -507,13 +611,14 @@ CPLString OGRSQLiteTableLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
 
         osSpatialWHERE.Printf("ROWID IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
                         "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f)",
-                        pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
+                        pszEscapedTableName,
+                        OGRSQLiteEscape(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str(),
                         sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
                         sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
     }
 
     if( poFilterGeom != NULL &&
-        OGRSQLiteIsSpatialiteLoaded() && !bHasSpatialIndex )
+        poDS->IsSpatialiteLoaded() && !bHasSpatialIndex )
     {
         OGREnvelope  sEnvelope;
 
@@ -523,7 +628,7 @@ CPLString OGRSQLiteTableLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
 
         /* A bit inefficient but still faster than OGR filtering */
         osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f, %d))",
-                       OGRSQLiteEscapeName(osGeomColumn).c_str(),
+                       OGRSQLiteEscapeName(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str(),
                        sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
                        sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11,
                        nSRSId);
@@ -544,7 +649,8 @@ void OGRSQLiteTableLayer::BuildWhere()
 {
     osWHERE = "";
 
-    CPLString osSpatialWHERE = GetSpatialWhere(m_poFilterGeom);
+    CPLString osSpatialWHERE = GetSpatialWhere(m_iGeomFieldFilter,
+                                               m_poFilterGeom);
     if (osSpatialWHERE.size() != 0)
     {
         osWHERE = "WHERE ";
@@ -575,7 +681,7 @@ int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
 
 {
     if (EQUAL(pszCap,OLCFastFeatureCount))
-        return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
+        return m_poFilterGeom == NULL || pszGeomCol == NULL ||
                HasSpatialIndex();
 
     else if (EQUAL(pszCap,OLCFastSpatialFilter))
@@ -646,7 +752,7 @@ int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
         m_poFilterGeom->getEnvelope( &sEnvelope );
         pszSQL = CPLSPrintf("SELECT count(*) FROM 'idx_%s_%s' WHERE "
                             "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f",
-                            pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
+                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
                             sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
                             sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
     }
@@ -709,7 +815,7 @@ OGRErr OGRSQLiteTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
         const char* pszSQL;
 
         pszSQL = CPLSPrintf("SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
-                            pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
         CPLDebug("SQLITE", "Running %s", pszSQL);
 
@@ -825,6 +931,14 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     }
 
     ClearInsertStmt();
+    
+    if( poDS->IsSpatialiteDB() && EQUAL( oField.GetNameRef(), "ROWID") )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "In a Spatialite DB, a 'ROWID' column that is not the integer "
+                 "primary key can corrupt spatial index. "
+                 "See https://www.gaia-gis.it/fossil/libspatialite/wiki?name=Shadowed+ROWID+issues");
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Do we want to "launder" the column names into SQLite            */
@@ -887,31 +1001,9 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /* -------------------------------------------------------------------- */
 /*      Add the field to the OGRFeatureDefn.                            */
 /* -------------------------------------------------------------------- */
-    int iNewField;
-    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
-
-    if( poFeatureDefn->GetGeomType() != wkbNone )
-    {
-        iNextOrdinal++;
-    }
-
-    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
-
-        // we already added OGC_FID so don't do it again
-        if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
-            continue;
-
-        iNextOrdinal++;
-    }
-
     poFeatureDefn->AddFieldDefn( &oField );
 
-    iNewField = poFeatureDefn->GetFieldCount() - 1;
-    panFieldOrdinals = (int *)
-        CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
-    panFieldOrdinals[iNewField] = iNextOrdinal;
+    RecomputeOrdinals();
 
     return OGRERR_NONE;
 }
@@ -935,7 +1027,7 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
     nFieldListLen += 50 + (pszFIDColumn ? 2 * strlen(pszFIDColumn) : strlen("OGC_FID"));
     if( poFeatureDefn->GetGeomType() != wkbNone )
     {
-        nFieldListLen += 50 + 2 * strlen(osGeomColumn);
+        nFieldListLen += 50 + 2 * strlen(pszGeomCol);
     }
 
     pszFieldListForSelect = (char *) CPLCalloc(1,nFieldListLen);
@@ -953,11 +1045,11 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
         strcat( pszNewFieldList, "," );
 
         strcat( pszFieldListForSelect, "\"");
-        strcat( pszFieldListForSelect, OGRSQLiteEscapeName(osGeomColumn) );
+        strcat( pszFieldListForSelect, OGRSQLiteEscapeName(pszGeomCol) );
         strcat( pszFieldListForSelect, "\"");
         
         strcat( pszNewFieldList, "\"");
-        strcat( pszNewFieldList, OGRSQLiteEscapeName(osGeomColumn) );
+        strcat( pszNewFieldList, OGRSQLiteEscapeName(pszGeomCol) );
         strcat( pszNewFieldList, "\"");
 
         if ( eGeomFormat == OSGF_WKT )
@@ -1332,23 +1424,11 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
 /* -------------------------------------------------------------------- */
 /*      Finish                                                          */
 /* -------------------------------------------------------------------- */
-    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
+    eErr = poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
 
-    if( poFeatureDefn->GetGeomType() != wkbNone )
-    {
-        iNextOrdinal++;
-    }
-
-    int iNewField = 0;
-    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        if (iField == iFieldToDelete)
-            continue;
-
-        panFieldOrdinals[iNewField ++] = iNextOrdinal++;
-    }
+    RecomputeOrdinals();
 
-    return poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
+    return eErr;
 }
 
 /************************************************************************/
@@ -1548,7 +1628,11 @@ OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
 /*      Finish                                                          */
 /* -------------------------------------------------------------------- */
 
-    return poFeatureDefn->ReorderFieldDefns( panMap );
+    eErr = poFeatureDefn->ReorderFieldDefns( panMap );
+
+    RecomputeOrdinals();
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -1570,7 +1654,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     int nBindField = 1;
 
-    if( osGeomColumn.size() != 0 &&
+    if( poFeatureDefn->GetGeomFieldCount() != 0 &&
         eGeomFormat != OSGF_FGF )
     {
         OGRGeometry* poGeom = poFeature->GetGeometryRef();
@@ -1707,6 +1791,23 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                     break;
                 }
 
+                case OFTStringList:
+                {
+                    char** papszValues = poFeature->GetFieldAsStringList( iField );
+                    CPLString osValue;
+                    osValue += CPLSPrintf("(%d:", CSLCount(papszValues));
+                    for(int i=0; papszValues[i] != NULL; i++)
+                    {
+                        if( i != 0 )
+                            osValue += ",";
+                        osValue += papszValues[i];
+                    }
+                    osValue += ")";
+                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                                               osValue.c_str(), -1, SQLITE_TRANSIENT);
+                    break;
+                }
+
                 default:
                 {
                     pszRawValue = poFeature->GetFieldAsString( iField );
@@ -1797,11 +1898,11 @@ OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Add geometry field name.                                        */
 /* -------------------------------------------------------------------- */
-    if( osGeomColumn.size() != 0 &&
+    if( poFeatureDefn->GetGeomFieldCount() != 0 &&
         eGeomFormat != OSGF_FGF )
     {
         osCommand += "\"";
-        osCommand += OGRSQLiteEscapeName(osGeomColumn);
+        osCommand += OGRSQLiteEscapeName(pszGeomCol);
         osCommand += "\" = ?";
 
         bNeedComma = TRUE;
@@ -1944,7 +2045,7 @@ OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
 
-    if( osGeomColumn.size() != 0 &&
+    if( poFeatureDefn->GetGeomFieldCount() != 0 &&
         poGeom != NULL &&
         eGeomFormat != OSGF_FGF )
     {
@@ -1956,7 +2057,7 @@ OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
         }
 
         osCommand += "\"";
-        osCommand += OGRSQLiteEscapeName(osGeomColumn);
+        osCommand += OGRSQLiteEscapeName(pszGeomCol);
         osCommand += "\"";
 
         osValues += "?";
@@ -2151,8 +2252,11 @@ int OGRSQLiteTableLayer::CreateSpatialIndex()
 {
     CPLString osCommand;
 
+    if( pszGeomCol == NULL )
+        return FALSE;
+
     osCommand.Printf("SELECT CreateSpatialIndex('%s', '%s')",
-                     pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                     pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
     char* pszErrMsg = NULL;
     sqlite3 *hDB = poDS->GetDB();
@@ -2216,7 +2320,7 @@ int OGRSQLiteTableLayer::DoStatisticsNeedToBeFlushed()
 {
     return bStatisticsNeedsToBeFlushed &&
            poDS->IsSpatialiteDB() &&
-           OGRSQLiteIsSpatialiteLoaded();
+           poDS->IsSpatialiteLoaded();
 }
 
 /************************************************************************/
@@ -2243,11 +2347,14 @@ int OGRSQLiteTableLayer::AreStatisticsValid()
 
 void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
 {
+    if( pszGeomCol == NULL )
+        return;
+
     CPLString osSQL;
     CPLString osLastEvtDate;
     osSQL.Printf("SELECT MAX(last_insert, last_update, last_delete) FROM geometry_columns_time WHERE "
                  "f_table_name = '%s' AND f_geometry_column = '%s'",
-                 pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                 pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
     sqlite3 *hDB = poDS->GetDB();
     int nRowCount = 0, nColCount = 0;
@@ -2275,7 +2382,7 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
     osSQL.Printf("SELECT last_verified, row_count, extent_min_x, extent_min_y, "
                  "extent_max_x, extent_max_y FROM geometry_columns_statistics WHERE "
                  "f_table_name = '%s' AND f_geometry_column = '%s'",
-                 pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                 pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
     nRowCount = 0;
     nColCount = 0;
@@ -2340,7 +2447,7 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
 
 void OGRSQLiteTableLayer::LoadStatistics()
 {
-    if( !poDS->IsSpatialiteDB() || !OGRSQLiteIsSpatialiteLoaded() )
+    if( !poDS->IsSpatialiteDB() || !poDS->IsSpatialiteLoaded() || pszGeomCol == NULL )
         return;
 
     if( poDS->HasSpatialite4Layout() )
@@ -2360,7 +2467,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
                  "((table_name = '%s' AND geometry_column = '%s') OR "
                  "(table_name = 'ALL-TABLES' AND geometry_column = 'ALL-GEOMETRY-COLUMNS')) AND "
                  "event = 'UpdateLayerStatistics'",
-                 pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                 pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
     sqlite3 *hDB = poDS->GetDB();
     int nRowCount = 0, nColCount = 0;
@@ -2393,7 +2500,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
     {
         osSQL.Printf("SELECT row_count, extent_min_x, extent_min_y, extent_max_x, extent_max_y "
                         "FROM layer_statistics WHERE table_name = '%s' AND geometry_column = '%s'",
-                        pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                        pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
         sqlite3_free_table( papszResult );
         papszResult = NULL;
@@ -2446,7 +2553,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
 
 int OGRSQLiteTableLayer::SaveStatistics()
 {
-    if( !bStatisticsNeedsToBeFlushed || !poDS->IsSpatialiteDB()  || !OGRSQLiteIsSpatialiteLoaded() )
+    if( !bStatisticsNeedsToBeFlushed || !poDS->IsSpatialiteDB()  || !poDS->IsSpatialiteLoaded() || pszGeomCol == NULL )
         return -1;
 
     CPLString osSQL;
@@ -2462,7 +2569,7 @@ int OGRSQLiteTableLayer::SaveStatistics()
                             "table_name, geometry_column, row_count, extent_min_x, "
                             "extent_min_y, extent_max_x, extent_max_y) VALUES ("
                             "0, '%s', '%s', " CPL_FRMT_GIB ", %.18g, %.18g, %.18g, %.18g)",
-                            pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
+                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
                             nFeatureCount,
                             oCachedExtent.MinX, oCachedExtent.MinY,
                             oCachedExtent.MaxX, oCachedExtent.MaxY);
@@ -2473,7 +2580,7 @@ int OGRSQLiteTableLayer::SaveStatistics()
                             "table_name, geometry_column, row_count, extent_min_x, "
                             "extent_min_y, extent_max_x, extent_max_y) VALUES ("
                             "0, '%s', '%s', " CPL_FRMT_GIB ", NULL, NULL, NULL, NULL)",
-                            pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
+                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
                             nFeatureCount);
         }
     }
@@ -2483,7 +2590,7 @@ int OGRSQLiteTableLayer::SaveStatistics()
         /* we know that it will out-of-sync */
         osSQL.Printf("DELETE FROM layer_statistics WHERE "
                      "table_name = '%s' AND geometry_column = '%s'",
-                     pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
+                     pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
     }
 
     int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg );
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
index 06ac363..6a8cabb 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitevfs.cpp 24807 2012-08-19 20:14:37Z rouault $
+ * $Id: ogrsqlitevfs.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements SQLite VFS
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
 
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "cpl_atomic_ops.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitevfs.cpp 24807 2012-08-19 20:14:37Z rouault $");
+CPL_CVSID("$Id: ogrsqlitevfs.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 //#define DEBUG_IO 1
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
index 1dd2701..8a21166 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqliteviewlayer.cpp 25388 2012-12-29 16:47:45Z rouault $
+ * $Id: ogrsqliteviewlayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing spatialite view.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "ogr_sqlite.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 25388 2012-12-29 16:47:45Z rouault $");
+CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteViewLayer()                         */
@@ -114,7 +114,7 @@ OGRFeatureDefn* OGRSQLiteViewLayer::GetLayerDefn()
     {
         bLayerDefnError = TRUE;
 
-        poFeatureDefn = new OGRFeatureDefn( pszViewName );
+        poFeatureDefn = new OGRSQLiteFeatureDefn( pszViewName );
         poFeatureDefn->Reference();
     }
 
@@ -200,10 +200,6 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
         return CE_Failure;
     }
 
-    poSRS = poUnderlyingLayer->GetSpatialRef();
-    if (poSRS)
-        poSRS->Reference();
-
     this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex();
 
 /* -------------------------------------------------------------------- */
@@ -238,13 +234,23 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
 /*      Collect the rest of the fields.                                 */
 /* -------------------------------------------------------------------- */
     std::set<CPLString> aosEmpty;
-    BuildFeatureDefn( pszViewName, hColStmt, aosEmpty );
+    BuildFeatureDefn( pszViewName, hColStmt, osGeomColumn, aosEmpty );
     sqlite3_finalize( hColStmt );
 
 /* -------------------------------------------------------------------- */
-/*      Set the geometry type if we know it.                            */
+/*      Set the properties of the geometry column.                      */
 /* -------------------------------------------------------------------- */
-    poFeatureDefn->SetGeomType( poUnderlyingLayer->GetGeomType() );
+    if( poFeatureDefn->GetGeomFieldCount() != 0 )
+    {
+        poFeatureDefn->SetGeomType( poUnderlyingLayer->GetGeomType() );
+        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(0);
+        poGeomFieldDefn->SetSpatialRef(poUnderlyingLayer->GetSpatialRef());
+        poGeomFieldDefn->nSRSId = poUnderlyingLayer->myGetLayerDefn()->
+            myGetGeomFieldDefn(0)->nSRSId;
+        if( eGeomFormat != OSGF_None )
+            poGeomFieldDefn->eGeomFormat = eGeomFormat;
+    }
 
     return CE_None;
 }
@@ -286,19 +292,6 @@ OGRErr OGRSQLiteViewLayer::ResetStatement()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRSQLiteViewLayer::GetSpatialRef()
-
-{
-    if (HasLayerDefnError())
-        return NULL;
-
-    return poSRS;
-}
-
-/************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
@@ -407,11 +400,13 @@ void OGRSQLiteViewLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 /*                           GetSpatialWhere()                          */
 /************************************************************************/
 
-CPLString OGRSQLiteViewLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
+CPLString OGRSQLiteViewLayer::GetSpatialWhere(int iGeomCol,
+                                              OGRGeometry* poFilterGeom)
 {
     CPLString osSpatialWHERE;
 
-    if (HasLayerDefnError())
+    if (HasLayerDefnError() || poFeatureDefn == NULL ||
+        iGeomCol < 0 || iGeomCol >= poFeatureDefn->GetGeomFieldCount())
         return "";
 
     if( poFilterGeom != NULL && bHasSpatialIndex )
@@ -432,7 +427,7 @@ CPLString OGRSQLiteViewLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
             osSQL.Printf("SELECT name FROM sqlite_master "
                         "WHERE name='idx_%s_%s'",
                         pszEscapedUnderlyingTableName,
-                         OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
+                        OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
 
             int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
                                         &papszResult, &nRowCount,
@@ -474,7 +469,7 @@ CPLString OGRSQLiteViewLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
 
     }
 
-    if( poFilterGeom != NULL && OGRSQLiteIsSpatialiteLoaded() && !bHasSpatialIndex )
+    if( poFilterGeom != NULL && poDS->IsSpatialiteLoaded() && !bHasSpatialIndex )
     {
         OGREnvelope  sEnvelope;
 
@@ -482,7 +477,7 @@ CPLString OGRSQLiteViewLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
 
         /* A bit inefficient but still faster than OGR filtering */
         osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f))",
-                       OGRSQLiteEscapeName(osGeomColumn).c_str(),
+                       OGRSQLiteEscapeName(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str(),
                        sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
                        sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11);
     }
@@ -502,7 +497,8 @@ void OGRSQLiteViewLayer::BuildWhere()
 {
     osWHERE = "";
 
-    CPLString osSpatialWHERE = GetSpatialWhere(m_poFilterGeom);
+    CPLString osSpatialWHERE = GetSpatialWhere(m_iGeomFieldFilter,
+                                               m_poFilterGeom);
     if (osSpatialWHERE.size() != 0)
     {
         osWHERE = "WHERE ";
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
index e77b396..dda8866 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.cpp 25726 2013-03-10 13:26:42Z rouault $
+ * $Id: ogrsqlitevirtualogr.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -45,7 +45,7 @@
 #endif
 
 /* Declaration of sqlite3_api structure */
-SQLITE_EXTENSION_INIT1
+static SQLITE_EXTENSION_INIT1
 
 /* The layout of fields is :
    0   : RegularField0
@@ -422,6 +422,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     OGRDataSource* poDS = NULL;
     int bExposeOGR_STYLE = FALSE;
     int bCloseDS = FALSE;
+    int bInternalUse = FALSE;
     int i;
 
 #ifdef DEBUG_OGR2SQLITE
@@ -438,6 +439,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     if( poDS != NULL && argc == 6 &&
         CPLGetValueType(argv[3]) == CPL_VALUE_INTEGER )
     {
+        bInternalUse = TRUE;
         if( argc != 6 )
         {
             *pzErr = sqlite3_mprintf(
@@ -594,14 +596,41 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     if( !bExposeOGR_STYLE )
      osSQL += " HIDDEN";
 
-    if( poFDefn->GetGeomType() != wkbNone )
+    for(i=0;i<poFDefn->GetGeomFieldCount();i++)
     {
         if( bAddComma )
             osSQL += ",";
         bAddComma = TRUE;
 
-        osSQL += OGRSQLiteEscapeName(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
+        OGRGeomFieldDefn* poFieldDefn = poFDefn->GetGeomFieldDefn(i);
+
+        osSQL += "\"";
+        if( i == 0 )
+            osSQL += OGRSQLiteEscapeName(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
+        else
+            osSQL += OGRSQLiteEscapeName(poFieldDefn->GetNameRef());
+        osSQL += "\"";
         osSQL += " BLOB";
+
+        /* We use a special column type, e.g. BLOB_POINT_25D_4326 */
+        /* when the virtual table is created by OGRSQLiteExecuteSQL() */
+        /* and thus for interal use only. */
+        if( bInternalUse )
+        {
+            osSQL += "_";
+            osSQL += OGRToOGCGeomType(poFieldDefn->GetType());
+            osSQL += "_";
+            osSQL += (poFieldDefn->GetType() & wkb25DBit) ? "25D" : "2D";
+            OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
+            if( poSRS == NULL && i == 0 )
+                poSRS = poLayer->GetSpatialRef();
+            int nSRID = poModule->FetchSRSId(poSRS);
+            if( nSRID >= 0 )
+            {
+                osSQL += "_";
+                osSQL += CPLSPrintf("%d", nSRID);
+            }
+        }
     }
 
     osSQL += ")";
@@ -640,7 +669,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
         else if( iCol >= 0 && iCol < poFDefn->GetFieldCount() )
             pszFieldName = poFDefn->GetFieldDefn(iCol)->GetNameRef();
         else
-            pszFieldName = "unkown_field";
+            pszFieldName = "unknown_field";
 
         const char* pszOp;
         switch(pIndex->aConstraint[i].op)
@@ -1160,6 +1189,40 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
 
         return SQLITE_OK;
     }
+    else if( nCol > (nFieldCount + 1) &&
+             nCol - (nFieldCount + 1) < poFDefn->GetGeomFieldCount() )
+    {
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(nCol - (nFieldCount + 1));
+        if( poGeom == NULL )
+        {
+            sqlite3_result_null(pContext);
+        }
+        else
+        {
+            OGRSpatialReference* poSRS = poGeom->getSpatialReference();
+            int nSRSId = pMyCursor->pVTab->poModule->FetchSRSId(poSRS);
+
+            GByte* pabyGeomBLOB = NULL;
+            int nGeomBLOBLen = 0;
+            if( OGRSQLiteLayer::ExportSpatiaLiteGeometry(
+                    poGeom, nSRSId, wkbNDR, FALSE, FALSE, FALSE,
+                    &pabyGeomBLOB, &nGeomBLOBLen ) != CE_None )
+            {
+                nGeomBLOBLen = 0;
+            }
+
+            if( nGeomBLOBLen == 0 )
+            {
+                sqlite3_result_null(pContext);
+            }
+            else
+            {
+                sqlite3_result_blob(pContext, pabyGeomBLOB,
+                                    nGeomBLOBLen, CPLFree);
+            }
+        }
+        return SQLITE_OK;
+    }
     else if( nCol < 0 || nCol >= nFieldCount )
     {
         return SQLITE_ERROR;
@@ -1301,11 +1364,11 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
 {
     OGRFeatureDefn* poLayerDefn = poLayer->GetLayerDefn();
     int nFieldCount = poLayerDefn->GetFieldCount();
-    int bHasGeomField = (poLayerDefn->GetGeomType() != wkbNone);
-    if( argc != 2 + nFieldCount + 1 + bHasGeomField)
+    int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
+    if( argc != 2 + nFieldCount + 1 + nGeomFieldCount)
     {
         CPLDebug("OGR2SQLITE", "Did not get expect argument count : %d, %d", argc,
-                    2 + nFieldCount + 1 + bHasGeomField);
+                    2 + nFieldCount + 1 + nGeomFieldCount);
         return NULL;
     }
 
@@ -1360,9 +1423,9 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
         poFeature->SetStyleString((const char*) sqlite3_value_text(argv[nStyleIdx]));
     }
 
-    if( bHasGeomField )
+    for(i = 0; i < nGeomFieldCount; i++)
     {
-        int nGeomFieldIdx = 2 + nFieldCount + 1;
+        int nGeomFieldIdx = 2 + nFieldCount + 1 + i;
         if( sqlite3_value_type(argv[nGeomFieldIdx]) == SQLITE_BLOB )
         {
             GByte* pabyBlob = (GByte *) sqlite3_value_blob (argv[nGeomFieldIdx]);
@@ -1371,7 +1434,7 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
             if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
                             pabyBlob, nLen, &poGeom ) == CE_None )
             {
-                poFeature->SetGeometryDirectly(poGeom);
+                poFeature->SetGeomFieldDirectly(i, poGeom);
             }
         }
     }
@@ -2342,9 +2405,19 @@ int CPL_DLL OGR2SQLITE_static_register (sqlite3 * hDB, char **pzErrMsg,
                                         const sqlite3_api_routines * pApi);
 CPL_C_END
 
+#ifndef WIN32
+extern const struct sqlite3_api_routines OGRSQLITE_static_routines;
+#endif
+
 int OGR2SQLITE_static_register (sqlite3 * hDB, char **pzErrMsg,
                                 const sqlite3_api_routines * pApi)
 {
+#ifndef WIN32
+    if( pApi->create_module == NULL )
+    {
+        pApi = &OGRSQLITE_static_routines;
+    }
+#endif
     SQLITE_EXTENSION_INIT2 (pApi);
 
     *pzErrMsg = NULL;
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
index e981105..b5f1994 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.h 25409 2012-12-31 11:51:10Z rouault $
+ * $Id: ogrsqlitevirtualogr.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c b/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
index d1c9d85..4a936e8 100644
--- a/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
+++ b/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: test_load_virtual_ogr.c 24845 2012-08-25 09:11:20Z rouault $
+ * $Id: test_load_virtual_ogr.c 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Test dynamic loading of SQLite Virtual Table module using OGR layers
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/sua/ogr_sua.h b/ogr/ogrsf_frmts/sua/ogr_sua.h
index 72f0199..221924f 100644
--- a/ogr/ogrsf_frmts/sua/ogr_sua.h
+++ b/ogr/ogrsf_frmts/sua/ogr_sua.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_sua.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_sua.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Definition of classes for OGR .sua driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -61,9 +61,6 @@ class OGRSUALayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
index cc4d433..b84ec42 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsuadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
+ * $Id: ogrsuadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsuadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
+CPL_CVSID("$Id: ogrsuadatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRSUADataSource()                          */
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
index de2f11e..67e9346 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsuadriver.cpp 19988 2010-07-07 19:02:36Z rouault $
+ * $Id: ogrsuadriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_sua.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsuadriver.cpp 19988 2010-07-07 19:02:36Z rouault $");
+CPL_CVSID("$Id: ogrsuadriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRSUA();
 
diff --git a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
index 63325ee..d0d6812 100644
--- a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $
+ * $Id: ogrsualayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUALayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $");
+CPL_CVSID("$Id: ogrsualayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRSUALayer()                             */
@@ -53,6 +53,7 @@ OGRSUALayer::OGRSUALayer( VSILFILE* fp )
     poFeatureDefn = new OGRFeatureDefn( "layer" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPolygon );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     OGRFieldDefn    oField1( "TYPE", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
diff --git a/ogr/ogrsf_frmts/svg/ogr_svg.h b/ogr/ogrsf_frmts/svg/ogr_svg.h
index 569c035..a741616 100644
--- a/ogr/ogrsf_frmts/svg/ogr_svg.h
+++ b/ogr/ogrsf_frmts/svg/ogr_svg.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_svg.h 22110 2011-04-03 19:05:10Z rouault $
+ * $Id: ogr_svg.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Definition of classes for OGR .svg driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -106,9 +106,7 @@ class OGRSVGLayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn();
     
     virtual int                 TestCapability( const char * );
-    
-    virtual OGRSpatialReference*GetSpatialRef();
-    
+
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
index d675d4f..7ba6b0c 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsvgdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
+ * $Id: ogrsvgdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
+CPL_CVSID("$Id: ogrsvgdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRSVGDataSource()                          */
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
index 7f62b43..864379b 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsvgdriver.cpp 22110 2011-04-03 19:05:10Z rouault $
+ * $Id: ogrsvgdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdriver.cpp 22110 2011-04-03 19:05:10Z rouault $");
+CPL_CVSID("$Id: ogrsvgdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPL_C_START
 void RegisterOGRSVG();
diff --git a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
index 4c5f663..e6c9a91 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z rouault $
+ * $Id: ogrsvglayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGLayer class.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z rouault $");
+CPL_CVSID("$Id: ogrsvglayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRSVGLayer()                             */
@@ -587,16 +587,6 @@ OGRFeature *OGRSVGLayer::GetNextFeature()
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRSVGLayer::GetSpatialRef()
-
-{
-    return poSRS;
-}
-
-/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
@@ -651,6 +641,7 @@ void OGRSVGLayer::LoadSchema()
         poLayer->poFeatureDefn = new OGRFeatureDefn( poLayer->osLayerName );
         poLayer->poFeatureDefn->Reference();
         poLayer->poFeatureDefn->SetGeomType(poLayer->GetGeomType());
+        poLayer->poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poLayer->poSRS);
     }
 
     oSchemaParser = OGRCreateExpatXMLParser();
diff --git a/ogr/ogrsf_frmts/sxf/GNUmakefile b/ogr/ogrsf_frmts/sxf/GNUmakefile
new file mode 100644
index 0000000..f13c8c0
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrsxfdriver.o ogrsxfdatasource.o ogrsxflayer.o
+
+CPPFLAGS	:=	-I.. -I../..  $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_sxf.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/sxf/drv_sxf.html b/ogr/ogrsf_frmts/sxf/drv_sxf.html
new file mode 100644
index 0000000..fe3b714
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/drv_sxf.html
@@ -0,0 +1,42 @@
+<html>
+<head>
+<title>SXF</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>Storage and eXchange Format - SXF</h1>
+
+(GDAL/OGR >= 1.10.2)<p>
+
+This driver reads SXF files, open format often associated with Russian GIS Software Panorama.<p>
+The driver is read only, but supports deletion of data source. The driver supports SXF binary files version 3.0 and higher.<p>
+The SXF layer support the following capabilities:
+<ul>
+<li> Strings as UTF8
+<li> Random Read
+<li> Fast Feature Count
+<li> Fast Get Extent
+<li> Fast Set Next By Index
+</ul>
+The driver uses classifiers (RSC files) to map feature from SXF to layers. Features that do not belong to any layer are put to the layer named "Not_Classified". The layers with zero features are not present in data source.<p>
+To be used automatically, the RSC file should have the same name as SXF file. User can provide RSC file path using config option <b>SXF_RSC_FILENAME</b>. This config option overrides the use of same name RSC. <p>
+The RSC file usually stores long and short layer name. The long name is usually in Russian, and short in English. The <b>SXF_LAYER_FULLNAME</b> config option allows choosing which layer names to use. If SXF_LAYER_FULLNAME is TRUE - the driver uses long names, if FALSE - short.<p>
+The attributes are read from SXF file. Maximum number of fields is created for the same layer features with different number of attributes. If attribute has a code mapped to RSC file, driver adds only the code (don't get real value from RSC, as the value type may differ from field type).<p>
+If config option  <b>SXF_SET_VERTCS</b> set to ON, the layers spatial reference will include vertical coordinate system description if exist.<p>
+
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://gisinfo.ru">Panorama web page</a><p>
+<li> <a href="http://gistoolkit.ru/download/doc/sxf4bin.pdf">SXF binary format description v.4 (rus) - pdf</a><p>
+<li> <a href="http://gistoolkit.ru/download/classifiers/formatsxf.zip">SXF binary format description v.4 (rus) - doc</a><p>
+<li> <a href="http://loi.sscc.ru/gis/formats/Format-geo/sxf/sxf3-231.txt">SXF format description v.3 (rus)</a><p>
+<li> <a href="http://gistoolkit.ru/download/classifiers/formatrsc.zip">RSC format description (rus)</a><p>
+<li> <a href="http://www.gisinfo.ru/price/price_map.htm">Test spatial data in SXF format (rus)</a><p>
+<li> <a href="http://www.gisinfo.ru/classifiers/classifiers.htm">Some RSC files (rus)</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/sxf/makefile.vc b/ogr/ogrsf_frmts/sxf/makefile.vc
new file mode 100644
index 0000000..7a3c617
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrsxfdriver.obj ogrsxfdatasource.obj ogrsxflayer.obj
+EXTRAFLAGS =	 -I.. -I..\.. 
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/sxf/ogr_sxf.h b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
new file mode 100644
index 0000000..c76649e
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
@@ -0,0 +1,154 @@
+/******************************************************************************
+ * $Id: ogr_sxf.h  $
+ *
+ * Project:  SXF Translator
+ * Purpose:  Include file defining classes for OGR SXF driver, datasource and layers.
+ * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *           Alexandr Lisovenko, alexander.lisovenko at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Ben Ahmed Daho Ali
+ * Copyright (c) 2013, NextGIS
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_SXF_H_INCLUDED
+#define _OGR_SXF_H_INCLUDED
+
+#include <set>
+#include <vector>
+#include <map>
+
+#include "ogrsf_frmts.h"
+#include "org_sxf_defs.h"
+
+#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
+#define TO_DEGREES 57.2957795130823208766
+#define TO_RADIANS 0.017453292519943295769
+
+/************************************************************************/
+/*                         OGRSXFLayer                                */
+/************************************************************************/
+class OGRSXFLayer : public OGRLayer
+{
+protected:
+    OGRFeatureDefn*    poFeatureDefn;
+	VSILFILE*          fpSXF;
+    GByte              nLayerID;
+    std::map<unsigned, CPLString> mnClassificators;
+    std::map<long, vsi_l_offset> mnRecordDesc;
+    std::map<long, vsi_l_offset>::const_iterator oNextIt;
+    SXFMapDescription  stSXFMapDescription;
+    std::set<GUInt16> snAttributeCodes;
+    int m_nSXFFormatVer;
+    CPLString sFIDColumn_;
+    void            **m_hIOMutex;
+    double              m_dfCoeff;
+    virtual OGRFeature *       GetNextRawFeature(long nFID);
+
+    GUInt32 TranslateXYH(const SXFRecordDescription& certifInfo,
+                         const char *psBuff, GUInt32 nBufLen,
+                         double *dfX, double *dfY, double *dfH = NULL);
+
+
+    OGRFeature *TranslatePoint(const SXFRecordDescription& certifInfo, const char * psRecordBuf, GUInt32 nBufLen);
+    OGRFeature *TranslateText(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
+    OGRFeature *TranslatePolygon(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
+    OGRFeature *TranslateLine(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
+    OGRFeature *TranslateVetorAngle(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
+public:
+    OGRSXFLayer(VSILFILE* fp, void** hIOMutex, GByte nID, const char* pszLayerName, int nVer, const SXFMapDescription&  sxfMapDesc);
+    ~OGRSXFLayer();
+
+	virtual void                ResetReading();
+    virtual OGRFeature         *GetNextFeature();
+    virtual OGRErr              SetNextByIndex(long nIndex);
+    virtual OGRFeature         *GetFeature(long nFID);
+    virtual OGRFeatureDefn     *GetLayerDefn() { return poFeatureDefn;}
+
+    virtual int                 TestCapability( const char * );
+
+    virtual int         GetFeatureCount(int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRSpatialReference *GetSpatialRef();
+    virtual const char* GetFIDColumn();
+
+    virtual GByte GetId() const { return nLayerID; };
+    virtual void AddClassifyCode(unsigned nClassCode, const char *szName = NULL);
+    virtual int AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset, bool bHasSemantic, int nSemanticsSize);
+};
+
+
+/************************************************************************/
+/*                        OGRSXFDataSource                       */
+/************************************************************************/
+
+class OGRSXFDataSource : public OGRDataSource
+{
+    SXFPassport oSXFPassport;
+
+    CPLString               pszName;
+
+    OGRLayer**          papoLayers;
+    size_t              nLayers;
+
+    VSILFILE* fpSXF;    
+
+    void FillLayers(void);
+    void CreateLayers();
+    void CreateLayers(VSILFILE* fpRSC);
+    OGRErr ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& passport);
+    OGRErr ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passport);
+    void SetVertCS(const long iVCS, SXFPassport& passport);
+    OGRErr ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& passport);
+    OGRSXFLayer*       GetLayerById(GByte);
+public:
+                        OGRSXFDataSource();
+                        ~OGRSXFDataSource();
+
+    int                 Open( const char * pszFilename,
+                              int bUpdate );
+
+    virtual const char*     GetName() { return pszName; }
+
+    virtual int             GetLayerCount() { return nLayers; }
+    virtual OGRLayer*       GetLayer( int );
+
+    virtual int             TestCapability( const char * );
+    void                    CloseFile(); 
+};
+
+/************************************************************************/
+/*                         OGRSXFDriver                          */
+/************************************************************************/
+
+class OGRSXFDriver : public OGRSFDriver
+{
+  public:
+                ~OGRSXFDriver();
+
+    const char*     GetName();
+    OGRDataSource*  Open( const char *, int );
+    OGRErr          DeleteDataSource(const char* pszName);
+    int             TestCapability(const char *);
+};
+
+#endif 
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
new file mode 100644
index 0000000..b1d587b
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
@@ -0,0 +1,1295 @@
+/******************************************************************************
+ * $Id: ogr_sxfdatasource.cpp  $
+ *
+ * Project:  SXF Translator
+ * Purpose:  Definition of classes for OGR SXF Datasource.
+ * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *           Alexandr Lisovenko, alexander.lisovenko at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Ben Ahmed Daho Ali
+ * Copyright (c) 2013, NextGIS
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_sxf.h"
+#include "cpl_string.h"
+#include "cpl_multiproc.h"
+
+#include <math.h>
+#include <map>
+#include <string>
+
+CPL_CVSID("$Id: ogrsxfdatasource.cpp  $");
+
+static void  *hIOMutex = NULL;
+
+static const long aoVCS[] =
+{
+    0,
+    5705,   //1
+    5711,   //2
+    0,      //3
+    5710,   //4
+    5710,   //5
+    0,      //6
+    0,      //7
+    0,      //8
+    0,      //9
+    5716,   //10
+    5733,   //11
+    0,      //12
+    0,      //13
+    0,      //14
+    0,      //15
+    5709,   //16
+    5776,   //17
+    0,      //18
+    0,      //19
+    5717,   //20
+    5613,   //21
+    0,      //22
+    5775,   //23
+    5702,   //24
+    0,      //25
+    0,      //26
+    5714    //27
+};
+
+#define NUMBER_OF_VERTICALCS    (sizeof(aoVCS)/sizeof(aoVCS[0]))
+
+/************************************************************************/
+/*                         OGRSXFDataSource()                           */
+/************************************************************************/
+
+OGRSXFDataSource::OGRSXFDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    fpSXF = NULL;
+
+    oSXFPassport.stMapDescription.pSpatRef = NULL;
+}
+
+/************************************************************************/
+/*                          ~OGRSXFDataSource()                         */
+/************************************************************************/
+
+OGRSXFDataSource::~OGRSXFDataSource()
+
+{
+    for( size_t i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (NULL != oSXFPassport.stMapDescription.pSpatRef)
+    {
+        oSXFPassport.stMapDescription.pSpatRef->Release();
+    }
+
+    CloseFile();
+
+    if (hIOMutex != NULL)
+    {
+        CPLDestroyMutex(hIOMutex);
+        hIOMutex = NULL;
+    }
+}
+
+/************************************************************************/
+/*                     CloseFile()                                      */
+/************************************************************************/
+void  OGRSXFDataSource::CloseFile()
+{ 
+    if (NULL != fpSXF)
+    {
+        VSIFCloseL( fpSXF );
+        fpSXF = NULL;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSXFDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRSXFDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= (int)nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
+{
+    size_t nObjectsRead;
+    int nFileHeaderSize;
+
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = pszFilename;
+
+    fpSXF = VSIFOpenL(pszName, "rb");
+    if ( fpSXF == NULL )
+    {
+        CPLError(CE_Warning, CPLE_OpenFailed, "SXF open file %s failed", pszFilename);
+        return FALSE;
+    }
+    
+    //read header
+    nFileHeaderSize = sizeof(SXFHeader);
+    SXFHeader stSXFFileHeader;
+    nObjectsRead = VSIFReadL(&stSXFFileHeader, nFileHeaderSize, 1, fpSXF);
+
+    if (nObjectsRead != 1)
+    {
+        CPLError(CE_Failure, CPLE_None, "SXF head read failed");
+        CloseFile();
+		return FALSE;
+    }
+
+    //check version
+    oSXFPassport.version = 0;
+    if (stSXFFileHeader.nHeaderLength > 256) //if size == 400 then version >= 4
+    {
+        oSXFPassport.version = stSXFFileHeader.nFormatVersion[2];
+    }
+    else
+    {
+        oSXFPassport.version = stSXFFileHeader.nFormatVersion[1];
+    }
+
+    if ( oSXFPassport.version == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported , "SXF File version not supported");
+        CloseFile();
+        return FALSE;
+    }
+
+    // read description
+    if (ReadSXFDescription(fpSXF, oSXFPassport) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "SXF. Wrong description.");
+        CloseFile();
+        return FALSE;
+    }
+
+
+    //read flags 
+    if (ReadSXFInformationFlags(fpSXF, oSXFPassport) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "SXF. Wrong state of the data.");
+        CloseFile();
+        return FALSE;
+    }
+
+    if (oSXFPassport.informationFlags.bProjectionDataCompliance == false)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SXF. Data are not corresponde to the projection." );
+        CloseFile();
+        return FALSE;
+    }
+
+    //read spatial data
+    if (ReadSXFMapDescription(fpSXF, oSXFPassport) != OGRERR_NONE)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "SXF. Wrong state of the data.");
+        CloseFile();
+        return FALSE;
+    }
+
+    if(oSXFPassport.informationFlags.bRealCoordinatesCompliance == false )
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "SXF. Given material may be rotated in the conditional system of coordinates" );
+    }
+
+/*---------------- TRY READ THE RSC FILE HEADER  -----------------------*/
+
+    CPLString pszRSCRileName = CPLGetConfigOption("SXF_RSC_FILENAME", "");
+    if (CPLCheckForFile((char *)pszRSCRileName.c_str(), NULL) == FALSE)
+    {
+        pszRSCRileName = CPLResetExtension(pszFilename, "rsc");
+        if (CPLCheckForFile((char *)pszRSCRileName.c_str(), NULL) == FALSE)
+        {
+            CPLError(CE_Warning, CPLE_None, "RSC file %s not exist", pszRSCRileName.c_str());
+            pszRSCRileName.Clear();
+        }
+    }
+
+    //1. Create layers from RSC file or create default set of layers from osm.rsc
+
+    if (!pszRSCRileName.empty())
+    {
+        VSILFILE* fpRSC;
+
+        fpRSC = VSIFOpenL(pszRSCRileName, "rb");
+        if (fpRSC == NULL)
+        {
+            CPLError(CE_Warning, CPLE_OpenFailed, "RSC open file %s failed", pszFilename);
+        }
+        else
+        {
+            CreateLayers(fpRSC);
+            VSIFCloseL(fpRSC);
+        }
+    }
+
+    if (nLayers == 0)//create default set of layers
+    {
+        CreateLayers();
+    }
+
+    FillLayers();
+
+    return TRUE;
+}
+
+OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passport)
+{
+    int nObjectsRead;
+
+    if (passport.version == 3)
+    {
+        //78
+        GByte buff[62];
+        nObjectsRead = VSIFReadL(&buff, 62, 1, fpSXF);
+        char date[3] = { 0 };
+
+        //read year
+        memcpy(date, buff, 2);
+        passport.dtCrateDate.nYear = atoi(date);
+        if (passport.dtCrateDate.nYear < 50)
+            passport.dtCrateDate.nYear += 2000;
+        else
+            passport.dtCrateDate.nYear += 1900;
+
+        memcpy(date, buff + 2, 2);
+
+        passport.dtCrateDate.nMonth = atoi(date);
+
+        memcpy(date, buff + 4, 2);
+
+        passport.dtCrateDate.nDay = atoi(date);
+
+        char szName[26] = { 0 };
+        memcpy(szName, buff + 8, 24);
+        char* pszRecoded = CPLRecode(szName + 2, "CP1251", CPL_ENC_UTF8);
+        passport.sMapSheet = pszRecoded; //TODO: check the encoding in SXF created in Linux
+        CPLFree(pszRecoded);
+
+        memcpy(&passport.nScale, buff + 32, 4);
+        CPL_LSBPTR32(&passport.nScale);
+
+        memset(szName, 0, 26);
+        memcpy(szName, buff + 36, 26);
+        pszRecoded = CPLRecode(szName, "CP866", CPL_ENC_UTF8);
+        passport.sMapSheetName = pszRecoded; //TODO: check the encoding in SXF created in Linux
+        CPLFree(pszRecoded);
+
+    }
+    else if (passport.version == 4)
+    {
+        //96
+        GByte buff[80];
+        nObjectsRead = VSIFReadL(&buff, 80, 1, fpSXF);
+        char date[5] = { 0 };
+
+        //read year
+        memcpy(date, buff, 4);
+        passport.dtCrateDate.nYear = atoi(date);
+
+        memset(date, 0, 5);
+        memcpy(date, buff + 4, 2);
+
+        passport.dtCrateDate.nMonth = atoi(date);
+
+        memcpy(date, buff + 6, 2);
+
+        passport.dtCrateDate.nDay = atoi(date);
+
+        char szName[32] = { 0 };
+        memcpy(szName, buff + 12, 32);
+        char* pszRecoded = CPLRecode(szName + 2, "CP1251", CPL_ENC_UTF8);
+        passport.sMapSheet = pszRecoded; //TODO: check the encoding in SXF created in Linux
+        CPLFree(pszRecoded);
+        
+        memcpy(&passport.nScale, buff + 44, 4);
+        CPL_LSBPTR32(&passport.nScale);
+
+        memset(szName, 0, 32);
+        memcpy(szName, buff + 48, 32);
+        pszRecoded = CPLRecode(szName, "CP1251", CPL_ENC_UTF8);
+        passport.sMapSheetName = pszRecoded; //TODO: check the encoding in SXF created in Linux
+        CPLFree(pszRecoded);
+    }
+
+    return OGRERR_NONE;
+}
+
+OGRErr OGRSXFDataSource::ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& passport)
+{
+    int nObjectsRead;
+    GByte val[4];
+    nObjectsRead = VSIFReadL(&val, 4, 1, fpSXF);
+
+    if (!(CHECK_BIT(val[0], 0) && CHECK_BIT(val[0], 1)))
+    {
+        return OGRERR_UNSUPPORTED_OPERATION;
+    }
+
+    if (CHECK_BIT(val[0], 2))
+    {
+        passport.informationFlags.bProjectionDataCompliance = true;
+    }
+    else
+    {
+        passport.informationFlags.bProjectionDataCompliance = false;
+    }
+
+    if (CHECK_BIT(val[0], 4))
+    {
+        passport.informationFlags.bRealCoordinatesCompliance = true;
+    }
+    else
+    {
+        passport.informationFlags.bRealCoordinatesCompliance = false;
+    }
+
+    if (CHECK_BIT(val[0], 6))
+    {
+        passport.informationFlags.stCodingType = SXF_SEM_TXT;
+    }
+    else
+    {
+        if (CHECK_BIT(val[0], 5))
+        {
+            passport.informationFlags.stCodingType = SXF_SEM_HEX;
+        }
+        else
+        {
+            passport.informationFlags.stCodingType = SXF_SEM_DEC;
+        }
+    }
+
+    if (CHECK_BIT(val[0], 7))
+    {
+        passport.informationFlags.stGenType = SXF_GT_LARGE_SCALE;
+    }
+    else
+    {
+        passport.informationFlags.stGenType = SXF_GT_SMALL_SCALE;
+    }
+
+    //version specific
+
+    if (passport.version == 3)
+    {
+        //degrees are ints * 100 000 000
+        //meters are ints / 10
+        passport.informationFlags.stEnc = SXF_ENC_DOS;
+        passport.informationFlags.stCoordAcc = SXF_COORD_ACC_DM;
+        passport.informationFlags.bSort = false;
+    }
+    else if (passport.version == 4)
+    {
+        passport.informationFlags.stEnc = (SXFTextEncoding)val[1];
+        passport.informationFlags.stCoordAcc = (SXFCoordinatesAccuracy)val[2];
+        if (CHECK_BIT(val[3], 0))
+        {
+            passport.informationFlags.bSort = true;
+        }
+        else
+        {
+            passport.informationFlags.bSort = false;
+        }
+    }
+
+    return OGRERR_NONE;
+}
+
+void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
+{
+    if (!CSLTestBoolean(CPLGetConfigOption("SXF_SET_VERTCS", "NO")))
+        return;
+
+    const long nEPSG = aoVCS[iVCS];
+
+    if (nEPSG == 0)
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  CPLString().Printf("SXF. Vertical coordinate system (SXF index %ld) not supported", iVCS) );
+        return;
+    }
+
+    OGRSpatialReference* sr = new OGRSpatialReference();
+    OGRErr eImportFromEPSGErr = sr->importFromEPSG(nEPSG);
+    if (eImportFromEPSGErr != OGRERR_NONE)
+    {
+        CPLError( CE_Warning, CPLE_None,
+                  CPLString().Printf("SXF. Vertical coordinate system (SXF index %ld, EPSG %d) import from EPSG error", iVCS, nEPSG) );
+        return;
+    }
+
+    if (sr->IsVertical() != 1)
+    {
+        CPLError( CE_Warning, CPLE_None,
+                  CPLString().Printf("SXF. Coordinate system (SXF index %ld, EPSG %d) is not Vertical", iVCS, nEPSG) );
+        return;
+    }
+
+    //passport.stMapDescription.pSpatRef->SetVertCS("Baltic", "Baltic Sea");
+    OGRErr eSetVertCSErr = passport.stMapDescription.pSpatRef->SetVertCS(sr->GetAttrValue("VERT_CS"), sr->GetAttrValue("VERT_DATUM"));
+    if (eSetVertCSErr != OGRERR_NONE)
+    {
+        CPLError( CE_Warning, CPLE_None,
+                  CPLString().Printf("SXF. Vertical coordinate system (SXF index %ld, EPSG %d) set error", iVCS, nEPSG) );
+        return;
+    }
+}
+OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& passport)
+{
+    int nObjectsRead;
+    int i;
+    passport.stMapDescription.Env.MaxX = -100000000;
+    passport.stMapDescription.Env.MinX = 100000000;
+    passport.stMapDescription.Env.MaxY = -100000000;
+    passport.stMapDescription.Env.MinY = 100000000;
+
+    bool bIsX = true;// passport.informationFlags.bRealCoordinatesCompliance; //if real coordinates we need to swap x & y
+
+    //version specific
+    if (passport.version == 3)
+    {
+        short nNoObjClass, nNoSemClass;
+        nObjectsRead = VSIFReadL(&nNoObjClass, 2, 1, fpSXF);
+        nObjectsRead = VSIFReadL(&nNoSemClass, 2, 1, fpSXF);
+        GByte baMask[8];
+        nObjectsRead = VSIFReadL(&baMask, 8, 1, fpSXF);
+
+        int nCorners[8];
+
+        //get projected corner coords
+        nObjectsRead = VSIFReadL(&nCorners, 32, 1, fpSXF);
+
+        for (i = 0; i < 8; i++)
+        {
+            passport.stMapDescription.stProjCoords[i] = double(nCorners[i]) / 10.0;
+            if (bIsX) //X
+            {
+                if (passport.stMapDescription.Env.MaxY < passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MaxY = passport.stMapDescription.stProjCoords[i];
+                if (passport.stMapDescription.Env.MinY > passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MinY = passport.stMapDescription.stProjCoords[i];
+            }
+            else
+            {
+                if (passport.stMapDescription.Env.MaxX < passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MaxX = passport.stMapDescription.stProjCoords[i];
+                if (passport.stMapDescription.Env.MinX > passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MinX = passport.stMapDescription.stProjCoords[i];
+            }
+            bIsX = !bIsX;
+        }
+        //get geographic corner coords
+        nObjectsRead = VSIFReadL(&nCorners, 32, 1, fpSXF);
+
+        for (i = 0; i < 8; i++)
+        {
+            passport.stMapDescription.stGeoCoords[i] = double(nCorners[i]) * 0.00000057295779513082; //from radians to degree * 100 000 000
+        }
+    }
+    else if (passport.version == 4)
+    {
+        int nEPSG;
+        nObjectsRead = VSIFReadL(&nEPSG, 4, 1, fpSXF);
+
+        if (nEPSG != 0)
+        {
+            passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+            passport.stMapDescription.pSpatRef->importFromEPSG(nEPSG);
+        }
+
+        double dfCorners[8];
+        nObjectsRead = VSIFReadL(&dfCorners, 64, 1, fpSXF);
+
+        for (i = 0; i < 8; i++)
+        {
+            passport.stMapDescription.stProjCoords[i] = dfCorners[i];
+            if (bIsX) //X
+            {
+                if (passport.stMapDescription.Env.MaxY < passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MaxY = passport.stMapDescription.stProjCoords[i];
+                if (passport.stMapDescription.Env.MinY > passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MinY = passport.stMapDescription.stProjCoords[i];
+            }
+            else
+            {
+                if (passport.stMapDescription.Env.MaxX < passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MaxX = passport.stMapDescription.stProjCoords[i];
+                if (passport.stMapDescription.Env.MinX > passport.stMapDescription.stProjCoords[i])
+                    passport.stMapDescription.Env.MinX = passport.stMapDescription.stProjCoords[i];
+            }
+            bIsX = !bIsX;
+
+        }
+        //get geographic corner coords
+        nObjectsRead = VSIFReadL(&dfCorners, 64, 1, fpSXF);
+
+        for (i = 0; i < 8; i++)
+        {
+            passport.stMapDescription.stGeoCoords[i] = dfCorners[i] * TO_DEGREES; // to degree 
+        }
+
+    }
+
+    if (NULL != passport.stMapDescription.pSpatRef)
+    {
+        return OGRERR_NONE;
+    }
+
+    GByte anData[8] = { 0 };
+    nObjectsRead = VSIFReadL(&anData, 8, 1, fpSXF);
+    long iEllips = anData[0];
+    long iVCS = anData[1];
+    long iProjSys = anData[2];
+    long iDatum = anData[3];
+    double dfProjScale = 1;
+
+    double adfPrjParams[8] = { 0 };
+
+    if (passport.version == 3)
+    {
+        switch (anData[5])
+        {
+        case 1:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_DECIMETRE;
+            break;
+        case 2:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_CENTIMETRE;
+            break;
+        case 3:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_MILLIMETRE;
+            break;
+        case 130:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_RADIAN;
+            break;
+        case 129:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_DEGREE;
+            break;
+        default:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_METRE;
+            break;
+        }
+
+
+        VSIFSeekL(fpSXF, 212, SEEK_SET);
+        struct _buff{
+            GUInt32 nRes;
+            GInt16 anFrame[8];
+            GUInt32 nFrameCode;
+        } buff;
+        nObjectsRead = VSIFReadL(&buff, 20, 1, fpSXF);
+        passport.stMapDescription.nResolution = buff.nRes; //resolution
+
+        for (i = 0; i < 8; i++)
+            passport.stMapDescription.stFrameCoords[i] = buff.anFrame[i];
+
+        int anParams[5];
+        nObjectsRead = VSIFReadL(&anParams, 20, 1, fpSXF);
+
+        if (anParams[0] != -1)
+            dfProjScale = double(anParams[0]) / 100000000.0;
+
+        if (anParams[2] != -1)
+            passport.stMapDescription.dfXOr = double(anParams[2]) / 100000000.0 * TO_DEGREES;
+        else
+            passport.stMapDescription.dfXOr = 0;
+
+        if (anParams[3] != -1)
+            passport.stMapDescription.dfYOr = double(anParams[2]) / 100000000.0 * TO_DEGREES;
+        else
+            passport.stMapDescription.dfYOr = 0;
+
+        passport.stMapDescription.dfFalseNorthing = 0;
+        passport.stMapDescription.dfFalseEasting = 0;
+
+
+        //adfPrjParams[0] = double(anParams[0]) / 100000000.0; // to radians  
+        //adfPrjParams[1] = double(anParams[1]) / 100000000.0;
+        //adfPrjParams[2] = double(anParams[2]) / 100000000.0;
+        //adfPrjParams[3] = double(anParams[3]) / 100000000.0;
+        adfPrjParams[4] = dfProjScale;//?
+        //adfPrjParams[5] = 0;//?
+        //adfPrjParams[6] = 0;//?
+        //adfPrjParams[7] = 0;// importFromPanorama calc it by itself
+
+    }
+    else if (passport.version == 4)
+    {
+        switch (anData[5])
+        {
+        case 64:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_RADIAN;
+            break;
+        case 65:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_DEGREE;
+            break;
+        default:
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_METRE;
+            break;
+        }
+
+        VSIFSeekL(fpSXF, 312, SEEK_SET);
+        GUInt32 buff[10];
+        nObjectsRead = VSIFReadL(&buff, 40, 1, fpSXF);
+
+        passport.stMapDescription.nResolution = buff[0]; //resolution
+        for (i = 0; i < 8; i++)
+            passport.stMapDescription.stFrameCoords[i] = buff[1 + i];
+
+        double adfParams[6];
+        nObjectsRead = VSIFReadL(&adfParams, 48, 1, fpSXF);
+
+        if (adfParams[1] != -1)
+            dfProjScale = adfParams[1];
+        passport.stMapDescription.dfXOr = adfParams[2] * TO_DEGREES;
+        passport.stMapDescription.dfYOr = adfParams[3] * TO_DEGREES;
+        passport.stMapDescription.dfFalseNorthing = adfParams[4];
+        passport.stMapDescription.dfFalseEasting = adfParams[5];
+
+        //adfPrjParams[0] = adfParams[0]; // to radians 
+        //adfPrjParams[1] = adfParams[1];
+        //adfPrjParams[2] = adfParams[2];
+        //adfPrjParams[3] = adfParams[3];
+        adfPrjParams[4] = dfProjScale;//?
+        //adfPrjParams[5] = adfParams[4];
+        //adfPrjParams[6] = adfParams[5];
+        //adfPrjParams[7] = 0;// importFromPanorama calc it by itself
+    }
+
+    passport.stMapDescription.dfScale = passport.nScale;
+
+    double dfCoeff = double(passport.stMapDescription.dfScale) / passport.stMapDescription.nResolution;
+    passport.stMapDescription.bIsRealCoordinates = passport.informationFlags.bRealCoordinatesCompliance;
+    passport.stMapDescription.stCoordAcc = passport.informationFlags.stCoordAcc;
+
+    if (!passport.stMapDescription.bIsRealCoordinates)
+    {
+        if (passport.stMapDescription.stFrameCoords[0] == 0 && passport.stMapDescription.stFrameCoords[1] == 0 && passport.stMapDescription.stFrameCoords[2] == 0 && passport.stMapDescription.stFrameCoords[3] == 0 && passport.stMapDescription.stFrameCoords[4] == 0 && passport.stMapDescription.stFrameCoords[5] == 0 && passport.stMapDescription.stFrameCoords[6] == 0 && passport.stMapDescription.stFrameCoords[7] == 0)
+        {
+            passport.stMapDescription.bIsRealCoordinates = true;
+        }
+        else
+        {
+            //origin
+            passport.stMapDescription.dfXOr = passport.stMapDescription.stProjCoords[1] - passport.stMapDescription.stFrameCoords[1] * dfCoeff;
+            passport.stMapDescription.dfYOr = passport.stMapDescription.stProjCoords[0] - passport.stMapDescription.stFrameCoords[0] * dfCoeff;
+        }
+    }
+
+    //normalize some coordintatessystems
+    if (iEllips == 1 && iProjSys == 1) // Pulkovo 1942 / Gauss-Kruger
+    {
+        double dfCenterLongEnv = passport.stMapDescription.stGeoCoords[1] + fabs(passport.stMapDescription.stGeoCoords[5] - passport.stMapDescription.stGeoCoords[1]) / 2;
+
+        int nZoneEnv = (dfCenterLongEnv + 3.0) / 6.0 + 0.5;
+
+        if (nZoneEnv > 1 && nZoneEnv < 33)
+        {
+            int nEPSG = 28400 + nZoneEnv;
+            passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+            OGRErr eErr = passport.stMapDescription.pSpatRef->importFromEPSG(nEPSG);
+            SetVertCS(iVCS, passport);
+            return eErr;
+        }
+        else
+        {
+            adfPrjParams[7] = nZoneEnv;
+
+            if (adfPrjParams[5] == 0)//False Easting
+            {
+                if (passport.stMapDescription.Env.MaxX < 500000)
+                    adfPrjParams[5] = 500000;
+                else
+                    adfPrjParams[5] = nZoneEnv * 1000000 + 500000;
+            }
+        }
+    }
+    else if (iEllips == 9 && iProjSys == 17) // WGS84 / UTM
+    {
+        double dfCenterLongEnv = passport.stMapDescription.stGeoCoords[1] + fabs(passport.stMapDescription.stGeoCoords[5] - passport.stMapDescription.stGeoCoords[1]) / 2;
+        int nZoneEnv = 30 + (dfCenterLongEnv + 3.0) / 6.0 + 0.5;
+        bool bNorth = passport.stMapDescription.stGeoCoords[6] + (passport.stMapDescription.stGeoCoords[2] - passport.stMapDescription.stGeoCoords[6]) / 2 < 0;
+        int nEPSG;
+        if (bNorth)
+        {
+            nEPSG = 32600 + nZoneEnv;
+        }
+        else
+        {
+            nEPSG = 32700 + nZoneEnv;
+        }
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+        OGRErr eErr = passport.stMapDescription.pSpatRef->importFromEPSG(nEPSG);
+        SetVertCS(iVCS, passport);
+        return eErr;
+    }
+   else if (iEllips == 45 && iProjSys == 35) //Mercator 3395 on sphere wgs84
+    {
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference("PROJCS[\"WGS_1984_Web_Mercator\",GEOGCS[\"GCS_WGS_1984_Major_Auxiliary_Sphere\",DATUM[\"WGS_1984_Major_Auxiliary_Sphere\",SPHEROID[\"WGS_1984_Major_Auxiliary_Sphere\",6378137.0,0.0]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"latitude_of_origin\",0.0],UNIT[\ [...]
+        OGRErr eErr = OGRERR_NONE; //passport.stMapDescription.pSpatRef->importFromEPSG(3395);
+        SetVertCS(iVCS, passport);
+        return eErr;
+    }
+    else if (iEllips == 9 && iProjSys == 34) //Miller 54003
+    {
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+        OGRErr eErr = passport.stMapDescription.pSpatRef->importFromEPSG(54003);
+        SetVertCS(iVCS, passport);
+        return eErr;
+    }
+
+    //TODO: Need to normalise more SRS:
+    //PAN_PROJ_WAG1
+    //PAN_PROJ_MERCAT
+    //PAN_PROJ_PS
+    //PAN_PROJ_POLYC
+    //PAN_PROJ_EC
+    //PAN_PROJ_LCC
+    //PAN_PROJ_STEREO
+    //PAN_PROJ_AE
+    //PAN_PROJ_GNOMON
+    //PAN_PROJ_MOLL
+    //PAN_PROJ_LAEA
+    //PAN_PROJ_EQC
+    //PAN_PROJ_CEA
+    //PAN_PROJ_IMWP
+    //
+
+    passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+    OGRErr eErr = passport.stMapDescription.pSpatRef->importFromPanorama(anData[2], anData[3], anData[0], adfPrjParams);
+    SetVertCS(iVCS, passport);
+    return eErr;
+}
+
+void OGRSXFDataSource::FillLayers()
+{
+    CPLDebug("SXF","Create layers");
+
+    //2. Read all records (only classify code and offset) and add this to correspondence layer
+    long nFID;
+    int nObjectsRead;
+    size_t i;
+    vsi_l_offset nOffset, nOffsetSemantic;
+    int nDeletedLayerIndex;
+
+    //get record count
+    GUInt32 nRecordCountMax = 0;
+    if (oSXFPassport.version == 3)
+    {
+        VSIFSeekL(fpSXF, 288, SEEK_SET);
+        nObjectsRead = VSIFReadL(&nRecordCountMax, 4, 1, fpSXF);
+        nOffset = 300;
+    }
+    else if (oSXFPassport.version == 4)
+    {
+        VSIFSeekL(fpSXF, 440, SEEK_SET);
+        nObjectsRead = VSIFReadL(&nRecordCountMax, 4, 1, fpSXF);
+        nOffset = 452;
+    }
+
+    if (nObjectsRead != 1)
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Get record count failed");
+        return;
+    }
+
+    VSIFSeekL(fpSXF, nOffset, SEEK_SET);
+
+    for (nFID = 0; nFID < nRecordCountMax; nFID++)
+    {
+        GInt32 buff[6];
+        nObjectsRead = VSIFReadL(&buff, 24, 1, fpSXF);
+
+        if (nObjectsRead != 1 || buff[0] != IDSXFOBJ)
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Read record %ld failed", nFID);
+            return;
+        }
+
+        bool bHasSemantic = CHECK_BIT(buff[5], 9);
+        if (bHasSemantic) //check has attributes
+        {
+            //we have already 24 byte readed
+            nOffsetSemantic = 8 + buff[2];
+            VSIFSeekL(fpSXF, nOffsetSemantic, SEEK_CUR);
+        }
+
+        int nSemanticSize = buff[1] - 32 - buff[2];
+        if( nSemanticSize < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid value");
+            break;
+        }
+        for (i = 0; i < nLayers; i++)
+        {
+            OGRSXFLayer* pOGRSXFLayer = (OGRSXFLayer*)papoLayers[i];
+            if (pOGRSXFLayer && pOGRSXFLayer->AddRecord(nFID, buff[3], nOffset, bHasSemantic, nSemanticSize) == TRUE)
+            {
+                break;
+            }
+        }
+        nOffset += buff[1];
+        VSIFSeekL(fpSXF, nOffset, SEEK_SET);
+    }
+
+    //3. delete empty layers
+    for (i = 0; i < nLayers; i++)
+    {
+        OGRSXFLayer* pOGRSXFLayer = (OGRSXFLayer*)papoLayers[i];
+        if (pOGRSXFLayer && pOGRSXFLayer->GetFeatureCount() == 0)
+        {
+            delete pOGRSXFLayer;
+            nDeletedLayerIndex = i;
+            while (nDeletedLayerIndex < nLayers - 1)
+            {
+                papoLayers[nDeletedLayerIndex] = papoLayers[nDeletedLayerIndex + 1];
+                nDeletedLayerIndex++;
+            }
+            nLayers--;
+            i--;
+        }
+        else if (pOGRSXFLayer)
+            pOGRSXFLayer->ResetReading();
+    }
+}
+
+OGRSXFLayer* OGRSXFDataSource::GetLayerById(GByte nID)
+{
+    for (size_t i = 0; i < nLayers; i++)
+    {
+        OGRSXFLayer* pOGRSXFLayer = (OGRSXFLayer*)papoLayers[i];
+        if (pOGRSXFLayer && pOGRSXFLayer->GetId() == nID)
+        {
+            return pOGRSXFLayer;
+        }
+    }
+    return NULL;
+}
+
+void OGRSXFDataSource::CreateLayers()
+{
+    //codes get from OSM.rsc http://gistoolkit.ru/download/classifiers/osm.zip
+
+    //default layers set
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    OGRSXFLayer* pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 0, CPLString("SYSTEM"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    //default codes
+    for (size_t i = 1000000001; i < 1000000015; i++)
+    {
+        pLayer->AddClassifyCode(i);
+    }
+    pLayer->AddClassifyCode(91000000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 1, CPLString("boundary"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(81110000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 2, CPLString("water"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(31410000);
+    pLayer->AddClassifyCode(31120000);
+    pLayer->AddClassifyCode(31710000);
+    pLayer->AddClassifyCode(72310000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 3, CPLString("city"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(41100000);
+    pLayer->AddClassifyCode(91100001);
+    pLayer->AddClassifyCode(91100002);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 4, CPLString("poi"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(123);
+    pLayer->AddClassifyCode(32410000);
+    pLayer->AddClassifyCode(44200000);
+    pLayer->AddClassifyCode(44200010);
+    pLayer->AddClassifyCode(47140000);
+    pLayer->AddClassifyCode(51121000);
+    pLayer->AddClassifyCode(51130000);
+    pLayer->AddClassifyCode(51410000);
+    pLayer->AddClassifyCode(51410001);
+    pLayer->AddClassifyCode(51420000);
+    pLayer->AddClassifyCode(53110000);
+    pLayer->AddClassifyCode(53311400);
+    pLayer->AddClassifyCode(53421000);
+    pLayer->AddClassifyCode(53510000);
+    pLayer->AddClassifyCode(53612000);
+    pLayer->AddClassifyCode(53612100);
+    pLayer->AddClassifyCode(53612101);
+    pLayer->AddClassifyCode(53612102);
+    pLayer->AddClassifyCode(53612103);
+    pLayer->AddClassifyCode(53612104);
+    pLayer->AddClassifyCode(53612105);
+    pLayer->AddClassifyCode(53612106);
+    pLayer->AddClassifyCode(53612107);
+    pLayer->AddClassifyCode(53612200);
+    pLayer->AddClassifyCode(53612201);
+    pLayer->AddClassifyCode(53612202);
+    pLayer->AddClassifyCode(53612203);
+    pLayer->AddClassifyCode(53612204);
+    pLayer->AddClassifyCode(53612205);
+    pLayer->AddClassifyCode(53612211);
+    pLayer->AddClassifyCode(53612300);
+    pLayer->AddClassifyCode(53612301);
+    pLayer->AddClassifyCode(53612302);
+    pLayer->AddClassifyCode(53612303);
+    pLayer->AddClassifyCode(53612304);
+    pLayer->AddClassifyCode(53612400);
+    pLayer->AddClassifyCode(53612401);
+    pLayer->AddClassifyCode(53612402);
+    pLayer->AddClassifyCode(53612403);
+    pLayer->AddClassifyCode(53612404);
+    pLayer->AddClassifyCode(53623000);
+    pLayer->AddClassifyCode(53623100);
+    pLayer->AddClassifyCode(53623110);
+    pLayer->AddClassifyCode(53623200);
+    pLayer->AddClassifyCode(53623300);
+    pLayer->AddClassifyCode(53623400);
+    pLayer->AddClassifyCode(53623500);
+    pLayer->AddClassifyCode(53623600);
+    pLayer->AddClassifyCode(53624000);
+    pLayer->AddClassifyCode(53624001);
+    pLayer->AddClassifyCode(53624002);
+    pLayer->AddClassifyCode(53624003);
+    pLayer->AddClassifyCode(53624004);
+    pLayer->AddClassifyCode(53624005);
+    pLayer->AddClassifyCode(53630000);
+    pLayer->AddClassifyCode(53631000);
+    pLayer->AddClassifyCode(53632101);
+    pLayer->AddClassifyCode(53632102);
+    pLayer->AddClassifyCode(53632103);
+    pLayer->AddClassifyCode(53632104);
+    pLayer->AddClassifyCode(53632105);
+    pLayer->AddClassifyCode(53632106);
+    pLayer->AddClassifyCode(53633001);
+    pLayer->AddClassifyCode(53633101);
+    pLayer->AddClassifyCode(53633102);
+    pLayer->AddClassifyCode(53633112);
+    pLayer->AddClassifyCode(53633114);
+    pLayer->AddClassifyCode(53635000);
+    pLayer->AddClassifyCode(53640000);
+    pLayer->AddClassifyCode(53641000);
+    pLayer->AddClassifyCode(53642000);
+    pLayer->AddClassifyCode(53643000);
+    pLayer->AddClassifyCode(53644000);
+    pLayer->AddClassifyCode(53646011);
+    pLayer->AddClassifyCode(53646013);
+    pLayer->AddClassifyCode(53646014);
+    pLayer->AddClassifyCode(53650000);
+    pLayer->AddClassifyCode(53650001);
+    pLayer->AddClassifyCode(53650002);
+    pLayer->AddClassifyCode(53650003);
+    pLayer->AddClassifyCode(53650004);
+    pLayer->AddClassifyCode(53650006);
+    pLayer->AddClassifyCode(53660000);
+    pLayer->AddClassifyCode(53661001);
+    pLayer->AddClassifyCode(53661002);
+    pLayer->AddClassifyCode(53661003);
+    pLayer->AddClassifyCode(53661004);
+    pLayer->AddClassifyCode(53661005);
+    pLayer->AddClassifyCode(53661006);
+    pLayer->AddClassifyCode(53661007);
+    pLayer->AddClassifyCode(53661008);
+    pLayer->AddClassifyCode(53661009);
+    pLayer->AddClassifyCode(53661010);
+    pLayer->AddClassifyCode(53661021);
+    pLayer->AddClassifyCode(53661100);
+    pLayer->AddClassifyCode(53662001);
+    pLayer->AddClassifyCode(53662002);
+    pLayer->AddClassifyCode(53662003);
+    pLayer->AddClassifyCode(53662004);
+    pLayer->AddClassifyCode(53672600);
+    pLayer->AddClassifyCode(53673300);
+    pLayer->AddClassifyCode(53700000);
+    pLayer->AddClassifyCode(53710000);
+    pLayer->AddClassifyCode(53720100);
+    pLayer->AddClassifyCode(53720200);
+    pLayer->AddClassifyCode(53720300);
+    pLayer->AddClassifyCode(53720301);
+    pLayer->AddClassifyCode(53720400);
+    pLayer->AddClassifyCode(53720500);
+    pLayer->AddClassifyCode(53720510);
+    pLayer->AddClassifyCode(53720520);
+    pLayer->AddClassifyCode(53720970);
+    pLayer->AddClassifyCode(53890000);
+
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 5, CPLString("highway"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(10715);
+    pLayer->AddClassifyCode(11118);
+    pLayer->AddClassifyCode(2000253);
+    pLayer->AddClassifyCode(2000727);
+    pLayer->AddClassifyCode(51133200);
+    pLayer->AddClassifyCode(51220000);
+    pLayer->AddClassifyCode(61230000);
+    pLayer->AddClassifyCode(61230000);
+    pLayer->AddClassifyCode(62132000);
+    pLayer->AddClassifyCode(62213100);
+    pLayer->AddClassifyCode(62213101);
+    pLayer->AddClassifyCode(62213102);
+    pLayer->AddClassifyCode(62223000);
+    pLayer->AddClassifyCode(62331000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 6, CPLString("railway"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(61111000);
+    pLayer->AddClassifyCode(61121100);
+    pLayer->AddClassifyCode(61121200);
+    pLayer->AddClassifyCode(61122000);
+    pLayer->AddClassifyCode(62131000);
+
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 7, CPLString("building"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(44100000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 8, CPLString("landuse"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(97);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 9, CPLString("vegetation"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(71111111);
+    pLayer->AddClassifyCode(71325000);
+    pLayer->AddClassifyCode(53890000);
+    pLayer->AddClassifyCode(22700000);
+    pLayer->AddClassifyCode(32282000);
+    pLayer->AddClassifyCode(71211000);
+    pLayer->AddClassifyCode(72120000);
+    pLayer->AddClassifyCode(71314000);
+    pLayer->AddClassifyCode(71312000);
+
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 10, CPLString("fire"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(96);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 11, CPLString("roaddesign"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(60000000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 13, CPLString("RoadStructure"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(62315000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 14, CPLString("signature"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    papoLayers[nLayers] = pLayer;
+    nLayers++;
+
+    pLayer->AddClassifyCode(91100000);
+    pLayer->AddClassifyCode(91200000);
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, 255, CPLString("Not_Classified"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    nLayers++;
+
+}
+
+void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
+{
+
+    RSCHeader stRSCFileHeader;
+    int nFileHeaderSize = sizeof(stRSCFileHeader);
+    int nObjectsRead = VSIFReadL(&stRSCFileHeader, nFileHeaderSize, 1, fpRSC);
+
+    if (nObjectsRead != 1)
+    {
+        CPLError(CE_Warning, CPLE_None, "RSC head read failed");
+        return;
+    }
+
+    GByte szLayersID[4];
+    struct _layer{
+        GUInt32 nLength;
+        char szName[32];
+        char szShortName[16];
+        GByte nNo;
+        GByte nPos;
+        GUInt16 nSematicCount;
+    };
+
+    int i;
+    size_t nLayerStructSize = sizeof(_layer);
+
+    VSIFSeekL(fpRSC, stRSCFileHeader.Layers.nOffset - sizeof(szLayersID), SEEK_SET);
+    VSIFReadL(&szLayersID, sizeof(szLayersID), 1, fpRSC);
+    vsi_l_offset nOffset = stRSCFileHeader.Layers.nOffset;
+    _layer LAYER;
+
+    for (i = 0; i < stRSCFileHeader.Layers.nRecordCount; ++i)
+    {
+        VSIFReadL(&LAYER, nLayerStructSize, 1, fpRSC);
+
+        papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+        bool bLayerFullName = CSLTestBoolean(CPLGetConfigOption("SXF_LAYER_FULLNAME", "NO"));
+
+        char* pszRecoded;
+        if (bLayerFullName)
+        {
+            if (stRSCFileHeader.nFontEnc == 125)
+                pszRecoded = CPLRecode(LAYER.szName, "KOI8-R", CPL_ENC_UTF8);
+            else if (stRSCFileHeader.nFontEnc == 126)
+                pszRecoded = CPLRecode(LAYER.szName, "CP1251", CPL_ENC_UTF8);
+            else
+                pszRecoded = CPLStrdup(LAYER.szName);
+
+            papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, LAYER.nNo, CPLString(pszRecoded), oSXFPassport.version, oSXFPassport.stMapDescription);
+        }
+        else
+        {
+            if (stRSCFileHeader.nFontEnc == 125)
+                pszRecoded = CPLRecode(LAYER.szShortName, "KOI8-R", CPL_ENC_UTF8);
+            else if (stRSCFileHeader.nFontEnc == 126)
+                pszRecoded = CPLRecode(LAYER.szShortName, "CP1251", CPL_ENC_UTF8);
+            else
+                pszRecoded = CPLStrdup(LAYER.szShortName);
+
+            papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, LAYER.nNo, CPLString(pszRecoded), oSXFPassport.version, oSXFPassport.stMapDescription);
+        }
+        CPLFree(pszRecoded);
+        nLayers++;
+
+        nOffset += LAYER.nLength;
+        VSIFSeekL(fpRSC, nOffset, SEEK_SET);
+    }
+
+    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
+    papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, 255, CPLString("Not_Classified"), oSXFPassport.version, oSXFPassport.stMapDescription);
+    nLayers++;
+
+
+    char szObjectsID[4];
+    struct _object{
+        unsigned nLength;
+        unsigned nClassifyCode;
+        unsigned nObjectNumber;
+        unsigned nObjectCode;
+        char szShortName[32];
+        char szName[32];
+        char szGeomType;
+        char szLayernNo;
+        char szUnimportantSeg[14];
+    };
+
+    VSIFSeekL(fpRSC, stRSCFileHeader.Objects.nOffset - sizeof(szObjectsID), SEEK_SET);
+    VSIFReadL(&szObjectsID, sizeof(szObjectsID), 1, fpRSC);
+    nOffset = stRSCFileHeader.Objects.nOffset;
+    _object OBJECT;
+
+    for (unsigned i = 0; i < stRSCFileHeader.Objects.nRecordCount; ++i)
+    {
+        VSIFReadL(&OBJECT, sizeof(_object), 1, fpRSC);
+
+        OGRSXFLayer* pLayer = GetLayerById(OBJECT.szLayernNo);
+        if (NULL != pLayer)
+        {
+            char* pszRecoded;
+            if (stRSCFileHeader.nFontEnc == 125)
+                pszRecoded = CPLRecode(OBJECT.szName, "KOI8-R", CPL_ENC_UTF8);
+            else if (stRSCFileHeader.nFontEnc == 126)
+                pszRecoded = CPLRecode(OBJECT.szName, "CP1251", CPL_ENC_UTF8);
+            else
+                pszRecoded = CPLStrdup(OBJECT.szName); //already in  CPL_ENC_UTF8
+            pLayer->AddClassifyCode(OBJECT.nClassifyCode, pszRecoded);
+            //printf("%d;%s\n", OBJECT.nClassifyCode, OBJECT.szName);
+            CPLFree(pszRecoded);
+        }
+
+        nOffset += OBJECT.nLength;
+        VSIFSeekL(fpRSC, nOffset, SEEK_SET);
+    }
+}
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
new file mode 100644
index 0000000..8f06ce4
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * $Id: ogr_sxfdriver.cpp  $
+ *
+ * Project:  SXF Translator
+ * Purpose:  Definition of classes for OGR SXF driver.
+ * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Ben Ahmed Daho Ali
+ * Copyright (c) 2013, NextGIS
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_sxf.h"
+
+CPL_CVSID("$Id: ogrsxfdriver.cpp  $");
+
+
+extern "C" void RegisterOGRSXF();  
+
+/************************************************************************/
+/*                       ~OGRSXFDriver()                         */
+/************************************************************************/
+
+OGRSXFDriver::~OGRSXFDriver()
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRSXFDriver::GetName()
+
+{
+    return "SXF";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRSXFDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Determine what sort of object this is.                          */
+/* -------------------------------------------------------------------- */
+
+    VSIStatBufL sStatBuf;
+    if (!EQUAL(CPLGetExtension(pszFilename), "sxf") ||
+        VSIStatL(pszFilename, &sStatBuf) != 0 ||
+        !VSI_ISREG(sStatBuf.st_mode))
+        return FALSE;
+
+    OGRSXFDataSource   *poDS = new OGRSXFDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           DeleteDataSource()                         */
+/************************************************************************/
+
+OGRErr OGRSXFDriver::DeleteDataSource(const char* pszName)
+{
+    int iExt;
+    //TODO: add more extensions if aplicable
+    static const char *apszExtensions[] = { "szf", "rsc", NULL }; 
+
+    VSIStatBufL sStatBuf;
+    if (VSIStatL(pszName, &sStatBuf) != 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "%s does not appear to be a valid sxf file.",
+            pszName);
+
+        return OGRERR_FAILURE;
+    }
+
+    for (iExt = 0; apszExtensions[iExt] != NULL; iExt++)
+    {
+        const char *pszFile = CPLResetExtension(pszName,
+            apszExtensions[iExt]);
+        if (VSIStatL(pszFile, &sStatBuf) == 0)
+            VSIUnlink(pszFile);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSXFDriver::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, ODrCDeleteDataSource))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                        RegisterOGRSXF()                       */
+/************************************************************************/
+void RegisterOGRSXF()
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRSXFDriver );   
+}
+
+
+
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
new file mode 100644
index 0000000..a733fd3
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
@@ -0,0 +1,1429 @@
+/******************************************************************************
+ * $Id: ogr_sxflayer.cpp  $
+ *
+ * Project:  SXF Translator
+ * Purpose:  Definition of classes for OGR SXF Layers.
+ * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *           Alexandr Lisovenko, alexander.lisovenko at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Ben Ahmed Daho Ali
+ * Copyright (c) 2013, NextGIS
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+#define  _USE_MATH_DEFINES
+
+#include "ogr_sxf.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: ogrsxflayer.cpp $");
+
+/************************************************************************/
+/*                        OGRSXFLayer()                                 */
+/************************************************************************/
+
+OGRSXFLayer::OGRSXFLayer(VSILFILE* fp, void** hIOMutex, GByte nID, const char* pszLayerName, int nVer, const SXFMapDescription&  sxfMapDesc) : OGRLayer()
+{
+    sFIDColumn_ = "ogc_fid";
+    fpSXF = fp;
+    nLayerID = nID;
+    stSXFMapDescription = sxfMapDesc;
+    stSXFMapDescription.pSpatRef->Reference();
+    m_nSXFFormatVer = nVer;
+    oNextIt = mnRecordDesc.begin();
+    m_hIOMutex = hIOMutex;
+    m_dfCoeff = stSXFMapDescription.dfScale / stSXFMapDescription.nResolution;
+    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+    poFeatureDefn->Reference();
+    
+    poFeatureDefn->SetGeomType(wkbUnknown);
+    if (poFeatureDefn->GetGeomFieldCount() != 0)
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(stSXFMapDescription.pSpatRef);
+
+    //OGRGeomFieldDefn oGeomFieldDefn("Shape", wkbGeometryCollection);
+    //oGeomFieldDefn.SetSpatialRef(stSXFMapDescription.pSpatRef);
+    //poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
+
+    OGRFieldDefn oFIDField = OGRFieldDefn(sFIDColumn_, OFTInteger);
+    poFeatureDefn->AddFieldDefn(&oFIDField);
+
+    OGRFieldDefn oClCodeField = OGRFieldDefn( "CLCODE", OFTInteger );
+    oClCodeField.SetWidth(10);
+    poFeatureDefn->AddFieldDefn( &oClCodeField );
+
+    OGRFieldDefn oClNameField = OGRFieldDefn( "CLNAME", OFTString );
+    oClNameField.SetWidth(32);
+    poFeatureDefn->AddFieldDefn( &oClNameField );
+
+    OGRFieldDefn oNumField = OGRFieldDefn( "OBJECTNUMB", OFTInteger );
+    oNumField.SetWidth(10);
+    poFeatureDefn->AddFieldDefn( &oNumField );
+
+    OGRFieldDefn oAngField = OGRFieldDefn("ANGLE", OFTReal);
+    poFeatureDefn->AddFieldDefn(&oAngField);
+
+    OGRFieldDefn  oTextField( "TEXT", OFTString );
+    oTextField.SetWidth(255);
+    poFeatureDefn->AddFieldDefn( &oTextField );
+}
+
+/************************************************************************/
+/*                         ~OGRSXFLayer()                               */
+/************************************************************************/
+
+OGRSXFLayer::~OGRSXFLayer()
+{
+    stSXFMapDescription.pSpatRef->Release();
+    poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                AddClassifyCode(unsigned nClassCode)                  */
+/* Add layer supported classify codes. Only records with this code can  */
+/* be in layer                                                          */
+/************************************************************************/
+
+void OGRSXFLayer::AddClassifyCode(unsigned nClassCode, const char *szName)
+{
+    if (szName != NULL)
+    {
+        mnClassificators[nClassCode] = CPLString(szName);
+    }
+    else
+    {
+        CPLString szIdName;
+        szIdName.Printf("%d", nClassCode);
+        mnClassificators[nClassCode] = szIdName;
+    }
+}
+
+/************************************************************************/
+/*                         AddRecord()                               */
+/************************************************************************/
+
+int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset, bool bHasSemantic, int nSemanticsSize)
+{
+    if (mnClassificators.empty() || mnClassificators.find(nClassCode) != mnClassificators.end())
+    {
+        mnRecordDesc[nFID] = nOffset;
+        //add addtionals semantics (attribute fields)
+        if (bHasSemantic)
+        {
+            size_t offset = 0;
+
+            while (offset < nSemanticsSize)
+            {
+                SXFRecordAttributeInfo stAttrInfo;
+                bool bAddField = false;
+                size_t nCurrOff = 0;
+                int nReadObj = VSIFReadL(&stAttrInfo, 4, 1, fpSXF);
+                if (nReadObj == 1)
+                {
+                    CPLString oFieldName;
+                    if (snAttributeCodes.find(stAttrInfo.nCode) == snAttributeCodes.end())
+                    {
+                        bAddField = true;
+                        snAttributeCodes.insert(stAttrInfo.nCode);
+                        oFieldName.Printf("SC_%d", stAttrInfo.nCode);
+                    }
+
+                    SXFRecordAttributeType eType = (SXFRecordAttributeType)stAttrInfo.nType;
+
+                    offset += 4;
+
+
+                    switch (eType) //TODO: set field type form RSC as here sometimes we have the codes and string values can be get from RSC by this code
+                    {
+                    case SXF_RAT_ASCIIZ_DOS:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTString);
+                            oField.SetWidth(255);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        offset += stAttrInfo.nScale + 1;
+                        nCurrOff = stAttrInfo.nScale + 1;
+                        break;
+                    }
+                    case SXF_RAT_ONEBYTE:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTReal);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        offset += 1;
+                        nCurrOff = 1;
+                        break;
+                    }
+                    case SXF_RAT_TWOBYTE:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTReal);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        offset += 2;
+                        nCurrOff = 2;
+                        break;
+                    }
+                    case SXF_RAT_FOURBYTE:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTReal);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        offset += 4;
+                        nCurrOff = 4;
+                        break;
+                    }
+                    case SXF_RAT_EIGHTBYTE:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTReal);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        offset += 8;
+                        nCurrOff = 8;
+                        break;
+                    }
+                    case SXF_RAT_ANSI_WIN:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTString);
+                            oField.SetWidth(255);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        unsigned nLen = unsigned(stAttrInfo.nScale) + 1;
+                        offset += nLen;
+                        nCurrOff = nLen;
+                        break;
+                    }
+                    case SXF_RAT_UNICODE:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTString);
+                            oField.SetWidth(255);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        unsigned nLen = unsigned(stAttrInfo.nScale) + 1;
+                        offset += nLen;
+                        nCurrOff = nLen;
+                        break;
+                    }
+                    case SXF_RAT_BIGTEXT:
+                    {
+                        if (bAddField)
+                        {
+                            OGRFieldDefn  oField(oFieldName, OFTString);
+                            oField.SetWidth(1024);
+                            poFeatureDefn->AddFieldDefn(&oField);
+                        }
+                        GUInt32 scale2;
+                        VSIFReadL(&scale2, sizeof(GUInt32), 1, fpSXF);
+                        CPL_LSBUINT32PTR(&scale2);
+
+                        offset += scale2;
+                        nCurrOff = scale2;
+                        break;
+                    }
+                    default:
+                        break;
+                    }
+                }
+                if( nCurrOff == 0 )
+                    break;
+                VSIFSeekL(fpSXF, nCurrOff, SEEK_CUR);
+            }
+        }
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           SetNextByIndex()                           */
+/************************************************************************/
+
+OGRErr OGRSXFLayer::SetNextByIndex(long nIndex)
+{
+    if (nIndex < 0 || nIndex > mnRecordDesc.size())
+        return OGRERR_FAILURE;
+
+    oNextIt = mnRecordDesc.begin();
+    std::advance(oNextIt, nIndex);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::GetFeature(long nFID)
+{
+    std::map<long, vsi_l_offset>::const_iterator IT = mnRecordDesc.find(nFID);
+    if (IT != mnRecordDesc.end())
+    {
+        VSIFSeekL(fpSXF, IT->second, SEEK_SET);
+        OGRFeature *poFeature = GetNextRawFeature(IT->first);
+        if (poFeature != NULL && poFeature->GetGeometryRef() != NULL && GetSpatialRef() != NULL)
+        {
+            poFeature->GetGeometryRef()->assignSpatialReference(GetSpatialRef());
+        }
+        return poFeature;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRSXFLayer::GetSpatialRef()
+{
+    return stSXFMapDescription.pSpatRef;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRSXFLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    if (bForce)
+    {
+        return OGRLayer::GetExtent(psExtent, bForce);
+    }
+    else
+    {
+        psExtent->MinX = stSXFMapDescription.Env.MinX;
+        psExtent->MaxX = stSXFMapDescription.Env.MaxX;
+        psExtent->MinY = stSXFMapDescription.Env.MinY;
+        psExtent->MaxY = stSXFMapDescription.Env.MaxY;
+
+        return OGRERR_NONE;
+    }
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRSXFLayer::GetFeatureCount(int bForce)
+{
+    if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+        return static_cast<int>(mnRecordDesc.size());
+    else
+        return OGRLayer::GetFeatureCount(bForce);
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSXFLayer::ResetReading()
+
+{
+    oNextIt = mnRecordDesc.begin();
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::GetNextFeature()
+{
+    CPLMutexHolderD(m_hIOMutex);
+    while (oNextIt != mnRecordDesc.end())
+    {
+        VSIFSeekL(fpSXF, oNextIt->second, SEEK_SET);
+        OGRFeature  *poFeature = GetNextRawFeature(oNextIt->first);	
+
+        ++oNextIt;
+
+        if (poFeature == NULL)
+            continue;
+
+        if ((m_poFilterGeom == NULL
+            || FilterGeometry(poFeature->GetGeometryRef()))
+            && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate(poFeature)))
+        {
+            if (poFeature->GetGeometryRef() != NULL && GetSpatialRef() != NULL)
+            {
+                poFeature->GetGeometryRef()->assignSpatialReference(GetSpatialRef());
+            }
+	    
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSXFLayer::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, OLCStringsAsUTF8))
+        return TRUE;
+    else if (EQUAL(pszCap, OLCRandomRead))
+        return TRUE;
+    else if (EQUAL(pszCap, OLCFastFeatureCount))
+        return TRUE;
+    else if (EQUAL(pszCap, OLCFastGetExtent))
+        return TRUE;
+    else if (EQUAL(pszCap, OLCFastSetNextByIndex))
+        return TRUE;
+        
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                TranslateXYH()                        */
+/************************************************************************/
+/****
+ * TODO : Take into account informations given in the passport 
+ * like unit of mesurement, type and dimensions (integer, float, double) of coordinate,
+ * the vector format ....
+ */
+
+GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
+                                  const char *psBuff, GUInt32 nBufLen,
+                          double *dfX, double *dfY, double *dfH)
+{
+    //Xp, Yp(м) = Xo, Yo(м) + (Xd, Yd / R * S), (1)
+
+	int offset = 0;
+    switch (certifInfo.eValType)
+    {
+    case SXF_VT_SHORT:
+    {
+        if( nBufLen < 4 )
+            return 0;
+        GInt16 x, y;
+        memcpy(&x, psBuff, 2);
+        CPL_LSBINT16PTR(&x);
+        memcpy(&y, psBuff + 2, 2);
+        CPL_LSBINT16PTR(&y);
+
+
+        if (stSXFMapDescription.bIsRealCoordinates)
+        {
+            *dfX = (double)y;
+            *dfY = (double)x;
+        }
+        else
+        {
+            if (m_nSXFFormatVer == 3)
+            {
+                *dfX = stSXFMapDescription.dfXOr + (double)y * m_dfCoeff;
+                *dfY = stSXFMapDescription.dfYOr + (double)x * m_dfCoeff;
+            }
+            else if (m_nSXFFormatVer == 4)
+            {
+                //TODO: check on real data
+                *dfX = stSXFMapDescription.dfXOr + (double)y * m_dfCoeff;
+                *dfY = stSXFMapDescription.dfYOr + (double)x * m_dfCoeff;
+            }
+        }
+
+        offset += 4;
+
+        if (dfH != NULL)
+        {
+            if( nBufLen < 4 + 4 )
+                return 0;
+            float h;
+            memcpy(&h, psBuff + 4, 4); // H always in float
+            CPL_LSBPTR32(&h);
+            *dfH = (double)h;
+
+            offset += 4;
+        }
+    }
+        break;
+    case SXF_VT_FLOAT:
+    {
+        float x, y;
+        if( nBufLen < 8 )
+            return 0;
+        memcpy(&y, psBuff, 4);
+        CPL_LSBPTR32(&y);
+        memcpy(&x, psBuff + 4, 4);
+        CPL_LSBPTR32(&x);
+
+        if (stSXFMapDescription.bIsRealCoordinates)
+        {
+            *dfX = (double)y;
+            *dfY = (double)x;
+        }
+        else
+        {
+            *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
+            *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
+        }
+
+        offset += 8;
+
+        if (dfH != NULL)
+        {
+            if( nBufLen < 8 + 4 )
+                return 0;
+            float h;
+            memcpy(&h, psBuff + 8, 4); // H always in float
+            CPL_LSBPTR32(&h);
+            *dfH = (double)h;
+
+            offset += 4;
+        }
+    }
+        break;
+    case SXF_VT_INT:
+    {
+        if( nBufLen < 8 )
+            return 0;
+        GInt32 x, y;
+        memcpy(&y, psBuff, 4);
+        CPL_LSBPTR32(&y);
+        memcpy(&x, psBuff + 4, 4);
+        CPL_LSBPTR32(&x);
+
+        if (stSXFMapDescription.bIsRealCoordinates)
+        {
+            *dfX = (double)y;
+            *dfY = (double)x;
+        }
+        else
+        {
+            //TODO: check on real data
+            if (m_nSXFFormatVer == 3)
+            {
+                *dfX = stSXFMapDescription.dfXOr + (double)y * m_dfCoeff;
+                *dfY = stSXFMapDescription.dfYOr + (double)x * m_dfCoeff;
+            }
+            else if (m_nSXFFormatVer == 4)
+            {
+                *dfX = stSXFMapDescription.dfXOr + (double)y * m_dfCoeff;
+                *dfY = stSXFMapDescription.dfYOr + (double)x * m_dfCoeff;
+            }
+        }
+        offset += 8;
+
+        if (dfH != NULL)
+        {
+            if( nBufLen < 8 + 4 )
+                return 0;
+            float h;
+            memcpy(&h, psBuff + 8, 4); // H always in float
+            CPL_LSBPTR32(&h);
+            *dfH = (double)h;
+
+            offset += 4;
+        }
+    }
+        break;
+    case SXF_VT_DOUBLE:
+    {
+        if( nBufLen < 16 )
+            return 0;
+        double x, y;
+        memcpy(&y, psBuff, 8);
+        CPL_LSBPTR64(&y);
+        memcpy(&x, psBuff + 8, 8);
+        CPL_LSBPTR64(&x);
+
+        if (stSXFMapDescription.bIsRealCoordinates)
+        {
+            *dfY = y;
+            *dfX = x;
+        }
+        else
+        {
+            *dfX = stSXFMapDescription.dfXOr + x * m_dfCoeff;
+            *dfY = stSXFMapDescription.dfYOr + y * m_dfCoeff;
+        }
+
+        offset += 16;
+
+        if (dfH != NULL)
+        {
+            if( nBufLen < 16 + 8 )
+                return 0;
+            double h;
+            memcpy(&h, psBuff + 16, 8); // H in double
+            CPL_LSBPTR64(&h);
+            *dfH = (double)h;
+
+            offset += 8;
+        }
+    }
+        break;
+    };
+
+    return offset;
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
+{
+    SXFRecordHeader stRecordHeader;
+    int nObjectRead;
+
+    nObjectRead = VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF);
+
+    if (nObjectRead != 1 || stRecordHeader.nID != IDSXFOBJ)
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "SXF. Read record failed.");
+        return NULL;
+    }
+
+    SXFGeometryType eGeomType;
+    GByte code;
+    if (m_nSXFFormatVer == 3)
+    {
+        if (CHECK_BIT(stRecordHeader.nRef[2], 3))
+        {
+            if (CHECK_BIT(stRecordHeader.nRef[2], 4))
+            {
+                code = 0x22;
+                stRecordHeader.nSubObjectCount = 0;
+            }
+            else
+            {
+                code = 0x21; 
+                stRecordHeader.nSubObjectCount = 0;
+            }
+        }
+        else
+        {
+            code = stRecordHeader.nRef[0] & 3;//get first 2 bits
+        }
+    }
+    else if (m_nSXFFormatVer == 4)
+    {
+        if (CHECK_BIT(stRecordHeader.nRef[2], 5))
+        {
+            stRecordHeader.nSubObjectCount = 0;
+        }
+
+        //check if vector
+        code = stRecordHeader.nRef[0] & 15;//get first 4 bits
+        if (code == 0x04) // xxxx0100
+        {
+            code = 0x21;
+            stRecordHeader.nSubObjectCount = 0;
+            //if (CHECK_BIT(stRecordHeader.nRef[2], 5))
+            //{
+            //    code = 0x22;
+            //    stRecordHeader.nSubObjectCount = 0;
+            //}
+            //else
+            //{
+            //    code = 0x21;
+            //    stRecordHeader.nSubObjectCount = 0;
+            //}
+            //if (CHECK_BIT(stRecordHeader.nRef[2], 4))
+            //{
+            //}
+            //else
+            //{
+            //}
+        }
+    }
+
+    if (code == 0x00) // xxxx0000
+        eGeomType = SXF_GT_Line;
+    else if (code == 0x01) // xxxx0001
+        eGeomType = SXF_GT_Polygon;
+    else if (code == 0x02) // xxxx0010
+        eGeomType = SXF_GT_Point;
+    else if (code == 0x03) // xxxx0011
+        eGeomType = SXF_GT_Text;
+    //beginning 4.0
+    else if (code == 0x04) // xxxx0100
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+            "SXF. Not support type.");
+        eGeomType = SXF_GT_Vector;
+    }
+    else if (code == 0x05) // xxxx0101
+        eGeomType = SXF_GT_TextTemplate;
+    else if (code == 0x21) 
+        eGeomType = SXF_GT_VectorAngle;
+    else if (code == 0x22) 
+        eGeomType = SXF_GT_VectorScaled;
+    bool bHasAttributes = CHECK_BIT(stRecordHeader.nRef[1], 1);
+    bool bHasRefVector = CHECK_BIT(stRecordHeader.nRef[1], 3);
+    if (bHasRefVector == true)
+        CPLError(CE_Failure, CPLE_NotSupported,
+        "SXF. Parsing the vector of the tying not support.");
+
+    SXFRecordDescription stCertInfo;
+    if (stRecordHeader.nPointCountSmall == 65535)
+    {
+        stCertInfo.nPointCount = stRecordHeader.nPointCount;
+    }
+    else
+    {
+        stCertInfo.nPointCount = stRecordHeader.nPointCountSmall;
+    }
+    stCertInfo.nSubObjectCount = stRecordHeader.nSubObjectCount;
+
+    bool bFloatType, bBigType;
+    bool b3D(true);
+    if (m_nSXFFormatVer == 3)
+    {
+        b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
+        bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
+        bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
+        stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 5);
+    }
+    else if (m_nSXFFormatVer == 4)
+    {
+        b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
+        bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
+        bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
+        stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 3);
+    }
+
+    if (b3D) //xххххх1х
+        stCertInfo.bDim = 1;
+    else
+        stCertInfo.bDim = 0;
+
+    if (bFloatType)
+    {
+        if (bBigType)
+        {
+            stCertInfo.eValType = SXF_VT_DOUBLE;
+        }
+        else
+        {
+            stCertInfo.eValType = SXF_VT_FLOAT;
+        }
+    }
+    else
+    {
+        if (bBigType)
+        {
+            stCertInfo.eValType = SXF_VT_INT;
+        }
+        else
+        {
+            stCertInfo.eValType = SXF_VT_SHORT;
+        }
+    }
+
+
+    stCertInfo.bFormat = CHECK_BIT(stRecordHeader.nRef[2], 0);
+    stCertInfo.eGeomType = eGeomType;
+
+    OGRFeature *poFeature = NULL;
+    if( stRecordHeader.nGeometryLength > 100 * 1024 * 1024 )
+        return NULL;
+    char * recordCertifBuf = (char *)VSIMalloc(stRecordHeader.nGeometryLength);
+    if( recordCertifBuf == NULL )
+        return NULL;
+    nObjectRead = VSIFReadL(recordCertifBuf, stRecordHeader.nGeometryLength, 1, fpSXF);
+    if (nObjectRead != 1)
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+            "SXF. Read geometry failed.");
+        CPLFree(recordCertifBuf);
+        return NULL;
+    }
+
+    if (eGeomType == SXF_GT_Point)
+        poFeature = TranslatePoint(stCertInfo, recordCertifBuf,
+                                   stRecordHeader.nGeometryLength);
+    else if (eGeomType == SXF_GT_Line || eGeomType == SXF_GT_VectorScaled)
+        poFeature = TranslateLine(stCertInfo, recordCertifBuf,
+                                   stRecordHeader.nGeometryLength);
+    else if (eGeomType == SXF_GT_Polygon)
+        poFeature = TranslatePolygon(stCertInfo, recordCertifBuf,
+                                   stRecordHeader.nGeometryLength);
+    else if (eGeomType == SXF_GT_Text)
+        poFeature = TranslateText(stCertInfo, recordCertifBuf,
+                                   stRecordHeader.nGeometryLength);
+    else if (eGeomType == SXF_GT_VectorAngle)
+    {
+        poFeature = TranslateVetorAngle(stCertInfo, recordCertifBuf,
+            stRecordHeader.nGeometryLength);
+    }
+    else if (eGeomType == SXF_GT_Vector ) 
+    {
+      CPLError( CE_Warning, CPLE_NotSupported,
+      "SXF. Geometry type Vector do not support." );
+      return NULL;
+    }
+    else if (eGeomType == SXF_GT_TextTemplate ) // TODO realise this
+    {
+      CPLError( CE_Warning, CPLE_NotSupported,
+      "SXF. Geometry type Text Template do not support." );
+      return NULL;
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+            "SXF. Unsupported geometry type.");
+        CPLFree(recordCertifBuf);
+        return NULL;
+    }
+    
+    if( poFeature == NULL )
+    {
+        CPLFree(recordCertifBuf);
+        return NULL;
+    }
+
+    poFeature->SetField(sFIDColumn_, (int)nFID);
+
+    poFeature->SetField("CLCODE", (int)stRecordHeader.nClassifyCode);
+
+    CPLString szName = mnClassificators[stRecordHeader.nClassifyCode];
+
+    if (szName.empty())
+    {
+        szName.Printf("%d", stRecordHeader.nClassifyCode);
+    }
+    poFeature->SetField("CLNAME", szName);
+
+    poFeature->SetField("OBJECTNUMB", stRecordHeader.nSubObjectCount);
+
+    if (bHasAttributes)
+    {
+        if( stRecordHeader.nFullLength < 32 ||
+            stRecordHeader.nGeometryLength > stRecordHeader.nFullLength - 32 )
+        {
+            CPLFree(recordCertifBuf);
+            delete poFeature;
+            return NULL;
+        }
+        size_t  nSemanticsSize = stRecordHeader.nFullLength - 32 - stRecordHeader.nGeometryLength;
+        if( nSemanticsSize > 1024 * 1024 )
+        {
+            CPLFree(recordCertifBuf);
+            delete poFeature;
+            return NULL;
+        }
+        char * psSemanticsdBuf = (char *)VSIMalloc(nSemanticsSize);
+        if( psSemanticsdBuf == NULL )
+        {
+            CPLFree(recordCertifBuf);
+            delete poFeature;
+            return NULL;
+        }
+        char * psSemanticsdBufOrig = psSemanticsdBuf;
+        nObjectRead = VSIFReadL(psSemanticsdBuf, nSemanticsSize, 1, fpSXF);
+        if (nObjectRead == 1)
+        {
+            size_t offset = 0;
+            double nVal = 0;
+
+            while (offset + sizeof(SXFRecordAttributeInfo) < nSemanticsSize)
+            {
+                char *psSemanticsdBufBeg = psSemanticsdBuf + offset;
+                SXFRecordAttributeInfo stAttInfo = *(SXFRecordAttributeInfo*)psSemanticsdBufBeg;
+                offset += 4;
+
+                CPLString oFieldName;
+                oFieldName.Printf("SC_%d", stAttInfo.nCode);
+
+                CPLString oFieldValue;
+
+                SXFRecordAttributeType eType = (SXFRecordAttributeType)stAttInfo.nType;
+
+                switch (eType)
+                {
+                case SXF_RAT_ASCIIZ_DOS:
+                {
+                    unsigned nLen = unsigned(stAttInfo.nScale) + 1;
+                    if( nLen > nSemanticsSize || nSemanticsSize - nLen < offset )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    char * value = (char*)CPLMalloc(nLen);
+                    memcpy(value, psSemanticsdBuf + offset, nLen);
+                    value[nLen-1] = 0;
+                    char* pszRecoded = CPLRecode(value, "CP866", CPL_ENC_UTF8);
+                    poFeature->SetField(oFieldName, pszRecoded);
+                    CPLFree(pszRecoded);
+                    CPLFree(value);
+
+                    offset += stAttInfo.nScale + 1;
+                    break;
+                }
+                case SXF_RAT_ONEBYTE:
+                {
+                    GByte nTmpVal;
+                    if( offset + sizeof(GByte) > nSemanticsSize )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GByte));
+                    nVal = double(nTmpVal) * pow(10.0, (double)stAttInfo.nScale);
+
+                    poFeature->SetField(oFieldName, nVal);
+                    offset += 1;
+                    break;
+                }
+                case SXF_RAT_TWOBYTE:
+                {
+                    GInt16 nTmpVal;
+                    if( offset + sizeof(GInt16) > nSemanticsSize )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GInt16));
+                    nVal = double(CPL_LSBWORD16(nTmpVal)) * pow(10.0, (double)stAttInfo.nScale);
+   
+                    poFeature->SetField(oFieldName, nVal);
+                    offset += 2;
+                    break;
+                }
+                case SXF_RAT_FOURBYTE:
+                {
+                    GInt32 nTmpVal;
+                    if( offset + sizeof(GInt32) > nSemanticsSize )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GInt32));
+                    nVal = double(CPL_LSBWORD32(nTmpVal)) * pow(10.0, (double)stAttInfo.nScale);
+
+                    poFeature->SetField(oFieldName, nVal);
+                    offset += 4;
+                    break;
+                }
+                case SXF_RAT_EIGHTBYTE:
+                {
+                    double dfTmpVal;
+                    if( offset + sizeof(double) > nSemanticsSize )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    memcpy(&dfTmpVal, psSemanticsdBuf + offset, sizeof(double));
+                    CPL_LSBPTR64(&dfTmpVal);
+                    double d = dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
+
+                    poFeature->SetField(oFieldName, d);
+
+                    offset += 8;
+                    break;
+                }
+                case SXF_RAT_ANSI_WIN:
+                {
+                    unsigned nLen = unsigned(stAttInfo.nScale) + 1;
+                    if( nLen > nSemanticsSize || nSemanticsSize - nLen < offset )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    char * value = (char*)CPLMalloc(nLen);
+                    memcpy(value, psSemanticsdBuf + offset, nLen);
+                    value[nLen-1] = 0;
+                    char* pszRecoded = CPLRecode(value, "CP1251", CPL_ENC_UTF8);
+                    poFeature->SetField(oFieldName, pszRecoded);
+                    CPLFree(pszRecoded);
+                    CPLFree(value);
+
+                    offset += nLen;
+                    break;
+                }
+                case SXF_RAT_UNICODE:
+                {
+                    unsigned nLen = unsigned(stAttInfo.nScale) + 1;
+                    if( nLen > nSemanticsSize || nSemanticsSize - nLen < offset )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    char * value = (char*)CPLMalloc(nLen);
+                    memcpy(value, psSemanticsdBuf + offset, nLen);
+                    value[nLen-1] = 0;
+                    poFeature->SetField(oFieldName, value);
+                    CPLFree(value);
+
+                    offset += nLen;
+                    break;
+                }
+                case SXF_RAT_BIGTEXT:
+                {
+                    GUInt32 scale2;
+                    if( offset + sizeof(GUInt32) > nSemanticsSize )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+                    memcpy(&scale2, psSemanticsdBuf + offset, sizeof(GUInt32));
+                    CPL_LSBUINT32PTR(&scale2);
+                    /* FIXME add ?: offset += sizeof(GUInt32); */
+                    if( scale2 > nSemanticsSize - 1 || nSemanticsSize - (scale2 + 1) < offset )
+                    {
+                        nSemanticsSize = 0;
+                        break;
+                    }
+
+                    char * value = (char*)CPLMalloc(scale2 + 1);
+                    memcpy(value, psSemanticsdBuf + offset, scale2 + 1);
+                    value[scale2] = 0;
+                    char* pszRecoded = CPLRecode(value, CPL_ENC_UTF16, CPL_ENC_UTF8);
+                    poFeature->SetField(oFieldName, pszRecoded);
+                    CPLFree(pszRecoded);
+                    CPLFree(value);
+
+                    offset += scale2;
+                    break;
+                }
+                default:
+                    CPLFree(recordCertifBuf);
+                    CPLFree(psSemanticsdBufOrig);
+                    delete poFeature;
+                    return NULL;
+                }
+            }
+            CPLFree(psSemanticsdBufOrig);
+        }
+    }    
+   
+    poFeature->SetFID(nFID);
+
+    CPLFree(recordCertifBuf);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         TranslatePoint   ()                          */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription& certifInfo,
+                                        const char * psRecordBuf, GUInt32 nBufLen)
+{
+    double dfX = 1.0;
+    double dfY = 1.0;
+    GUInt32 nOffset = 0;
+
+    GUInt32 nDelta = TranslateXYH( certifInfo, psRecordBuf , nBufLen, &dfX, &dfY );
+    if( nDelta == 0 )
+        return NULL;
+    nOffset += nDelta;
+
+	//OGRFeatureDefn *fd = poFeatureDefn->Clone();
+	//fd->SetGeomType( wkbMultiPoint );
+ //   OGRFeature *poFeature = new OGRFeature(fd);
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRMultiPoint* poMPt = new OGRMultiPoint();
+
+    if (certifInfo.bDim == 1) // TODO realise this
+	{
+		CPLError( CE_Failure, CPLE_NotSupported, 
+				"SXF. 3D metrics do not support." );
+	}
+
+
+    poMPt->addGeometryDirectly( new OGRPoint( dfX, dfY ) );
+
+/*---------------------- Reading SubObjects --------------------------------*/
+
+    for(int count=0 ; count <  certifInfo.nSubObjectCount ; count++)
+    {
+        if( nOffset + 4 > nBufLen )
+            break;
+
+        GUInt16 nSubObj;
+        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
+        CPL_LSBUINT16PTR(&nSubObj);
+
+        GUInt16 nCoords;
+        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
+        CPL_LSBUINT16PTR(&nCoords);
+
+        nOffset +=4;
+
+        for (int i=0; i < nCoords ; i++)
+        {
+            const char * psCoords = psRecordBuf + nOffset ;
+
+            nDelta = TranslateXYH( certifInfo, psCoords , nBufLen - nOffset, &dfX, &dfY ) ;
+            if( nDelta == 0 )
+                break;
+            nOffset +=  nDelta;
+
+            poMPt->addGeometryDirectly( new OGRPoint( dfX, dfY ) );
+        } 
+    }
+
+/*****
+ * TODO : 
+ *          - Translate graphics 
+ *          - Translate 3D vector
+ */
+
+    poFeature->SetGeometryDirectly( poMPt );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         TranslateLine    ()                          */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription& certifInfo,
+                                       const char * psRecordBuf, GUInt32 nBufLen)
+{
+    double dfX = 1.0;
+    double dfY = 1.0;
+
+    GUInt32 nOffset = 0;
+
+	//OGRFeatureDefn *fd = poFeatureDefn->Clone();
+	//fd->SetGeomType( wkbMultiLineString );
+ //   OGRFeature *poFeature = new OGRFeature(fd);
+
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRMultiLineString *poMLS = new  OGRMultiLineString ();
+
+/*---------------------- Reading Primary Line --------------------------------*/
+
+    OGRLineString* poLS = new OGRLineString();
+
+    if (certifInfo.bDim == 1) // TODO realise this
+	{
+		 CPLError( CE_Failure, CPLE_NotSupported, 
+                  "SXF. 3D metrics do not support." );
+	}
+
+    for(int count=0 ; count <  certifInfo.nPointCount ; count++)
+    {
+        const char * psCoords = psRecordBuf + nOffset ;
+        GUInt32 nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY );
+        if( nDelta == 0 )
+            break;
+        nOffset += nDelta;
+
+        poLS->addPoint( dfX  , dfY );
+    }
+
+    poMLS->addGeometry( poLS );
+
+/*---------------------- Reading Sub Lines --------------------------------*/
+
+    for(int count=0 ; count <  certifInfo.nSubObjectCount ; count++)
+    {
+        poLS->empty();
+
+        if( nOffset + 4 > nBufLen )
+            break;
+
+        GUInt16 nSubObj;
+        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
+        CPL_LSBUINT16PTR(&nSubObj);
+
+        GUInt16 nCoords;
+        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
+        CPL_LSBUINT16PTR(&nCoords);
+
+        nOffset +=4;
+
+        for (int i=0; i < nCoords ; i++)
+        {
+            const char * psCoords = psRecordBuf + nOffset ;
+
+            GUInt32 nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY );
+            if( nDelta == 0 )
+                break;
+            nOffset += nDelta;
+
+            poLS->addPoint( dfX  , dfY );
+        }
+
+        poMLS->addGeometry( poLS );
+    }    // for
+
+    delete poLS;
+    poFeature->SetGeometryDirectly( poMLS );
+
+/*****
+ * TODO : 
+ *          - Translate graphics 
+ *          - Translate 3D vector
+ */
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                       TranslateVetorAngle()                          */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription& certifInfo,
+    const char * psRecordBuf, GUInt32 nBufLen)
+{
+    if (certifInfo.nPointCount != 2)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+            "SXF. The vector object should have 2 points, but not.");
+        return NULL;
+    }
+
+    double dfX = 1.0;
+    double dfY = 1.0;
+
+    GUInt32 nOffset = 0;
+
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRPoint *poPT = new OGRPoint();
+
+    /*---------------------- Reading Primary Line --------------------------------*/
+
+    OGRLineString* poLS = new OGRLineString();
+
+    if (certifInfo.bDim == 1) // TODO realise this
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+            "SXF. 3D metrics do not support.");
+    }
+
+    for (int count = 0; count < certifInfo.nPointCount; count++)
+    {
+        const char * psCoords = psRecordBuf + nOffset;
+        GUInt32 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY);
+        if (nDelta == 0)
+            break;
+        nOffset += nDelta;
+
+        poLS->addPoint(dfX, dfY);
+    }
+
+    poLS->StartPoint(poPT);
+
+    OGRPoint *poAngPT = new OGRPoint();
+    poLS->EndPoint(poAngPT);
+
+    double xDiff = poPT->getX() - poAngPT->getX();
+    double yDiff = poPT->getY() - poAngPT->getY();
+    double dfAngle = atan2(xDiff, yDiff) * TO_DEGREES - 90;
+    if (dfAngle < 0)
+        dfAngle += 360;
+
+    poFeature->SetGeometryDirectly(poPT);
+    poFeature->SetField("ANGLE", dfAngle);
+
+    delete poAngPT;
+    delete poLS;
+
+    return poFeature;
+}
+
+
+/************************************************************************/
+/*                         TranslatePolygon ()                          */
+/************************************************************************/
+
+OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo,
+                                          const char * psRecordBuf, GUInt32 nBufLen)
+{
+    double dfX = 1.0;
+    double dfY = 1.0;
+    GUInt32 nOffset = 0;
+
+	//OGRFeatureDefn *fd = poFeatureDefn->Clone();
+	//fd->SetGeomType( wkbMultiPolygon );
+ //   OGRFeature *poFeature = new OGRFeature(fd);
+
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRPolygon *poPoly = new OGRPolygon();
+    OGRLineString* poLS = new OGRLineString();
+
+/*---------------------- Reading Primary Polygon --------------------------------*/
+
+    if (certifInfo.bDim == 1) // TODO realise this
+	{
+			CPLError( CE_Failure, CPLE_NotSupported, 
+					"SXF. 3D metrics do not support." );
+	}
+
+    for(int count=0 ; count <  certifInfo.nPointCount ; count++)
+    {
+        const char * psBuf = psRecordBuf + nOffset ;
+
+        GUInt32 nDelta = TranslateXYH( certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY );
+        if( nDelta == 0 )
+            break;
+        nOffset += nDelta;
+        poLS->addPoint( dfX  , dfY );
+
+    }    // for
+
+    OGRLinearRing *poLR = new OGRLinearRing();
+    poLR->addSubLineString( poLS, 0 );
+
+    poPoly->addRingDirectly( poLR );
+
+/*---------------------- Reading Sub Lines --------------------------------*/
+
+    for(int count=0 ; count <  certifInfo.nSubObjectCount ; count++)
+    {
+        poLS->empty();
+
+        if( nOffset + 4 > nBufLen )
+            break;
+
+        GUInt16 nSubObj;
+        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
+        CPL_LSBUINT16PTR(&nSubObj);
+
+        GUInt16 nCoords;
+        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
+        CPL_LSBUINT16PTR(&nCoords);
+
+        nOffset +=4;
+
+        int i;
+        for (i=0; i < nCoords ; i++)
+        {
+            const char * psCoords = psRecordBuf + nOffset ;
+
+            GUInt32 nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY );
+            if( nDelta == 0 )
+                break;
+            nOffset += nDelta;
+
+            poLS->addPoint( dfX  , dfY );
+        }
+
+        OGRLinearRing *poLR = new OGRLinearRing();
+        poLR->addSubLineString( poLS, 0 );
+
+        poPoly->addRingDirectly( poLR );
+    }    // for
+
+    poFeature->SetGeometryDirectly( poPoly );   //poLS);
+    delete poLS;
+
+/*****
+ * TODO : 
+ *          - Translate graphics 
+ *          - Translate 3D vector
+ */
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         TranslateText    ()                          */
+/************************************************************************/
+OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription& certifInfo,
+                                       const char * psRecordBuf, GUInt32 nBufLen)
+{
+    double dfX = 1.0;
+    double dfY = 1.0;
+    GUInt32 nOffset = 0;
+
+	//OGRFeatureDefn *fd = poFeatureDefn->Clone();
+	//fd->SetGeomType( wkbLineString );
+ //   OGRFeature *poFeature = new OGRFeature(fd);
+
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRLineString* poLS = new OGRLineString();
+
+    if (certifInfo.bDim == 1) // TODO realise this
+	{
+			CPLError( CE_Failure, CPLE_NotSupported, 
+					"SXF. 3D metrics do not support." );
+	}
+
+    for(int count=0 ; count <  certifInfo.nPointCount ; count++)
+    {
+        const char * psBuf = psRecordBuf + nOffset;
+        GUInt32 nDelta = TranslateXYH( certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY );
+        if( nDelta == 0 )
+            break;
+        nOffset += nDelta;
+        poLS->addPoint( dfX  , dfY );
+    }
+
+    poFeature->SetGeometryDirectly( poLS );
+
+/*------------------     READING TEXT VALUE   ---------------------------------------*/
+
+    if ( certifInfo.nSubObjectCount == 0 && certifInfo.bHasTextSign == true)
+    {
+        if( nOffset + 1 > nBufLen )
+            return poFeature;
+        const char * pszTxt = psRecordBuf + nOffset;
+        GByte nTextL = (GByte) *pszTxt;
+        if( nOffset + 1 + nTextL > nBufLen )
+            return poFeature;
+
+        char * pszTextBuf = (char *)CPLMalloc( nTextL+1 );
+
+        strncpy(pszTextBuf, (pszTxt+1),    nTextL);
+        pszTextBuf[nTextL] = '\0';
+
+        //TODO: Check encoding from sxf
+        poFeature->SetField("TEXT", pszTextBuf);
+ 
+        CPLFree( pszTextBuf );
+    }
+
+
+/*****
+ * TODO : 
+ *          - Translate graphics 
+ *          - Translate 3D vector
+ */
+
+    return poFeature;
+}
+
+const char* OGRSXFLayer::GetFIDColumn()
+{
+    return sFIDColumn_.c_str();
+}
+
diff --git a/ogr/ogrsf_frmts/sxf/org_sxf_defs.h b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
new file mode 100644
index 0000000..b24b09e
--- /dev/null
+++ b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
@@ -0,0 +1,372 @@
+/******************************************************************************
+ * $Id: org_sxf_defs.h  $
+ *
+ * Project:  SXF Translator
+ * Purpose:  Include file defining Records Structures for file reading and 
+ *           basic constants.
+ * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *           Alexandr Lisovenko, alexander.lisovenko at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Ben Ahmed Daho Ali
+ * Copyright (c) 2013, NextGIS
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ******************************************************************************
+ * Structure of the SXF file : 
+ * ----------------------
+ *    - Header 
+ *    - Passport
+ *    - Descriptor of data
+ *    - Records 
+ *         - Title of the record 
+ *         - The certificate of the object (the geomety)
+ *             - sub-objects
+ *             - The graphic description of object
+ *             - The description of the vector of the tying of the 3d- model of object
+ *         - Semantics of object
+ *
+ * Notes  : 
+ * -------
+ * Note 1.  Flag of the state of data (2 bits):
+ * xxxxxx11- given in the state e (size of the exchange of data).
+ *
+ * Note 2.  Flag of the correspondence to projection (1 bit):
+ * xxxxx0xx - do not correspond to the projection (i.e. map it can have turning 
+ *                 relative to true position and certain deformation);
+ * xxxxx1xx - correspond to projection.
+ *
+ * Note 3.  Flag of the presence of real coordinates (2 bits):
+ * xxx00xxx - entire certificate of objects is represented in the conditional 
+ *                                 system of coordinates (in the samples);
+ * xxx11xxx - entire certificate of objects is represented in the real coordinates 
+ *            in the locality in accordance with the specifications of sheet 
+ *            (projection, the coordinate system, unit of measurement), 
+ *            the data about the scale and the discretion of digitization bear 
+ *            reference nature.
+ *
+ * Note 4. Flag of the method of coding (2 bits):
+ * x00xxxxx - the classification codes of objects and semantic characteristics 
+ *          are represented by the decimal numbers, recorded in the binary 
+ *          form (for example: the code of the object �32100000� will be written 
+ *          down in the form 0x01E9CEA0, the code of semantics �253� - in the form 0x00FD).
+ *
+ * Note 5. Table of generalization (1 bit):
+ * 0xxxxxxx - the level of generalization is assigned according to the table of the 
+ *           general maps (it is described in Table 2.4);
+ * 1xxxxxxx - noload condition the level of generalization is assigned according to 
+ *           the table of the large-scale maps (it is described in Table 2.5).
+ *
+ * Note 6.  Flag of coding the texts of the Texts objects (1 bytes):
+ * 0- in the coding ASCIIZ (Dos);
+ * 1- in the coding ANSI (Windows);
+ * 2- in the coding KOI-8 (Unix).
+ *
+ * Note 7.  Flag of the accuracy of coordinates (1 bytes):
+ * 0 � are not established;
+ * 1 � the increased accuracy of storage of coordinates (meters, radians or degrees);
+ * 2 � of coordinate are recorded with an accuracy to centimeter (meters, 2 signs after comma);
+ * 3 � coordinates are recorded with an accuracy to millimeter (meters, 3 sign after comma).
+ *
+ * Note 8. Form of the framework (1 byte):
+ * -1- it is not established;
+ *  0- map is unconfined by the framework;
+ *  1- trapeziform without the salient points;
+ *  2- trapeziform with the salient points;
+ *  3- rectangular;
+ *  4- circular;
+ *  5- arbitrary.
+ *
+ * Note 9. Sign of output to the framework (4 bits):
+ * 0000xxxx - there are no outputs to the framework;
+ * 1000xxxx - northern framework;
+ * 0100xxxx - eastern framework;
+ * 0010xxxx - southern framework;
+ * 0001xxxx - western framework.
+ *
+ * Note 10. Size of the element of certificate (1 bit):
+ * xxxxx0xx - 2 bytes (for the integer value); 
+ *            4 bytes (for the floating point); 
+ * xxxxx1xx - 4 bytes (for the integer value); 
+ *            8 bytes (for the floating point).
+ *
+ * Note 11. Sign of certificate with the text (1 bit): 
+ * xxxx0xxx - certificate contains only the coordinates of points; 
+ * xxxx1xxx - no-load condition certificate contains the text of signature, 
+ *         is allowed only for the objects of the type "signature" or 
+ *         "the template of signature".
+ *
+ * Note 12. [Masshtabiruemost] of drawing (sign) (1 bit):
+ * xx0xxxxx - arbitrary symbol of object not scaled;
+ * xx1xxxxx - the arbitrary symbol of object is scaled during the mapping.
+ * 
+ * Note 13. Sign of the construction of spline on the certificate (2 bits):
+ * 00xxxxxx � the construction of spline with the visualization is not carried out;
+ * 01xxxxxx � smoothing out spline (cutting angles);
+ * 10xxxxxx � enveloping spline (it penetrates all points of certificate).
+ ****************************************************************************/
+
+#ifndef SXF_DEFS_H
+#define SXF_DEFS_H
+
+#define IDSXF          0x00465853     /* SXF  */
+
+#define IDSXFDATA      0x00544144     /* DAT  */
+#define IDSXFOBJ       0X7FFF7FFF     /* Object */
+#define IDSXFGRAPH     0X7FFF7FFE     /* graphics section */
+#define IDSXFVECT3D    0X7FFF7FFD     /* 3D vector section */
+
+#include <map>
+
+#include "cpl_port.h"
+
+enum SXFDataState /* Flag of the state of the data (Note 1) */
+{
+    SXF_DS_UNKNOWN = 0,
+    SXF_DS_EXCHANGE = 8
+};
+
+enum SXFCodingType /* Flag of the semantics coding type (Note 4) */
+{
+    SXF_SEM_DEC = 0,
+    SXF_SEM_HEX = 1,
+    SXF_SEM_TXT = 2
+};
+
+enum SXFGeneralizationType /* Flag of the source for generalization data (Note 5) */
+{
+    SXF_GT_SMALL_SCALE = 0,
+    SXF_GT_LARGE_SCALE = 1
+};
+
+enum SXFTextEncoding /* Flag of text encoding (Note 6) */
+{
+    SXF_ENC_DOS = 0,
+    SXF_ENC_WIN = 1,
+    SXF_ENC_KOI_8 = 2
+};
+
+enum SXFCoordinatesAccuracy /* Flag of coordinate storing accuracy (Note 7) */
+{
+    SXF_COORD_ACC_UNDEFINED = 0,
+    SXF_COORD_ACC_HIGH = 1, //meters, radians or degree
+    SXF_COORD_ACC_CM = 2,   //cantimeters
+    SXF_COORD_ACC_MM = 3,   //millimeters
+    SXF_COORD_ACC_DM = 4    //decimeters
+};
+
+typedef struct
+{
+//    SXFDataState   stDataState;         /* Flag of the state of the data (Note 1) may be will be needed in future*/
+    bool bProjectionDataCompliance;     /* Flag of the correspondence to the projection (Note 2) */
+    bool bRealCoordinatesCompliance;    /* Flag of the presence of the real coordinates (Note 3) */
+    SXFCodingType stCodingType;         /* Flag of the semantics coding type (Note 4) */
+    SXFGeneralizationType stGenType;    /* Flag of the source for generalization data (Note 5) */
+    SXFTextEncoding stEnc;              /* Flag of text encoding (Note 6) */
+    SXFCoordinatesAccuracy stCoordAcc;  /* Flag of coordinate storing accuracy (Note 7) */
+    bool bSort;
+} SXFInformationFlags;
+
+enum SXFCoordinateMeasUnit
+{
+    SXF_COORD_MU_METRE = 1,
+    SXF_COORD_MU_DECIMETRE,
+    SXF_COORD_MU_CENTIMETRE,
+    SXF_COORD_MU_MILLIMETRE,
+    SXF_COORD_MU_DEGREE,
+    SXF_COORD_MU_RADIAN
+} ;
+
+typedef struct
+{
+    long double stProjCoords[8]; //X(0) & Y(1) South West, X(2) & Y(3) North West, X(4) & Y(5) North East, X(6) & Y(7) South East
+    long double stGeoCoords[8];
+    long double stFrameCoords[8];
+    OGREnvelope Env;
+    OGRSpatialReference *pSpatRef;
+    SXFCoordinateMeasUnit eUnitInPlan;
+    double dfXOr;
+    double dfYOr;
+    double dfFalseNorthing;
+    double dfFalseEasting;
+    GUInt32 nResolution;
+    long double dfScale;
+    bool bIsRealCoordinates;
+    SXFCoordinatesAccuracy stCoordAcc;
+
+} SXFMapDescription;
+
+
+enum SXFCoordinateType
+{
+    SXF_CT_RECTANGULAR = 0,
+    SXF_CT_GEODETIC
+};
+
+
+/*
+ * List of SXF file format geometry types.
+ */
+enum SXFGeometryType
+{
+    SXF_GT_Line    = 0,     /* MultiLineString geometric object                  */
+    SXF_GT_Polygon = 1,     /* Polygon geometric object                          */
+    SXF_GT_Point = 2,       /* MultiPoint geometric object                       */
+    SXF_GT_Text = 3,        /* LineString geometric object with associated label */
+    SXF_GT_Vector = 4,      /* Vector geometric object with associated label */
+    SXF_GT_TextTemplate = 5, /* Text template */
+    SXF_GT_VectorAngle = 21,       /* Rotated symbol */
+    SXF_GT_VectorScaled = 22       /* Scaled symbol */
+};
+
+enum SXFValueType
+{
+    SXF_VT_SHORT = 0,     /* 2 byte integer */
+    SXF_VT_FLOAT = 1,   /* 2 byte float */
+    SXF_VT_INT = 2,    /* 4 byte integer*/
+    SXF_VT_DOUBLE = 3  /* 8 byte float */
+};
+
+typedef struct
+{
+    SXFGeometryType eGeomType;  // Geometry type (Note 1)
+    SXFValueType eValType;      // size of values (Note 3)
+    int bFormat;                 // Has 3D vector (Note 4) /* Format of the certificate (0- linear size, 1-vector format ) */
+    GByte bDim;                 // Dimensionality of the idea (0- 2D, 1- 3D) (Note 6)
+    int bHasTextSign;           // Sign of certificate with the text (Note 8)
+    GUInt32 nPointCount;        // Point count
+    GUInt16 nSubObjectCount;    // The sub object count
+
+} SXFRecordDescription;
+
+typedef struct{
+    GUInt32 nID;                /* Identifier of the beginning of record (0x7FFF7FFF) */
+    GUInt32 nFullLength;        /* The overall length of record (with the title) */
+    GUInt32 nGeometryLength;    /* Length of certificate (in bytes) */
+    GUInt32 nClassifyCode;      /* Classification code */
+    GUInt16 anGroup[2];         /* 0 - group no, 1 - no in group */
+    GByte   nRef[3];            /* Reference data */
+    GByte   byPadding;
+    GUInt32 nPointCount;        /* Point count */
+    GUInt16 nSubObjectCount;    /* The sub object count */
+    GUInt16 nPointCountSmall;   /* Point count in small geometries */
+} SXFRecordHeader;
+
+typedef struct
+{
+    GUInt16 nCode;       //type
+    char   nType;
+    char   nScale;
+} SXFRecordAttributeInfo;
+
+enum SXFRecordAttributeType
+{
+    SXF_RAT_ASCIIZ_DOS = 0, //text in DOS encoding
+    SXF_RAT_ONEBYTE = 1,    //number 1 byte
+    SXF_RAT_TWOBYTE = 2,    //number 2 byte
+    SXF_RAT_FOURBYTE = 4,   //number 4 byte
+    SXF_RAT_EIGHTBYTE = 8,  //float point number 8 byte
+    SXF_RAT_ANSI_WIN = 126, //text in Win encoding
+    SXF_RAT_UNICODE = 127,  //text in unicode
+    SXF_RAT_BIGTEXT = 128   //text more than 255 chars
+};
+
+/************************************************************************/
+/*                         SXFPassport                                  */
+/************************************************************************/
+
+typedef struct{
+    GUInt16 nYear, nMonth, nDay;
+} SXFDate;
+
+struct SXFPassport
+{
+    GUInt32 version;
+    SXFDate dtCrateDate;
+    CPLString sMapSheet;   
+    GUInt32 nScale;
+    CPLString sMapSheetName;
+    SXFInformationFlags informationFlags;
+    SXFMapDescription stMapDescription;
+};
+
+typedef struct
+{
+    char szID[4]; //the file ID should be "SXF"
+    GUInt32 nHeaderLength; //the Header length
+    GByte nFormatVersion[4]; //the format version (e.g. 4)
+    GUInt32 nCheckSum; //check sum
+}  SXFHeader;
+
+
+/************************************************************************/
+/*                         RSCInfo                                      */
+/************************************************************************/
+
+/*
+    RSC File record
+*/
+typedef struct  {
+    GUInt32 nOffset;      //RSC Section offset in bytes from the beginning of the RSC file
+    GUInt32 nLenght;      //RSC Section record length
+    GUInt32 nRecordCount; //count of records in the section
+} RSCSection;
+
+/*
+    RSC File header
+*/
+typedef struct{
+    char szID[4];
+    GUInt32 nFileLength;
+    GUInt32 nVersion;
+    GUInt32 nEncoding;
+    GUInt32 nFileState;
+    GUInt32 nFileModState;
+    GUInt32 nLang;                  //1 - en, 2 - rus
+    GUInt32 nNextID;
+    GByte date[8];
+    char szMapType[32];
+    char szClassifyName[32];
+    char szClassifyCode[8];
+    GUInt32 nScale;
+    char nScales[4];
+    RSCSection Objects;
+    RSCSection Semantic;
+    RSCSection ClassifySemantic;
+    RSCSection Defaults;
+    RSCSection Semantics;
+    RSCSection Layers;
+    RSCSection Limits;
+    RSCSection Parameters;
+    RSCSection Print;
+    RSCSection Palettes;
+    RSCSection Fonts;
+    RSCSection Libs;
+    RSCSection ImageParams;
+    RSCSection Tables;
+    GByte nFlagKeysAsCodes;
+    GByte nFlagPalleteMods;
+    GByte Reserved[30];
+    GUInt32 nFontEnc;
+    GUInt32 nColorsInPalette;
+} RSCHeader;
+
+#endif  /* SXF_DEFS_H */
diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
index 23539ee..e353574 100644
--- a/ogr/ogrsf_frmts/tiger/ogr_tiger.h
+++ b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
@@ -1,6 +1,6 @@
 /*-*-C++-*-*/
 /******************************************************************************
- * $Id: ogr_tiger.h 23871 2012-02-02 03:24:07Z warmerdam $
+ * $Id: ogr_tiger.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Main declarations for Tiger translator.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -524,8 +525,6 @@ class OGRTigerLayer : public OGRLayer
 
     int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual OGRErr      CreateFeature( OGRFeature *poFeature );
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
index 4ad9454..95670bd 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtigerlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogrtigerlayer.cpp 26466 2013-09-14 09:07:46Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerLayer class.
@@ -29,7 +29,7 @@
 
 #include "ogr_tiger.h"
 
-CPL_CVSID("$Id: ogrtigerlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrtigerlayer.cpp 26466 2013-09-14 09:07:46Z rouault $");
 
 /************************************************************************/
 /*                           OGRTigerLayer()                            */
@@ -226,23 +226,19 @@ int OGRTigerLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRTigerLayer::GetSpatialRef()
-
-{
-    return poDS->GetSpatialRef();
-}
-
-/************************************************************************/
 /*                            GetLayerDefn()                            */
 /************************************************************************/
 
 OGRFeatureDefn *OGRTigerLayer::GetLayerDefn()
 
 {
-    return poReader->GetFeatureDefn();
+    OGRFeatureDefn* poFDefn = poReader->GetFeatureDefn();
+    if( poFDefn != NULL )
+    {
+        if( poFDefn->GetGeomFieldCount() > 0 )
+            poFDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
+    }
+    return poFDefn;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
index 47ad77b..b2bfbca 100644
--- a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerentitynames.cpp 22961 2011-08-20 17:09:59Z rouault $
+ * $Id: tigerentitynames.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerEntityNames, providing access to .RTC files.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerentitynames.cpp 22961 2011-08-20 17:09:59Z rouault $");
+CPL_CVSID("$Id: tigerentitynames.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define FILE_CODE "C"
 
diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
index 061bd9e..1593d8a 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerfilebase.cpp 23871 2012-02-02 03:24:07Z warmerdam $
+ * $Id: tigerfilebase.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerBaseFile class, providing common services to all
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: tigerfilebase.cpp 23871 2012-02-02 03:24:07Z warmerdam $");
+CPL_CVSID("$Id: tigerfilebase.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           TigerFileBase()                            */
@@ -341,7 +342,7 @@ int TigerFileBase::WritePoint( char *pachRecord, int nStart,
 
     if( dfX == 0.0 && dfY == 0.0 )
     {
-        strncpy( pachRecord + nStart - 1, "+000000000+00000000", 19 );
+        memcpy( pachRecord + nStart - 1, "+000000000+00000000", 19 );
     }
     else
     {
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
index 209c368..a288df7 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygon.cpp 23871 2012-02-02 03:24:07Z warmerdam $
+ * $Id: tigerpolygon.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygon, providing access to .RTA files.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygon.cpp 23871 2012-02-02 03:24:07Z warmerdam $");
+CPL_CVSID("$Id: tigerpolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static const TigerFieldInfo rtA_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/vfk/drv_vfk.html b/ogr/ogrsf_frmts/vfk/drv_vfk.html
index e307e2d..fd787d1 100644
--- a/ogr/ogrsf_frmts/vfk/drv_vfk.html
+++ b/ogr/ogrsf_frmts/vfk/drv_vfk.html
@@ -10,7 +10,7 @@
 This driver reads VFK files, ie. data in the <em>Czech cadastral
 exchange data format</em>. The VFK file is recognized as an OGR
 datasource with zero or more OGR layers. The filenames must end with
-.vfk extension.
+".vfk" extension.
 
 <p>
 Note: starting with OGR 1.10, the driver is compiled only if GDAL
@@ -25,11 +25,14 @@ used. Feature types cannot be mixed in one layer.
 
 Starting with OGR 1.9, the driver reads and writes VFK data from/to
 internal SQLite database. Default name of the database is
-<input_vfk_file>.db. Since OGR 1.10, you can define an
-alternative DB name with <tt>OGR_VFK_DB_NAME</tt> configuration
+"<input_vfk_file>.db". Since OGR 1.10, you can define
+an alternative DB name with <tt>OGR_VFK_DB_NAME</tt> configuration
 option. If <tt>OGR_VFK_DB_OVERWRITE=YES</tt> configuration option is
 given, than the driver overwrites existing SQLite database and reads
-data from original input VFK file.
+data from original input VFK file. By default, the internal SQLite
+database is not automatically deleted. Since OGR 1.11, the internal
+database is deleted if <tt>OGR_VFK_DB_DELETE=YES</tt> configuration
+option is given.
 
 <p>
 Starting with OGR 1.10, resolved geometries are stored also in SQLite
@@ -42,12 +45,18 @@ this case the geometries are resolved from DB.
 
 <h3>Internal working and performance tweaking</h3>
 
-Since OGR 1.9, the driver will use an internal SQLite database to
-resolve geometries. By default, this file will be written in the same
+Since OGR 1.9, the driver uses an internal SQLite database to resolve
+geometries. By default, this file will be written in the same
 directory as input VFK file. If SQLite database already exists then
-the driver reads VFK features directly from database (and not from
+the driver reads VFK features directly from the database (and not from
 original VFK file).
 
+<p>
+Since OGR 1.11, the driver reads by default all data blocks. When
+configuration option <tt>OGR_VFK_DB_READ_ALL_BLOCKS=NO</tt> is given
+than the driver reads only data blocks which are requested by the
+user.
+
 <h2>Datasource name</h2>
 
 Datasource name is a full path to the VFK file.
diff --git a/ogr/ogrsf_frmts/vfk/ogr_vfk.h b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
index 85e3069..abdcaed 100644
--- a/ogr/ogrsf_frmts/vfk/ogr_vfk.h
+++ b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vfk.h 24067 2012-03-04 11:27:45Z martinl $
+ * $Id: ogr_vfk.h 26468 2013-09-14 09:46:19Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VFK driver.
@@ -79,7 +79,6 @@ public:
     void                 ResetReading();
     
     int                  TestCapability(const char *);
-    OGRSpatialReference *GetSpatialRef();
 
     int                  GetFeatureCount(int = TRUE);
 };
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
index 8c09159..acdd245 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfkdatasource.cpp 25703 2013-03-07 18:23:48Z martinl $
+ * $Id: ogrvfkdatasource.cpp 26906 2014-01-31 16:28:21Z martinl $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKDatasource class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfkdatasource.cpp 25703 2013-03-07 18:23:48Z martinl $");
+CPL_CVSID("$Id: ogrvfkdatasource.cpp 26906 2014-01-31 16:28:21Z martinl $");
 
 /*!
   \brief OGRVFKDataSource constructor
@@ -99,7 +99,7 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
         szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
         
         // TODO: improve check
-        if (strncmp(szHeader, "&HVERZE;", 8) != 0) {
+        if (strncmp(szHeader, "&H", 2) != 0) {
             VSIFClose(fp);
             return FALSE;
         } 
@@ -131,6 +131,10 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
         nLayers++;
     }
     
+    /* read data records if required */
+    if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_READ_ALL_BLOCKS", "YES")))
+        poReader->ReadDataRecords();
+
     return TRUE;
 }
 
@@ -158,6 +162,11 @@ OGRLayer *OGRVFKDataSource::GetLayer(int iLayer)
 */
 int OGRVFKDataSource::TestCapability(const char * pszCap)
 {
+    if (EQUAL(pszCap, "IsPreProcessed") && poReader) {
+        if (poReader->IsPreProcessed())
+            return TRUE;
+    }
+
     return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
index 0c51de0..e448009 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfklayer.cpp 25702 2013-03-07 17:17:54Z martinl $
+ * $Id: ogrvfklayer.cpp 26596 2013-11-08 17:59:47Z martinl $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKLayer class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfklayer.cpp 25702 2013-03-07 17:17:54Z martinl $");
+CPL_CVSID("$Id: ogrvfklayer.cpp 26596 2013-11-08 17:59:47Z martinl $");
 
 /*!
   \brief OGRVFKLayer constructor
@@ -87,6 +87,7 @@ OGRVFKLayer::OGRVFKLayer(const char *pszName,
 
     /* feature definition */
     poFeatureDefn = new OGRFeatureDefn(pszName);
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(eReqType);
@@ -145,14 +146,6 @@ OGRGeometry *OGRVFKLayer::CreateGeometry(IVFKFeature * poVfkFeature)
 }
 
 /*!
-  \brief Get spatial reference information
-*/
-OGRSpatialReference *OGRVFKLayer::GetSpatialRef()
-{
-    return poSRS;
-}
-
-/*!
   \brief Get feature count
 
   This method overwrites OGRLayer::GetFeatureCount(), 
@@ -165,15 +158,13 @@ int OGRVFKLayer::GetFeatureCount(int bForce)
 {
     int nfeatures;
 
-    if(!bForce)
-        return -1;
-    
-    if (m_poFilterGeom || m_poAttrQuery)
+    if (m_poFilterGeom || m_poAttrQuery || bForce)
         nfeatures = OGRLayer::GetFeatureCount(bForce);
     else
         nfeatures = poDataBlock->GetFeatureCount();
     
-    CPLDebug("OGR_VFK", "OGRVFKLayer::GetFeatureCount(): n=%d", nfeatures);
+    CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeatureCount(): name=%s -> n=%d",
+             GetName(), nfeatures);
     
     return nfeatures;
 }
@@ -234,7 +225,7 @@ OGRFeature *OGRVFKLayer::GetFeature(long nFID)
         return NULL;
 
     CPLAssert(nFID == poVFKFeature->GetFID());
-    CPLDebug("OGR_VFK", "OGRVFKLayer::GetFeature(): fid=%ld", nFID);
+    CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeature(): name=%s fid=%ld", GetName(), nFID);
     
     return GetFeature(poVFKFeature);
 }
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
index 1114c2a..51b9fde 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkdatablock.cpp 26317 2013-08-14 08:17:37Z rouault $
+ * $Id: vfkdatablock.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VFK Reader - Data block definition
  * Purpose:  Implements VFKDataBlock class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -59,6 +60,10 @@ IVFKDataBlock::IVFKDataBlock(const char *pszName, const IVFKReader *poReader)
     m_bGeometryPerBlock = TRUE;    /* load geometry per block/feature */
 
     m_poReader       = (IVFKReader *) poReader;
+    
+    m_nRecordCount[RecordValid]      = 0L;      /* number of valid records */
+    m_nRecordCount[RecordSkipped]    = 0L;      /* number of skipped (invalid) records */
+    m_nRecordCount[RecordDuplicated] = 0L;      /* number of duplicated records */
 }
 
 /*!
@@ -466,11 +471,11 @@ int IVFKDataBlock::LoadGeometry()
 
     if (nInvalid > 0) {
         CPLError(CE_Warning, CPLE_AppDefined, 
-                 "%s: %d invalid features found", m_pszName, nInvalid);
+                 "%s: %d features with invalid or empty geometry found", m_pszName, nInvalid);
     }
 
 #ifdef DEBUG_TIMING
-    CPLDebug("OGR_VFK", "VFKDataBlock::LoadGeometry(): name=%s time=%ld sec",
+    CPLDebug("OGR-VFK", "VFKDataBlock::LoadGeometry(): name=%s time=%ld sec",
              m_pszName, (long)((end - start) / CLOCKS_PER_SEC));
 #endif
 
@@ -580,6 +585,28 @@ void IVFKDataBlock::AddFeature(IVFKFeature *poNewFeature)
 }
 
 /*!
+  \brief Get number of records
+
+  \param iRec record type (valid, skipped, duplicated)
+
+  \return number of records
+*/
+int IVFKDataBlock::GetRecordCount(RecordType iRec) const
+{
+    return m_nRecordCount[iRec];
+}
+
+/*!
+  \brief Increment number of records
+
+  \param iRec record type (valid, skipped, duplicated)
+*/
+void IVFKDataBlock::SetIncRecordCount(RecordType iRec)
+{
+    m_nRecordCount[iRec]++;
+}
+
+/*!
   \brief Get first found feature based on it's properties
   
   Note: modifies next feature.
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
index 044ecb1..137f946 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
@@ -1,12 +1,13 @@
 /******************************************************************************
- * $Id: vfkdatablocksqlite.cpp 25721 2013-03-09 16:21:46Z martinl $
+ * $Id: vfkdatablocksqlite.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VFK Reader - Data block definition (SQLite)
  * Purpose:  Implements VFKDataBlockSQLite
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2012-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2014, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -92,7 +93,7 @@ int VFKDataBlockSQLite::LoadGeometryPoint()
 	    nGeometries++;
     }
     
-    /* update number of geometries in 'vfk_blocks' table */
+    /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
@@ -211,13 +212,13 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 		}
 		else {
 		    CPLDebug("OGR-VFK", 
-			     "Geometry (point ID = %lld) not valid", id);
+			     "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
 		    bValid = FALSE;
 		}
 	    }
 	    else {
                 CPLDebug("OGR-VFK", 
-                         "Point ID = %lld not found (rowid = %d)",
+                         "Point ID = " CPL_FRMT_GUIB " not found (rowid = %d)",
                          id, rowId);
 		bValid = FALSE;
             }
@@ -256,7 +257,7 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 	    poReader->ExecuteSQL("COMMIT");
     }
 
-    /* update number of geometries in 'vfk_blocks' table */
+    /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
     
     return nInvalid;
@@ -330,6 +331,9 @@ int VFKDataBlockSQLite::LoadGeometryLineStringHP()
 	    poOgrGeometry = poLine->GetGeometry();
 	}
 	if (!poOgrGeometry || !poFeature->SetGeometry(poOgrGeometry)) {
+            CPLDebug("OGR-VFK", "VFKDataBlockSQLite::LoadGeometryLineStringHP(): name=%s fid=%ld "
+                     "id=" CPL_FRMT_GUIB " -> %s geometry", m_pszName, iFID, vrValue[0],
+                     poOgrGeometry ? "invalid" : "empty");
 	    nInvalid++;
             continue;
         }
@@ -341,7 +345,7 @@ int VFKDataBlockSQLite::LoadGeometryLineStringHP()
 	    nGeometries++;
     }
     
-    /* update number of geometries in 'vfk_blocks' table */
+    /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
     
     if (poReader->IsSpatial())
@@ -597,7 +601,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
     CPLDebug("OGR-VFK", "%s: nolines = %d norings = %d",
              m_pszName, nInvalidNoLines, nInvalidNoRings);
     
-    /* update number of geometries in 'vfk_blocks' table */
+    /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
@@ -686,10 +690,10 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig va
         return NULL;
     
     idx = sqlite3_column_int(hStmt, 0) - 1;
+    sqlite3_finalize(hStmt);
+    
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
         return NULL;
-    
-    sqlite3_finalize(hStmt);
 
     return (VFKFeatureSQLite *) GetFeatureByIndex(idx);
 }
@@ -733,11 +737,10 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char **column, GUIntBig *
         return NULL;
     
     idx = sqlite3_column_int(hStmt, 0) - 1; /* rowid starts at 1 */
-    
+    sqlite3_finalize(hStmt);    
+
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
         return NULL;
-
-    sqlite3_finalize(hStmt);
     
     return (VFKFeatureSQLite *) GetFeatureByIndex(idx);
 }
@@ -854,8 +857,8 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
     if (!poReader->IsSpatial())   /* check if DB is spatial */
 	return FALSE;
 
-    osSQL.Printf("SELECT num_geometries FROM 'vfk_blocks' WHERE table_name = '%s'",
-		 m_pszName);
+    osSQL.Printf("SELECT num_geometries FROM %s WHERE table_name = '%s'",
+		 VFK_DB_TABLE, m_pszName);
     hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
         return FALSE;
@@ -901,6 +904,7 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 	    if (!poFeature->SetGeometry(poGeometry)) {
 		nInvalid++;
 	    }
+	    delete poGeometry;
 	}
 	else {
 	    nInvalid++;
@@ -918,7 +922,7 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 
     if (nInvalid > 0 && !bSkipInvalid) {
 	CPLError(CE_Warning, CPLE_AppDefined, 
-                 "%s: %d invalid features found",
+                 "%s: %d features with invalid or empty geometry found",
 		 m_pszName, nInvalid);
     }
 
@@ -926,7 +930,7 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 }
 
 /*!
-  \brief Update vfk_blocks table
+  \brief Update VFK_DB_TABLE table
 
   \param nGeometries number of geometries to update
 */
@@ -939,11 +943,12 @@ void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
 
     if (nGeometries > 0) {
         CPLDebug("OGR-VFK", 
-                 "%d geometries in '%s' saved", nGeometries, m_pszName);
+                 "VFKDataBlockSQLite::UpdateVfkBlocks(): name=%s -> "
+                 "%d geometries saved to internal DB", m_pszName, nGeometries);
         
-	/* update number of geometries in 'vfk_blocks' table */
-	osSQL.Printf("UPDATE vfk_blocks SET num_geometries = %d WHERE table_name = '%s'",
-		     nGeometries, m_pszName);
+	/* update number of geometries in VFK_DB_TABLE table */
+	osSQL.Printf("UPDATE %s SET num_geometries = %d WHERE table_name = '%s'",
+		     VFK_DB_TABLE, nGeometries, m_pszName);
 	poReader->ExecuteSQL(osSQL.c_str());
     }
 }
@@ -961,7 +966,7 @@ void VFKDataBlockSQLite::UpdateFID(long int iFID, std::vector<int> rowId)
     
     poReader = (VFKReaderSQLite*) m_poReader;
     
-    /* update number of geometries in 'vfk_blocks' table */
+    /* update number of geometries in VFK_DB_TABLE table */
     osSQL.Printf("UPDATE %s SET %s = %ld WHERE rowid IN (",
                  m_pszName, FID_COLUMN, iFID);
     for (size_t i = 0; i < rowId.size(); i++) {
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
index 99482fa..4d8183a 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkfeature.cpp 25702 2013-03-07 17:17:54Z martinl $
+ * $Id: vfkfeature.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VFK Reader - Feature definition
  * Purpose:  Implements IVFKFeature/VFKFeature class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2009-2010, 2012-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
index 25f7046..1fa5707 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkfeaturesqlite.cpp 25721 2013-03-09 16:21:46Z martinl $
+ * $Id: vfkfeaturesqlite.cpp 26343 2013-08-20 14:51:07Z martinl $
  *
  * Project:  VFK Reader - Feature definition (SQLite)
  * Purpose:  Implements VFKFeatureSQLite class.
@@ -113,7 +113,7 @@ OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
                          &m_hStmt, NULL);
     if (rc != SQLITE_OK) {
         CPLError(CE_Failure, CPLE_AppDefined, 
-                 "In LoadProperties(): sqlite3_prepare(%s):\n  %s",
+                 "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(poDB));
         
         if(m_hStmt != NULL) {
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.cpp b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
index abf41b0..e2a0bee 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
@@ -1,12 +1,13 @@
 /******************************************************************************
- * $Id: vfkreader.cpp 25721 2013-03-09 16:21:46Z martinl $
+ * $Id: vfkreader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VFK Reader
  * Purpose:  Implements VFKReader class.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2009-2010, 2012-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2009-2014, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -139,7 +140,7 @@ char *VFKReader::ReadLine(bool bRecode)
         pszLine = (char *) CPLMalloc(strlen(pszRawLine) + 1);
         strcpy(pszLine, pszRawLine);
     }
-    
+
     return pszLine;
 }
 
@@ -199,25 +200,40 @@ int VFKReader::ReadDataBlocks()
   \brief Load data records (&D)
 
   Call VFKReader::OpenFile() before this function.
-  
+
+  \param poDataBlock limit to selected data block or NULL for all
+
   \return number of data records or -1 on error
 */
 int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
 {
     const char *pszName;
     char       *pszBlockName, *pszLine;
-    long        iFID;
+    CPLString   osBlockNameLast;
     int         nLength, iLine, nSkipped, nDupl, nRecords;
+    int         iDataBlock;
+    
+    IVFKDataBlock *poDataBlockCurrent;
     
     CPLString pszMultiLine;
 
     VFKFeature *poNewFeature;
-    
-    poDataBlock->SetFeatureCount(0);
-    pszName = poDataBlock->GetName();
 
+    if (poDataBlock) {  /* read only given data block */
+        poDataBlockCurrent = poDataBlock;
+        poDataBlockCurrent->SetFeatureCount(0);
+        pszName = poDataBlockCurrent->GetName();
+    }
+    else {              /* read all data blocks */
+        pszName = NULL; 
+        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+            poDataBlockCurrent = GetDataBlock(iDataBlock);
+            poDataBlockCurrent->SetFeatureCount(0);
+        }
+        poDataBlockCurrent = NULL;
+    }
+    
     VSIFSeek(m_poFD, 0, SEEK_SET);
-    iFID = 1L;
     iLine = nSkipped = nDupl = nRecords = 0;
     while ((pszLine = ReadLine()) != NULL) {
         iLine++;
@@ -227,7 +243,7 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
         
         if (pszLine[1] == 'D') {
             pszBlockName = GetDataBlockName(pszLine);
-            if (pszBlockName && EQUAL(pszBlockName, pszName)) {
+            if (pszBlockName && (!pszName || EQUAL(pszBlockName, pszName))) {
                 /* merge lines if needed */
                 if (pszLine[nLength - 2] == '\302' &&
                     pszLine[nLength - 1] == '\244') {
@@ -258,25 +274,39 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                     pszLine[nLength] = '\0';
                 }
                 
-                poNewFeature = new VFKFeature(poDataBlock, iFID++);
+                if (!poDataBlock && pszBlockName) { /* read all data blocks */
+                    if (osBlockNameLast.empty() ||
+                        !EQUAL(pszBlockName, osBlockNameLast.c_str())) {
+                        poDataBlockCurrent = GetDataBlock(pszBlockName);
+                        osBlockNameLast = CPLString(pszBlockName);
+                    }
+                }
+                if (!poDataBlockCurrent)
+                {
+                    CPLFree(pszBlockName);
+                    continue; // assert ?
+                }
+                
+                poNewFeature = new VFKFeature(poDataBlockCurrent,
+                                              poDataBlockCurrent->GetFeatureCount() + 1);
                 if (poNewFeature->SetProperties(pszLine)) {
-                    if (AddFeature(poDataBlock, poNewFeature) != OGRERR_NONE) {
+                    if (AddFeature(poDataBlockCurrent, poNewFeature) != OGRERR_NONE) {
                         CPLDebug("OGR-VFK", 
                                  "%s: duplicated VFK data recored skipped (line %d).\n%s\n",
                                  pszBlockName, iLine, pszLine);
-                        nDupl++;
-                        iFID--;
+                        poDataBlockCurrent->SetIncRecordCount(RecordDuplicated);
                     }
                     else {
                         nRecords++;
+                        poDataBlockCurrent->SetIncRecordCount(RecordValid);
                     }
                     delete poNewFeature;
-		}
+                }
                 else {
                     CPLDebug("OGR-VFK", 
                              "Invalid VFK data record skipped (line %d).\n%s\n", iLine, pszLine);
-		    nSkipped++;
-		}
+                    poDataBlockCurrent->SetIncRecordCount(RecordSkipped);
+                }
             }
             CPLFree(pszBlockName);
         }
@@ -287,18 +317,28 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
         }
         CPLFree(pszLine);
     }
-    
-    if (nSkipped > 0)
-	CPLError(CE_Warning, CPLE_AppDefined, 
-		 "%s: %d invalid VFK data records skipped",
-                 poDataBlock->GetName(), nSkipped);
-    if (nDupl > 0)
-	CPLError(CE_Warning, CPLE_AppDefined, 
-		 "%s: %d duplicated VFK data records skipped",
-                 poDataBlock->GetName(), nDupl);
-
-    CPLDebug("OGR_VFK", "VFKReader::ReadDataRecords(): name=%s n=%d",
-             poDataBlock->GetName(), nRecords);
+
+    for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+        poDataBlockCurrent = GetDataBlock(iDataBlock);
+
+        if (poDataBlock && poDataBlock != poDataBlockCurrent)
+            continue;
+        
+        nSkipped = poDataBlockCurrent->GetRecordCount(RecordSkipped);
+        nDupl    = poDataBlockCurrent->GetRecordCount(RecordDuplicated);
+        if (nSkipped > 0)
+            CPLError(CE_Warning, CPLE_AppDefined, 
+                     "%s: %d invalid VFK data records skipped",
+                     poDataBlockCurrent->GetName(), nSkipped);
+        if (nDupl > 0)
+            CPLError(CE_Warning, CPLE_AppDefined, 
+                     "%s: %d duplicated VFK data records skipped",
+                     poDataBlockCurrent->GetName(), nDupl);
+
+        CPLDebug("OGR-VFK", "VFKReader::ReadDataRecords(): name=%s n=%d",
+                 poDataBlockCurrent->GetName(),
+                 poDataBlockCurrent->GetRecordCount(RecordValid));
+    }
 
     return nRecords;
 }
@@ -393,9 +433,10 @@ int VFKReader::LoadGeometry()
 */
 void VFKReader::AddInfo(const char *pszLine)
 {
-    int         iKeyLength, iValueLength;
+    int         i, iKeyLength, iValueLength;
+    int         nSkip;
     char       *pszKey, *pszValue;
-    const char *poChar, *poKey, *poValue;
+    const char *poChar, *poKey;
     CPLString   key, value;
     
     poChar = poKey = pszLine + 2; /* &H */
@@ -411,21 +452,36 @@ void VFKReader::AddInfo(const char *pszLine)
     strncpy(pszKey, poKey, iKeyLength);
     pszKey[iKeyLength] = '\0';
 
-    poValue = ++poChar; /* skip ';' */
+    poChar++; /* skip ; */
+
     iValueLength = 0;
+    nSkip = 3; /* &H + ; */
     while (*poChar != '\0') {
-        iValueLength++;
+        if (*poChar == '"' && iValueLength == 0) {
+            nSkip++;
+        }
+        else {
+            iValueLength++; 
+        }
         poChar++;
     }
-
+    if (nSkip > 3)
+        iValueLength--;
+    
     pszValue = (char *) CPLMalloc(iValueLength + 1);
-    strncpy(pszValue, poValue, iValueLength);
+    for (i = 0; i < iValueLength; i++) {
+        pszValue[i] = pszLine[iKeyLength+nSkip+i];
+        if (pszValue[i] == '"') {
+            pszValue[i] = '\''; /* " -> ' */
+        }
+    }
+
     pszValue[iValueLength] = '\0';
 
     poInfo[pszKey] = pszValue;
 
     if (EQUAL(pszKey, "CODEPAGE")) {
-        if (!EQUAL(pszValue, "\"WE8ISO8859P2\""))
+        if (!EQUAL(pszValue, "WE8ISO8859P2"))
             m_bLatin2 = FALSE;
     }
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.h b/ogr/ogrsf_frmts/vfk/vfkreader.h
index d2efe9f..42593c0 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: vfkreader.h 25721 2013-03-09 16:21:46Z martinl $
+ * $Id: vfkreader.h 26907 2014-01-31 17:54:09Z martinl $
  *
  * Project:  VFK Reader
  * Purpose:  Public Declarations for OGR free VFK Reader code.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2009-2010, 2012-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2009-2014, Martin Landa <landa.martin gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -54,6 +54,12 @@ typedef std::vector<VFKFeatureSQLite *> VFKFeatureSQLiteList;
 #define FID_COLUMN   "ogr_fid"
 #define GEOM_COLUMN  "geometry"
 
+#define VFK_DB_HEADER   "vfk_header"
+#define VFK_DB_TABLE    "vfk_tables"
+
+
+enum RecordType { RecordValid, RecordSkipped, RecordDuplicated };
+
 /************************************************************************/
 /*                              VFKProperty                             */
 /************************************************************************/
@@ -233,6 +239,8 @@ protected:
 
     IVFKReader        *m_poReader;
 
+    long               m_nRecordCount[3];
+    
     bool               AppendLineToRing(PointListArray *, const OGRLineString *, bool, bool = FALSE);
     int                LoadData();
     
@@ -271,6 +279,8 @@ public:
     int                LoadGeometry();
 
     IVFKReader        *GetReader() const { return m_poReader; }
+    int                GetRecordCount(RecordType = RecordValid)  const;
+    void               SetIncRecordCount(RecordType);
 };
 
 /************************************************************************/
@@ -340,8 +350,9 @@ public:
     
     virtual bool           IsLatin2() const = 0;
     virtual bool           IsSpatial() const = 0;
+    virtual bool           IsPreProcessed() const = 0;
     virtual int            ReadDataBlocks() = 0;
-    virtual int            ReadDataRecords(IVFKDataBlock *) = 0;
+    virtual int            ReadDataRecords(IVFKDataBlock * = NULL) = 0;
     virtual int            LoadGeometry() = 0;
 
     virtual int            GetDataBlockCount() const = 0;
diff --git a/ogr/ogrsf_frmts/vfk/vfkreaderp.h b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
index 0e33001..4e8a9ac 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreaderp.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: vfkreaderp.h 25703 2013-03-07 18:23:48Z martinl $
+ * $Id: vfkreaderp.h 26911 2014-02-01 11:46:09Z martinl $
  *
  * Project:  VFK Reader
  * Purpose:  Private Declarations for OGR free VFK Reader code.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2009-2010, 2012, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2009-2010, 2012-2013, Martin Landa <landa.martin gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -53,9 +53,6 @@ private:
     FILE          *m_poFD;
     char          *ReadLine(bool = FALSE);
     
-    /* metadata */
-    std::map<CPLString, CPLString> poInfo;
-    
     void          AddInfo(const char *);
 
 protected:
@@ -67,14 +64,18 @@ protected:
     void            AddDataBlock(IVFKDataBlock *, const char *);
     OGRErr          AddFeature(IVFKDataBlock *, VFKFeature *);
 
+    /* metadata */
+    std::map<CPLString, CPLString> poInfo;
+    
 public:
     VFKReader(const char *);
     virtual ~VFKReader();
 
     bool           IsLatin2() const { return m_bLatin2; }
     bool           IsSpatial() const { return FALSE; }
+    bool           IsPreProcessed() const { return FALSE; }
     int            ReadDataBlocks();
-    int            ReadDataRecords(IVFKDataBlock *);
+    int            ReadDataRecords(IVFKDataBlock * = NULL);
     int            LoadGeometry();
     
     int            GetDataBlockCount() const { return m_nDataBlockCount; }
@@ -91,13 +92,17 @@ public:
 class VFKReaderSQLite : public VFKReader 
 {
 private:
+    char          *m_pszDBname;
     sqlite3       *m_poDB;
     bool           m_bSpatial;
+    bool           m_bNewDb;
 
     IVFKDataBlock *CreateDataBlock(const char *);
     void           AddDataBlock(IVFKDataBlock *, const char *);
     OGRErr         AddFeature(IVFKDataBlock *, VFKFeature *);
 
+    void           StoreInfo2DB();
+
     void           CreateIndex(const char *, const char *, const char *, bool = TRUE);
     
     friend class   VFKFeatureSQLite;
@@ -106,8 +111,9 @@ public:
     virtual ~VFKReaderSQLite();
 
     bool          IsSpatial() const { return m_bSpatial; }
+    bool          IsPreProcessed() const { return !m_bNewDb; }
     int           ReadDataBlocks();
-    int           ReadDataRecords(IVFKDataBlock *);
+    int           ReadDataRecords(IVFKDataBlock * = NULL);
 
     sqlite3_stmt *PrepareStatement(const char *);
     OGRErr        ExecuteSQL(const char *, bool = FALSE);
diff --git a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
index 8ffa4cb..fd60349 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
@@ -1,12 +1,13 @@
 /******************************************************************************
- * $Id: vfkreadersqlite.cpp 25721 2013-03-09 16:21:46Z martinl $
+ * $Id: vfkreadersqlite.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VFK Reader (SQLite)
  * Purpose:  Implements VFKReaderSQLite class.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2012-2013, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2014, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -37,6 +38,8 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+#include <cstring>
+
 #define SUPPORT_GEOMETRY
 
 #ifdef SUPPORT_GEOMETRY
@@ -51,8 +54,7 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
     const char *pszDbNameConf;
     CPLString   pszDbName;
     CPLString   osCommand;
-    VSIStatBufL sStatBuf;
-    bool        bNewDb;
+    VSIStatBufL sStatBufDb, sStatBufVfk;
     
     /* open tmp SQLite DB (re-use DB file if already exists) */
     pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL);
@@ -62,28 +64,49 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
     else {
 	pszDbName.Printf("%s.db", m_pszFilename);
     }
+    m_pszDBname = new char [pszDbName.length()+1];
+    std::strcpy(m_pszDBname, pszDbName.c_str());
+    CPLDebug("OGR-VFK", "Using internal DB: %s",
+             m_pszDBname);
     
     if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES")))
 	m_bSpatial = TRUE;    /* build geometry from DB */
     else
 	m_bSpatial = FALSE;   /* store also geometry in DB */
     
-    bNewDb = TRUE;
-    if (VSIStatL(pszDbName, &sStatBuf ) == 0) {
+    m_bNewDb = TRUE;
+    if (VSIStatL(pszDbName, &sStatBufDb) == 0) {
 	if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) {
-	    bNewDb = TRUE;     /* overwrite existing DB */
+	    m_bNewDb = TRUE;     /* overwrite existing DB */
+            CPLDebug("OGR-VFK", "Internal DB (%s) already exists and will be overwritten",
+                     m_pszDBname);
 	    VSIUnlink(pszDbName);
 	}
 	else {
-	    bNewDb = FALSE;    /* re-use exising DB */
+            if (VSIStatL(pszFilename, &sStatBufVfk) == 0 &&
+                sStatBufVfk.st_mtime > sStatBufDb.st_mtime) {
+                CPLDebug("OGR-VFK",
+                         "Found %s but ignoring because it appears\n"
+                         "be older than the associated VFK file.",
+                         pszDbName.c_str());
+                m_bNewDb = TRUE;
+                VSIUnlink(pszDbName);
+            }
+            else {
+                m_bNewDb = FALSE;    /* re-use exising DB */
+            }
 	}
     }
-    else {
-      	CPLError(CE_Warning, CPLE_AppDefined, 
-                 "SQLite DB not found. Reading VFK data may take some time...");
+    
+    /*
+    if (m_bNewDb) {
+      CPLError(CE_Warning, CPLE_AppDefined, 
+               "INFO: No internal SQLite DB found. Reading VFK data may take some time...");
     }
+    */
+
     CPLDebug("OGR-VFK", "New DB: %s Spatial: %s",
-	     bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no");
+	     m_bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no");
 
     if (SQLITE_OK != sqlite3_open(pszDbName, &m_poDB)) {
         CPLError(CE_Failure, CPLE_AppDefined, 
@@ -95,11 +118,14 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
         sqlite3_free(pszErrMsg);
     }
     
-    if (bNewDb) {
+    if (m_bNewDb) {
         /* new DB, create support metadata tables */
-        osCommand = "CREATE TABLE 'vfk_blocks' "
-	  "(file_name text, table_name text, num_records integer, "
-	    "num_geometries integer, table_defn text)";
+        osCommand.Printf("CREATE TABLE %s (file_name text, table_name text, num_records integer, "
+                         "num_geometries integer, table_defn text)", VFK_DB_TABLE);
+        ExecuteSQL(osCommand.c_str());
+
+        /* header table */
+        osCommand.Printf("CREATE TABLE %s (key text, value text)", VFK_DB_HEADER);
         ExecuteSQL(osCommand.c_str());
     }
 }
@@ -109,16 +135,21 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
 */
 VFKReaderSQLite::~VFKReaderSQLite()
 {
-    CPLString pszDbName(m_pszFilename);
-
-    pszDbName += ".db";
-    
     /* close tmp SQLite DB */
     if (SQLITE_OK != sqlite3_close(m_poDB)) {
         CPLError(CE_Failure, CPLE_AppDefined, 
                  "Closing SQLite DB failed\n  %s",
                  sqlite3_errmsg(m_poDB));
     }
+    CPLDebug("OGR-VFK", "Internal DB (%s) closed",
+             m_pszDBname);
+    
+    /* delete tmp SQLite DB if requested */
+    if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_DELETE", "NO"))) {
+        CPLDebug("OGR-VFK", "Internal DB (%s) deleted",
+                 m_pszDBname);
+        VSIUnlink(m_pszDBname);
+    }
 }
 
 /*!
@@ -137,7 +168,7 @@ int VFKReaderSQLite::ReadDataBlocks()
     
     sqlite3_stmt *hStmt;
     
-    osSQL.Printf("SELECT table_name, table_defn FROM 'vfk_blocks'");
+    osSQL.Printf("SELECT table_name, table_defn FROM %s", VFK_DB_TABLE);
     hStmt = PrepareStatement(osSQL.c_str());
     while(ExecuteSQL(hStmt) == OGRERR_NONE) {
         pszName = (const char*) sqlite3_column_text(hStmt, 0);
@@ -153,6 +184,8 @@ int VFKReaderSQLite::ReadDataBlocks()
         /* CREATE TABLE ... */
         nDataBlocks = VFKReader::ReadDataBlocks();
         sqlite3_exec(m_poDB, "COMMIT", 0, 0, 0);
+
+        StoreInfo2DB();
     }
     
     return nDataBlocks;
@@ -163,100 +196,105 @@ int VFKReaderSQLite::ReadDataBlocks()
 
   Call VFKReader::OpenFile() before this function.
   
+  \param poDataBlock limit to selected data block or NULL for all
+  
   \return number of data records or -1 on error
 */
 int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
 {
     int         nDataRecords;
+    int         iDataBlock;
     const char *pszName;
     CPLString   osSQL;
-
+    
+    IVFKDataBlock *poDataBlockCurrent;
+    
     sqlite3_stmt *hStmt;
     
+    pszName = NULL;
     nDataRecords = 0;
     
-    /* table name */
-    pszName = poDataBlock->GetName();
-    
-    /* check for existing records (re-use already inserted data) */
-    osSQL.Printf("SELECT num_records FROM vfk_blocks WHERE "
-                 "table_name = '%s'",
-                 pszName);
-    hStmt = PrepareStatement(osSQL.c_str());
-    nDataRecords = -1;
-    if (ExecuteSQL(hStmt) == OGRERR_NONE) {
-        nDataRecords = sqlite3_column_int(hStmt, 0);
+    if (poDataBlock) { /* read records only for selected data block */
+        /* table name */
+        pszName = poDataBlock->GetName();
+        
+        /* check for existing records (re-use already inserted data) */
+        osSQL.Printf("SELECT num_records FROM %s WHERE "
+                     "table_name = '%s'",
+                     VFK_DB_TABLE, pszName);
+        hStmt = PrepareStatement(osSQL.c_str());
+        nDataRecords = -1;
+        if (ExecuteSQL(hStmt) == OGRERR_NONE) {
+            nDataRecords = sqlite3_column_int(hStmt, 0);
+        }
+        sqlite3_finalize(hStmt);
+    }
+    else {
+                      /* read all data blocks */
+        
+        /* check for existing records (re-use already inserted data) */
+        osSQL.Printf("SELECT COUNT(*) FROM %s WHERE num_records = -1", VFK_DB_TABLE);
+        hStmt = PrepareStatement(osSQL.c_str());
+        if (ExecuteSQL(hStmt) == OGRERR_NONE &&
+            sqlite3_column_int(hStmt, 0) == 0)
+            nDataRecords = 0;     /* -> read from DB */
+        else
+            nDataRecords = -1;    /* -> read from VFK file */
+        
+        sqlite3_finalize(hStmt);
     }
-    sqlite3_finalize(hStmt);
 
-    poDataBlock->SetFeatureCount(0); /* avoid recursive calls */
-    
-    if (nDataRecords > -1) {
+    if (nDataRecords > -1) {        /* read records from DB */
         /* read from  DB */
         long iFID;
         VFKFeatureSQLite *poNewFeature = NULL;
 
-        if (EQUAL(pszName, "SBP")) {
-            return 0; /* see LoadGeometry() */
-        }
+        poDataBlockCurrent = NULL;
+        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+            poDataBlockCurrent = GetDataBlock(iDataBlock);
+           
+            if (poDataBlock && poDataBlock != poDataBlockCurrent)
+                continue;
+
+            poDataBlockCurrent->SetFeatureCount(0); /* avoid recursive call */
             
-        osSQL.Printf("SELECT %s FROM %s", FID_COLUMN, pszName);
-        hStmt = PrepareStatement(osSQL.c_str());
-        nDataRecords = 1;
-        while (ExecuteSQL(hStmt) == OGRERR_NONE) {
-            iFID = sqlite3_column_int(hStmt, 0);
-            poNewFeature = new VFKFeatureSQLite(poDataBlock, nDataRecords++, iFID);
-            poDataBlock->AddFeature(poNewFeature);
+            pszName = poDataBlockCurrent->GetName();
+            if (pszName && EQUAL(pszName, "SBP")) {
+                continue; /* see LoadGeometry() */
+            }
+            
+            osSQL.Printf("SELECT %s FROM %s", FID_COLUMN, pszName);
+            hStmt = PrepareStatement(osSQL.c_str());
+            nDataRecords = 1;
+            while (ExecuteSQL(hStmt) == OGRERR_NONE) {
+                iFID = sqlite3_column_int(hStmt, 0);
+                poNewFeature = new VFKFeatureSQLite(poDataBlockCurrent, nDataRecords++, iFID);
+                poDataBlockCurrent->AddFeature(poNewFeature);
+            }
         }
     }
-    else {
-        /* read from VFK file and insert records into DB */
-        bool bUnique;
-        const char *pszKey;
-        
-        bUnique = !CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_IGNORE_DUPLICATES", "NO"));
-        
+    else {                          /* read from VFK file and insert records into DB */
         /* begin transaction */
         ExecuteSQL("BEGIN");
         
-        /* create indeces */
-        osSQL.Printf("%s_%s", pszName, FID_COLUMN);
-        CreateIndex(osSQL.c_str(), pszName, FID_COLUMN, !EQUAL(pszName, "SBP"));
-
-        pszKey = ((VFKDataBlockSQLite *) poDataBlock)->GetKey();
-        if (pszKey) {
-            osSQL.Printf("%s_%s", pszName, pszKey);
-            CreateIndex(osSQL.c_str(), pszName, pszKey, bUnique);
-        }
-        
-        if (EQUAL(pszName, "SBP")) {
-            /* create extra indices for SBP */
-            CreateIndex("SBP_OB",        pszName, "OB_ID", FALSE);
-            CreateIndex("SBP_HP",        pszName, "HP_ID", FALSE);
-            CreateIndex("SBP_DPM",       pszName, "DPM_ID", FALSE);
-            CreateIndex("SBP_OB_HP_DPM", pszName, "OB_ID,HP_ID,DPM_ID", bUnique);
-            CreateIndex("SBP_OB_POR",    pszName, "OB_ID,PORADOVE_CISLO_BODU", FALSE);
-            CreateIndex("SBP_HP_POR",    pszName, "HP_ID,PORADOVE_CISLO_BODU", FALSE);
-            CreateIndex("SBP_DPM_POR",   pszName, "DPM_ID,PORADOVE_CISLO_BODU", FALSE);
-        }
-        else if (EQUAL(pszName, "HP")) {
-            /* create extra indices for HP */
-            CreateIndex("HP_PAR1",        pszName, "PAR_ID_1", FALSE);
-            CreateIndex("HP_PAR2",        pszName, "PAR_ID_2", FALSE);
-        }
-        else if (EQUAL(pszName, "OB")) {
-            /* create extra indices for OP */
-            CreateIndex("OB_BUD",        pszName, "BUD_ID", FALSE);
-        }
-        
         /* INSERT ... */
         nDataRecords = VFKReader::ReadDataRecords(poDataBlock);
-        
-        /* update 'vfk_blocks' table */
-        osSQL.Printf("UPDATE vfk_blocks SET num_records = %d WHERE "
-		     "table_name = '%s'",
-                     nDataRecords, pszName);
-	ExecuteSQL(osSQL);
+
+        /* update VFK_DB_TABLE table */        
+        poDataBlockCurrent = NULL;
+        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+            poDataBlockCurrent = GetDataBlock(iDataBlock);
+            
+            if (poDataBlock && poDataBlock != poDataBlockCurrent)
+                continue;
+            
+            osSQL.Printf("UPDATE %s SET num_records = %d WHERE "
+                         "table_name = '%s'",
+                         VFK_DB_TABLE, poDataBlockCurrent->GetRecordCount(),
+                         poDataBlockCurrent->GetName());
+            
+            ExecuteSQL(osSQL);
+        }
         
         /* commit transaction */
         ExecuteSQL("COMMIT");
@@ -266,6 +304,28 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
 }
 
 /*!
+  \brief Store header info to VFK_DB_HEADER
+*/
+void VFKReaderSQLite::StoreInfo2DB()
+{
+    CPLString osSQL;
+    const char *value;
+    char q;
+
+    for(std::map<CPLString, CPLString>::iterator i = poInfo.begin();
+        i != poInfo.end(); ++i) {
+        value = i->second.c_str();
+
+        q = (value[0] == '"') ? ' ' : '"';
+
+        osSQL.Printf("INSERT INTO %s VALUES(\"%s\", %c%s%c)",
+                     VFK_DB_HEADER, i->first.c_str(),
+                     q, value, q);
+        ExecuteSQL(osSQL);
+    }
+}
+
+/*!
   \brief Create index
 
   If creating unique index fails, then non-unique index is created instead.
@@ -302,6 +362,7 @@ void VFKReaderSQLite::CreateIndex(const char *name, const char *table, const cha
 */
 IVFKDataBlock *VFKReaderSQLite::CreateDataBlock(const char *pszBlockName)
 {
+    /* create new data block, ie. table in DB */
     return new VFKDataBlockSQLite(pszBlockName, (IVFKReader *) this);
 }
 
@@ -312,21 +373,29 @@ IVFKDataBlock *VFKReaderSQLite::CreateDataBlock(const char *pszBlockName)
 */
 void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDefn)
 {
-    CPLString osCommand, osColumn;
-    
+    const char *pszBlockName;
+    const char *pszKey;
+    CPLString   osCommand, osColumn;
+    bool        bUnique;
+        
     VFKPropertyDefn *poPropertyDefn;
     
     sqlite3_stmt *hStmt;
 
-    /* register table in 'vfk_blocks' */
-    osCommand.Printf("SELECT COUNT(*) FROM vfk_blocks WHERE "
+    bUnique = !CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_IGNORE_DUPLICATES", "NO"));
+    
+    pszBlockName = poDataBlock->GetName();
+    
+    /* register table in VFK_DB_TABLE */
+    osCommand.Printf("SELECT COUNT(*) FROM %s WHERE "
                      "table_name = '%s'",
-                     poDataBlock->GetName());
+                     VFK_DB_TABLE, pszBlockName);
     hStmt = PrepareStatement(osCommand.c_str());
+    
     if (ExecuteSQL(hStmt) == OGRERR_NONE &&
         sqlite3_column_int(hStmt, 0) == 0) {
         
-        osCommand.Printf("CREATE TABLE '%s' (", poDataBlock->GetName());
+        osCommand.Printf("CREATE TABLE '%s' (", pszBlockName);
         for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
             poPropertyDefn = poDataBlock->GetProperty(i);
             if (i > 0)
@@ -344,10 +413,42 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
 	osCommand += ")";
         ExecuteSQL(osCommand.c_str()); /* CREATE TABLE */
         
-        osCommand.Printf("INSERT INTO 'vfk_blocks' (file_name, table_name, "
+        /* create indeces */
+        osCommand.Printf("%s_%s", pszBlockName, FID_COLUMN);
+        CreateIndex(osCommand.c_str(), pszBlockName, FID_COLUMN,
+                    !EQUAL(pszBlockName, "SBP"));
+        
+        pszKey = ((VFKDataBlockSQLite *) poDataBlock)->GetKey();
+        if (pszKey) {
+            osCommand.Printf("%s_%s", pszBlockName, pszKey);
+            CreateIndex(osCommand.c_str(), pszBlockName, pszKey, bUnique);
+        }
+        
+        if (EQUAL(pszBlockName, "SBP")) {
+            /* create extra indices for SBP */
+            CreateIndex("SBP_OB",        pszBlockName, "OB_ID", FALSE);
+            CreateIndex("SBP_HP",        pszBlockName, "HP_ID", FALSE);
+            CreateIndex("SBP_DPM",       pszBlockName, "DPM_ID", FALSE);
+            CreateIndex("SBP_OB_HP_DPM", pszBlockName, "OB_ID,HP_ID,DPM_ID", bUnique);
+            CreateIndex("SBP_OB_POR",    pszBlockName, "OB_ID,PORADOVE_CISLO_BODU", FALSE);
+            CreateIndex("SBP_HP_POR",    pszBlockName, "HP_ID,PORADOVE_CISLO_BODU", FALSE);
+            CreateIndex("SBP_DPM_POR",   pszBlockName, "DPM_ID,PORADOVE_CISLO_BODU", FALSE);
+        }
+        else if (EQUAL(pszBlockName, "HP")) {
+            /* create extra indices for HP */
+            CreateIndex("HP_PAR1",        pszBlockName, "PAR_ID_1", FALSE);
+            CreateIndex("HP_PAR2",        pszBlockName, "PAR_ID_2", FALSE);
+        }
+        else if (EQUAL(pszBlockName, "OB")) {
+            /* create extra indices for OP */
+            CreateIndex("OB_BUD",        pszBlockName, "BUD_ID", FALSE);
+        }
+        
+        /* update VFK_DB_TABLE meta-table */
+        osCommand.Printf("INSERT INTO %s (file_name, table_name, "
                          "num_records, num_geometries, table_defn) VALUES "
 			 "('%s', '%s', -1, 0, '%s')",
-			 m_pszFilename, poDataBlock->GetName(), pszDefn);
+			 VFK_DB_TABLE, m_pszFilename, pszBlockName, pszDefn);
 	
         ExecuteSQL(osCommand.c_str());
 
@@ -369,7 +470,7 @@ sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
     int rc;
     sqlite3_stmt *hStmt = NULL;
     
-    /* CPLDebug("OGR-VFK", "PrepareStatement(): %s", pszSQLCommand); */
+    CPLDebug("OGR-VFK", "VFKReaderSQLite::PrepareStatement(): %s", pszSQLCommand);
 
     rc = sqlite3_prepare(m_poDB, pszSQLCommand, strlen(pszSQLCommand),
                          &hStmt, NULL);
@@ -424,22 +525,25 @@ OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
 /*!
   \brief Execute SQL statement (SQLITE only)
 
+  \param pszSQLCommand SQL command to execute
+  \param bQuiet TRUE to print debug message on failure instead of error message
+
   \return OGRERR_NONE on success or OGRERR_FAILURE on failure
 */
 OGRErr VFKReaderSQLite::ExecuteSQL(const char *pszSQLCommand, bool bQuiet)
 {
     char *pszErrMsg = NULL;
     
-    /*
-    CPLDebug("OGR-VFK", 
-	     "ExecuteSQL(): %s", pszSQLCommand);
-    */
-
     if (SQLITE_OK != sqlite3_exec(m_poDB, pszSQLCommand, NULL, NULL, &pszErrMsg)) {
         if (!bQuiet)
             CPLError(CE_Failure, CPLE_AppDefined, 
                      "In ExecuteSQL(%s): %s",
                      pszSQLCommand, pszErrMsg);
+        else
+            CPLDebug("OGR-VFK", 
+                     "In ExecuteSQL(%s): %s",
+                     pszSQLCommand, pszErrMsg);
+        
         return  OGRERR_FAILURE;
     }
 
@@ -504,7 +608,7 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
     if (ExecuteSQL(osCommand.c_str(), TRUE) != OGRERR_NONE)
         return OGRERR_FAILURE;
     
-    if (!EQUAL(pszBlockName, "SBP")) {
+    if (!EQUAL(pszBlockName, "SBP")) { /* SBP features are added when building geometry */
         VFKFeatureSQLite *poNewFeature;
         
         poNewFeature = new VFKFeatureSQLite(poDataBlock, poDataBlock->GetFeatureCount() + 1,
diff --git a/ogr/ogrsf_frmts/vrt/drv_vrt.html b/ogr/ogrsf_frmts/vrt/drv_vrt.html
index 099f0ae..f38e0a1 100644
--- a/ogr/ogrsf_frmts/vrt/drv_vrt.html
+++ b/ogr/ogrsf_frmts/vrt/drv_vrt.html
@@ -36,6 +36,11 @@ The root element of the XML control file is <b>OGRVRTDataSource</b>.  It has
 an <b>OGRVRTLayer</b> (or <b>OGRVRTWarpedLayer</b> or <b>OGRVRTUnionLayer</b> starting
 with GDAL 1.10.0) child for each layer in the virtual datasource.<p>
 
+A <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/ogrvrt.xsd">XML schema of the OGR VRT format</a>
+is available. Starting with GDAL 1.11, when GDAL is configured with libXML2 support, that
+schema will be used to validate the VRT documents. Non-conformities will be reported only as
+warnings. That validation can be disabled by setting the GDAL_XML_VALIDATION configuration option to NO.<p>
+
 A <b>OGRVRTLayer</b> element should have a <b>name</b> attribute with the layer name, and may have the
 following subelements:
 
@@ -112,7 +117,31 @@ Starting with GDAL 1.7.0, the optional <b>reportSrcColumn</b> attribute can be u
 whether the source geometry fields (the fields set in the <b>field</b>, <b>x</b>, <b>x</b>
 or <b>z</b> attributes) should be reported as fields of the VRT layer. It defaults to TRUE.
 If set to FALSE, the source geometry fields will only be used to build the geometry of the features of the VRT layer.</li>
-
+<p>
+Starting with OGR 1.11, the GeometryField element can be repeated as many times
+as necessary to create multiple geometry fields. It accepts a <b>name</b>
+attribute (recommanded) that will be used to define the VRT geometry field name. When <b>encoding</b> is
+not specified, the <b>field</b> attribute will be used to determine the corresponding
+geometry field name in the source layer. If neither <b>encoding</b> nor <b>field</b>
+are specified, it is assumed that the name of source geometry field is the value
+of the <b>name</b> attribute.
+</p>
+<p>
+When several geometry fields are used, the following child elements of <b>GeometryField</b>
+can be defined to explicitely set the geometry type, SRS, source region, or extent.
+<ul>
+<li><b>GeometryType</b> (optional) : same syntax as OGRVRTLayer-level <b>GeometryType</b>.</li>
+<li><b>SRS</b> (optional) : same syntax as OGRVRTLayer-level <b>LayerSRS</b> (note SRS vs LayerSRS)</li>
+<li><b>SrcRegion</b> (optional) : same syntax as OGRVRTLayer-level <b>SrcRegion</b></li>
+<li><b>ExtentXMin</b>, <b>ExtentYMin</b>, <b>ExtentXMax</b> and <b>ExtentXMax</b> (optional) :
+same syntax as OGRVRTLayer-level elements of same name</li>
+</ul>
+</p>
+<p>If no <b>GeometryField</b> element is specified, all the geometry fields of the
+source layer will be exposed by the VRT layer. In order not to expose any geometry
+field of the source layer, you need to specify OGRVRTLayer-level <b>GeometryType</b>
+element to wkbNone.
+</p>
 <br>
 
 <li> <b>SrcRegion</b> (optionnal, from GDAL 1.7.0) : This element is used
@@ -133,11 +162,11 @@ may have the following attributes:
 <li> <b>name</b> (required): the name of the field.
 <li> <b>type</b>: the field type, one of "Integer", "IntegerList", 
 "Real", "RealList", "String", "StringList", "Binary", "Date", "Time", 
-or "DateTime" - defaults to "String".
-<li> <b>width</b>: the field width, defaults to unknown.
-<li> <b>precision</b>: the field width, defaults to zero.
-<li> <b>src</b>: the name of the source field to be copied to this one.  By
-default defaults to the value of "name".
+or "DateTime". Defaults to "String".
+<li> <b>width</b>: the field width. Defaults to unknown.
+<li> <b>precision</b>: the field width. Defaults to zero.
+<li> <b>src</b>: the name of the source field to be copied to this one.
+Defaults to the value of "name".
 </ul>
 </li>
 
@@ -168,7 +197,7 @@ a source layer. It may have the following subelements:
 the source layer to reproject.</li>
 <br>
 
-<li> <b>SrcSRS</b> (mandatory): The value of this element is the spatial
+<li> <b>SrcSRS</b> (optional): The value of this element is the spatial
 reference to use for the layer before reprojection. If not specified, it is deduced from
 the source layer.</li>
 <br>
@@ -180,7 +209,12 @@ reference to use for the layer after reprojection. </li>
 <li> <b>ExtentXMin</b>, <b>ExtentYMin</b>, <b>ExtentXMax</b> and <b>ExtentXMax</b> (optional, from GDAL 1.10.0) :
 Those elements are used to define the extent of the layer. This can be usefull on static data, when
 getting the extent from the source layer is slow.</li>
+<br>
 
+<li> <b>WarpedGeomFieldName</b> (optional, from GDAL 1.11) : The value of this element
+is the geometry field name of the source layer to wrap. If not specified, the first geometry
+field will be used. If there are several geometry fields, only the one matching
+WarpedGeomFieldName will be warped; the other ones will be untouched.</li>
 <br>
 
 </ul>
@@ -213,7 +247,7 @@ will be deduced from the geometry type of all source layers.</li>
 SRS of the first source layer.</li>
 <br>
 
-<li> <b>FieldStrategy</b> (optional, exclusive with <b>Field</b>) :
+<li> <b>FieldStrategy</b> (optional, exclusive with <b>Field</b> or <b>GeometryField</b>) :
 may be <b>FirstLayer</b> to use the fields from the first layer found,
 <b>Union</b> to use a super-set of all the fields from all source layers, or
 <b>Intersection</b> to use a sub-set of all the common fields from all source layers. Defaults to <b>Union</b>.</li>
@@ -223,6 +257,10 @@ may be <b>FirstLayer</b> to use the fields from the first layer found,
 is not supported in the context of a OGRVRTUnionLayer element (field names are assumed to be identical).</li>
 <br>
 
+<li> <b>GeometryField</b> (optional, exclusive with <b>FieldStrategy</b>, GDAL >= 1.11) : the <b>name</b> attribute and
+the following sub-elements <b>GeometryType</b>, <b>SRS</b> and <b>Extent[X|Y][Min|Max]</b> are available.</li>
+<br>
+
 <li> <b>FeatureCount</b> (optional) : see above for the syntax</li>
 <br>
 
@@ -327,6 +365,108 @@ and source2.shp.<p>
 </OGRVRTDataSource>
 </pre>
 
+<h2>Example: SQLite/Spatialite SQL dialect (GDAL >=1.10.0)</h2>
+
+The following example will return four different layers which are generated in a fly
+from the same polygon shapefile. The first one is the shapefile layer as it stands.
+The second layer gives simplified polygons by applying Spatialite function "Simplify"
+with parameter tolerance=10. In the third layer the original geometries are replaced by
+their convace hulls. In the fourth layer Spatialite function PointOnSurface is used for
+replacing the original geometries by points which are inside the corresponding source
+polygons. Note that for using the last three layers of this VRT file GDAL must be
+compiled with SQLite and Spatialite.<p>
+
+<pre>
+<OGRVRTDataSource>
+    <OGRVRTLayer name="polygons">
+        <SrcDataSource>polygons.shp</SrcDataSource>
+        </OGRVRTLayer>
+    <OGRVRTLayer name="polygons_as_simplified">
+        <SrcDataSource>polygons.shp</SrcDataSource>
+        <SrcSQL dialect="sqlite">SELECT Simplify(geometry,10) from polygons</SrcSQL>
+    </OGRVRTLayer>
+    <OGRVRTLayer name="polygons_as_hulls">
+        <SrcDataSource>polygons.shp</SrcDataSource>
+        <SrcSQL dialect="sqlite">SELECT ConvexHull(geometry) from polygons</SrcSQL>
+    </OGRVRTLayer>
+    <OGRVRTLayer name="polygons_as_points">
+        <SrcDataSource>polygons.shp</SrcDataSource>
+        <SrcSQL dialect="sqlite">SELECT PointOnSurface(geometry) from polygons</SrcSQL>
+    </OGRVRTLayer>
+</OGRVRTDataSource>
+</pre>
+
+<h2>Example: Multiple geometry fields (GDAL >= 1.11)</h2>
+
+<p>
+The following example will expose all the attribute and geometry fields of the
+source layer:
+</p>
+<pre><OGRVRTDataSource>
+    <OGRVRTLayer name="test">
+        <SrcDataSource>PG:dbname=testdb</SrcDataSource>
+    </OGRVRTLayer>
+</OGRVRTDataSource>
+</pre>
+
+<p>
+To expose only part (or all!) of the fields:
+</p>
+<pre><OGRVRTDataSource>
+    <OGRVRTLayer name="other_test">
+        <SrcDataSource>PG:dbname=testdb</SrcDataSource>
+        <SrcLayer>test</SrcLayer>
+        <GeometryField name="pg_geom_field_1" />
+        <GeometryField name="vrt_geom_field_2" field="pg_geom_field_2">
+            <GeometryType>wkbPolygon</GeometryType>
+            <SRS>EPSG:4326</SRS>
+            <ExtentXMin>-180</ExtentXMin>
+            <ExtentYMin>-90</ExtentYMin>
+            <ExtentXMax>180</ExtentXMax>
+            <ExtentYMax>90</ExtentYMax>
+        </GeometryField>
+        <Field name="vrt_field_1" src="src_field_1" />
+    </OGRVRTLayer>w
+</OGRVRTDataSource>
+</pre>
+
+To reproject the 'pg_geom_field_2' geometry field to EPSG:4326:<p>
+
+<pre><OGRVRTDataSource>
+    <OGRVRTWarpedLayer>
+        <OGRVRTLayer name="other_test">
+            <SrcDataSource>PG:dbname=testdb</SrcDataSource>
+        </OGRVRTLayer>
+        <WarpedGeomFieldName>pg_geom_field_2</WarpedGeomFieldName>
+        <TargetSRS>EPSG:32631</TargetSRS>
+    </OGRVRTWarpedLayer>
+</OGRVRTDataSource>
+</pre>
+
+To make the union of several multi-geometry layers and keep only a few of them:<p>
+
+<pre><OGRVRTDataSource>
+    <OGRVRTUnionLayer name="unionLayer">
+        <OGRVRTLayer name="source1">
+            <SrcDataSource>PG:dbname=testdb</SrcDataSource>
+        </OGRVRTLayer>
+        <OGRVRTLayer name="source2">
+            <SrcDataSource>PG:dbname=testdb</SrcDataSource>
+        </OGRVRTLayer>
+        <GeometryField name="pg_geom_field_2">
+            <GeometryType>wkbPolygon</GeometryType>
+            <SRS>EPSG:4326</SRS>
+            <ExtentXMin>-180</ExtentXMin>
+            <ExtentYMin>-90</ExtentYMin>
+            <ExtentXMax>180</ExtentXMax>
+            <ExtentYMax>90</ExtentYMax>
+        </GeometryField>
+        <GeometryField name="pg_geom_field_3" />
+        <Field name="src_field_1" />
+    </OGRVRTUnionLayer>
+</OGRVRTDataSource>
+</pre>
+
 <h2>Other Notes</h2>
 
 <ul>
@@ -344,10 +484,6 @@ datastore, if that is possible.  For instance if the source is an RDBMS.
 You can turn off that feature by setting the <i>useSpatialSubquery</i> attribute
 of the GeometryField element to FALSE.<p>
 
-<li> Normally the <i>SrcDataSource</i> is a non-spatial tabular format (such as
-MySQL, SQLite, CSV, OCI, or ODBC) but it can also be a spatial database in which
-case the geometry can be directly copied over. <p>
-
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/vrt/ogr_vrt.h b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
index b7d63b8..12b59b7 100644
--- a/ogr/ogrsf_frmts/vrt/ogr_vrt.h
+++ b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vrt.h 25110 2012-10-13 13:53:53Z rouault $
+ * $Id: ogr_vrt.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VRT driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -49,6 +50,37 @@ typedef enum {
 } OGRVRTGeometryStyle;
 
 /************************************************************************/
+/*                         OGRVRTGeomFieldProps                         */
+/************************************************************************/
+
+class OGRVRTGeomFieldProps
+{
+    public:
+        CPLString           osName;         /* Name of the VRT geometry field */
+        OGRwkbGeometryType  eGeomType;
+        OGRSpatialReference *poSRS;
+
+        int                 bSrcClip;
+        OGRGeometry         *poSrcRegion;
+
+        // Geometry interpretation related.
+        OGRVRTGeometryStyle eGeometryStyle;
+
+        /* points to a OGRField for VGS_WKT, VGS_WKB, VGS_Shape and OGRGeomField for VGS_Direct */
+        int                 iGeomField;
+
+                            // VGS_PointFromColumn
+        int                 iGeomXField, iGeomYField, iGeomZField;
+        int                 bReportSrcColumn;
+        int                 bUseSpatialSubquery;
+
+        OGREnvelope         sStaticEnvelope;
+
+                        OGRVRTGeomFieldProps();
+                       ~OGRVRTGeomFieldProps();
+};
+
+/************************************************************************/
 /*                            OGRVRTLayer                                */
 /************************************************************************/
 
@@ -58,10 +90,10 @@ class OGRVRTLayer : public OGRLayer
 {
   protected:
     OGRVRTDataSource*   poDS;
+    std::vector<OGRVRTGeomFieldProps*> apoGeomFieldProps;
 
     int                 bHasFullInitialized;
     CPLString           osName;
-    OGRwkbGeometryType  eGeomType;
     CPLXMLNode         *psLTree;
     CPLString           osVRTDirectory;
 
@@ -75,27 +107,11 @@ class OGRVRTLayer : public OGRLayer
     int                 bSrcDSShared;
     int                 bAttrFilterPassThrough;
 
-    // Layer spatial reference system, and srid.
-    OGRSpatialReference *poSRS;
-
     char                *pszAttrFilter;
 
-    int                 bSrcClip;
-    OGRGeometry         *poSrcRegion;
-
     int                 iFIDField; // -1 means pass through. 
     int                 iStyleField; // -1 means pass through.
 
-    // Geometry interpretation related.
-    OGRVRTGeometryStyle eGeometryStyle;
-    
-    int                 iGeomField; 
-
-                        // VGS_PointFromColumn
-    int                 iGeomXField, iGeomYField, iGeomZField;
-
-    int                 bUseSpatialSubquery;
-
     // Attribute Mapping
     std::vector<int>    anSrcField;
     std::vector<int>    abDirectCopy;
@@ -113,7 +129,12 @@ class OGRVRTLayer : public OGRLayer
     void                ClipAndAssignSRS(OGRFeature* poFeature);
 
     int                 nFeatureCount;
-    OGREnvelope         sStaticEnvelope;
+
+    int                 bError;
+
+    int                 ParseGeometryField(CPLXMLNode* psNode,
+                                           CPLXMLNode* psNodeParent,
+                                           OGRVRTGeomFieldProps* poProps);
 
   public:
                         OGRVRTLayer(OGRVRTDataSource* poDSIn);
@@ -148,9 +169,12 @@ class OGRVRTLayer : public OGRLayer
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
+                                  int bForce = TRUE);
 
     virtual void        SetSpatialFilter( OGRGeometry * poGeomIn );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn );
 
     virtual OGRErr      CreateFeature( OGRFeature* poFeature );
 
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrt.xsd b/ogr/ogrsf_frmts/vrt/ogrvrt.xsd
deleted file mode 100644
index 83aa9f3..0000000
--- a/ogr/ogrsf_frmts/vrt/ogrvrt.xsd
+++ /dev/null
@@ -1,319 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/******************************************************************************
- * $Id: ogrvrt.xsd 24860 2012-08-26 07:37:14Z rouault $
- *
- * Project:  GDAL/OGR
- * Purpose:  (Non normative) XML Schema for OGR VRT files.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2012, Even Rouault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
--->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.0">
-    <xs:element name="OGRVRTDataSource">
-        <xs:complexType>
-            <xs:sequence>
-                <xs:choice minOccurs="0" maxOccurs="unbounded">
-                    <xs:element name="OGRVRTLayer" type="OGRVRTLayerType"/>
-                    <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType"/>
-                    <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType"/>
-                </xs:choice>
-            </xs:sequence>
-        </xs:complexType>
-    </xs:element>
-
-    <xs:complexType name="OGRVRTLayerType">
-        <xs:sequence>
-            <xs:choice minOccurs="0" maxOccurs="unbounded">
-                <xs:element name="SrcDataSource" type="SrcDataSourceType">
-                    <xs:annotation>
-                        <xs:documentation>Required element</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="SrcLayer" type="nonEmptyStringType">
-                    <xs:annotation>
-                        <xs:documentation>SrcLayer or(eclusive) SrcSQL are required elements</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="SrcSQL">
-                    <xs:complexType>
-                        <xs:simpleContent>
-                            <xs:extension base="nonEmptyStringType">
-                                <xs:attribute name="dialect" type="nonEmptyStringType"/>
-                            </xs:extension>
-                        </xs:simpleContent>
-                    </xs:complexType>
-                </xs:element>
-                <xs:element name="FID" type="nonEmptyStringType"/>
-                <xs:element name="Style" type="nonEmptyStringType"/>
-                <xs:element name="GeometryType" type="GeometryTypeType"/>
-                <xs:element name="GeometryField" type="GeometryFieldType"/>
-                <xs:element name="LayerSRS" type="nonEmptyStringType"/>
-                <xs:element name="Field" type="FieldType">
-                    <xs:annotation>
-                        <xs:documentation>May be repeated</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="SrcRegion" type="SrcRegionType"/>
-                <xs:element name="attrFilterPassThrough" type="OGRBooleanType">
-                    <xs:annotation>
-                        <xs:documentation>Default to FALSE.</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="FeatureCount" type="xs:integer"/>
-                <xs:group ref="ExtentType"/>
-            </xs:choice>
-        </xs:sequence>
-        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
-    </xs:complexType>
-
-    <xs:group name="ExtentType">
-        <xs:sequence>
-            <xs:element name="ExtentXMin" type="xs:double" minOccurs="1" maxOccurs="1"/>
-            <xs:element name="ExtentYMin" type="xs:double" minOccurs="1" maxOccurs="1"/>
-            <xs:element name="ExtentXMax" type="xs:double" minOccurs="1" maxOccurs="1"/>
-            <xs:element name="ExtentYMax" type="xs:double" minOccurs="1" maxOccurs="1"/>
-        </xs:sequence>
-    </xs:group>
-
-    <xs:complexType name="SrcDataSourceType">
-        <xs:simpleContent>
-            <xs:extension base="nonEmptyStringType">
-                <xs:attribute name="relativeToVRT" type="OGRBooleanType" default="FALSE">
-                    <xs:annotation>
-                        <xs:documentation>Default to FALSE.</xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="shared" type="OGRBooleanType"/>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="nonEmptyStringType">
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="GeometryTypeType">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="wkbNone"/>
-            <xs:enumeration value="wkbUnknown"/>
-            <xs:enumeration value="wkbPoint"/>
-            <xs:enumeration value="wkbLineString"/>
-            <xs:enumeration value="wkbPolygon"/>
-            <xs:enumeration value="wkbMultiPoint"/>
-            <xs:enumeration value="wkbMultiLineString"/>
-            <xs:enumeration value="wkbMultiPolygon"/>
-            <xs:enumeration value="wkbGeometryCollection"/>
-            <xs:enumeration value="wkbPoint25D"/>
-            <xs:enumeration value="wkbLineString25D"/>
-            <xs:enumeration value="wkbPolygon25D"/>
-            <xs:enumeration value="wkbMultiPoint25D"/>
-            <xs:enumeration value="wkbMultiLineString25D"/>
-            <xs:enumeration value="wkbMultiPolygon25D"/>
-            <xs:enumeration value="wkbGeometryCollection25D"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:complexType name="FieldType">
-        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
-        <xs:attribute name="type" type="OGRFieldTypeType" default="String"/>
-        <xs:attribute name="src" type="nonEmptyStringType">
-            <xs:annotation>
-                <xs:documentation>Defaults to the value of "name" if not specified.</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="width" type="xs:nonNegativeInteger"/>
-        <xs:attribute name="precision" type="xs:nonNegativeInteger"/>
-    </xs:complexType>
-
-    <xs:simpleType name="OGRFieldTypeType">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="Integer"/>
-            <xs:enumeration value="Real"/>
-            <xs:enumeration value="String"/>
-            <xs:enumeration value="IntegerList"/>
-            <xs:enumeration value="RealList"/>
-            <xs:enumeration value="StringList"/>
-            <xs:enumeration value="Binary"/>
-            <xs:enumeration value="Date"/>
-            <xs:enumeration value="Time"/>
-            <xs:enumeration value="DateTime"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:complexType name="GeometryFieldType">
-        <xs:attribute name="encoding">
-            <xs:annotation>
-                <xs:documentation>Defaults to Direct.</xs:documentation>
-            </xs:annotation>
-            <xs:simpleType>
-                <xs:restriction base="xs:string">
-                    <xs:enumeration value="Direct"/>
-                    <xs:enumeration value="None"/>
-                    <xs:enumeration value="WKT"/>
-                    <xs:enumeration value="WKB"/>
-                    <xs:enumeration value="Shape"/>
-                    <xs:enumeration value="PointFromColumns"/>
-                </xs:restriction>
-            </xs:simpleType>
-        </xs:attribute>
-        <xs:attribute name="field" type="nonEmptyStringType">
-            <xs:annotation>
-                <xs:documentation>Only used if encoding = "WKT", "WKB" or "Shape"</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="x" type="nonEmptyStringType">
-            <xs:annotation>
-                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="y" type="nonEmptyStringType">
-            <xs:annotation>
-                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="z" type="nonEmptyStringType">
-            <xs:annotation>
-                <xs:documentation>Only used if encoding = "PointFromColumns"</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useSpatialSubquery" type="OGRBooleanType">
-            <xs:annotation>
-                <xs:documentation>Only used if encoding = "PointFromColumns". Defaults to TRUE.</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="reportSrcColumn" type="OGRBooleanType">
-            <xs:annotation>
-                <xs:documentation>Only used if no Field element is found at the OGRVRTLayer level</xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-    </xs:complexType>
-
-    <xs:complexType name="SrcRegionType">
-        <xs:simpleContent>
-            <xs:extension base="PolygonWKTType">
-                <xs:attribute name="clip" type="OGRBooleanType">
-                    <xs:annotation>
-                        <xs:documentation>Defaults to FALSE.</xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="PolygonWKTType">
-        <xs:annotation>
-            <xs:documentation>A valid WKT for a POLYGON</xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:pattern value="POLYGON.*"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="OGRBooleanType">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="1"/>
-            <xs:enumeration value="0"/>
-            <xs:enumeration value="ON"/>
-            <xs:enumeration value="OFF"/>
-            <xs:enumeration value="on"/>
-            <xs:enumeration value="off"/>
-            <xs:enumeration value="YES"/>
-            <xs:enumeration value="NO"/>
-            <xs:enumeration value="yes"/>
-            <xs:enumeration value="no"/>
-            <xs:enumeration value="TRUE"/>
-            <xs:enumeration value="FALSE"/>
-            <xs:enumeration value="true"/>
-            <xs:enumeration value="false"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:complexType name="OGRVRTWarpedLayerType">
-        <xs:sequence>
-            <xs:choice minOccurs="1" maxOccurs="1">
-                <xs:element name="OGRVRTLayer" type="OGRVRTLayerType"/>
-                <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType"/>
-                <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType"/>
-            </xs:choice>
-            <xs:element name="SrcSRS" type="nonEmptyStringType" minOccurs="0" maxOccurs="1"/>
-            <xs:element name="TargetSRS" type="nonEmptyStringType" minOccurs="1" maxOccurs="1"/>
-            <xs:group ref="ExtentType" minOccurs="0" maxOccurs="1"/>
-        </xs:sequence>
-    </xs:complexType>
-
-    <xs:complexType name="OGRVRTUnionLayerType">
-        <xs:sequence>
-            <xs:choice minOccurs="0" maxOccurs="unbounded">
-                <xs:element name="OGRVRTLayer" type="OGRVRTLayerType">
-                    <xs:annotation>
-                        <xs:documentation>May be repeated</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="OGRVRTWarpedLayer" type="OGRVRTWarpedLayerType">
-                    <xs:annotation>
-                        <xs:documentation>May be repeated</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="OGRVRTUnionLayer" type="OGRVRTUnionLayerType">
-                    <xs:annotation>
-                        <xs:documentation>May be repeated</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-
-                <xs:element name="GeometryType" type="GeometryTypeType"/>
-                <xs:element name="LayerSRS" type="nonEmptyStringType"/>
-                <xs:element name="FieldStrategy" type="FieldStrategyType">
-                    <xs:annotation>
-                        <xs:documentation>Defaults to Union if no Field element is speicified.</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="Field" type="FieldType">
-                    <xs:annotation>
-                        <xs:documentation>May be repeated</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="PreserveSrcFID" type="OGRBooleanType">
-                    <xs:annotation>
-                        <xs:documentation>Defaults to FALSE.</xs:documentation>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="SourceLayerFieldName" type="nonEmptyStringType"/>
-                <xs:element name="FeatureCount" type="xs:integer"/>
-                <xs:group ref="ExtentType"/>
-            </xs:choice>
-        </xs:sequence>
-        <xs:attribute name="name" type="nonEmptyStringType" use="required"/>
-    </xs:complexType>
-
-    <xs:simpleType name="FieldStrategyType">
-        <xs:restriction base="xs:string">
-            <xs:enumeration value="FirstLayer"/>
-            <xs:enumeration value="Union"/>
-            <xs:enumeration value="Intersection"/>
-        </xs:restriction>
-    </xs:simpleType>
-
-</xs:schema>
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
index 4b7b8cd..39555b1 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdatasource.cpp 25110 2012-10-13 13:53:53Z rouault $
+ * $Id: ogrvrtdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDataSource class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "ogrwarpedlayer.h"
 #include "ogrunionlayer.h"
 
-CPL_CVSID("$Id: ogrvrtdatasource.cpp 25110 2012-10-13 13:53:53Z rouault $");
+CPL_CVSID("$Id: ogrvrtdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                       OGRVRTGetGeometryType()                        */
@@ -168,16 +169,31 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing TargetSRS element within OGRVRTWarpedLayer" );
+        delete poSrcLayer;
         return NULL;
     }
 
+    const char* pszGeomFieldName = CPLGetXMLValue(psLTree, "WarpedGeomFieldName", NULL);
+    int iGeomField = 0;
+    if( pszGeomFieldName != NULL )
+    {
+        iGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomFieldName);
+        if( iGeomField < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot find source geometry field '%s'", pszGeomFieldName );
+            delete poSrcLayer;
+            return NULL;
+        }
+    }
+
     OGRSpatialReference* poSrcSRS;
     OGRSpatialReference* poTargetSRS;
     const char* pszSourceSRS = CPLGetXMLValue(psLTree, "SrcSRS", NULL);
 
     if( pszSourceSRS == NULL )
     {
-        poSrcSRS = poSrcLayer->GetSpatialRef();
+        poSrcSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef();
         if( poSrcSRS != NULL)
             poSrcSRS = poSrcSRS->Clone();
     }
@@ -240,7 +256,8 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
 /*      Build the OGRWarpedLayer.                                       */
 /* -------------------------------------------------------------------- */
 
-    OGRWarpedLayer* poLayer = new OGRWarpedLayer(poSrcLayer, TRUE, poCT, poReversedCT);
+    OGRWarpedLayer* poLayer = new OGRWarpedLayer(poSrcLayer, iGeomField,
+                                                 TRUE, poCT, poReversedCT);
 
 /* -------------------------------------------------------------------- */
 /*      Set Extent if provided                                          */
@@ -293,12 +310,13 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
 /*      source layer.                                                   */
 /* -------------------------------------------------------------------- */
     const char* pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
-    OGRwkbGeometryType eGeomType = wkbUnknown;
-    GeometryTypeUnionStrategy eGeometryTypeStrategy = GEOMTYPE_UNION_ALL_LAYERS;
+    int bGlobalGeomTypeSet = FALSE;
+    OGRwkbGeometryType eGlobalGeomType = wkbUnknown;
     if( pszGType != NULL )
     {
         int bError;
-        eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
+        bGlobalGeomTypeSet = TRUE;
+        eGlobalGeomType = OGRVRTGetGeometryType(pszGType, &bError);
         if( bError )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -306,22 +324,18 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
                     pszGType );
             return NULL;
         }
-
-        eGeometryTypeStrategy = GEOMTYPE_SPECIFIED;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Apply a spatial reference system if provided                    */
 /* -------------------------------------------------------------------- */
      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
-     OGRSpatialReference* poSRS = NULL;
-     int bSRSSet = FALSE;
+     OGRSpatialReference* poGlobalSRS = NULL;
+     int bGlobalSRSSet = FALSE;
      if( pszLayerSRS != NULL )
      {
-         bSRSSet = TRUE;
-         if( EQUAL(pszLayerSRS,"NULL") )
-             poSRS = NULL;
-         else
+         bGlobalSRSSet = TRUE;
+         if( !EQUAL(pszLayerSRS,"NULL") )
          {
              OGRSpatialReference oSRS;
 
@@ -331,7 +345,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
                            "Failed to import LayerSRS `%s'.", pszLayerSRS );
                  return FALSE;
              }
-             poSRS = oSRS.Clone();
+             poGlobalSRS = oSRS.Clone();
          }
      }
 
@@ -340,6 +354,8 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
 /* -------------------------------------------------------------------- */
     OGRFieldDefn** papoFields = NULL;
     int nFields = 0;
+    OGRUnionLayerGeomFieldDefn** papoGeomFields = NULL;
+    int nGeomFields = 0;
 
     for( psSubNode=psLTree->psChild;
          psSubNode != NULL;
@@ -419,6 +435,130 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
              papoFields[nFields] = new OGRFieldDefn(&oFieldDefn);
              nFields ++;
          }
+
+         else if( psSubNode->eType == CXT_Element &&
+                  EQUAL(psSubNode->pszValue,"GeometryField") )
+         {
+             const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
+             if( pszName == NULL )
+             {
+                 CPLError( CE_Failure, CPLE_AppDefined,
+                           "Unable to identify GeometryField name." );
+                 break;
+             }
+
+             pszGType = CPLGetXMLValue( psSubNode, "GeometryType", NULL );
+             if( pszGType == NULL && nGeomFields == 0 )
+                 pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
+             OGRwkbGeometryType eGeomType = wkbUnknown;
+             int bGeomTypeSet = FALSE;
+             if( pszGType != NULL )
+             {
+                int bError;
+                eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
+                bGeomTypeSet = TRUE;
+                if( bError || eGeomType == wkbNone )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                            "GeometryType %s not recognised.",
+                            pszGType );
+                    break;
+                }
+             }
+
+             const char* pszSRS = CPLGetXMLValue( psSubNode, "SRS", NULL );
+             if( pszSRS == NULL && nGeomFields == 0 )
+                 pszSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
+             OGRSpatialReference* poSRS = NULL;
+             int bSRSSet = FALSE;
+             if( pszSRS != NULL )
+             {
+                 bSRSSet = TRUE;
+                 if( !EQUAL(pszSRS,"NULL") )
+                 {
+                    OGRSpatialReference oSRS;
+
+                    if( oSRS.SetFromUserInput( pszSRS ) != OGRERR_NONE )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                "Failed to import SRS `%s'.", pszSRS );
+                        break;
+                    }
+                    poSRS = oSRS.Clone();
+                }
+             }
+
+             OGRUnionLayerGeomFieldDefn* poFieldDefn =
+                    new OGRUnionLayerGeomFieldDefn(pszName, eGeomType);
+             if( poSRS != NULL )
+             {
+                poFieldDefn->SetSpatialRef(poSRS);
+                poSRS->Dereference();
+             }
+             poFieldDefn->bGeomTypeSet = bGeomTypeSet;
+             poFieldDefn->bSRSSet = bSRSSet;
+
+             const char* pszExtentXMin = CPLGetXMLValue( psSubNode, "ExtentXMin", NULL );
+             const char* pszExtentYMin = CPLGetXMLValue( psSubNode, "ExtentYMin", NULL );
+             const char* pszExtentXMax = CPLGetXMLValue( psSubNode, "ExtentXMax", NULL );
+             const char* pszExtentYMax = CPLGetXMLValue( psSubNode, "ExtentYMax", NULL );
+             if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
+                 pszExtentXMax != NULL && pszExtentYMax != NULL )
+             {
+                poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
+                poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
+                poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
+                poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
+             }
+
+             papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields,
+                                        sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1));
+             papoGeomFields[nGeomFields] = poFieldDefn;
+             nGeomFields ++;
+         }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set Extent if provided                                          */
+/* -------------------------------------------------------------------- */
+    const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
+    const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
+    const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
+    const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
+
+    if( eGlobalGeomType != wkbNone && nGeomFields == 0 &&
+        (bGlobalGeomTypeSet || bGlobalSRSSet ||
+         (pszExtentXMin != NULL && pszExtentYMin != NULL &&
+          pszExtentXMax != NULL && pszExtentYMax != NULL)) )
+    {
+        OGRUnionLayerGeomFieldDefn* poFieldDefn =
+                new OGRUnionLayerGeomFieldDefn("", eGlobalGeomType);
+        if( poGlobalSRS != NULL )
+        {
+            poFieldDefn->SetSpatialRef(poGlobalSRS);
+            poGlobalSRS->Dereference();
+            poGlobalSRS = NULL;
+        }
+        poFieldDefn->bGeomTypeSet = bGlobalGeomTypeSet;
+        poFieldDefn->bSRSSet = bGlobalSRSSet;
+        if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
+            pszExtentXMax != NULL && pszExtentYMax != NULL )
+        {
+            poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
+            poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
+            poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
+            poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
+        }
+
+        papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields,
+                                sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1));
+        papoGeomFields[nGeomFields] = poFieldDefn;
+        nGeomFields ++;
+    }
+    else
+    {
+        delete poGlobalSRS;
+        poGlobalSRS = NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -450,10 +590,13 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot find source layers" );
-        for(int iField = 0; iField < nFields; iField++)
+        int iField;
+        for(iField = 0; iField < nFields; iField++)
             delete papoFields[iField];
         CPLFree(papoFields);
-        delete poSRS;
+        for(iField = 0; iField < nGeomFields; iField++)
+            delete papoGeomFields[iField];
+        CPLFree(papoGeomFields);
         return NULL;
     }
 
@@ -466,19 +609,6 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
                                                 TRUE );
 
 /* -------------------------------------------------------------------- */
-/*      Set SRS if provided                                             */
-/* -------------------------------------------------------------------- */
-    if( bSRSSet )
-        poLayer->SetSRS(poSRS);
-
-    delete poSRS;
-
-/* -------------------------------------------------------------------- */
-/*      Set geometry type                                               */
-/* -------------------------------------------------------------------- */
-    poLayer->SetGeometryType(eGeometryTypeStrategy, eGeomType);
-
-/* -------------------------------------------------------------------- */
 /*      Set the source layer field name attribute.                      */
 /* -------------------------------------------------------------------- */
     const char* pszSourceLayerFieldName =
@@ -513,18 +643,24 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
                       "Unhandled value for FieldStrategy `%s'.", pszFieldStrategy );
         }
     }
-    if( nFields != 0 )
+    if( nFields != 0 || nGeomFields > 1 )
     {
         if( pszFieldStrategy != NULL )
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Ignoring FieldStrategy value, because explicit Field is provided") ;
+                      "Ignoring FieldStrategy value, because explicit Field or GeometryField is provided") ;
         eFieldStrategy = FIELD_SPECIFIED;
     }
 
-    poLayer->SetFields(eFieldStrategy, nFields, papoFields);
-    for(int iField = 0; iField < nFields; iField++)
+    poLayer->SetFields(eFieldStrategy, nFields, papoFields,
+                       (nGeomFields == 0 && eGlobalGeomType == wkbNone) ? -1 : nGeomFields,
+                       papoGeomFields);
+    int iField;
+    for(iField = 0; iField < nFields; iField++)
         delete papoFields[iField];
     CPLFree(papoFields);
+    for(iField = 0; iField < nGeomFields; iField++)
+        delete papoGeomFields[iField];
+    CPLFree(papoGeomFields);
 
 /* -------------------------------------------------------------------- */
 /*      Set FeatureCount if provided                                    */
@@ -535,22 +671,6 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
         poLayer->SetFeatureCount(atoi(pszFeatureCount));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set Extent if provided                                          */
-/* -------------------------------------------------------------------- */
-    const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
-    const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
-    const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
-    const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
-    if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
-        pszExtentXMax != NULL && pszExtentYMax != NULL )
-    {
-        poLayer->SetExtent( CPLAtof(pszExtentXMin),
-                            CPLAtof(pszExtentYMin),
-                            CPLAtof(pszExtentXMax),
-                            CPLAtof(pszExtentYMax) );
-    }
-
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
index 28ae909..4159648 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdriver.cpp 24154 2012-03-23 21:47:11Z warmerdam $
+ * $Id: ogrvrtdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDriver class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "ogr_vrt.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrvrtdriver.cpp 24154 2012-03-23 21:47:11Z warmerdam $");
+CPL_CVSID("$Id: ogrvrtdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRVRTDriver()                            */
@@ -52,6 +53,16 @@ const char *OGRVRTDriver::GetName()
 }
 
 /************************************************************************/
+/*                           OGRVRTErrorHandler()                       */
+/************************************************************************/
+
+static void CPL_STDCALL OGRVRTErrorHandler(CPLErr eErr, int nType, const char* pszMsg)
+{
+    std::vector<CPLString>* paosErrors = (std::vector<CPLString>* )CPLGetErrorHandlerUserData();
+    paosErrors->push_back(pszMsg);
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -134,10 +145,40 @@ OGRDataSource *OGRVRTDriver::Open( const char * pszFilename,
 /*      Parse the XML.                                                  */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psTree = CPLParseXMLString( pszXML );
-    CPLFree( pszXML );
 
     if( psTree == NULL )
+    {
+        CPLFree( pszXML );
         return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      XML Validation.                                                 */
+/* -------------------------------------------------------------------- */
+    if( CSLTestBoolean(CPLGetConfigOption("GDAL_XML_VALIDATION", "YES")) )
+    {
+        const char* pszXSD = CPLFindFile( "gdal", "ogrvrt.xsd" );
+        if( pszXSD != NULL )
+        {
+            std::vector<CPLString> aosErrors;
+            CPLPushErrorHandlerEx(OGRVRTErrorHandler, &aosErrors);
+            int bRet = CPLValidateXML(pszXML, pszXSD, NULL);
+            CPLPopErrorHandler();
+            if( !bRet )
+            {
+                if( aosErrors.size() > 0 &&
+                    strstr(aosErrors[0].c_str(), "missing libxml2 support") == NULL )
+                {
+                    for(size_t i = 0; i < aosErrors.size(); i++)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined, "%s", aosErrors[i].c_str());
+                    }
+                }
+            }
+            CPLErrorReset();
+        }
+    }
+    CPLFree( pszXML );
 
 /* -------------------------------------------------------------------- */
 /*      Create a virtual datasource configured based on this XML input. */
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
index ca3a82a..ad27ee1 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtlayer.cpp 25311 2012-12-15 12:48:14Z rouault $
+ * $Id: ogrvrtlayer.cpp 27080 2014-03-23 00:26:43Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTLayer class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,10 +34,39 @@
 #include "ogrpgeogeometry.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrvrtlayer.cpp 25311 2012-12-15 12:48:14Z rouault $");
+CPL_CVSID("$Id: ogrvrtlayer.cpp 27080 2014-03-23 00:26:43Z rouault $");
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
+
+/************************************************************************/
+/*                       OGRVRTGeomFieldProps()                         */
+/************************************************************************/
+
+OGRVRTGeomFieldProps::OGRVRTGeomFieldProps()
+{
+    eGeomType = wkbUnknown;
+    bUseSpatialSubquery = FALSE;
+    eGeometryStyle = VGS_Direct;
+    poSRS = NULL;
+    iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
+    bSrcClip = FALSE;
+    poSrcRegion = NULL;
+    bReportSrcColumn = TRUE;
+}
+
+/************************************************************************/
+/*                      ~OGRVRTGeomFieldProps()                         */
+/************************************************************************/
+
+OGRVRTGeomFieldProps::~OGRVRTGeomFieldProps()
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+    if( poSrcRegion != NULL )
+        delete poSrcRegion;
+}
+
 /************************************************************************/
 /*                            OGRVRTLayer()                             */
 /************************************************************************/
@@ -47,33 +77,26 @@ OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn)
     poDS = poDSIn;
 
     bHasFullInitialized = FALSE;
-    eGeomType = wkbUnknown;
     psLTree = NULL;
 
     poFeatureDefn = NULL;
     poSrcLayer = NULL;
-    poSRS = NULL;
     poSrcDS = NULL;
     poSrcFeatureDefn = NULL;
 
-    bUseSpatialSubquery = FALSE;
     iFIDField = -1;
     iStyleField = -1;
 
-    eGeometryStyle = VGS_Direct;
-    iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
-
     pszAttrFilter = NULL;
 
     bNeedReset = TRUE;
     bSrcLayerFromSQL = FALSE;
 
-    bSrcClip = FALSE;
-    poSrcRegion = NULL;
     bUpdate = FALSE;
     bAttrFilterPassThrough = FALSE;
 
     nFeatureCount = -1;
+    bError = FALSE;
 }
 
 /************************************************************************/
@@ -89,12 +112,19 @@ OGRVRTLayer::~OGRVRTLayer()
                   (int) m_nFeaturesRead, 
                   poFeatureDefn->GetName() );
     }
-
-    if( poSRS != NULL )
-        poSRS->Release();
+    
+    for(size_t i=0;i<apoGeomFieldProps.size();i++)
+        delete apoGeomFieldProps[i];
 
     if( poSrcDS != NULL )
     {
+        if( poSrcLayer )
+        {
+            poSrcLayer->SetIgnoredFields(NULL);
+            poSrcLayer->SetAttributeFilter(NULL);
+            poSrcLayer->SetSpatialFilter(NULL);
+        }
+
         if( bSrcLayerFromSQL && poSrcLayer )
             poSrcDS->ReleaseResultSet( poSrcLayer );
 
@@ -108,9 +138,6 @@ OGRVRTLayer::~OGRVRTLayer()
         poFeatureDefn->Release();
 
     CPLFree( pszAttrFilter );
-
-    if( poSrcRegion != NULL )
-        delete poSrcRegion;
 }
 
 /************************************************************************/
@@ -160,7 +187,11 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
 /* -------------------------------------------------------------------- */
 /*      Do we have a fixed geometry type?  If so use it                 */
 /* -------------------------------------------------------------------- */
+     CPLXMLNode* psGeometryFieldNode = CPLGetXMLNode(psLTree, "GeometryField");
      const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
+     if( pszGType == NULL && psGeometryFieldNode != NULL )
+         pszGType = CPLGetXMLValue( psGeometryFieldNode, "GeometryType", NULL );
+     OGRwkbGeometryType eGeomType = wkbUnknown;
      if( pszGType != NULL )
      {
          int bError;
@@ -174,15 +205,21 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
          }
      }
 
+     if( eGeomType != wkbNone )
+     {
+         apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+         apoGeomFieldProps[0]->eGeomType = eGeomType;
+     }
+
 /* -------------------------------------------------------------------- */
 /*      Apply a spatial reference system if provided                    */
 /* -------------------------------------------------------------------- */
      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
-     if( pszLayerSRS != NULL )
+     if( pszLayerSRS == NULL && psGeometryFieldNode != NULL )
+         pszLayerSRS = CPLGetXMLValue( psGeometryFieldNode, "SRS", NULL );
+     if( apoGeomFieldProps.size() != 0 && pszLayerSRS != NULL )
      {
-         if( EQUAL(pszLayerSRS,"NULL") )
-             poSRS = NULL;
-         else
+         if( !(EQUAL(pszLayerSRS,"NULL")) )
          {
              OGRSpatialReference oSRS;
 
@@ -192,7 +229,7 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
                            "Failed to import LayerSRS `%s'.", pszLayerSRS );
                  return FALSE;
              }
-             poSRS = oSRS.Clone();
+             apoGeomFieldProps[0]->poSRS = oSRS.Clone();
          }
      }
 
@@ -212,19 +249,259 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
      const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
      const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
      const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
-     if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
+     if( pszExtentXMin == NULL && psGeometryFieldNode != NULL )
+     {
+        pszExtentXMin = CPLGetXMLValue( psGeometryFieldNode, "ExtentXMin", NULL );
+        pszExtentYMin = CPLGetXMLValue( psGeometryFieldNode, "ExtentYMin", NULL );
+        pszExtentXMax = CPLGetXMLValue( psGeometryFieldNode, "ExtentXMax", NULL );
+        pszExtentYMax = CPLGetXMLValue( psGeometryFieldNode, "ExtentYMax", NULL );
+     }
+     if( apoGeomFieldProps.size() != 0 &&
+         pszExtentXMin != NULL && pszExtentYMin != NULL &&
          pszExtentXMax != NULL && pszExtentYMax != NULL )
      {
-         sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
-         sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
-         sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
-         sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
+         apoGeomFieldProps[0]->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
+         apoGeomFieldProps[0]->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
+         apoGeomFieldProps[0]->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
+         apoGeomFieldProps[0]->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
      }
 
      return TRUE;
 }
 
 /************************************************************************/
+/*                       ParseGeometryField()                           */
+/************************************************************************/
+
+int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
+                                    CPLXMLNode* psNodeParent,
+                                    OGRVRTGeomFieldProps* poProps)
+{
+    const char* pszName = CPLGetXMLValue( psNode, "name", NULL);
+    poProps->osName = (pszName ) ? pszName : "";
+    if( pszName == NULL &&
+        apoGeomFieldProps.size() > 1 && poProps != apoGeomFieldProps[0] )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+            "A 'name' attribute should be defined when there are several geometry fields");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a fixed geometry type?                               */
+/* -------------------------------------------------------------------- */
+    const char* pszGType = CPLGetXMLValue( psNode, "GeometryType", NULL );
+    if( pszGType == NULL && poProps == apoGeomFieldProps[0] )
+        pszGType = CPLGetXMLValue( psNodeParent, "GeometryType", NULL );
+    if( pszGType != NULL )
+    {
+        int bError;
+        poProps->eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
+        if( bError )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                     "GeometryType %s not recognised.",
+                      pszGType );
+            return FALSE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Determine which field(s) to get the geometry from               */
+/* -------------------------------------------------------------------- */
+    const char *pszEncoding = CPLGetXMLValue( psNode,"encoding", "direct");
+
+    if( EQUAL(pszEncoding,"Direct") )
+        poProps->eGeometryStyle = VGS_Direct;
+    else if( EQUAL(pszEncoding,"None") )
+        poProps->eGeometryStyle = VGS_None;
+    else if( EQUAL(pszEncoding,"WKT") )
+        poProps->eGeometryStyle = VGS_WKT;
+    else if( EQUAL(pszEncoding,"WKB") )
+        poProps->eGeometryStyle = VGS_WKB;
+    else if( EQUAL(pszEncoding,"Shape") )
+        poProps->eGeometryStyle = VGS_Shape;
+    else if( EQUAL(pszEncoding,"PointFromColumns") )
+    {
+        poProps->eGeometryStyle = VGS_PointFromColumns;
+        poProps->bUseSpatialSubquery = 
+            CSLTestBoolean(
+                CPLGetXMLValue(psNode, 
+                            "GeometryField.useSpatialSubquery",
+                            "TRUE"));
+
+        poProps->iGeomXField = GetSrcLayerDefn()->GetFieldIndex(
+            CPLGetXMLValue( psNode, "x", "missing" ) );
+        poProps->iGeomYField = GetSrcLayerDefn()->GetFieldIndex(
+            CPLGetXMLValue( psNode, "y", "missing" ) );
+        poProps->iGeomZField = GetSrcLayerDefn()->GetFieldIndex(
+            CPLGetXMLValue( psNode, "z", "missing" ) );
+
+        if( poProps->iGeomXField == -1 || poProps->iGeomYField == -1 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                    "Unable to identify source X or Y field for PointFromColumns encoding." );
+            return FALSE;
+        }
+
+        if( pszGType == NULL )
+        {
+            if( poProps->iGeomZField != -1 )
+                poProps->eGeomType = wkbPoint25D;
+            else
+                poProps->eGeomType = wkbPoint;
+        }
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                "encoding=\"%s\" not recognised.", pszEncoding );
+        return FALSE;
+    }
+
+    if( poProps->eGeometryStyle == VGS_WKT
+        || poProps->eGeometryStyle == VGS_WKB
+        || poProps->eGeometryStyle == VGS_Shape )
+    {
+        const char *pszFieldName = 
+            CPLGetXMLValue( psNode, "field", "missing" );
+
+        poProps->iGeomField = GetSrcLayerDefn()->GetFieldIndex(pszFieldName);
+
+        if( poProps->iGeomField == -1 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                    "Unable to identify source field '%s' for geometry.",
+                    pszFieldName );
+            return FALSE;
+        }
+    }
+    else if( poProps->eGeometryStyle == VGS_Direct )
+    {
+        const char *pszFieldName = 
+            CPLGetXMLValue( psNode, "field", NULL );
+
+        if( pszFieldName != NULL || GetSrcLayerDefn()->GetGeomFieldCount() > 1 )
+        {
+            if( pszFieldName == NULL )
+                pszFieldName = poProps->osName;
+            poProps->iGeomField = GetSrcLayerDefn()->GetGeomFieldIndex(pszFieldName);
+
+            if( poProps->iGeomField == -1 )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                        "Unable to identify source geometry field '%s' for geometry.",
+                        pszFieldName );
+                return FALSE;
+            }
+        }
+        else if( GetSrcLayerDefn()->GetGeomFieldCount() == 1 )
+        {
+            poProps->iGeomField = 0;
+        }
+        else if( psNode != NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                    "Unable to identify source geometry field." );
+            return FALSE;
+        }
+    }
+
+    poProps->bReportSrcColumn =
+        CSLTestBoolean(CPLGetXMLValue( psNode, "reportSrcColumn", "YES" ));
+
+/* -------------------------------------------------------------------- */
+/*      Guess geometry type if not explicitely provided (or computed)   */
+/* -------------------------------------------------------------------- */
+    if( pszGType == NULL && poProps->eGeomType == wkbUnknown )
+    {
+        if( GetSrcLayerDefn()->GetGeomFieldCount() == 1 )
+            poProps->eGeomType = poSrcLayer->GetGeomType();
+        else if( poProps->eGeometryStyle == VGS_Direct &&
+                 poProps->iGeomField >= 0 )
+        {
+            poProps->eGeomType =
+                GetSrcLayerDefn()->GetGeomFieldDefn(poProps->iGeomField)->GetType();
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Copy spatial reference system from source if not provided       */
+/* -------------------------------------------------------------------- */
+     const char* pszSRS = CPLGetXMLValue( psNode, "SRS", NULL );
+     if( pszSRS == NULL && poProps == apoGeomFieldProps[0] )
+        pszSRS = CPLGetXMLValue( psNodeParent, "LayerSRS", NULL );
+     if( pszSRS == NULL )
+     {
+         OGRSpatialReference* poSRS = NULL;
+         if( GetSrcLayerDefn()->GetGeomFieldCount() == 1 )
+         {
+            poSRS = poSrcLayer->GetSpatialRef();
+         }
+         else if( poProps->eGeometryStyle == VGS_Direct &&
+                 poProps->iGeomField >= 0 )
+         {
+             poSRS = GetSrcLayerDefn()->
+                    GetGeomFieldDefn(poProps->iGeomField)->GetSpatialRef();
+         }
+         if( poSRS != NULL )
+            poProps->poSRS = poSRS->Clone();
+     }
+     else if( poProps->poSRS == NULL )
+     {
+         if( !(EQUAL(pszSRS,"NULL")) )
+         {
+             OGRSpatialReference oSRS;
+
+             if( oSRS.SetFromUserInput( pszSRS ) != OGRERR_NONE )
+             {
+                 CPLError( CE_Failure, CPLE_AppDefined,
+                           "Failed to import SRS `%s'.", pszSRS );
+                 return FALSE;
+             }
+             poProps->poSRS = oSRS.Clone();
+         }
+     }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a SrcRegion?                                         */
+/* -------------------------------------------------------------------- */
+    const char *pszSrcRegion = CPLGetXMLValue( psNode, "SrcRegion", NULL );
+    if( pszSrcRegion == NULL && poProps == apoGeomFieldProps[0] )
+        pszSrcRegion = CPLGetXMLValue( psNodeParent, "SrcRegion", NULL );
+    if( pszSrcRegion != NULL )
+    {
+        OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poProps->poSrcRegion );
+        if( poProps->poSrcRegion == NULL || wkbFlatten(poProps->poSrcRegion->getGeometryType()) != wkbPolygon)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                        "Ignoring SrcRegion. It must be a valid WKT polygon");
+            delete poProps->poSrcRegion;
+            poProps->poSrcRegion = NULL;
+        }
+
+        poProps->bSrcClip = CSLTestBoolean(CPLGetXMLValue( psNode, "SrcRegion.clip", "FALSE" ));
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set Extent if provided                                          */
+/* -------------------------------------------------------------------- */
+     const char* pszExtentXMin = CPLGetXMLValue( psNode, "ExtentXMin", NULL );
+     const char* pszExtentYMin = CPLGetXMLValue( psNode, "ExtentYMin", NULL );
+     const char* pszExtentXMax = CPLGetXMLValue( psNode, "ExtentXMax", NULL );
+     const char* pszExtentYMax = CPLGetXMLValue( psNode, "ExtentYMax", NULL );
+     if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
+         pszExtentXMax != NULL && pszExtentYMax != NULL )
+     {
+         poProps->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
+         poProps->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
+         poProps->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
+         poProps->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
+     }
+
+    return TRUE;
+}
+
+/************************************************************************/
 /*                         FullInitialize()                             */
 /************************************************************************/
 
@@ -233,13 +510,10 @@ int OGRVRTLayer::FullInitialize()
 {
     const char *pszSharedSetting = NULL;
     const char *pszSQL = NULL;
-    const char *pszSrcRegion = NULL;
-    const char *pszGType = NULL;
-    const char *pszLayerSRS = NULL;
-    const char *pszEncoding = NULL;
     const char *pszFIDFieldName = NULL;
     const char *pszStyleFieldName = NULL;
     CPLXMLNode *psChild = NULL;
+    int bFoundGeometryField = FALSE;
 
     if (bHasFullInitialized)
         return TRUE;
@@ -269,8 +543,31 @@ int OGRVRTLayer::FullInitialize()
     if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT", 
                                        "0")) )
     {
-        pszSrcDSName = CPLStrdup(
-            CPLProjectRelativeFilename( osVRTDirectory, pszSrcDSName ) );
+        static const char* apszPrefixes[] = { "CSV:", "GPSBABEL:" };
+        int bDone = FALSE;
+        for( size_t i = 0; i < sizeof(apszPrefixes) / sizeof(apszPrefixes[0]); i ++)
+        {
+            const char* pszPrefix = apszPrefixes[i];
+            if( EQUALN(pszSrcDSName, pszPrefix, strlen(pszPrefix)) )
+            {
+                const char* pszLastPart = strrchr(pszSrcDSName, ':') + 1;
+                /* CSV:z:/foo.xyz */
+                if( (pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
+                    pszLastPart - pszSrcDSName >= 3 && pszLastPart[-3] == ':' )
+                    pszLastPart -= 2;
+                CPLString osPrefix(pszSrcDSName);
+                osPrefix.resize(pszLastPart - pszSrcDSName);
+                pszSrcDSName = CPLStrdup( (osPrefix +
+                    CPLProjectRelativeFilename( osVRTDirectory, pszLastPart )).c_str() );
+                bDone = TRUE;
+                break;
+            }
+        }
+        if( !bDone )
+        {
+            pszSrcDSName = CPLStrdup(
+                CPLProjectRelativeFilename( osVRTDirectory, pszSrcDSName ) );
+        }
     }
     else
     {
@@ -416,97 +713,97 @@ try_again:
             goto error;
         }
     }
-        
+
     CPLFree( pszSrcDSName );
     pszSrcDSName = NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Do we have a fixed geometry type?  If not derive from the       */
-/*      source layer.                                                   */
-/* -------------------------------------------------------------------- */
-     pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
-     if( pszGType == NULL )
-     {
-         eGeomType = poSrcLayer->GetGeomType();
-     }
-     poFeatureDefn->SetGeomType(eGeomType);
-
-/* -------------------------------------------------------------------- */
-/*      Copy spatial reference system from source if not provided       */
-/* -------------------------------------------------------------------- */
-     pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
-     if( pszLayerSRS == NULL )
-     {
-         CPLAssert(poSRS == NULL);
-         if( poSrcLayer->GetSpatialRef() != NULL )
-             poSRS = poSrcLayer->GetSpatialRef()->Clone();
-         else
-             poSRS = NULL;
-     }
-
-/* -------------------------------------------------------------------- */
-/*      Handle GeometryField.                                           */
+/*      Search for GeometryField definitions                            */
 /* -------------------------------------------------------------------- */
+    if( apoGeomFieldProps.size() != 0 )
+    {
+        /* First pass: create as many OGRVRTGeomFieldProps as there are */
+        /* GeometryField elements */
+        for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
+        {
+        if( psChild->eType == CXT_Element &&
+            EQUAL(psChild->pszValue,"GeometryField") )
+        {
+            if( !bFoundGeometryField )
+            {
+                bFoundGeometryField = TRUE;
+            }
+            else
+                apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+        }
+        }
 
-     pszEncoding = CPLGetXMLValue( psLTree,"GeometryField.encoding", "direct");
-
-     if( EQUAL(pszEncoding,"Direct") )
-         eGeometryStyle = VGS_Direct;
-     else if( EQUAL(pszEncoding,"None") )
-         eGeometryStyle = VGS_None;
-     else if( EQUAL(pszEncoding,"WKT") )
-         eGeometryStyle = VGS_WKT;
-     else if( EQUAL(pszEncoding,"WKB") )
-         eGeometryStyle = VGS_WKB;
-     else if( EQUAL(pszEncoding,"Shape") )
-         eGeometryStyle = VGS_Shape;
-     else if( EQUAL(pszEncoding,"PointFromColumns") )
-     {
-         eGeometryStyle = VGS_PointFromColumns;
-         bUseSpatialSubquery = 
-             CSLTestBoolean(
-                 CPLGetXMLValue(psLTree, 
-                                "GeometryField.useSpatialSubquery",
-                                "TRUE"));
-
-         iGeomXField = GetSrcLayerDefn()->GetFieldIndex(
-             CPLGetXMLValue( psLTree, "GeometryField.x", "missing" ) );
-         iGeomYField = GetSrcLayerDefn()->GetFieldIndex(
-             CPLGetXMLValue( psLTree, "GeometryField.y", "missing" ) );
-         iGeomZField = GetSrcLayerDefn()->GetFieldIndex(
-             CPLGetXMLValue( psLTree, "GeometryField.z", "missing" ) );
-
-         if( iGeomXField == -1 || iGeomYField == -1 )
-         {
-             CPLError( CE_Failure, CPLE_AppDefined, 
-                       "Unable to identify source X or Y field for PointFromColumns encoding." );
-             goto error;
-         }
-     }
-     else
-     {
-         CPLError( CE_Failure, CPLE_AppDefined, 
-                   "encoding=\"%s\" not recognised.", pszEncoding );
-         goto error;
-     }
+        if( !bFoundGeometryField )
+        {
+            /* If no GeometryField is found but several source geometry fields */
+            /* exist, use them */
+            if( GetSrcLayerDefn()->GetGeomFieldCount() > 1 )
+            {
+                delete apoGeomFieldProps[0];
+                apoGeomFieldProps.resize(0);
+                for( int iGeomField = 0;
+                        iGeomField < GetSrcLayerDefn()->GetGeomFieldCount();
+                        iGeomField++ )
+                {
+                    OGRVRTGeomFieldProps* poProps;
+                    poProps = new OGRVRTGeomFieldProps();
+                    apoGeomFieldProps.push_back(poProps);
+                    OGRGeomFieldDefn* poFDefn =
+                        GetSrcLayerDefn()->GetGeomFieldDefn(iGeomField);
+                    poProps->osName = poFDefn->GetNameRef();
+                    poProps->eGeomType = poFDefn->GetType();
+                    if( poFDefn->GetSpatialRef() != NULL )
+                    poProps->poSRS = poFDefn->GetSpatialRef()->Clone();
+                    poProps->iGeomField = iGeomField;
+                }
+            }
 
-     if( eGeometryStyle == VGS_WKT
-         || eGeometryStyle == VGS_WKB
-         || eGeometryStyle == VGS_Shape )
-     {
-         const char *pszFieldName = 
-             CPLGetXMLValue( psLTree, "GeometryField.field", "missing" );
+            /* Otherwise use the top-level elements such as SrcRegion */
+            else
+            {
+            if( !ParseGeometryField(NULL, psLTree, apoGeomFieldProps[0] ) )
+                    goto error;
+            }
+        }
+        else
+        {
+            /* Second pass: fill the OGRVRTGeomFieldProps objects from the */
+            /* GeometryField definitions */
+        int iGeomField = 0;
+        for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
+        {
+            if( psChild->eType == CXT_Element &&
+                EQUAL(psChild->pszValue,"GeometryField") )
+            {
+                if( !ParseGeometryField(psChild, psLTree,
+                                        apoGeomFieldProps[iGeomField] ) )
+                    goto error;
+                iGeomField ++;
+            }
+        }
+        }
 
-         iGeomField = GetSrcLayerDefn()->GetFieldIndex(pszFieldName);
+        /* Instanciate real geometry fields from VRT properties */
+        poFeatureDefn->SetGeomType(wkbNone);
+        for( size_t i = 0; i < apoGeomFieldProps.size(); i ++ )
+        {
+            OGRGeomFieldDefn oFieldDefn( apoGeomFieldProps[i]->osName,
+                                        apoGeomFieldProps[i]->eGeomType );
+            oFieldDefn.SetSpatialRef( apoGeomFieldProps[i]->poSRS );
+            poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
+        }
 
-         if( iGeomField == -1 )
-         {
-             CPLError( CE_Failure, CPLE_AppDefined, 
-                       "Unable to identify source field '%s' for geometry.",
-                       pszFieldName );
-             goto error;
-         }
-     }
+        poFeatureDefn->SetGeomType( apoGeomFieldProps[0]->eGeomType );
+    }
+    else
+    {
+        poFeatureDefn->SetGeomType(wkbNone);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out what should be used as an FID.                       */
@@ -664,52 +961,33 @@ try_again:
 /* -------------------------------------------------------------------- */
      if( poFeatureDefn->GetFieldCount() == 0 )
      {
-         int bReportSrcColumn =
-             CSLTestBoolean(CPLGetXMLValue( psLTree, "GeometryField.reportSrcColumn", "YES" ));
-
          int iSrcField;
-         int iDstField;
          int nSrcFieldCount = GetSrcLayerDefn()->GetFieldCount();
-         int nDstFieldCount = nSrcFieldCount;
-         if (bReportSrcColumn == FALSE)
-         {
-             if (iGeomXField != -1) nDstFieldCount --;
-             if (iGeomYField != -1) nDstFieldCount --;
-             if (iGeomZField != -1) nDstFieldCount --;
-             if (iGeomField != -1) nDstFieldCount --;
-         }
-         
-         for( iSrcField = 0, iDstField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
+
+         for( iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
          {
-             if (bReportSrcColumn == FALSE &&
-                 (iSrcField == iGeomXField || iSrcField == iGeomYField ||
-                  iSrcField == iGeomZField || iSrcField == iGeomField))
+             int bSkip = FALSE;
+             for( size_t iGF = 0; iGF < apoGeomFieldProps.size(); iGF++ )
+             {
+                if( apoGeomFieldProps[iGF]->bReportSrcColumn == FALSE &&
+                    (iSrcField == apoGeomFieldProps[iGF]->iGeomXField ||
+                     iSrcField == apoGeomFieldProps[iGF]->iGeomYField ||
+                     iSrcField == apoGeomFieldProps[iGF]->iGeomZField ||
+                     iSrcField == apoGeomFieldProps[iGF]->iGeomField) )
+                {
+                    bSkip = TRUE;
+                    break;
+                }
+             }
+             if( bSkip )
                  continue;
-             
+
              poFeatureDefn->AddFieldDefn( GetSrcLayerDefn()->GetFieldDefn( iSrcField ) );
              anSrcField.push_back( iSrcField );
              abDirectCopy.push_back( TRUE );
-             iDstField++;
          }
-         bAttrFilterPassThrough = TRUE;
-     }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have a SrcRegion?                                         */
-/* -------------------------------------------------------------------- */
-     pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
-     if( pszSrcRegion != NULL )
-     {
-        OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poSrcRegion );
-        if( poSrcRegion == NULL || wkbFlatten(poSrcRegion->getGeometryType()) != wkbPolygon)
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                        "Ignoring SrcRegion. It must be a valid WKT polygon");
-            delete poSrcRegion;
-            poSrcRegion = NULL;
-        }
 
-        bSrcClip = CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcRegion.clip", "FALSE" ));
+         bAttrFilterPassThrough = TRUE;
      }
 
 /* -------------------------------------------------------------------- */
@@ -717,15 +995,37 @@ try_again:
 /*      If so, use it directly, and save the translation of features.   */
 /* -------------------------------------------------------------------- */
      if (poSrcFeatureDefn != NULL && iFIDField == -1 && iStyleField == -1 &&
-         eGeometryStyle == VGS_Direct &&
          poSrcFeatureDefn->IsSame(poFeatureDefn))
      {
-        CPLDebug("VRT", "Source feature definition is identical to VRT feature definition. Use optimized path");
-        poFeatureDefn->Release();
-        poFeatureDefn = poSrcFeatureDefn;
-        poFeatureDefn->Reference();
+        int bSame = TRUE;
+        for(size_t i = 0; i < apoGeomFieldProps.size(); i++ )
+        {
+            if( apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct ||
+                apoGeomFieldProps[i]->iGeomField != (int)i )
+            {
+                bSame = FALSE;
+                break;
+            }
+        }
+        if( bSame )
+        {
+            CPLDebug("VRT", "Source feature definition is identical to VRT feature definition. Use optimized path");
+            poFeatureDefn->Release();
+            poFeatureDefn = poSrcFeatureDefn;
+            poFeatureDefn->Reference();
+            for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+            {
+                if( apoGeomFieldProps[i]->poSRS != NULL )
+                    apoGeomFieldProps[i]->poSRS->Release();
+                apoGeomFieldProps[i]->poSRS = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
+                if( apoGeomFieldProps[i]->poSRS != NULL )
+                    apoGeomFieldProps[i]->poSRS->Reference();
+            }
+        }
      }
 
+     CPLAssert( poFeatureDefn->GetGeomFieldCount() == (int)apoGeomFieldProps.size() );
+
 /* -------------------------------------------------------------------- */
 /*      Allow vrt to override whether attribute filters should be       */
 /*      passed through.                                                 */
@@ -741,9 +1041,9 @@ try_again:
      return TRUE;
 
 error:
+    bError = TRUE;
     CPLFree( pszSrcDSName );
-    if( poFeatureDefn )
-        poFeatureDefn->Release();
+    poFeatureDefn->Release();
     poFeatureDefn = new OGRFeatureDefn( osName );
     poFeatureDefn->Reference();
     return FALSE;
@@ -772,66 +1072,110 @@ int OGRVRTLayer::ResetSourceReading()
 /*      Do we want to let source layer do spatial restriction?          */
 /* -------------------------------------------------------------------- */
     char *pszFilter = NULL;
-    if( (m_poFilterGeom || poSrcRegion) && bUseSpatialSubquery &&
-         eGeometryStyle == VGS_PointFromColumns )
+    for(size_t i=0; i < apoGeomFieldProps.size(); i++ )
     {
-        const char *pszXField, *pszYField;
-
-        pszXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetNameRef();
-        pszYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetNameRef();
-        if (bUseSpatialSubquery)
+        if( (m_poFilterGeom || apoGeomFieldProps[i]->poSrcRegion) &&
+            apoGeomFieldProps[i]->bUseSpatialSubquery &&
+            apoGeomFieldProps[i]->eGeometryStyle == VGS_PointFromColumns )
         {
-            OGRFieldType xType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetType();
-            OGRFieldType yType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetType();
-            if (!((xType == OFTReal || xType == OFTInteger) && (yType == OFTReal || yType == OFTInteger)))
+            const char *pszXField, *pszYField;
+            OGRFieldDefn* poXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(apoGeomFieldProps[i]->iGeomXField);
+            OGRFieldDefn* poYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(apoGeomFieldProps[i]->iGeomYField);
+
+            pszXField = poXField->GetNameRef();
+            pszYField = poYField->GetNameRef();
+            if (apoGeomFieldProps[i]->bUseSpatialSubquery)
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
-                        "so the spatial filter cannot be turned into an attribute filter on them",
-                         pszXField, pszYField);
-                bUseSpatialSubquery = FALSE;
+                OGRFieldType xType = poXField->GetType();
+                OGRFieldType yType = poYField->GetType();
+                if (!((xType == OFTReal || xType == OFTInteger) && (yType == OFTReal || yType == OFTInteger)))
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
+                            "so the spatial filter cannot be turned into an attribute filter on them",
+                            pszXField, pszYField);
+                    apoGeomFieldProps[i]->bUseSpatialSubquery = FALSE;
+                }
             }
-        }
-        if (bUseSpatialSubquery)
-        {
-            OGREnvelope sEnvelope;
-
-            pszFilter = (char *) 
-                CPLMalloc(2*strlen(pszXField)+2*strlen(pszYField) + 100);
-
-            if (poSrcRegion != NULL)
+            if (apoGeomFieldProps[i]->bUseSpatialSubquery)
             {
-                if (m_poFilterGeom == NULL)
-                    poSrcRegion->getEnvelope( &sEnvelope );
-                else
+                OGREnvelope sEnvelope;
+                CPLString osFilter;
+
+                if (apoGeomFieldProps[i]->poSrcRegion != NULL)
                 {
-                    OGRGeometry* poIntersection = poSrcRegion->Intersection(m_poFilterGeom);
-                    if (poIntersection)
-                    {
-                        poIntersection->getEnvelope( &sEnvelope );
-                        delete poIntersection;
-                    }
+                    if (m_poFilterGeom == NULL)
+                        apoGeomFieldProps[i]->poSrcRegion->getEnvelope( &sEnvelope );
                     else
                     {
-                        sEnvelope.MinX = 0;
-                        sEnvelope.MaxX = 0;
-                        sEnvelope.MinY = 0;
-                        sEnvelope.MaxY = 0;
+                        OGRGeometry* poIntersection =
+                            apoGeomFieldProps[i]->poSrcRegion->Intersection(m_poFilterGeom);
+                        if (poIntersection && !poIntersection->IsEmpty())
+                        {
+                            poIntersection->getEnvelope( &sEnvelope );
+                        }
+                        else
+                        {
+                            sEnvelope.MinX = 0;
+                            sEnvelope.MaxX = 0;
+                            sEnvelope.MinY = 0;
+                            sEnvelope.MaxY = 0;
+                        }
+                        delete poIntersection;
                     }
                 }
+                else
+                    m_poFilterGeom->getEnvelope( &sEnvelope );
+
+                if( !CPLIsInf(sEnvelope.MinX) )
+                    osFilter += CPLSPrintf("%s > %.15g", pszXField, sEnvelope.MinX);
+                else if( sEnvelope.MinX > 0 )
+                    osFilter += "0 = 1";
+
+                if( !CPLIsInf(sEnvelope.MaxX) )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += CPLSPrintf("%s < %.15g", pszXField, sEnvelope.MaxX);
+                }
+                else if( sEnvelope.MaxX < 0 )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += "0 = 1";
+                }
+
+                if( !CPLIsInf(sEnvelope.MinY) )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += CPLSPrintf("%s > %.15g", pszYField, sEnvelope.MinY);
+                }
+                else if( sEnvelope.MinY > 0 )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += "0 = 1";
+                }
+
+                if( !CPLIsInf(sEnvelope.MaxY) )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += CPLSPrintf("%s < %.15g", pszYField, sEnvelope.MaxY);
+                }
+                else if( sEnvelope.MaxY < 0 )
+                {
+                    if( osFilter.size() ) osFilter += " AND ";
+                    osFilter += "0 = 1";
+                }
+
+                if( osFilter.size() != 0 )
+                {
+                    pszFilter = CPLStrdup(osFilter);
+                    char* pszComma;
+                    while((pszComma = strchr(pszFilter, ',')) != NULL)
+                        *pszComma = '.';
+                }
             }
-            else
-                m_poFilterGeom->getEnvelope( &sEnvelope );
-
-            sprintf( pszFilter, 
-                    "%s > %.15g AND %s < %.15g AND %s > %.15g AND %s < %.15g", 
-                    pszXField, sEnvelope.MinX,
-                    pszXField, sEnvelope.MaxX,
-                    pszYField, sEnvelope.MinY,
-                    pszYField, sEnvelope.MaxY );
-            char* pszComma;
-            while((pszComma = strchr(pszFilter, ',')) != NULL)
-                *pszComma = '.';
+
+            /* Just do it on one geometry field. To complicated otherwise ! */
+            break;
         }
     }
 
@@ -864,27 +1208,53 @@ int OGRVRTLayer::ResetSourceReading()
 /*      Clear spatial filter (to be safe) for non direct geometries     */
 /*      and reset reading.                                              */
 /* -------------------------------------------------------------------- */
-    if (eGeometryStyle == VGS_Direct)
+    if (m_iGeomFieldFilter < (int)apoGeomFieldProps.size() &&
+        apoGeomFieldProps[m_iGeomFieldFilter]->eGeometryStyle == VGS_Direct &&
+        apoGeomFieldProps[m_iGeomFieldFilter]->iGeomField >= 0 )
     {
+        OGRGeometry* poSpatialGeom = NULL;
+        OGRGeometry* poSrcRegion = apoGeomFieldProps[m_iGeomFieldFilter]->poSrcRegion;
+        int bToDelete = FALSE;
+
         if (poSrcRegion == NULL)
-            poSrcLayer->SetSpatialFilter( m_poFilterGeom );
+            poSpatialGeom = m_poFilterGeom;
         else if (m_poFilterGeom == NULL)
-            poSrcLayer->SetSpatialFilter( poSrcRegion );
+            poSpatialGeom = poSrcRegion;
         else
         {
             if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Spatial filter should be polygon when a SrcRegion is defined. Ignoring it");
-                poSrcLayer->SetSpatialFilter( poSrcRegion );
+                poSpatialGeom = poSrcRegion;
             }
             else
             {
-                OGRGeometry* poIntersection = m_poFilterGeom->Intersection(poSrcRegion);
-                poSrcLayer->SetSpatialFilter( poIntersection );
-                delete poIntersection;
+                int bDoIntersection = TRUE;
+                if( m_bFilterIsEnvelope )
+                {
+                    OGREnvelope sEnvelope;
+                    m_poFilterGeom->getEnvelope(&sEnvelope);
+                    if( CPLIsInf(sEnvelope.MinX) && CPLIsInf(sEnvelope.MinY) &&
+                        CPLIsInf(sEnvelope.MaxX) && CPLIsInf(sEnvelope.MaxY) &&
+                        sEnvelope.MinX < 0 && sEnvelope.MinY < 0 &&
+                        sEnvelope.MaxY > 0 && sEnvelope.MaxY > 0 )
+                    {
+                        poSpatialGeom = poSrcRegion;
+                        bDoIntersection = FALSE;
+                    }
+                }
+                if( bDoIntersection )
+                {
+                    poSpatialGeom = m_poFilterGeom->Intersection(poSrcRegion);
+                    bToDelete = TRUE;
+                }
             }
         }
+        poSrcLayer->SetSpatialFilter( apoGeomFieldProps[m_iGeomFieldFilter]->iGeomField,
+                                      poSpatialGeom );
+        if( bToDelete )
+            delete poSpatialGeom;
     }
     else
         poSrcLayer->SetSpatialFilter( NULL );
@@ -903,6 +1273,8 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
 {
     if (!bHasFullInitialized) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
+    if( bError )
+        return NULL;
 
     if( bNeedReset )
     {
@@ -932,8 +1304,10 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
         if( poFeature == NULL )
             return NULL;
 
-        if( (eGeometryStyle == VGS_Direct || m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        if( ((m_iGeomFieldFilter < (int)apoGeomFieldProps.size() &&
+              apoGeomFieldProps[m_iGeomFieldFilter]->eGeometryStyle == VGS_Direct)
+            || m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ))
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
             return poFeature;
@@ -948,15 +1322,21 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
 
 void OGRVRTLayer::ClipAndAssignSRS(OGRFeature* poFeature)
 {
-    /* Clip the geometry to the SrcRegion if asked */
-    if (poSrcRegion != NULL && bSrcClip && poFeature->GetGeometryRef() != NULL)
+    for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        OGRGeometry* poClippedGeom = poFeature->GetGeometryRef()->Intersection(poSrcRegion);
-        poFeature->SetGeometryDirectly(poClippedGeom);
-    }
+        /* Clip the geometry to the SrcRegion if asked */
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if (apoGeomFieldProps[i]->poSrcRegion != NULL &&
+            apoGeomFieldProps[i]->bSrcClip &&
+            poGeom != NULL)
+        {
+            poGeom = poGeom->Intersection(apoGeomFieldProps[i]->poSrcRegion);
+            poFeature->SetGeomFieldDirectly(i, poGeom);
+        }
 
-    if (poFeature->GetGeometryRef() != NULL && poSRS != NULL)
-        poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
+        if (poGeom != NULL && apoGeomFieldProps[i]->poSRS != NULL)
+            poGeom->assignSpatialReference(apoGeomFieldProps[i]->poSRS);
+    }
 }
 
 /************************************************************************/
@@ -996,124 +1376,133 @@ retry:
             poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
     }
     
-/* -------------------------------------------------------------------- */
-/*      Handle the geometry.  Eventually there will be several more     */
-/*      supported options.                                              */
-/* -------------------------------------------------------------------- */
-    if( eGeometryStyle == VGS_None || GetLayerDefn()->IsGeometryIgnored() )
+    for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        /* do nothing */
-    }
-    else if( eGeometryStyle == VGS_WKT && iGeomField != -1 )
-    {
-        char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
-        
-        if( pszWKT != NULL )
+        OGRVRTGeometryStyle eGeometryStyle = apoGeomFieldProps[i]->eGeometryStyle;
+        int iGeomField = apoGeomFieldProps[i]->iGeomField;
+    /* -------------------------------------------------------------------- */
+    /*      Handle the geometry.  Eventually there will be several more     */
+    /*      supported options.                                              */
+    /* -------------------------------------------------------------------- */
+        if( eGeometryStyle == VGS_None ||
+            GetLayerDefn()->GetGeomFieldDefn(i)->IsIgnored() )
         {
-            OGRGeometry *poGeom = NULL;
-
-            OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
-            if( poGeom == NULL )
-                CPLDebug( "OGR_VRT", "Did not get geometry from %s",
-                          pszWKT );
-
-            poDstFeat->SetGeometryDirectly( poGeom );
+            /* do nothing */
         }
-    }
-    else if( eGeometryStyle == VGS_WKB && iGeomField != -1 )
-    {
-        int nBytes;
-        GByte *pabyWKB;
-        int bNeedFree = FALSE;
-
-        if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
+        else if( eGeometryStyle == VGS_WKT && iGeomField != -1 )
         {
-            pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
+            char *pszWKT = (char *) poSrcFeat->GetFieldAsString(
+                iGeomField );
+            
+            if( pszWKT != NULL )
+            {
+                OGRGeometry *poGeom = NULL;
+
+                OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
+                if( poGeom == NULL )
+                    CPLDebug( "OGR_VRT", "Did not get geometry from %s",
+                            pszWKT );
+
+                poDstFeat->SetGeomFieldDirectly( i, poGeom );
+            }
         }
-        else
+        else if( eGeometryStyle == VGS_WKB && iGeomField != -1 )
         {
-            const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
+            int nBytes;
+            GByte *pabyWKB;
+            int bNeedFree = FALSE;
 
-            pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
-            bNeedFree = TRUE;
+            if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
+            {
+                pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
+            }
+            else
+            {
+                const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
+
+                pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
+                bNeedFree = TRUE;
+            }
+            
+            if( pabyWKB != NULL )
+            {
+                OGRGeometry *poGeom = NULL;
+
+                if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
+                                                    nBytes ) == OGRERR_NONE )
+                    poDstFeat->SetGeomFieldDirectly( i, poGeom );
+            }
+
+            if( bNeedFree )
+                CPLFree( pabyWKB );
         }
-        
-        if( pabyWKB != NULL )
+        else if( eGeometryStyle == VGS_Shape && iGeomField != -1 )
         {
-            OGRGeometry *poGeom = NULL;
+            int nBytes;
+            GByte *pabyWKB;
+            int bNeedFree = FALSE;
 
-            if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
-                                                   nBytes ) == OGRERR_NONE )
-                poDstFeat->SetGeometryDirectly( poGeom );
-        }
+            if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
+            {
+                pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
+            }
+            else
+            {
+                const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
 
-        if( bNeedFree )
-            CPLFree( pabyWKB );
-    }
-    else if( eGeometryStyle == VGS_Shape && iGeomField != -1 )
-    {
-        int nBytes;
-        GByte *pabyWKB;
-        int bNeedFree = FALSE;
+                pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
+                bNeedFree = TRUE;
+            }
+            
+            if( pabyWKB != NULL )
+            {
+                OGRGeometry *poGeom = NULL;
 
-        if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
-        {
-            pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
+                if( OGRCreateFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
+                    poDstFeat->SetGeomFieldDirectly( i, poGeom );
+            }
+
+            if( bNeedFree )
+                CPLFree( pabyWKB );
         }
-        else
+        else if( eGeometryStyle == VGS_Direct && iGeomField != -1 )
         {
-            const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
-
-            pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
-            bNeedFree = TRUE;
+            poDstFeat->SetGeomField( i, poSrcFeat->GetGeomFieldRef(iGeomField) );
         }
-        
-        if( pabyWKB != NULL )
+        else if( eGeometryStyle == VGS_PointFromColumns )
         {
-            OGRGeometry *poGeom = NULL;
-
-            if( OGRCreateFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
-                poDstFeat->SetGeometryDirectly( poGeom );
+            if( apoGeomFieldProps[i]->iGeomZField != -1 )
+                poDstFeat->SetGeomFieldDirectly( i,
+                    new OGRPoint( poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomXField ),
+                                poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomYField ),
+                                poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomZField ) ) );
+            else
+                poDstFeat->SetGeomFieldDirectly( i,
+                    new OGRPoint( poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomXField ),
+                                poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomYField ) ) );
         }
-
-        if( bNeedFree )
-            CPLFree( pabyWKB );
-    }
-    else if( eGeometryStyle == VGS_Direct )
-    {
-        poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
-    }
-    else if( eGeometryStyle == VGS_PointFromColumns )
-    {
-        if( iGeomZField != -1 )
-            poDstFeat->SetGeometryDirectly( 
-                new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
-                              poSrcFeat->GetFieldAsDouble( iGeomYField ),
-                              poSrcFeat->GetFieldAsDouble( iGeomZField ) ) );
         else
-            poDstFeat->SetGeometryDirectly( 
-                new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
-                              poSrcFeat->GetFieldAsDouble( iGeomYField ) ) );
-    }
-    else
-        /* add other options here. */;
+            /* add other options here. */;
 
-    /* In the non direct case, we need to check that the geometry intersects the source */
-    /* region before an optionnal clipping */
-    if( bUseSrcRegion && eGeometryStyle != VGS_Direct && poSrcRegion != NULL )
-    {
-        OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
-        if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
+        /* In the non direct case, we need to check that the geometry intersects the source */
+        /* region before an optionnal clipping */
+        if( bUseSrcRegion &&
+            apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct &&
+            apoGeomFieldProps[i]->poSrcRegion != NULL )
         {
-            delete poSrcFeat;
-            delete poDstFeat;
+            OGRGeometry* poGeom = poDstFeat->GetGeomFieldRef(i);
+            if (poGeom != NULL && !poGeom->Intersects(apoGeomFieldProps[i]->poSrcRegion))
+            {
+                delete poSrcFeat;
+                delete poDstFeat;
 
-            /* Fetch next source feature and retry translating it */
-            poSrcFeat = poSrcLayer->GetNextFeature();
-            if (poSrcFeat == NULL)
-                return NULL;
+                /* Fetch next source feature and retry translating it */
+                poSrcFeat = poSrcLayer->GetNextFeature();
+                if (poSrcFeat == NULL)
+                    return NULL;
 
-            goto retry;
+                goto retry;
+            }
         }
     }
 
@@ -1266,80 +1655,90 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 /*      Handle the geometry.  Eventually there will be several more     */
 /*      supported options.                                              */
 /* -------------------------------------------------------------------- */
-    if( eGeometryStyle == VGS_None )
-    {
-        /* do nothing */
-    }
-    else if( eGeometryStyle == VGS_WKT )
+    for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
-        if (poGeom != NULL)
+        OGRVRTGeometryStyle eGeometryStyle = apoGeomFieldProps[i]->eGeometryStyle;
+        int iGeomField = apoGeomFieldProps[i]->iGeomField;
+
+        if( eGeometryStyle == VGS_None )
         {
-            char* pszWKT = NULL;
-            if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
-            {
-                poSrcFeat->SetField(iGeomField, pszWKT);
-            }
-            CPLFree(pszWKT);
+            /* do nothing */
         }
-    }
-    else if( eGeometryStyle == VGS_WKB )
-    {
-        OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
-        if (poGeom != NULL)
+        else if( eGeometryStyle == VGS_WKT && iGeomField >= 0 )
         {
-            int nSize = poGeom->WkbSize();
-            GByte* pabyData = (GByte*)CPLMalloc(nSize);
-            if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
+            OGRGeometry* poGeom = poVRTFeature->GetGeomFieldRef(i);
+            if (poGeom != NULL)
             {
-                if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
-                {
-                    poSrcFeat->SetField(iGeomField, nSize, pabyData);
-                }
-                else
+                char* pszWKT = NULL;
+                if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
                 {
-                    char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
-                    poSrcFeat->SetField(iGeomField, pszHexWKB);
-                    CPLFree(pszHexWKB);
+                    poSrcFeat->SetField(iGeomField, pszWKT);
                 }
+                CPLFree(pszWKT);
             }
-            CPLFree(pabyData);
         }
-    }
-    else if( eGeometryStyle == VGS_Shape )
-    {
-        CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
-    }
-    else if( eGeometryStyle == VGS_Direct )
-    {
-        poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
-    }
-    else if( eGeometryStyle == VGS_PointFromColumns )
-    {
-        OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
-        if (poGeom != NULL)
+        else if( eGeometryStyle == VGS_WKB && iGeomField >= 0)
         {
-            if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
+            OGRGeometry* poGeom = poVRTFeature->GetGeomFieldRef(i);
+            if (poGeom != NULL)
             {
-                CPLError(CE_Warning, CPLE_NotSupported,
-                         "Cannot set a non ponctual geometry for PointFromColumns geometry");
+                int nSize = poGeom->WkbSize();
+                GByte* pabyData = (GByte*)CPLMalloc(nSize);
+                if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
+                {
+                    if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
+                    {
+                        poSrcFeat->SetField(iGeomField, nSize, pabyData);
+                    }
+                    else
+                    {
+                        char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
+                        poSrcFeat->SetField(iGeomField, pszHexWKB);
+                        CPLFree(pszHexWKB);
+                    }
+                }
+                CPLFree(pabyData);
             }
-            else
+        }
+        else if( eGeometryStyle == VGS_Shape )
+        {
+            CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
+        }
+        else if( eGeometryStyle == VGS_Direct && iGeomField >= 0 )
+        {
+            poSrcFeat->SetGeomField( iGeomField, poVRTFeature->GetGeomFieldRef(i) );
+        }
+        else if( eGeometryStyle == VGS_PointFromColumns )
+        {
+            OGRGeometry* poGeom = poVRTFeature->GetGeomFieldRef(i);
+            if (poGeom != NULL)
             {
-                poSrcFeat->SetField( iGeomXField, ((OGRPoint*)poGeom)->getX() );
-                poSrcFeat->SetField( iGeomYField, ((OGRPoint*)poGeom)->getY() );
-                if( iGeomZField != -1 )
+                if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
                 {
-                    poSrcFeat->SetField( iGeomZField, ((OGRPoint*)poGeom)->getZ() );
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                            "Cannot set a non ponctual geometry for PointFromColumns geometry");
+                }
+                else
+                {
+                    poSrcFeat->SetField( apoGeomFieldProps[i]->iGeomXField,
+                                         ((OGRPoint*)poGeom)->getX() );
+                    poSrcFeat->SetField( apoGeomFieldProps[i]->iGeomYField,
+                                         ((OGRPoint*)poGeom)->getY() );
+                    if( apoGeomFieldProps[i]->iGeomZField != -1 )
+                    {
+                        poSrcFeat->SetField( apoGeomFieldProps[i]->iGeomZField,
+                                             ((OGRPoint*)poGeom)->getZ() );
+                    }
                 }
             }
         }
-    }
-    else
-        /* add other options here. */;
+        else
+            /* add other options here. */;
 
-    if (poSrcFeat->GetGeometryRef() != NULL && poSRS != NULL)
-        poSrcFeat->GetGeometryRef()->assignSpatialReference(poSRS);
+        OGRGeometry* poGeom = poSrcFeat->GetGeomFieldRef(i);
+        if ( poGeom != NULL && apoGeomFieldProps[i]->poSRS != NULL )
+            poGeom->assignSpatialReference(apoGeomFieldProps[i]->poSRS);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Copy fields.                                                    */
@@ -1349,9 +1748,20 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 
     for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
     {
-        /* Do not set source geometry columns. Have been set just above */
-        if (anSrcField[iVRTField] == iGeomField || anSrcField[iVRTField] == iGeomXField ||
-            anSrcField[iVRTField] == iGeomYField || anSrcField[iVRTField] == iGeomZField)
+        int bSkip = FALSE;
+        for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+        {
+            /* Do not set source geometry columns. Have been set just above */
+            if (anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomField ||
+                anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomXField ||
+                anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomYField ||
+                anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomZField)
+            {
+                bSkip = TRUE;
+                break;
+            }
+        }
+        if( bSkip )
             continue;
 
         OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
@@ -1515,7 +1925,8 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
         return TRUE;
 
     if ( EQUAL(pszCap,OLCFastGetExtent) &&
-         sStaticEnvelope.IsInit() )
+         apoGeomFieldProps.size() == 1 &&
+         apoGeomFieldProps[0]->sStaticEnvelope.IsInit() )
         return TRUE;
 
     if (!bHasFullInitialized) FullInitialize();
@@ -1523,19 +1934,39 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
 
     if ( EQUAL(pszCap,OLCFastFeatureCount) ||
          EQUAL(pszCap,OLCFastSetNextByIndex) )
-        return (eGeometryStyle == VGS_Direct ||
-               (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
-               m_poAttrQuery == NULL &&
-               poSrcLayer->TestCapability(pszCap);
+    {
+        if( m_poAttrQuery == NULL )
+        {
+            int bForward = TRUE;
+            for( size_t i=0; i<apoGeomFieldProps.size();i++ )
+            {
+                if( !(apoGeomFieldProps[i]->eGeometryStyle == VGS_Direct ||
+                    (apoGeomFieldProps[i]->poSrcRegion == NULL && m_poFilterGeom == NULL)) )
+                {
+                    bForward = FALSE;
+                    break;
+                }
+            }
+            if( bForward )
+            {
+                return poSrcLayer->TestCapability(pszCap);
+            }
+        }
+        return FALSE;
+    }
 
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return eGeometryStyle == VGS_Direct && m_poAttrQuery == NULL &&
+        return apoGeomFieldProps.size() == 1 &&
+               apoGeomFieldProps[0]->eGeometryStyle == VGS_Direct &&
+               m_poAttrQuery == NULL &&
                poSrcLayer->TestCapability(pszCap);
 
     else if ( EQUAL(pszCap,OLCFastGetExtent) )
-        return eGeometryStyle == VGS_Direct &&
+        return apoGeomFieldProps.size() == 1 &&
+               apoGeomFieldProps[0]->eGeometryStyle == VGS_Direct &&
                m_poAttrQuery == NULL &&
-               (poSrcRegion == NULL || bSrcClip) &&
+               (apoGeomFieldProps[0]->poSrcRegion == NULL ||
+                apoGeomFieldProps[0]->bSrcClip) &&
                poSrcLayer->TestCapability(pszCap);
 
     else if( EQUAL(pszCap,OLCRandomRead) )
@@ -1565,13 +1996,18 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
 OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
 
 {
-    if (CPLGetXMLValue( psLTree, "LayerSRS", NULL ) != NULL)
-        return poSRS;
+    if ((CPLGetXMLValue( psLTree, "LayerSRS", NULL ) != NULL ||
+         CPLGetXMLValue( psLTree, "GeometryField.SRS", NULL ) != NULL) &&
+        apoGeomFieldProps.size() >= 1)
+        return apoGeomFieldProps[0]->poSRS;
 
     if (!bHasFullInitialized) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
 
-    return poSRS;
+    if( apoGeomFieldProps.size() >= 1 )
+        return apoGeomFieldProps[0]->poSRS;
+    else
+        return NULL;
 }
 
 /************************************************************************/
@@ -1580,34 +2016,45 @@ OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
 
 OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 {
-    if( sStaticEnvelope.IsInit() )
+    return GetExtent( 0, psExtent, bForce );
+}
+
+OGRErr OGRVRTLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+        return OGRERR_FAILURE;
+
+    if( apoGeomFieldProps[iGeomField]->sStaticEnvelope.IsInit() )
     {
-        memcpy(psExtent, &sStaticEnvelope, sizeof(OGREnvelope));
+        memcpy(psExtent,&apoGeomFieldProps[iGeomField]->sStaticEnvelope,
+               sizeof(OGREnvelope));
         return OGRERR_NONE;
     }
 
     if (!bHasFullInitialized) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
-    if ( eGeometryStyle == VGS_Direct &&
+    if ( apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct &&
          m_poAttrQuery == NULL &&
-         (poSrcRegion == NULL || bSrcClip) )
+         (apoGeomFieldProps[iGeomField]->poSrcRegion == NULL ||
+          apoGeomFieldProps[iGeomField]->bSrcClip) )
     {
         if( bNeedReset )
             ResetSourceReading();
 
-        OGRErr eErr = poSrcLayer->GetExtent(psExtent, bForce);
-        if( eErr != OGRERR_NONE || poSrcRegion == NULL )
+        OGRErr eErr = poSrcLayer->GetExtent(
+                apoGeomFieldProps[iGeomField]->iGeomField, psExtent, bForce);
+        if( eErr != OGRERR_NONE || apoGeomFieldProps[iGeomField]->poSrcRegion == NULL )
             return eErr;
 
         OGREnvelope sSrcRegionEnvelope;
-        poSrcRegion->getEnvelope(&sSrcRegionEnvelope);
+        apoGeomFieldProps[iGeomField]->poSrcRegion->getEnvelope(&sSrcRegionEnvelope);
 
         psExtent->Intersect(sSrcRegionEnvelope);
         return eErr;
     }
 
-    return OGRLayer::GetExtent(psExtent, bForce);
+    return OGRLayer::GetExtentInternal(iGeomField, psExtent, bForce);
 }
 
 /************************************************************************/
@@ -1626,17 +2073,15 @@ int OGRVRTLayer::GetFeatureCount( int bForce )
     if (!bHasFullInitialized) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return 0;
 
-    if ((eGeometryStyle == VGS_Direct ||
-         (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
-         m_poAttrQuery == NULL )
+    if (TestCapability(OLCFastFeatureCount))
     {
         if( bNeedReset )
             ResetSourceReading();
 
         return poSrcLayer->GetFeatureCount( bForce );
     }
-    else
-        return OGRLayer::GetFeatureCount( bForce );
+
+    return OGRLayer::GetFeatureCount( bForce );
 }
 
 
@@ -1646,12 +2091,30 @@ int OGRVRTLayer::GetFeatureCount( int bForce )
 
 void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 {
+    SetSpatialFilter(0, poGeomIn);
+}
+
+void OGRVRTLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+    {
+        if( poGeomIn != NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+
     if (!bHasFullInitialized) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return;
 
-    if (eGeometryStyle == VGS_Direct)
+    if( apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct)
         bNeedReset = TRUE;
-    OGRLayer::SetSpatialFilter(poGeomIn);
+
+    m_iGeomFieldFilter = iGeomField;
+    if( InstallFilter( poGeomIn ) )
+        ResetReading();
 }
 
 /************************************************************************/
@@ -1683,8 +2146,13 @@ OGRFeatureDefn *OGRVRTLayer::GetLayerDefn()
 
 OGRwkbGeometryType OGRVRTLayer::GetGeomType()
 {
-    if (CPLGetXMLValue( psLTree, "GeometryType", NULL ) != NULL)
-        return eGeomType;
+    if( CPLGetXMLValue( psLTree, "GeometryType", NULL ) != NULL ||
+        CPLGetXMLValue( psLTree, "GeometryField.GeometryType", NULL ) != NULL )
+    {
+        if( apoGeomFieldProps.size() >= 1)
+            return apoGeomFieldProps[0]->eGeomType;
+        return wkbNone;
+    }
 
     return GetLayerDefn()->GetGeomType();
 }
@@ -1775,6 +2243,9 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
     const char** papszIter = papszFields;
     char** papszFieldsSrc = NULL;
     OGRFeatureDefn* poSrcFeatureDefn = poSrcLayer->GetLayerDefn();
+
+    /* Translate explicitely ignored fields of VRT layers to their equivalent */
+    /* source fields. */
     while ( papszIter != NULL && *papszIter != NULL )
     {
         const char* pszFieldName = *papszIter;
@@ -1795,10 +2266,27 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
                     papszFieldsSrc = CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
                 }
             }
+            else
+            {
+                iVRTField = GetLayerDefn()->GetGeomFieldIndex(pszFieldName);
+                if( iVRTField >= 0 &&
+                    apoGeomFieldProps[iVRTField]->eGeometryStyle == VGS_Direct )
+                {
+                    int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
+                    if( iSrcField >= 0 )
+                    {
+                        OGRGeomFieldDefn *poSrcDefn =
+                            poSrcFeatureDefn->GetGeomFieldDefn( iSrcField );
+                        papszFieldsSrc =
+                            CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
+                    }
+                }
+            }
         }
         papszIter++;
     }
 
+    /* Add source fields that are not referenced by VRT layer */
     int* panSrcFieldsUsed = (int*) CPLCalloc(sizeof(int), poSrcFeatureDefn->GetFieldCount());
     for(int iVRTField = 0; iVRTField < GetLayerDefn()->GetFieldCount(); iVRTField++)
     {
@@ -1806,6 +2294,35 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
         if (iSrcField >= 0)
             panSrcFieldsUsed[iSrcField] = TRUE;
     }
+    for(int iVRTField = 0;
+            iVRTField < GetLayerDefn()->GetGeomFieldCount(); iVRTField++)
+    {
+        OGRVRTGeometryStyle eGeometryStyle =
+            apoGeomFieldProps[iVRTField]->eGeometryStyle;
+        if( eGeometryStyle == VGS_PointFromColumns )
+        {
+            int iSrcField = apoGeomFieldProps[iVRTField]->iGeomXField;
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+            iSrcField = apoGeomFieldProps[iVRTField]->iGeomYField;
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+            iSrcField = apoGeomFieldProps[iVRTField]->iGeomZField;
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+        }
+        else if( eGeometryStyle == VGS_WKT || eGeometryStyle == VGS_WKB ||
+                 eGeometryStyle == VGS_Shape )
+        {
+            int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+        }
+    }
+    if( iStyleField >= 0 )
+        panSrcFieldsUsed[iStyleField] = TRUE;
+    if( iFIDField >= 0 )
+        panSrcFieldsUsed[iFIDField] = TRUE;
     for(int iSrcField = 0; iSrcField < poSrcFeatureDefn->GetFieldCount(); iSrcField ++)
     {
         if( !panSrcFieldsUsed[iSrcField] )
@@ -1816,6 +2333,31 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
     }
     CPLFree(panSrcFieldsUsed);
 
+    /* Add source geometry fields that are not referenced by VRT layer */
+    panSrcFieldsUsed = (int*) CPLCalloc(sizeof(int),
+                                        poSrcFeatureDefn->GetGeomFieldCount());
+    for(int iVRTField = 0;
+            iVRTField < GetLayerDefn()->GetGeomFieldCount(); iVRTField++)
+    {
+        if( apoGeomFieldProps[iVRTField]->eGeometryStyle == VGS_Direct )
+        {
+            int iSrcField = apoGeomFieldProps[iVRTField]->iGeomField;
+            if (iSrcField >= 0)
+                panSrcFieldsUsed[iSrcField] = TRUE;
+        }
+    }
+    for(int iSrcField = 0;
+            iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField ++)
+    {
+        if( !panSrcFieldsUsed[iSrcField] )
+        {
+            OGRGeomFieldDefn *poSrcDefn =
+                    poSrcFeatureDefn->GetGeomFieldDefn( iSrcField );
+            papszFieldsSrc = CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
+        }
+    }
+    CPLFree(panSrcFieldsUsed);
+
     eErr = poSrcLayer->SetIgnoredFields((const char**)papszFieldsSrc);
 
     CSLDestroy(papszFieldsSrc);
diff --git a/ogr/ogrsf_frmts/walk/GNUmakefile b/ogr/ogrsf_frmts/walk/GNUmakefile
new file mode 100644
index 0000000..418fdc0
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrwalkdriver.o ogrwalkdatasource.o ogrwalklayer.o ogrwalktablelayer.o ogrwalkselectlayer.o ogrwalktool.o
+
+CPPFLAGS	:=	-I.. -I../.. -I../generic -I../pgeo $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):  ogrwalk.h ../generic/ogrwarpedlayer.h ../generic/ogrunionlayer.h
diff --git a/ogr/ogrsf_frmts/walk/drv_walk.html b/ogr/ogrsf_frmts/walk/drv_walk.html
new file mode 100644
index 0000000..6dca633
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/drv_walk.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+
+<html>
+<head>
+
+  <title>Walk Spatial Data</title>
+</head>
+
+<body bgcolor="#FFFFFF">
+  <h1>Walk - Walk Spatial Data</h1>
+
+  <p>(OGR >= 1.11)</p>
+
+  <p>OGR optionally supports reading Walk spatial data via ODBC. Walk spatial data is a Microsoft Access database developed  by Walkinfo  Technologies mainly for land surveying, evaluation, planning, checking and data analysis in China.</p>
+
+  <p>Walk .mdb are accessed by passing the file name of
+  the .mdb file to be accessed as the data source name. On Windows,
+  no ODBC DSN is required. On Linux, there are problems with DSN-less
+  connection due to incomplete or buggy implementation of this feature 
+  in the <a href="http://mdbtools.sourceforge.net/" tppabs="http://mdbtools.sourceforge.net/">MDB Tools</a> package,
+  So, it is required to configure Data Source Name (DSN) if the MDB
+  Tools driver is used (check instructions below).</p>
+  
+  <p>OGR treats all feature tables as layers. Most geometry types
+  should be supported (arcs and circles are translated into line segments, while other curves are currently converted into straight lines). Coordinate system information should be properly
+  associated with layers. Currently no effort is made to preserve  styles and annotations.</p>
+  <p>Currently the OGR Walk driver does not take
+  advantage of spatial indexes for fast spatial queries.</p>
+
+<p>By default, SQL statements are handled by <a href="ogr_sql.html" tppabs="http://www.gdal.org/ogr/ogr_sql.html">OGR SQL</a> engine. SQL commands can also be passed directly to the ODBC database engine when SQL dialect is not "OGRSQL". In that case, the queries will deal with  tables (such as "XXXXFeatures", where XXXX is the   name of a layer) instead of layers.</p>
+
+  <h2>How to use Walk driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
+
+  <p>Refer to the similar section of the <a href="drv_pgeo.html" tppabs="http://www.gdal.org/ogr/drv_pgeo.html">PGeo</a> driver. The prefix to use
+  for this driver is Walk:</p>
+
+</body>
+</html>
+
diff --git a/ogr/ogrsf_frmts/walk/makefile.vc b/ogr/ogrsf_frmts/walk/makefile.vc
new file mode 100644
index 0000000..5efd830
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrwalkdriver.obj ogrwalkdatasource.obj ogrwalklayer.obj ogrwalktablelayer.obj ogrwalkselectlayer.obj ogrwalktool.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS = -I.. -I..\.. -I..\generic -I..\pgeo
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
+	-del *.exe
diff --git a/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
new file mode 100644
index 0000000..2d59465
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
@@ -0,0 +1,234 @@
+/******************************************************************************
+ * $Id: ogis_geometry_wkb_struct.h
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Definition of GeometryWkb Structs
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+/**************************************************************************/
+/* Basic Type definitions                                                 */
+/* unsigned char : 1 BYTE                                                 */
+/* GUInt32 : 32 bit unsigned integer (4 bytes)                            */
+/* double : double precision number (8 bytes)                             */
+/* Building Blocks : Point, LinearRing                                    */
+/**************************************************************************/
+
+#ifndef _OGIS_GEOMETRY_WKB_STRUCT_H
+#define _OGIS_GEOMETRY_WKB_STRUCT_H
+
+#define CPL_LSBPTRPOINT(p) \
+{                                                                 \
+    CPL_LSBPTR32(&p.x);                                           \
+    CPL_LSBPTR32(&p.y);                                           \
+    CPL_LSBPTR32(&p.z);                                           \
+}
+
+#ifdef CPL_MSB
+#define CPL_LSBPTRPOINTS(p,n) \
+{                                                                 \
+    GUInt32 count;                                                \
+    for(count=0; count<n; count++)                                \
+        CPL_LSBPTRPOINT(p[count]);                                \
+}
+#else
+#define CPL_LSBPTRPOINTS(p,n)
+#endif
+
+struct Point3D {
+    double x;
+    double y;
+    double z;
+};
+
+struct Point2D {
+    double x;
+    double y;
+};
+
+struct CurveSegment;
+struct LineString;
+
+typedef Point3D Point;       //3D by default
+typedef Point Vector;        //Space Vector    {dx, dy, dz}
+
+/**************************************************************************/
+/* Curves are continuous, connected and have a measurable length in terms */
+/* of the coordinate system. The curve segments are therefore connected   */
+/* to one another, with the end point of each segment being the start     */
+/* point of the next in the segment list.                                 */
+/* A curve is composed of one or more curve segments. Each curve segment  */
+/* may be defined using a different interpolation method than the other   */
+/* ones in the curve.                                                     */
+/* A LineString is a curve with linear interpolation between points. Each */
+/* consecutive pair of points defines a line segment.                     */
+/* Extention��LineString is composed of CurveSegment, but self-crossing   */
+/* is not allowed.                                                        */
+/**************************************************************************/
+
+enum wkLineType {
+    wkLineTypePoint        =0,   // Point
+    wkLineTypeStraight    =1,    // Straightline
+    wkLineTypeBezier    =2,      // Bezier
+    wkLineType3PArc        =3,   // 3-point Arc; Three points are defined
+    wkLineTypeRArc        =4,    // Radius Arc; Three points are defined
+    wkLineType5PEllipse    =5,   // 5-point Ellipse; from wkLineTypeRectArc
+    wkLineType3PCircle    =6,    // 3-point Circle;
+    wkLineTypeRCircle    =7,     // Radius Circle; 2 points
+    wkLineTypeRectCircle=8,      // Rectangular Circle; 2 points
+    wkLineTypeBCurve    =9,      // B Curve
+    wkLineTypeStrainCurve =10,   // Strain Curve
+};
+
+struct CurveSegment {
+    GUInt32 lineType;
+    GUInt32 numPoints;
+    Point *points;
+};
+
+struct LineString {
+    GUInt32 numSegments;
+    CurveSegment *segments;
+};
+
+typedef OGRwkbGeometryType wkbGeometryType;
+
+/**************************************************************************/
+/*    BYTE byteOrder;                                                     */
+/*    This enum should be used to head base structure, only as operation  */
+/*    system is no_windows. See struct WKBPoint                           */
+/**************************************************************************/
+typedef OGRwkbByteOrder wkbByteOrder;
+
+/**************************************************************************/
+/*    A Point is a 0-dimensional geometry and represents a single         */
+/*    location in coordinate space.                                       */
+/*    A point has an x-coordinate value and a y-coordinate value.         */
+/*    The boundary of a point is the empty set.                           */
+/**************************************************************************/
+typedef Point WKBPoint;
+typedef LineString WKBLineString;
+
+/**************************************************************************/
+/*    A Polygon is a planar surface, defined by 1 exterior boundary       */
+/*    and 0 or more interior boundaries.                                  */
+/*        Each interior boundary defines a hole in the polygon.           */
+/*    The assertions for polygons (the rules that define valid polygons)  */
+/*    are:                                                                */
+/*    1. Polygons are topologically closed.                               */
+/*    2. The boundary of a polygon consists of a set of LinearRings that  */
+/*       make up its exterior and interior boundaries.                    */
+/*    3. No two rings in the boundary cross, the rings in the boundary    */
+/*       of a polygon may intersect at a point but only as a tangent.     */
+/*    4. A Polygon may not have cut lines, spikes or punctures.           */
+/*    5. The Interior of every Polygon is a connected point set.          */
+/*    6. The Exterior of a Polygon with 1 or more holes is not connected. */
+/*       Each hole defines a connected component of the Exterior.         */
+/*    In the above assertions, Interior, Closure and Exterior have the    */
+/*    standard topological definitions. The combination of 1 and 3 make   */
+/*    a Polygon a Regular Closed point set.                               */
+/*    Polygons are simple geometries.                                     */
+/**************************************************************************/
+struct WKBPolygon {
+    GUInt32 numRings;
+    LineString *rings;
+};
+
+/**************************************************************************/
+/*    A MultiPoint is a 0 dimensional geometric collection. The elements  */
+/*        of a MultiPoint are restricted to Points.                       */
+/*    The points are not connected or ordered.                            */
+/*    A MultiPoint is simple if no two Points in the MultiPoint are       */
+/*          equal (have identical coordinate values).                     */
+/*    The boundary of a MultiPoint is the empty set.                      */
+/**************************************************************************/
+struct WKBMultiPoint {
+    GUInt32 num_wkbPoints;
+    WKBPoint *WKBPoints;
+};
+
+struct WKBMultiLineString {
+    GUInt32 num_wkbLineStrings;
+    WKBLineString *WKBLineStrings;
+};
+
+/**************************************************************************/
+/*    The assertions for MultiPolygons are :                              */
+/*    1. The interiors of 2 Polygons that are elements of a MultiPolygon  */
+/*       may not intersect.                                               */
+/*    2. The Boundaries of any 2 Polygons that are elements of a          */
+/*       MultiPolygon may not 'cross' and may touch at only a finite      */
+/*       number of points. (Note that crossing is prevented by            */
+/*       assertion 1 above).                                              */
+/*    3. A MultiPolygon is defined as topologically closed.               */
+/*    4. A MultiPolygon may not have cut lines, spikes or punctures,      */
+/*       a MultiPolygon is a Regular, Closed point set:                   */
+/*    5. The interior of a MultiPolygon with more than 1 Polygon is not   */ 
+/*       connected, the number of connected components of the interior    */
+/*       of a MultiPolygon is equal to the number of Polygons in the      */
+/*       MultiPolygon.                                                    */
+/*    The boundary of a MultiPolygon is a set of closed curves            */
+/*       (LineStrings) corresponding to the boundaries of its element     */
+/*       Polygons. Each curve in the boundary of the MultiPolygon is in   */
+/*       the boundary of exactly 1 element Polygon, and every curve in    */
+/*       the boundary of an element Polygon is in the boundary of the     */ 
+/*       MultiPolygon.                                                    */
+/**************************************************************************/
+struct WKBMultiPolygon {
+    GUInt32 num_wkbPolygons;
+    WKBPolygon *WKBPolygons;
+};
+
+struct WKBSimpleGeometry {
+    GUInt32 wkbType;
+    union     {
+        WKBPoint point;
+        WKBLineString linestring;
+        WKBPolygon polygon;
+    };
+};
+
+struct WKBGeometryCollection {
+    GUInt32 num_wkbSGeometries;
+    WKBSimpleGeometry *WKBGeometries;
+};
+
+struct WKBGeometry {
+    GUInt32 wkbType;
+    union {
+        WKBPoint point;
+        WKBLineString linestring;
+        WKBPolygon polygon;
+        WKBMultiPoint mpoint;
+        WKBMultiLineString mlinestring;
+        WKBMultiPolygon mpolygon;
+        WKBGeometryCollection mgeometries;
+    };
+public:
+    WKBGeometry () { wkbType=wkbUnknown; }
+};
+
+#endif /* ndef OGIS_GEOMETRY_WKB_STRUCT_H */
+
+
diff --git a/ogr/ogrsf_frmts/walk/ogrwalk.h b/ogr/ogrsf_frmts/walk/ogrwalk.h
new file mode 100644
index 0000000..a6e3136
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalk.h
@@ -0,0 +1,211 @@
+/******************************************************************************
+ * $Id: ogrwalk.h
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Definition of classes for OGR Walk driver.
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGRWALK_H_INCLUDED
+#define _OGRWALK_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_odbc.h"
+#include "cpl_error.h"
+#include "ogis_geometry_wkb_struct.h"
+#include "ogr_pgeo.h"
+
+/************************************************************************/
+/*             Functions for WalkBinary Translation                     */
+/************************************************************************/
+
+OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBuffer);
+OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom);
+void DeleteWKBGeometry(WKBGeometry &obj);
+
+/************************************************************************/
+/*                            OGRWalkLayer                              */
+/************************************************************************/
+
+class OGRWalkDataSource;
+
+class OGRWalkLayer : public OGRLayer
+{
+protected:
+    OGRFeatureDefn     *poFeatureDefn;
+
+    CPLODBCStatement   *poStmt;
+
+    // Layer spatial reference system
+    OGRSpatialReference *poSRS;
+
+    int                 iNextShapeId;
+
+    OGRWalkDataSource    *poDS;
+
+    int                bGeomColumnWKB;
+    char               *pszGeomColumn;
+    char               *pszFIDColumn;
+
+    int                *panFieldOrdinals;
+
+    CPLErr              BuildFeatureDefn( const char *pszLayerName,
+                                          CPLODBCStatement *poStmt );
+
+    virtual CPLODBCStatement *  GetStatement() { return poStmt; }
+    void                LookupSpatialRef( const char * );
+
+public:
+                        OGRWalkLayer();
+                        ~OGRWalkLayer();
+
+    void                ResetReading();
+    OGRFeature *        GetNextFeature();
+    OGRFeature *        GetNextRawFeature();
+
+    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    
+    int         TestCapability( const char * ) { return FALSE; }
+
+    virtual const char * GetFIDColumn (); 
+    virtual const char * GetGeometryColumn ();
+};
+
+/************************************************************************/
+/*                           OGRWalkTableLayer                          */
+/************************************************************************/
+
+class OGRWalkTableLayer : public OGRWalkLayer
+{
+    char                *pszQuery;
+
+    void                ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+    OGREnvelope         sExtent;
+
+public:
+                        OGRWalkTableLayer( OGRWalkDataSource * );
+                        ~OGRWalkTableLayer();
+
+    CPLErr              Initialize( const char *pszTableName, 
+                                    const char *pszGeomCol,
+                                    double minE,
+                                    double maxE,
+                                    double minN,
+                                    double maxN,
+                                    const char *pszMemo );
+
+    virtual void        ResetReading();
+    virtual int         GetFeatureCount( int );
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRFeature *GetFeature( long nFeatureId );
+    
+    virtual int         TestCapability( const char * );
+
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+};
+
+/************************************************************************/
+/*                          OGRWalkSelectLayer                          */
+/************************************************************************/
+
+class OGRWalkSelectLayer : public OGRWalkLayer
+{
+    char                *pszBaseStatement;
+
+    void                ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+  public:
+                        OGRWalkSelectLayer( OGRWalkDataSource *, 
+                                           CPLODBCStatement * );
+                        ~OGRWalkSelectLayer();
+
+    virtual void        ResetReading();
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+};
+
+/************************************************************************/
+/*                          OGRWalkDataSource                           */
+/************************************************************************/
+
+class OGRWalkDataSource : public OGRDataSource
+{
+    char               *pszName;
+    OGRWalkLayer        **papoLayers;
+    int                 nLayers;   
+
+    int                 bDSUpdate;
+    CPLODBCSession      oSession;
+
+public:
+                        OGRWalkDataSource();
+                        ~OGRWalkDataSource();
+
+    int                 Open( const char * , int );
+
+    const char            *GetName() { return pszName; }
+    int                    GetLayerCount() { return nLayers; }
+    OGRLayer            *GetLayer( int );
+
+    int                    TestCapability( const char * ) { return FALSE; }
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+    // For Internal Use
+    CPLODBCSession     *GetSession() { return &oSession; }
+
+};
+
+/************************************************************************/
+/*                            OGRWalkDriver                             */
+/************************************************************************/
+
+class OGRWalkDriver : public OGRODBCMDBDriver
+{
+public:
+                ~OGRWalkDriver();
+                
+    const char    *GetName();
+    OGRDataSource *Open( const char *, int );
+
+    OGRDataSource *CreateDataSource( const char *, char ** );
+    
+    int            TestCapability( const char * );
+};
+
+void RegisterOGRWalk();
+
+#endif /* ndef _OGRWALK_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
new file mode 100644
index 0000000..105503f
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
@@ -0,0 +1,249 @@
+/******************************************************************************
+ * $Id: ogrwalkdatasource.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRWalkDatasource class.
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwalk.h"
+#include <vector>
+
+/************************************************************************/
+/*                         OGRWalkDataSource()                          */
+/************************************************************************/
+
+OGRWalkDataSource::OGRWalkDataSource()
+
+{
+    pszName = NULL;
+    papoLayers = NULL;
+    nLayers = 0;
+}
+
+/************************************************************************/
+/*                        ~OGRWalkDataSource()                          */
+/************************************************************************/
+
+OGRWalkDataSource::~OGRWalkDataSource()
+
+{
+    int i;
+
+    CPLFree( pszName );
+
+    for( i = 0; i < nLayers; i++ )
+    {
+        CPLAssert( NULL != papoLayers[i] );
+
+        delete papoLayers[i];
+    }
+
+    CPLFree( papoLayers );
+}
+
+/************************************************************************/
+/*                              Open()                                  */
+/************************************************************************/
+
+int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
+{
+/* -------------------------------------------------------------------- */
+/*      If this is the name of an MDB file, then construct the          */
+/*      appropriate connection string.  Otherwise clip of WALK: to      */
+/*      get the DSN.                                                    */
+/* -------------------------------------------------------------------- */
+    char *pszDSN;
+
+    if( EQUALN(pszNewName,"WALK:",5) )
+        pszDSN = CPLStrdup( pszNewName + 5 );
+    else
+    {
+        const char *pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
+        pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
+
+        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize based on the DSN.                                    */
+/* -------------------------------------------------------------------- */
+    CPLDebug( "Walk", "EstablishSession(%s)", pszDSN );
+
+    if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to initialize ODBC connection to DSN for %s,\n"
+                  "%s", pszDSN, oSession.GetLastError() );
+        CPLFree( pszDSN );
+        return FALSE;
+    }
+
+    CPLFree( pszDSN );
+
+    pszName = CPLStrdup( pszNewName );
+
+    bDSUpdate = bUpdate;
+
+/* -------------------------------------------------------------------- */
+/*      Collect list of layers and their attributes.                    */
+/* -------------------------------------------------------------------- */
+    std::vector<char **> apapszGeomColumns;
+    CPLODBCStatement oStmt( &oSession );
+
+    oStmt.Append( "SELECT LayerID, LayerName, minE, maxE, minN, maxN, Memo  FROM WalkLayers" );
+
+    if( !oStmt.ExecuteSQL() )
+    {
+        CPLDebug( "Walk", 
+                  "SELECT on WalkLayers fails, perhaps not a walk database?\n%s", 
+                  oSession.GetLastError() );
+        return FALSE;
+    }
+
+    while( oStmt.Fetch() )
+    {
+        int i, iNew = apapszGeomColumns.size();
+        char **papszRecord = NULL;
+        
+        for( i = 1; i < 7; i++ )
+            papszRecord = CSLAddString( papszRecord, oStmt.GetColData(i) ); //Add LayerName, Extent and Memo
+
+        apapszGeomColumns.resize(iNew+1);
+        apapszGeomColumns[iNew] = papszRecord;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a layer for each spatial table.                          */
+/* -------------------------------------------------------------------- */
+    unsigned int iTable;
+
+    papoLayers = (OGRWalkLayer **) CPLCalloc(apapszGeomColumns.size(),
+                                             sizeof( void * ));
+
+    for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
+    {
+        char **papszRecord = apapszGeomColumns[iTable];
+
+        OGRWalkTableLayer  *poLayer = new OGRWalkTableLayer( this );
+
+        if( poLayer->Initialize( papszRecord[0],        // LayerName
+                                 "Geometry",            // Geometry Column Name
+                                 atof(papszRecord[1]),  // Extent MinE
+                                 atof(papszRecord[2]),  // Extent MaxE
+                                 atof(papszRecord[3]),  // Extent MinN
+                                 atof(papszRecord[4]),  // Extent MaxN
+                                 papszRecord[5])        // Memo for SpatialRef
+            != CE_None )
+        {
+            delete poLayer;
+        }
+        else
+            papoLayers[nLayers++] = poLayer;
+
+        CSLDestroy( papszRecord );
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRWalkDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRWalkDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                          OGRGeometry *poSpatialFilter,
+                                          const char *pszDialect )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
+                                          poSpatialFilter, 
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Execute normal SQL statement in Walk.                           */
+/*      Table_name = Layer_name + Postfix                               */
+/*      Postfix: "Features", "Annotations" or "Styles"                  */
+/* -------------------------------------------------------------------- */
+    CPLODBCStatement *poStmt = new CPLODBCStatement( &oSession );
+
+    CPLDebug( "Walk", "ExecuteSQL(%s) called.", pszSQLCommand );
+    poStmt->Append( pszSQLCommand );
+    if( !poStmt->ExecuteSQL() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "%s", oSession.GetLastError() );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Are there result columns for this statement?                    */
+/* -------------------------------------------------------------------- */
+    if( poStmt->GetColCount() == 0 )
+    {
+        delete poStmt;
+        CPLErrorReset();
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a results layer.  It will take ownership of the          */
+/*      statement.                                                      */
+/* -------------------------------------------------------------------- */
+    OGRWalkSelectLayer *poLayer = NULL;
+
+    poLayer = new OGRWalkSelectLayer( this, poStmt );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+    
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRWalkDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
new file mode 100644
index 0000000..3f8385e
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
@@ -0,0 +1,147 @@
+/******************************************************************************
+ * $Id: ogrwalkdriver.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRWalkDriver class.
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwalk.h"
+
+/************************************************************************/
+/*                          ~OGRWalkDriver()                            */
+/************************************************************************/
+
+OGRWalkDriver::~OGRWalkDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRWalkDriver::GetName()
+
+{
+    return "Walk";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRWalkDriver::Open( const char * pszFilename, int bUpdate )
+{
+
+    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+        return NULL;
+
+    if( !EQUALN(pszFilename,"WALK:", strlen("WALK:"))
+        && !EQUAL(CPLGetExtension(pszFilename), "MDB") )
+        return NULL;
+
+#ifndef WIN32
+    // Try to register MDB Tools driver
+    //
+    // ODBCINST.INI NOTE:
+    // This operation requires write access to odbcinst.ini file
+    // located in directory pointed by ODBCINISYS variable.
+    // Usually, it points to /etc, so non-root users can overwrite this
+    // setting ODBCINISYS with location they have write access to, e.g.:
+    // $ export ODBCINISYS=$HOME/etc
+    // $ touch $ODBCINISYS/odbcinst.ini
+    //
+    // See: http://www.unixodbc.org/internals.html
+    //
+    if ( !InstallMdbDriver() )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
+    }
+    else
+        CPLDebug( "Walk", "MDB Tools driver installed successfully!");
+
+#endif /* ndef WIN32 */
+
+    OGRWalkDataSource  *poDS = new OGRWalkDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                          CreateDataSource()                          */
+/************************************************************************/
+
+OGRDataSource *OGRWalkDriver::CreateDataSource( const char * pszName,
+                                                 char **papszOptions )
+
+{
+    //if( !EQUAL(CPLGetExtension(pszName), "MDB") )
+    //    return NULL;
+
+    OGRWalkDataSource  *poDS = new OGRWalkDataSource();
+    
+    if( !poDS->Open( pszName, TRUE ) )
+    {
+        delete poDS;
+        CPLError( CE_Failure, CPLE_AppDefined, 
+         "Walk driver doesn't currently support database creation.\n"
+                  "Please create database with the `createdb' command." );
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRWalkDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          RegisterOGRWalk()                           */
+/************************************************************************/
+
+void RegisterOGRWalk()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRWalkDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
new file mode 100644
index 0000000..3ddd3a7
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
@@ -0,0 +1,383 @@
+/******************************************************************************
+ * $Id: ogrwalklayer.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRWalkLayer class.
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwalk.h"
+
+/************************************************************************/
+/*                            OGRWalkLayer()                            */
+/************************************************************************/
+
+OGRWalkLayer::OGRWalkLayer( )
+
+{
+    poDS = NULL;
+
+    bGeomColumnWKB = FALSE;
+    pszGeomColumn = NULL;
+    pszFIDColumn = NULL;
+    panFieldOrdinals = NULL;
+
+    poStmt = NULL;
+
+    poFeatureDefn = NULL;
+    iNextShapeId = 0;
+
+    poSRS = NULL;
+}
+
+/************************************************************************/
+/*                           ~OGRWalkLayer()                            */
+/************************************************************************/
+
+OGRWalkLayer::~OGRWalkLayer()
+
+{
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "Walk", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead, 
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poFeatureDefn != NULL )
+    {
+        poFeatureDefn->Release();
+        poFeatureDefn = NULL;
+    }
+
+    if( poSRS )
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                          BuildFeatureDefn()                          */
+/*                                                                      */
+/*      Build feature definition from a set of column definitions       */
+/*      set on a statement.  Sift out geometry and FID fields.          */
+/************************************************************************/
+
+CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName, 
+                                    CPLODBCStatement *poStmt )
+
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    int    nRawColumns = poStmt->GetColCount();
+
+    poFeatureDefn->Reference();
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+
+    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
+
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+
+        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+
+        if( pszGeomColumn != NULL 
+            && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )    //If Geometry Column, continue to next field
+            continue;
+
+        switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
+        {
+            case SQL_C_SSHORT:
+            case SQL_C_USHORT:
+            case SQL_C_SLONG:
+            case SQL_C_ULONG:
+                oField.SetType( OFTInteger );
+                break;
+
+            case SQL_C_BINARY:
+                oField.SetType( OFTBinary );
+                break;
+
+            case SQL_C_NUMERIC:
+                oField.SetType( OFTReal );
+                oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+                break;
+
+            case SQL_C_FLOAT:
+            case SQL_C_DOUBLE:
+                oField.SetType( OFTReal );
+                oField.SetWidth( 0 );
+                break;
+
+            case SQL_C_DATE:
+                oField.SetType( OFTDate );
+                break;
+
+            case SQL_C_TIME:
+                oField.SetType( OFTTime );
+                break;
+
+            case SQL_C_TIMESTAMP:
+                oField.SetType( OFTDateTime );
+                break;
+
+            default:
+                /* leave it as OFTString */;
+        }
+
+        poFeatureDefn->AddFieldDefn( &oField );
+        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we don't already have an FID, check if there is a special    */
+/*      FID named column available.                                     */
+/* -------------------------------------------------------------------- */
+    if( pszFIDColumn == NULL )
+    {
+        const char *pszOGR_FID = CPLGetConfigOption("WALK_OGR_FID","FeatureID");
+        if( poFeatureDefn->GetFieldIndex( pszOGR_FID ) != -1 )
+            pszFIDColumn = CPLStrdup(pszOGR_FID);
+    }
+
+    if( pszFIDColumn != NULL )
+        CPLDebug( "Walk", "Using column %s as FID for table %s.",
+                  pszFIDColumn, poFeatureDefn->GetName() );
+    else
+        CPLDebug( "Walk", "Table %s has no identified FID column.",
+                  poFeatureDefn->GetName() );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRWalkLayer::ResetReading()
+
+{
+    iNextShapeId = 0;
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRWalkLayer::GetNextFeature()
+
+{
+    while( TRUE )
+    {
+        OGRFeature      *poFeature;
+
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            return poFeature;
+
+        delete poFeature;
+    }
+}
+
+OGRFeature *OGRWalkLayer::GetNextRawFeature()
+
+{
+    if( GetStatement() == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If we are marked to restart then do so, and fetch a record.     */
+/* -------------------------------------------------------------------- */
+    if( !poStmt->Fetch() )
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a feature from the current result.                       */
+/* -------------------------------------------------------------------- */
+    int         iField;
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
+        poFeature->SetFID( 
+            atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
+    else
+        poFeature->SetFID( iNextShapeId );
+
+    iNextShapeId++;
+    m_nFeaturesRead++;
+
+/* -------------------------------------------------------------------- */
+/*      Set the fields.                                                 */
+/* -------------------------------------------------------------------- */
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        int iSrcField = panFieldOrdinals[iField]-1;
+        const char *pszValue = poStmt->GetColData( iSrcField );
+
+        if( pszValue == NULL )
+            /* no value */;
+        else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
+            poFeature->SetField( iField, 
+                                 poStmt->GetColDataLength(iSrcField),
+                                 (GByte *) pszValue );
+        else
+            poFeature->SetField( iField, pszValue );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to extract a geometry.                                      */
+/* -------------------------------------------------------------------- */
+    if( pszGeomColumn != NULL )
+    {
+        int iField = poStmt->GetColId( pszGeomColumn );
+        const char *pszGeomBin = poStmt->GetColData( iField );
+        int nGeomLength = poStmt->GetColDataLength( iField );
+        OGRGeometry *poGeom = NULL;
+        OGRErr eErr = OGRERR_NONE;
+
+        if( pszGeomBin != NULL && bGeomColumnWKB )
+        {
+            WKBGeometry *WalkGeom = (WKBGeometry *)CPLMalloc(sizeof(WKBGeometry));
+            if( Binary2WkbGeom((unsigned char *)pszGeomBin, WalkGeom, nGeomLength) 
+                != OGRERR_NONE )
+                return NULL;
+            eErr = TranslateWalkGeom(&poGeom, WalkGeom);
+
+            DeleteWKBGeometry(*WalkGeom);
+            CPLFree(WalkGeom);
+        }
+
+        if ( eErr != OGRERR_NONE )
+        {
+            const char *pszMessage;
+
+            switch ( eErr )
+            {
+                case OGRERR_NOT_ENOUGH_DATA:
+                    pszMessage = "Not enough data to deserialize";
+                    break;
+                case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
+                    pszMessage = "Unsupported geometry type";
+                    break;
+                case OGRERR_CORRUPT_DATA:
+                    pszMessage = "Corrupt data";
+                    break;
+                default:
+                    pszMessage = "Unrecognized error";
+            }
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GetNextRawFeature(): %s", pszMessage);
+        }
+
+        if( poGeom != NULL && eErr == OGRERR_NONE )
+        {
+            poGeom->assignSpatialReference( poSRS );
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         LookupSpatialRef()                           */
+/************************************************************************/
+
+void OGRWalkLayer::LookupSpatialRef( const char * pszMemo )
+
+{
+    char *pszProj4 = NULL;
+    const char *pszStart = NULL;
+    char *pszEnd = NULL;
+
+    if ( !pszMemo )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Only proj4 is currently used                                    */
+/* -------------------------------------------------------------------- */
+    if ( (pszStart = strstr(pszMemo, "<proj4>")) != NULL )
+    {
+        pszProj4 = CPLStrdup( pszStart + 7 );
+        if ( (pszEnd = (char *)strstr(pszProj4, "</proj4>")) != NULL )
+            pszEnd[0] = '\0';
+    }
+    else if ( (pszStart = strstr(pszMemo, "proj4={")) != NULL )
+    {
+        pszProj4 = CPLStrdup( pszStart + 7 );
+        if ( (pszEnd = (char *)strstr(pszProj4, "};")) != NULL )
+            pszEnd[0] = '\0';
+    }
+
+/* -------------------------------------------------------------------- */
+/*      No Spatial Reference specified                                  */
+/* -------------------------------------------------------------------- */
+    if ( !pszProj4 )
+        return;
+
+    if ( strlen(pszProj4) > 0 )
+    {
+        poSRS = new OGRSpatialReference();
+    
+        if( poSRS->importFromProj4( pszProj4 ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "importFromProj4() failed on SRS '%s'.",
+                      pszProj4);
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+    CPLFree( pszProj4 );
+}
+
+/************************************************************************/
+/*                             GetFIDColumn                             */
+/************************************************************************/
+
+const char *OGRWalkLayer::GetFIDColumn()
+
+{
+    return pszFIDColumn ? pszFIDColumn : "";
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRWalkLayer::GetGeometryColumn()
+
+{
+    return pszGeomColumn ? pszGeomColumn : "";
+}
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp
new file mode 100644
index 0000000..a7bc6e2
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * $Id: ogrwalkselectlayer.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRWalkSelectLayer class, layer access to the results
+ *           of a SELECT statement executed via ExecuteSQL().
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogrwalk.h"
+
+/************************************************************************/
+/*                          OGRWalkSelectLayer()                        */
+/************************************************************************/
+
+OGRWalkSelectLayer::OGRWalkSelectLayer( OGRWalkDataSource *poDSIn,
+                                        CPLODBCStatement * poStmtIn )
+
+{
+    poDS = poDSIn;
+
+    iNextShapeId = 0;
+    poFeatureDefn = NULL;
+
+    poStmt = poStmtIn;
+    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
+
+    BuildFeatureDefn( "SELECT", poStmt );
+}
+
+/************************************************************************/
+/*                          ~OGRWalkSelectLayer()                       */
+/************************************************************************/
+
+OGRWalkSelectLayer::~OGRWalkSelectLayer()
+
+{
+    ClearStatement();
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRWalkSelectLayer::ClearStatement()
+
+{
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+CPLODBCStatement *OGRWalkSelectLayer::GetStatement()
+
+{
+    if( poStmt == NULL )
+        ResetStatement();
+
+    return poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRWalkSelectLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    CPLDebug( "Walk", "Recreating statement." );
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( pszBaseStatement );
+
+    if( poStmt->ExecuteSQL() )
+        return OGRERR_NONE;
+    else
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRWalkSelectLayer::ResetReading()
+
+{
+    if( iNextShapeId != 0 )
+        ClearStatement();
+
+    OGRWalkLayer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      Since SELECT layers currently cannot ever have geometry, we     */
+/*      can optimize the GetExtent() method!                            */
+/************************************************************************/
+
+OGRErr OGRWalkSelectLayer::GetExtent(OGREnvelope *, int )
+
+{
+    return OGRERR_FAILURE;
+}
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
new file mode 100644
index 0000000..dc7dc8d
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
@@ -0,0 +1,361 @@
+/******************************************************************************
+ * $Id: ogrwalktablelayer.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRWalkTableLayer class, access to an existing table.
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwalk.h"
+#include "cpl_conv.h"
+
+/************************************************************************/
+/*                          OGRWalkTableLayer()                         */
+/************************************************************************/
+
+OGRWalkTableLayer::OGRWalkTableLayer( OGRWalkDataSource *poDSIn )
+
+{
+    poDS = poDSIn;
+
+    pszQuery = NULL;
+
+    iNextShapeId = 0;
+    poFeatureDefn = NULL;
+
+    memset( &sExtent, 0, sizeof(sExtent) );
+}
+
+/************************************************************************/
+/*                         ~OGRWalkTableLayer()                         */
+/************************************************************************/
+
+OGRWalkTableLayer::~OGRWalkTableLayer()
+
+{
+    CPLFree( pszQuery );
+    ClearStatement();
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName, 
+                                      const char *pszGeomCol,
+                                      double minE,
+                                      double maxE,
+                                      double minN,
+                                      double maxN,
+                                      const char *pszMemo)
+
+{
+    CPLODBCSession *poSession = poDS->GetSession();
+
+    CPLFree( pszFIDColumn );
+    pszFIDColumn = NULL;
+
+    sExtent.MinX = minE;
+    sExtent.MaxX = maxE;
+    sExtent.MinY = minN;
+    sExtent.MaxY = maxN;
+
+/* -------------------------------------------------------------------- */
+/*      Look up the Spatial Reference                                   */
+/* -------------------------------------------------------------------- */
+    LookupSpatialRef( pszMemo );
+
+/* -------------------------------------------------------------------- */
+/*      Generate the Feature Tablename from the Layer Name              */
+/*      which is in the form <layername>Features                        */
+/* -------------------------------------------------------------------- */
+    char* pszFeatureTableName = (char *) CPLMalloc(strlen(pszLayerName)+10);
+
+    sprintf(pszFeatureTableName, "%sFeatures", pszLayerName);
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a simple primary key?                                */
+/* -------------------------------------------------------------------- */
+    CPLODBCStatement oGetKey( poSession );
+    
+    if( oGetKey.GetPrimaryKeys( pszFeatureTableName, NULL, NULL ) 
+        && oGetKey.Fetch() )
+    {
+        pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
+        
+        if( oGetKey.Fetch() ) // more than one field in key! 
+        {
+            CPLFree( pszFIDColumn );
+            pszFIDColumn = NULL;
+
+            CPLDebug( "Walk", "Table %s has multiple primary key fields, "
+                      "ignoring them all.", pszFeatureTableName );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Have we been provided a geometry column?                        */
+/* -------------------------------------------------------------------- */
+    CPLFree( pszGeomColumn );
+    if( pszGeomCol == NULL )
+        pszGeomColumn = NULL;
+    else
+        pszGeomColumn = CPLStrdup( pszGeomCol );
+
+/* -------------------------------------------------------------------- */
+/*      Get the column definitions for this table.                      */
+/* -------------------------------------------------------------------- */
+    CPLODBCStatement oGetCol( poSession );
+    CPLErr eErr;
+
+    if( !oGetCol.GetColumns( pszFeatureTableName, NULL, NULL ) )
+    {
+        CPLFree( pszFeatureTableName );
+        return CE_Failure;
+    }
+
+    eErr = BuildFeatureDefn( pszLayerName, &oGetCol );
+    if( eErr != CE_None )
+    {
+        CPLFree( pszFeatureTableName );
+        return eErr;
+    }
+
+    if( poFeatureDefn->GetFieldCount() == 0 )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "No column definitions found for table '%s', layer not usable.", 
+                  pszLayerName );
+        CPLFree( pszFeatureTableName );
+        return CE_Failure;
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      If we got a geometry column, does it exist?  Is it binary?      */
+/* -------------------------------------------------------------------- */
+    if( pszGeomColumn != NULL )
+    {
+        int iColumn = oGetCol.GetColId( pszGeomColumn );
+        if( iColumn < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Column %s requested for geometry, but it does not exist.", 
+                      pszGeomColumn );
+            CPLFree( pszGeomColumn );
+            pszGeomColumn = NULL;
+        }
+        else
+        {
+            if( CPLODBCStatement::GetTypeMapping(
+                    oGetCol.GetColType( iColumn )) == SQL_C_BINARY )
+                bGeomColumnWKB = TRUE;
+        }
+    }
+
+    CPLFree( pszFeatureTableName );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRWalkTableLayer::ClearStatement()
+
+{
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+CPLODBCStatement *OGRWalkTableLayer::GetStatement()
+
+{
+    if( poStmt == NULL )
+        ResetStatement();
+
+    return poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRWalkTableLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( "SELECT * FROM " );
+    poStmt->Append( poFeatureDefn->GetName() );
+    poStmt->Append( "Features" );
+
+    /* Append attribute query if we have it */
+    if( (pszQuery != NULL) && strcmp(pszQuery, "") )
+        poStmt->Appendf( " WHERE %s", pszQuery );
+
+    CPLDebug( "Walk", "ExecuteSQL(%s)", poStmt->GetCommand() );
+    if( poStmt->ExecuteSQL() )
+        return OGRERR_NONE;
+    else
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRWalkTableLayer::ResetReading()
+
+{
+    ClearStatement();
+    OGRWalkLayer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRWalkTableLayer::GetFeature( long nFeatureId )
+
+{
+    if( pszFIDColumn == NULL )
+        return OGRWalkLayer::GetFeature( nFeatureId );
+
+    ClearStatement();
+
+    iNextShapeId = nFeatureId;
+
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( "SELECT * FROM " );
+    poStmt->Append( poFeatureDefn->GetName() );
+    poStmt->Append( "Features" );
+    poStmt->Appendf( " WHERE %s = %ld", pszFIDColumn, nFeatureId );
+
+    if( !poStmt->ExecuteSQL() )
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return NULL;
+    }
+
+    return GetNextRawFeature();
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRWalkTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
+    if( (pszQuery == NULL && this->pszQuery == NULL)
+        || (pszQuery != NULL && this->pszQuery != NULL 
+            && EQUAL(pszQuery,this->pszQuery)) )
+        return OGRERR_NONE;
+
+    CPLFree( this->pszQuery );
+    this->pszQuery = (pszQuery != NULL ) ? CPLStrdup( pszQuery ) : NULL;
+
+    ClearStatement();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRWalkTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+        
+    else 
+        return OGRWalkLayer::TestCapability( pszCap );
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/*                                                                      */
+/*      If a spatial filter is in effect, we turn control over to       */
+/*      the generic counter.  Otherwise we return the total count.      */
+/*      Eventually we should consider implementing a more efficient     */
+/*      way of counting features matching a spatial query.              */
+/************************************************************************/
+
+int OGRWalkTableLayer::GetFeatureCount( int bForce )
+
+{
+    if( m_poFilterGeom != NULL )
+        return OGRWalkLayer::GetFeatureCount( bForce );
+
+    CPLODBCStatement oStmt( poDS->GetSession() );
+    oStmt.Append( "SELECT COUNT(*) FROM " );
+    oStmt.Append( poFeatureDefn->GetName() );
+    oStmt.Append( "Features" );
+
+    if( (pszQuery != NULL) && strcmp(pszQuery, "") )
+        oStmt.Appendf( " WHERE %s", pszQuery );
+
+    if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "GetFeatureCount() failed on query %s.\n%s",
+                  oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
+        return OGRWalkLayer::GetFeatureCount(bForce);
+    }
+
+    return atoi(oStmt.GetColData(0));
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRWalkTableLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+
+{
+    *psExtent = sExtent;
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktool.cpp b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
new file mode 100644
index 0000000..2758688
--- /dev/null
+++ b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
@@ -0,0 +1,753 @@
+/******************************************************************************
+ * $Id: ogrwalktool.cpp
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements Walk Binary Data to Walk Geometry and OGC WKB
+ * Author:   Xian Chen, chenxian at walkinfo.com.cn
+ *
+ ******************************************************************************
+ * Copyright (c) 2013,  ZJU Walkinfo Technology Corp., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwalk.h"
+
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
+/************************************************************************/
+/*                   OGRWalkArcCenterFromEdgePoints()                   */
+/*                                                                      */
+/*      Compute the center of an arc/circle from three edge points.     */
+/************************************************************************/
+
+static int 
+OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
+                               double x_c1, double y_c1, 
+                               double x_c2, double y_c2, 
+                               double *x_center, double *y_center )
+    
+{
+/* -------------------------------------------------------------------- */
+/*      Compute the inverse of the slopes connecting the first and      */
+/*      second points.  Also compute the center point of the two        */
+/*      points ... the point our crossing line will go through.          */
+/* -------------------------------------------------------------------- */
+    double m1, x1, y1;
+
+    if( (y_c1 - y_c0) != 0.0 )
+        m1 = (x_c0 - x_c1) / (y_c1 - y_c0);
+    else
+        m1 = 1e+10;
+
+    x1 = (x_c0 + x_c1) * 0.5;
+    y1 = (y_c0 + y_c1) * 0.5;
+
+/* -------------------------------------------------------------------- */
+/*      Compute the same for the second point compared to the third     */
+/*      point.                                                          */
+/* -------------------------------------------------------------------- */
+    double m2, x2, y2;
+
+    if( (y_c2 - y_c1) != 0.0 )
+        m2 = (x_c1 - x_c2) / (y_c2 - y_c1);
+    else
+        m2 = 1e+10;
+
+    x2 = (x_c1 + x_c2) * 0.5;
+    y2 = (y_c1 + y_c2) * 0.5;
+
+/* -------------------------------------------------------------------- */
+/*      Turn these into the Ax+By+C = 0 form of the lines.              */
+/* -------------------------------------------------------------------- */
+    double      a1, a2, b1, b2, c1, c2;
+
+    a1 = m1;
+    a2 = m2;
+
+    b1 = -1.0;
+    b2 = -1.0;
+    
+    c1 = (y1 - m1*x1);
+    c2 = (y2 - m2*x2);
+    
+/* -------------------------------------------------------------------- */
+/*      Compute the intersection of the two lines through the center    */
+/*      of the circle, using Kramers rule.                              */
+/* -------------------------------------------------------------------- */
+    double      det_inv;
+
+    if( a1*b2 - a2*b1 == 0.0 )
+        return FALSE;
+
+    det_inv = 1 / (a1*b2 - a2*b1);
+
+    *x_center = (b1*c2 - b2*c1) * det_inv;
+    *y_center = (a2*c1 - a1*c2) * det_inv;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       OGRWalkArcToLineString()                       */
+/************************************************************************/
+static int 
+OGRWalkArcToLineString( double dfStartX, double dfStartY,
+                        double dfAlongX, double dfAlongY,
+                        double dfEndX, double dfEndY,
+                        double dfCenterX, double dfCenterY, 
+                        double dfCenterZ, double dfRadius,
+                        int nNumPoints, OGRLineString *poLS )
+{
+    double dfStartAngle, dfEndAngle, dfAlongAngle;
+    double dfDeltaX, dfDeltaY;
+
+    dfDeltaX = dfStartX - dfCenterX;
+    dfDeltaY = dfStartY - dfCenterY;
+    dfStartAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+
+    dfDeltaX = dfAlongX - dfCenterX;
+    dfDeltaY = dfAlongY - dfCenterY;
+    dfAlongAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+
+    dfDeltaX = dfEndX - dfCenterX;
+    dfDeltaY = dfEndY - dfCenterY;
+    dfEndAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+
+    // Try positive (clockwise?) winding.
+    while( dfAlongAngle < dfStartAngle )
+        dfAlongAngle += 360.0;
+
+    while( dfEndAngle < dfAlongAngle )
+        dfEndAngle += 360.0;
+
+    if( nNumPoints == 3 )        //Arc
+    {
+        if( dfEndAngle - dfStartAngle > 360.0 )
+        {
+            while( dfAlongAngle > dfStartAngle )
+                dfAlongAngle -= 360.0;
+
+            while( dfEndAngle > dfAlongAngle )
+                dfEndAngle -= 360.0;
+        }
+    }
+    else if( nNumPoints == 5 )  //Circle
+    {
+        // If anticlockwise, then start angle - end angle = 360.0;
+        // Otherwise end angle - start angle = 360.0;
+        if( dfEndAngle - dfStartAngle > 360.0 )
+            dfEndAngle = dfStartAngle - 360.0;
+        else
+            dfEndAngle = dfStartAngle + 360.0;
+    }
+    else
+        return FALSE;
+
+    OGRLineString* poArcpoLS = 
+        (OGRLineString*)OGRGeometryFactory::approximateArcAngles(
+            dfCenterX, dfCenterY, dfCenterZ,
+            dfRadius, dfRadius, 0.0, 
+            dfStartAngle, dfEndAngle, 0.0 );
+
+    if( poArcpoLS == NULL )
+        return FALSE;
+
+    poLS->addSubLineString(poArcpoLS);
+    delete poArcpoLS;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       Binary2WkbMGeom()                              */
+/************************************************************************/
+OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
+{
+    GUInt32 i,j,k;
+
+    if( nBytes < 28 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "WalkGeom binary size (%d) too small",
+                 nBytes);
+        return OGRERR_FAILURE;
+    }
+
+    memcpy(&geom->wkbType, p, 4);
+    CPL_LSBPTR32( &geom->wkbType );
+    p += 4;
+
+    switch(geom->wkbType)
+    {
+    case wkbPoint:
+        memcpy(&geom->point, p, sizeof(WKBPoint));
+        CPL_LSBPTRPOINT(geom->point);
+        p += sizeof(WKBPoint);
+        break;
+    case wkbLineString:
+        memcpy(&geom->linestring.numSegments, p, 4);
+        CPL_LSBPTR32(&geom->linestring.numSegments);
+        p += 4;
+
+        geom->linestring.segments = new CurveSegment[geom->linestring.numSegments];
+        
+        for(i = 0; i < geom->linestring.numSegments; i++)
+        {
+            memcpy(&geom->linestring.segments[i].lineType, p, 4);
+            CPL_LSBPTR32(&geom->linestring.segments[i].lineType);
+            p += 4;
+            memcpy(&geom->linestring.segments[i].numPoints, p, 4);
+            CPL_LSBPTR32(&geom->linestring.segments[i].numPoints);
+            p += 4;
+            geom->linestring.segments[i].points = 
+                new Point[geom->linestring.segments[i].numPoints];
+            memcpy(geom->linestring.segments[i].points, p,
+                sizeof(Point) * geom->linestring.segments[i].numPoints);
+            CPL_LSBPTRPOINTS(geom->linestring.segments[i].points, 
+                geom->linestring.segments[i].numPoints);
+            p += sizeof(Point) * geom->linestring.segments[i].numPoints;
+        }
+        break;
+    case wkbPolygon:
+        memcpy(&geom->polygon.numRings, p, 4);
+        CPL_LSBPTR32(&geom->polygon.numRings);
+        p += 4;
+        geom->polygon.rings = new LineString[geom->polygon.numRings];
+        
+        for(i = 0; i < geom->polygon.numRings; i++)
+        {
+            memcpy(&geom->polygon.rings[i].numSegments, p, 4);
+            CPL_LSBPTR32(&geom->polygon.rings[i].numSegments);
+            p += 4;
+            geom->polygon.rings[i].segments = 
+                new CurveSegment[geom->polygon.rings[i].numSegments];
+            
+            for(j = 0; j < geom->polygon.rings[i].numSegments; j++)
+            {
+                memcpy(&geom->polygon.rings[i].segments[j].lineType, p, 4);
+                CPL_LSBPTR32(&geom->polygon.rings[i].segments[j].lineType);
+                p += 4;
+                memcpy(&geom->polygon.rings[i].segments[j].numPoints, p, 4);
+                CPL_LSBPTR32(&geom->polygon.rings[i].segments[j].numPoints);
+                p += 4;
+                geom->polygon.rings[i].segments[j].points = 
+                    new Point[geom->polygon.rings[i].segments[j].numPoints];
+                memcpy(geom->polygon.rings[i].segments[j].points, p, 
+                    sizeof(Point) * geom->polygon.rings[i].segments[j].numPoints);
+                CPL_LSBPTRPOINTS(geom->polygon.rings[i].segments[j].points, 
+                    geom->polygon.rings[i].segments[j].numPoints);
+                p += sizeof(Point) * geom->polygon.rings[i].segments[j].numPoints;
+            }
+        }
+        break;
+    case wkbMultiPoint:
+        memcpy(&geom->mpoint.num_wkbPoints, p, 4);
+        CPL_LSBPTR32(&geom->mpoint.num_wkbPoints);
+        p += 4;
+        geom->mpoint.WKBPoints = new WKBPoint[geom->mpoint.num_wkbPoints];
+        memcpy(geom->mpoint.WKBPoints, p, sizeof(WKBPoint) * geom->mpoint.num_wkbPoints);
+        CPL_LSBPTRPOINTS(geom->mpoint.WKBPoints, geom->mpoint.num_wkbPoints);
+        p += sizeof(WKBPoint) * geom->mpoint.num_wkbPoints;
+        break;
+    case wkbMultiLineString:
+        memcpy(&geom->mlinestring.num_wkbLineStrings, p, 4);
+        CPL_LSBPTR32(&geom->mlinestring.num_wkbLineStrings);
+        p += 4;
+        geom->mlinestring.WKBLineStrings = 
+            new WKBLineString[geom->mlinestring.num_wkbLineStrings];
+        
+        for(i = 0; i < geom->mlinestring.num_wkbLineStrings; i++)
+        {
+            memcpy(&geom->mlinestring.WKBLineStrings[i].numSegments, p, 4);
+            CPL_LSBPTR32(&geom->mlinestring.WKBLineStrings[i].numSegments);
+            p += 4;
+            geom->mlinestring.WKBLineStrings[i].segments = 
+                new CurveSegment[geom->mlinestring.WKBLineStrings[i].numSegments];
+            
+            for(j = 0; j < geom->mlinestring.WKBLineStrings[i].numSegments; j++)
+            {
+                memcpy(&geom->mlinestring.WKBLineStrings[i].segments[j].lineType, p, 4);
+                CPL_LSBPTR32(&geom->mlinestring.WKBLineStrings[i].segments[j].lineType);
+                p += 4;
+                memcpy(&geom->mlinestring.WKBLineStrings[i].segments[j].numPoints, p, 4);
+                CPL_LSBPTR32(&geom->mlinestring.WKBLineStrings[i].segments[j].numPoints);
+                p += 4;
+                geom->mlinestring.WKBLineStrings[i].segments[j].points = 
+                    new Point[geom->mlinestring.WKBLineStrings[i].segments[j].numPoints];
+                memcpy(geom->mlinestring.WKBLineStrings[i].segments[j].points, p,
+                    sizeof(Point) * geom->mlinestring.WKBLineStrings[i].segments[j].numPoints);
+                CPL_LSBPTRPOINTS(geom->mlinestring.WKBLineStrings[i].segments[j].points,
+                    geom->mlinestring.WKBLineStrings[i].segments[j].numPoints);
+                p += sizeof(Point) * geom->mlinestring.WKBLineStrings[i].segments[j].numPoints;
+            }
+        }
+        break;
+    case wkbMultiPolygon:
+        memcpy(&geom->mpolygon.num_wkbPolygons, p, 4);
+        CPL_LSBPTR32(&geom->mpolygon.num_wkbPolygons);
+        p += 4;
+        geom->mpolygon.WKBPolygons = new WKBPolygon[geom->mpolygon.num_wkbPolygons];
+        
+        for(i = 0; i < geom->mpolygon.num_wkbPolygons; i++)
+        {
+            memcpy(&geom->mpolygon.WKBPolygons[i].numRings, p, 4);
+            CPL_LSBPTR32(&geom->mpolygon.WKBPolygons[i].numRings);
+            p += 4;
+            geom->mpolygon.WKBPolygons[i].rings =
+                new LineString[geom->mpolygon.WKBPolygons[i].numRings];
+            
+            for(j = 0; j < geom->mpolygon.WKBPolygons[i].numRings; j++)
+            {
+                memcpy(&geom->mpolygon.WKBPolygons[i].rings[j].numSegments, p, 4);
+                CPL_LSBPTR32(&geom->mpolygon.WKBPolygons[i].rings[j].numSegments);
+                p += 4;
+                geom->mpolygon.WKBPolygons[i].rings[j].segments =
+                    new CurveSegment[geom->mpolygon.WKBPolygons[i].rings[j].numSegments];
+                
+                for(k = 0; k < geom->mpolygon.WKBPolygons[i].rings[j].numSegments; k++)
+                {
+                    memcpy(&geom->mpolygon.WKBPolygons[i].rings[j].segments[k].lineType, p, 4);
+                    CPL_LSBPTR32(&geom->mpolygon.WKBPolygons[i].rings[j].segments[k].lineType);
+                    p += 4;
+                    memcpy(&geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints, p, 4);
+                    CPL_LSBPTR32(&geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints);
+                    p += 4;
+                    geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points =
+                        new Point[geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints];
+                    memcpy(geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points, 
+                        p, sizeof(Point) * 
+                        geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints);
+                    CPL_LSBPTRPOINTS(geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points,
+                        geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints);
+                    p += sizeof(Point) * 
+                        geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints;
+                }
+            }
+        }
+        break;
+    default:
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       Binary2WkbGeom()                               */
+/************************************************************************/
+OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBytes)
+{
+    GUInt32 i;
+
+    if( nBytes < 28 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "WalkGeom binary size (%d) too small",
+                 nBytes);
+        return OGRERR_FAILURE;
+    }
+
+    memcpy(&geom->wkbType, p, 4);
+    CPL_LSBPTR32( &geom->wkbType );
+
+    switch(geom->wkbType)
+    {
+    case wkbPoint:
+    case wkbLineString:
+    case wkbPolygon:
+    case wkbMultiPoint:
+    case wkbMultiLineString:
+    case wkbMultiPolygon:
+        return Binary2WkbMGeom(p, geom, nBytes);
+    case wkbGeometryCollection:
+        p += 4;
+        memcpy(&geom->mgeometries.num_wkbSGeometries, p, 4);
+        CPL_LSBPTR32( &geom->mgeometries.num_wkbSGeometries );
+        p += 4;
+        geom->mgeometries.WKBGeometries =
+            new WKBSimpleGeometry[geom->mgeometries.num_wkbSGeometries];
+
+        for(i = 0; i < geom->mgeometries.num_wkbSGeometries; i++)
+            Binary2WkbMGeom(p, (WKBGeometry*)(&geom->mgeometries.WKBGeometries[i]), nBytes-8);
+        break;
+    default:
+        geom->wkbType=wkbUnknown;
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       TranslateWalkPoint()                           */
+/************************************************************************/
+OGRBoolean TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
+{
+    if ( poPoint == NULL || pWalkWkbPoint == NULL ) 
+        return FALSE;
+
+    poPoint->setX(pWalkWkbPoint->x);
+    poPoint->setY(pWalkWkbPoint->y);
+    poPoint->setZ(pWalkWkbPoint->z);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                    TranslateCurveSegment()                           */
+/************************************************************************/
+OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
+{
+    if ( poLS == NULL || pSegment == NULL )
+        return FALSE;
+
+    switch(pSegment->lineType)
+    {
+    case wkLineType3PArc:
+    case wkLineType3PCircle:
+        {
+            double      dfCenterX, dfCenterY, dfCenterZ, dfRadius;
+
+            if ( !OGRWalkArcCenterFromEdgePoints( pSegment->points[0].x, pSegment->points[0].y,
+                                           pSegment->points[1].x, pSegment->points[1].y,
+                                           pSegment->points[2].x, pSegment->points[2].y,
+                                           &dfCenterX, &dfCenterY ) )
+                return FALSE;
+
+            //Use Z value of the first point
+            dfCenterZ = pSegment->points[0].z;
+            dfRadius = sqrt( (dfCenterX - pSegment->points[0].x) * (dfCenterX - pSegment->points[0].x)
+                           + (dfCenterY - pSegment->points[0].y) * (dfCenterY - pSegment->points[0].y) );
+
+            if ( !OGRWalkArcToLineString( pSegment->points[0].x, pSegment->points[0].y,
+                        pSegment->points[1].x, pSegment->points[1].y,
+                        pSegment->points[2].x, pSegment->points[2].y,
+                        dfCenterX, dfCenterY, dfCenterZ, dfRadius,
+                        pSegment->numPoints, poLS ) )
+                return FALSE;
+        }
+        break;
+    case wkLineTypeStraight:
+    default:
+        {
+            for (GUInt32 i = 0; i < pSegment->numPoints; ++i)
+            {
+                Point point = pSegment->points[i];
+                poLS->addPoint(point.x, point.y, point.z);
+            }
+        }
+        break;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                    TranslateWalkLineString()                         */
+/************************************************************************/
+OGRBoolean TranslateWalkLineString(OGRLineString *poLS, LineString* pLineString)
+{
+    if ( poLS == NULL || pLineString == NULL )
+        return FALSE;
+
+    for (GUInt32 i = 0; i < pLineString->numSegments; ++i)
+    {
+        if ( !TranslateCurveSegment(poLS, &pLineString->segments[i]) )
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                    TranslateWalkLinearring()                         */
+/************************************************************************/
+OGRBoolean TranslateWalkLinearring(OGRLinearRing *poRing, LineString* pLineString)
+{
+    if ( poRing == NULL || pLineString == NULL )
+        return FALSE;
+
+    for(GUInt32 i = 0; i < pLineString->numSegments; i++)
+        TranslateCurveSegment(poRing, &pLineString->segments[i]);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                    TranslateWalkPolygon()                            */
+/************************************************************************/
+OGRBoolean TranslateWalkPolygon(OGRPolygon *poPolygon, WKBPolygon* pWalkWkbPolgon)
+{
+    if ( poPolygon == NULL || pWalkWkbPolgon == NULL )
+        return FALSE;
+
+    for (GUInt32 i = 0; i < pWalkWkbPolgon->numRings; ++i)
+    {
+        OGRLinearRing* poRing = new OGRLinearRing();
+        LineString* lineString = &pWalkWkbPolgon->rings[i];
+        TranslateWalkLinearring(poRing, lineString);
+        poPolygon->addRingDirectly(poRing);
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        TranslateWalkGeom()                           */
+/************************************************************************/
+OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
+{
+    if ( ppoGeom == NULL || geom == NULL )
+        return OGRERR_NOT_ENOUGH_DATA;
+
+    OGRGeometry* poGeom = 
+        OGRGeometryFactory::createGeometry(wkbFlatten(geom->wkbType));
+
+    if ( poGeom == NULL )
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+
+    switch (geom->wkbType)
+    {
+    case wkbPoint:
+        {
+            if (!TranslateWalkPoint((OGRPoint *)poGeom, &geom->point))
+                return OGRERR_CORRUPT_DATA;
+        }
+        break;
+    case wkbLineString:
+        {
+            if (!TranslateWalkLineString((OGRLineString *)poGeom, &geom->linestring))
+                return OGRERR_CORRUPT_DATA;
+        }
+        break;
+    case wkbPolygon:
+        {
+            if (!TranslateWalkPolygon((OGRPolygon *)poGeom, &geom->polygon))
+                return OGRERR_CORRUPT_DATA;
+        }
+        break;
+    case wkbMultiPoint:
+        {
+            for (GUInt32 i = 0; i < geom->mpoint.num_wkbPoints; ++i)
+            {
+                OGRPoint* poPoint = new OGRPoint();
+                if (!TranslateWalkPoint(poPoint, &geom->mpoint.WKBPoints[i]))
+                    return OGRERR_CORRUPT_DATA;
+                ((OGRMultiPoint *)poGeom)->addGeometryDirectly(poPoint);
+            }
+        }
+        break;
+    case wkbMultiLineString:
+        {
+            for (GUInt32 i = 0; i < geom->mlinestring.num_wkbLineStrings; ++i)
+            {
+                OGRLineString* poLS = new OGRLineString();
+                if (!TranslateWalkLineString(poLS, &geom->mlinestring.WKBLineStrings[i]))
+                    return OGRERR_CORRUPT_DATA;
+                ((OGRMultiLineString *)poGeom)->addGeometryDirectly(poLS);
+            }
+        }
+        break;
+    case wkbMultiPolygon:
+        {
+            for (GUInt32 i = 0; i < geom->mpolygon.num_wkbPolygons; ++i)
+            {
+                OGRPolygon* poPolygon = new OGRPolygon();
+                if (!TranslateWalkPolygon(poPolygon, &geom->mpolygon.WKBPolygons[i]))
+                    return OGRERR_CORRUPT_DATA;
+                ((OGRMultiPolygon *)poGeom)->addGeometryDirectly(poPolygon);
+            }
+        }
+        break;
+    case wkbGeometryCollection:
+        {
+            for (GUInt32 i = 0; i < geom->mgeometries.num_wkbSGeometries; ++i)
+            {
+                WKBSimpleGeometry* sg = &geom->mgeometries.WKBGeometries[i];
+                switch (sg->wkbType)
+                {
+                    case wkbPoint:
+                        {
+                            OGRPoint* poPoint = new OGRPoint();
+                            if (!TranslateWalkPoint(poPoint, &sg->point))
+                                return OGRERR_CORRUPT_DATA;
+                            ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poPoint);
+                        }
+                        break;
+                    case wkbLineString:
+                        {
+                            OGRLineString* poLS = new OGRLineString();
+                            if (!TranslateWalkLineString(poLS, &sg->linestring))
+                                return OGRERR_CORRUPT_DATA;
+                            ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poLS);
+                        }
+                        break;
+                    case wkbPolygon:
+                        {
+                            OGRPolygon* poPolygon = new OGRPolygon();    
+                            if (!TranslateWalkPolygon(poPolygon, &sg->polygon))
+                                return OGRERR_CORRUPT_DATA;
+                            ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poPolygon);
+                        }
+                        break;
+                    default: return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+                }                
+            }
+        }
+        break;
+    default:
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+    }
+
+    *ppoGeom = poGeom;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                      DeleteCurveSegment()                            */
+/************************************************************************/
+void DeleteCurveSegment(CurveSegment &obj)
+{
+    if(obj.numPoints)
+        delete [] obj.points;
+}
+
+/************************************************************************/
+/*                      DeleteWKBMultiPoint()                           */
+/************************************************************************/
+void DeleteWKBMultiPoint(WKBMultiPoint &obj)
+{
+    if (obj.num_wkbPoints)
+    {
+        delete[] obj.WKBPoints;
+        obj.num_wkbPoints = 0;
+    }
+}
+
+/************************************************************************/
+/*                      DeleteWKBLineString()                           */
+/************************************************************************/
+void DeleteWKBLineString(WKBLineString &obj)
+{
+    if(obj.numSegments)
+    {
+        for (GUInt32 i = 0; i < obj.numSegments; i++)
+            DeleteCurveSegment(obj.segments[i]);
+        delete [] obj.segments;
+        obj.numSegments = 0;
+    }
+}
+
+/************************************************************************/
+/*                     DeleteWKBMultiLineString()                       */
+/************************************************************************/
+void DeleteWKBMultiLineString(WKBMultiLineString &obj)
+{
+    if (obj.num_wkbLineStrings)
+    {
+        for (GUInt32 i = 0; i < obj.num_wkbLineStrings; i++)
+            DeleteWKBLineString(obj.WKBLineStrings[i]);
+
+        delete [] obj.WKBLineStrings;
+        obj.num_wkbLineStrings = 0;
+    }
+}
+
+/************************************************************************/
+/*                        DeleteWKBPolygon()                            */
+/************************************************************************/
+void DeleteWKBPolygon(WKBPolygon &obj)
+{
+    if (obj.numRings)
+    {
+        for (GUInt32 i = 0; i < obj.numRings; i++)
+            DeleteWKBLineString(obj.rings[i]);
+
+        delete [] obj.rings;
+        obj.numRings = 0;
+    }
+}
+
+/************************************************************************/
+/*                      DeleteWKBMultiPolygon()                         */
+/************************************************************************/
+void DeleteWKBMultiPolygon(WKBMultiPolygon &obj)
+{
+    if (obj.num_wkbPolygons)
+    {
+        for (GUInt32 i = 0; i < obj.num_wkbPolygons; i++)
+            DeleteWKBPolygon(obj.WKBPolygons[i]);
+
+        delete [] obj.WKBPolygons;
+        obj.num_wkbPolygons = 0;
+    }
+}
+
+/************************************************************************/
+/*                    DeleteWKBGeometryCollection()                     */
+/************************************************************************/
+void DeleteWKBGeometryCollection(WKBGeometryCollection &obj)
+{
+    if (obj.num_wkbSGeometries)
+    {
+        for (GUInt32 i = 0; i < obj.num_wkbSGeometries; i++)
+            DeleteWKBGeometry(*(WKBGeometry*)&obj.WKBGeometries[i]);
+
+        delete [] obj.WKBGeometries;
+        obj.num_wkbSGeometries = 0;
+    }
+}
+
+/************************************************************************/
+/*                       DeleteWKBGeometry()                            */
+/************************************************************************/
+void DeleteWKBGeometry(WKBGeometry &obj)
+{
+    switch (obj.wkbType)
+    {
+    case wkbPoint:
+        break;
+
+    case wkbLineString:
+        DeleteWKBLineString(obj.linestring);
+        break;
+
+    case wkbPolygon:
+        DeleteWKBPolygon(obj.polygon);
+        break;
+
+    case wkbMultiPoint:
+        DeleteWKBMultiPoint(obj.mpoint);
+        break;
+
+    case wkbMultiLineString:
+        DeleteWKBMultiLineString(obj.mlinestring);
+        break;
+
+    case wkbMultiPolygon:
+        DeleteWKBMultiPolygon(obj.mpolygon);
+        break;
+
+    case wkbGeometryCollection:
+        DeleteWKBGeometryCollection(obj.mgeometries);
+        break;
+    }
+    obj.wkbType = wkbUnknown;
+}
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/wasp/GNUmakefile b/ogr/ogrsf_frmts/wasp/GNUmakefile
new file mode 100644
index 0000000..8c0f477
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/GNUmakefile
@@ -0,0 +1,15 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrwaspdriver.o ogrwaspdatasource.o ogrwasplayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ:.o=.$(OBJ_EXT)):	ogrwasp.h
diff --git a/ogr/ogrsf_frmts/wasp/drv_wasp.html b/ogr/ogrsf_frmts/wasp/drv_wasp.html
new file mode 100644
index 0000000..b6d44a5
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/drv_wasp.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+<title>WAsP - WAsP .map format</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>WAsP - WAsP .map format</h1>
+
+(GDAL/OGR <= 1.11.0)<p>
+
+This driver writes .map files to be used with WAsP. The only allowed geometries are linestrings.<p>
+
+<h3>Configuration options</h3>
+
+<ul>
+    <li>WASP_FIELDS : a coma separated list of fields. For elevation, the name of the height field. For rouhgness, the name of the left and right roughness fields resp.</li>
+    <li>WASP_MERGE : this may be set to "NO". Used only when generating roughness from polygons. All polygon boundaries will be output (including those with the same left and righ roughness). This is usefull (along with option -skipfailures) for debugging incorect input geometries.</li>
+    <li>WASP_GEOM_FIELD : in case input has several geometry columns and the first one (default) is not the right one.</li>
+    <li>WASP_TOLERANCE : specify a tolerance for line simplification of output.</li>
+</ul>
+
+<p>
+Note that if not option is specified, the layer is assumed to be an elevation layer where the elevation is the z-components of the linestrings' points. 
+</p>
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/wasp/makefile.vc b/ogr/ogrsf_frmts/wasp/makefile.vc
new file mode 100644
index 0000000..83ba113
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrwaspdriver.obj ogrwaspdatasource.obj ogrwasplayer.obj
+EXTRAFLAGS =	-I.. -I..\.. 
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasp.h b/ogr/ogrsf_frmts/wasp/ogrwasp.h
new file mode 100644
index 0000000..49260e0
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/ogrwasp.h
@@ -0,0 +1,204 @@
+/******************************************************************************
+ *
+ * Project:  WAsP Translator
+ * Purpose:  Definition of classes for OGR .map driver.
+ * Author:   Vincent Mora, vincent dot mora at oslandia dot com
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Oslandia <info at oslandia dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OGR_WASP_H_INCLUDED
+#define _OGR_WASP_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+#include <memory>
+#include <fstream>
+#include <vector>
+
+/************************************************************************/
+/*                             OGRWAsPLayer                             */
+/************************************************************************/
+
+class OGRWAsPLayer : public OGRLayer
+{
+    /* stuff for polygon processing */
+
+    /* note if shared ptr are available, replace the ptr in the two structs */
+    /* and remove deletion of array elements in ~OGRWAsPLayer() */
+    struct Zone
+    {
+        OGREnvelope       oEnvelope;
+        OGRPolygon *      poPolygon;
+        double            dfZ;
+    };
+
+    struct Boundary
+    {
+        OGRLineString * poLine;
+        double          dfLeft;
+        double          dfRight;
+    };
+
+    const bool              bMerge;
+    std::vector< Zone >     oZones;
+    std::vector< Boundary > oBoundaries;
+
+    static bool isEqual( const double & dfRouhness1, const double & dfRouhness2 ) { return fabs( dfRouhness1 - dfRouhness2 ) < 1e-3; }
+
+    /* end of stuff for polygon processing */
+
+    int iFeatureCount;
+
+    const CPLString       sName;
+    VSILFILE *            hFile;
+
+    /* for roughness zone, two fields for linestrings (left/right), one for polygons */
+    /* for elevation, one fiels (height) */
+    const CPLString       sFirstField;
+    const CPLString       sSecondField;
+    const CPLString       sGeomField;
+    int                   iFirstFieldIdx;
+    int                   iSecondFieldIdx;
+    int                   iGeomFieldIdx;
+
+    OGRFeatureDefn *      poLayerDefn;
+    OGRSpatialReference * poSpatialReference;
+
+    vsi_l_offset          iOffsetFeatureBegin;
+
+    enum OpenMode {READ_ONLY, WRITE_ONLY};
+    OpenMode              eMode;
+
+    std::auto_ptr<double> pdfTolerance;
+
+    OGRErr                WriteRoughness( OGRLineString *,
+                                          const double & dfZleft,
+                                          const double & dfZright );
+    OGRErr                WriteRoughness( OGRPolygon *,
+                                          const double & dfZ );
+    OGRErr                WriteRoughness( OGRGeometry *,
+                                          const double & dfZleft,
+                                          const double & dfZright );
+
+    OGRErr                WriteElevation( OGRLineString *, const double & dfZ );
+    OGRErr                WriteElevation( OGRGeometry *, const double & dfZ );
+
+    static double AvgZ( OGRLineString * poGeom );
+    static double AvgZ( OGRPolygon * poGeom );
+    static double AvgZ( OGRGeometryCollection * poGeom );
+    static double AvgZ( OGRGeometry * poGeom );
+  public:
+                        /* For writing */
+                        /* Takes ownership of poTolerance */
+                        OGRWAsPLayer( const char * pszName, 
+                                      VSILFILE * hFile,
+                                      OGRSpatialReference * poSpatialRef,
+                                      const CPLString & sFirstField,
+                                      const CPLString & sSecondField,
+                                      const CPLString & sGeomField,
+                                      bool bMerge,
+                                      double * poTolerance );
+
+                        /* For reading */
+                        OGRWAsPLayer( const char * pszName, 
+                                      VSILFILE * hFile,
+                                      OGRSpatialReference * poSpatialRef );
+
+                        ~OGRWAsPLayer();
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poLayerDefn; }
+
+    virtual void        ResetReading();
+    virtual int         TestCapability( const char * );
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE );
+
+    virtual OGRErr      CreateFeature( OGRFeature * poFeature );
+
+    virtual OGRFeature *GetNextFeature();
+    OGRFeature *GetNextRawFeature();
+    virtual OGRwkbGeometryType  GetGeomType() { return wkbLineString25D; }
+    virtual OGRSpatialReference *GetSpatialRef() { return poSpatialReference; }
+    virtual const char *GetName() { return sName.c_str(); }
+};
+
+/************************************************************************/
+/*                           OGRWAsPDataSource                          */
+/************************************************************************/
+
+class OGRWAsPDataSource : public OGRDataSource
+{
+    CPLString                     sFilename;
+    VSILFILE *                    hFile;
+    std::auto_ptr<OGRWAsPLayer>   oLayer;
+
+    void               GetOptions(CPLString & sFirstField, 
+                                  CPLString & sSecondField,
+                                  CPLString & sGeomField,
+                                  bool &      bMerge) const;
+  public:
+                        /** @note takes ownership of hFile (i.e. responsibility for closing) */
+                        OGRWAsPDataSource( const char * pszName, 
+                                           VSILFILE * hFile );
+                        ~OGRWAsPDataSource();
+
+    virtual const char *GetName() { return sFilename.c_str(); }
+    virtual int         GetLayerCount() { return oLayer.get() ? 1 : 0; }
+    virtual OGRLayer   *GetLayer( int );
+    virtual OGRLayer   *GetLayerByName( const char * );
+
+    virtual OGRLayer   *CreateLayer( const char *pszName, 
+                                     OGRSpatialReference *poSpatialRef = NULL,
+                                     OGRwkbGeometryType eGType = wkbUnknown,
+                                     char ** papszOptions = NULL );
+    
+    virtual int        TestCapability( const char * );
+    OGRErr             Load( bool bSilent = false );
+};
+
+/************************************************************************/
+/*                             OGRWAsPDriver                            */
+/************************************************************************/
+
+class OGRWAsPDriver : public OGRSFDriver
+{
+
+  public:
+                                ~OGRWAsPDriver() {}
+
+    virtual const char*         GetName() { return "WAsP"; }
+    virtual OGRDataSource*      Open( const char *, int );
+    
+    virtual OGRDataSource       *CreateDataSource( const char *pszName,
+                                                   char ** = NULL );
+
+    virtual OGRErr 	        DeleteDataSource (const char *pszName);
+
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_WASP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
new file mode 100644
index 0000000..1365c69
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
@@ -0,0 +1,300 @@
+/******************************************************************************
+ * $Id: ogrwaspdatasource.cpp 25307 2012-12-15 09:04:40Z rouault $
+ *
+ * Project:  WAsP Translator
+ * Purpose:  Implements OGRWAsPDataSource class
+ * Author:   Vincent Mora, vincent dot mora at oslandia dot com
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Oslandia <info at oslandia dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwasp.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+#include <cassert>
+#include <sstream>
+
+/************************************************************************/
+/*                          OGRWAsPDataSource()                          */
+/************************************************************************/
+
+OGRWAsPDataSource::OGRWAsPDataSource( const char * pszName, 
+                                      VSILFILE * hFileHandle )
+    : sFilename( pszName )
+    , hFile( hFileHandle )
+
+{
+}
+
+/************************************************************************/
+/*                         ~OGRWAsPDataSource()                          */
+/************************************************************************/
+
+OGRWAsPDataSource::~OGRWAsPDataSource()
+
+{
+    oLayer.reset(); /* we write to file int layer dtor */
+    VSIFCloseL( hFile ); /* nothing smart can be done here in case of error */
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRWAsPDataSource::TestCapability( const char * pszCap )
+
+{
+    return EQUAL(pszCap,ODsCCreateLayer) ;
+}
+
+/************************************************************************/
+/*                              GetLayerByName()                        */
+/************************************************************************/
+
+OGRLayer *OGRWAsPDataSource::GetLayerByName( const char * pszName )
+
+{
+    return ( oLayer.get() && EQUAL( pszName, oLayer->GetName() ) ) 
+        ? oLayer.get() 
+        : NULL;
+}
+
+/************************************************************************/
+/*                              Load()                                  */
+/************************************************************************/
+
+OGRErr OGRWAsPDataSource::Load(bool bSilent)
+
+{
+    /* if we don't have a layer, we read from file */
+    if ( oLayer.get() )
+    {
+        if (!bSilent) CPLError( CE_Failure, CPLE_NotSupported, "layer already loaded");
+        return OGRERR_FAILURE;
+    }
+    /* Parse the first line of the file in case it'a a spatial ref*/
+    const char * pszLine = CPLReadLine2L( hFile, 1024, NULL );
+    if ( !pszLine )
+    {
+        if (!bSilent) CPLError( CE_Failure, CPLE_FileIO, "empty file");
+        return OGRERR_FAILURE;
+    }
+    CPLString sLine( pszLine );
+    sLine = sLine.substr(0, sLine.find("|"));
+    OGRSpatialReference * poSpatialRef = new OGRSpatialReference;
+    if ( poSpatialRef->importFromProj4( sLine.c_str() ) != OGRERR_NONE )
+    {
+        if (!bSilent) CPLError( CE_Warning, CPLE_FileIO, "cannot find spatial reference");
+        delete poSpatialRef;
+        poSpatialRef = NULL;
+    }
+
+    /* TODO Parse those line since they define a coordinate transformation */
+    CPLReadLineL( hFile );
+    CPLReadLineL( hFile );
+    CPLReadLineL( hFile );
+
+    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(sFilename.c_str()), 
+                                    hFile, 
+                                    poSpatialRef ) );
+    if (poSpatialRef) poSpatialRef->Release();
+
+    const vsi_l_offset iOffset = VSIFTellL( hFile );
+    pszLine = CPLReadLineL( hFile );
+    if ( !pszLine ) 
+    {
+        if (!bSilent) CPLError( CE_Failure, CPLE_FileIO, "no feature in file");
+        oLayer.reset();
+        return OGRERR_FAILURE;
+    }
+    
+    double dfValues[4];
+    int iNumValues = 0;
+    {
+        std::istringstream iss(pszLine);
+        while ( iNumValues < 4 && (iss >> dfValues[iNumValues] ) ){ ++iNumValues; }
+
+        if ( iNumValues < 2 )
+        {
+            if (!bSilent && iNumValues) 
+                CPLError(CE_Failure, CPLE_FileIO, "no enough values" );
+            else if (!bSilent) 
+                CPLError(CE_Failure, CPLE_FileIO, "no feature in file" );
+
+            oLayer.reset();
+            return OGRERR_FAILURE;
+        }
+    }
+
+    if ( iNumValues == 3 || iNumValues == 4 )
+    {
+        OGRFieldDefn left("z_left", OFTReal);
+        OGRFieldDefn right("z_right", OFTReal);
+        oLayer->CreateField( &left );
+        oLayer->CreateField( &right );
+    }
+    if ( iNumValues == 2 || iNumValues == 4 )
+    {
+        OGRFieldDefn height("elevation", OFTReal);
+        oLayer->CreateField( &height );
+    }
+
+    VSIFSeekL( hFile, iOffset, SEEK_SET );	
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+
+OGRLayer *OGRWAsPDataSource::GetLayer( int iLayer )
+
+{
+    return ( iLayer == 0 ) ? oLayer.get() : NULL;
+}
+
+
+/************************************************************************/
+/*                              CreateLayer()                           */
+/************************************************************************/
+
+OGRLayer *OGRWAsPDataSource::CreateLayer(const char *pszName, 
+                                     OGRSpatialReference *poSpatialRef,
+                                     OGRwkbGeometryType eGType,
+                                     char ** papszOptions)
+
+{
+
+    if ( eGType != wkbLineString
+      && eGType != wkbLineString25D
+      && eGType != wkbMultiLineString
+      && eGType != wkbMultiLineString25D
+      && eGType != wkbPolygon
+      && eGType != wkbPolygon25D
+      && eGType != wkbMultiPolygon
+      && eGType != wkbMultiPolygon25D )
+    {
+        CPLError( CE_Failure, 
+                CPLE_NotSupported, 
+                "unsupported geometry type %s", OGRGeometryTypeToName( eGType ) );
+        return NULL;
+    }
+
+    if ( !OGRGeometryFactory::haveGEOS() 
+            && ( eGType == wkbPolygon
+              || eGType == wkbPolygon25D
+              || eGType == wkbMultiPolygon
+              || eGType == wkbMultiPolygon25D ))
+    {
+        CPLError( CE_Failure, 
+                CPLE_NotSupported, 
+                "unsupported geometry type %s without GEOS support", OGRGeometryTypeToName( eGType ) );
+        return NULL;
+    }
+
+    if ( oLayer.get() )
+    {
+        CPLError( CE_Failure, 
+                CPLE_NotSupported, 
+                "this data source does not support more than one layer" );
+        return NULL;
+    }
+
+    CPLString sFirstField, sSecondField, sGeomField;
+
+    const char *pszFields = CSLFetchNameValue( papszOptions, "WASP_FIELDS" );
+    const CPLString sFields( pszFields ? pszFields : "" );
+    if ( ! sFields.empty() )
+    {
+        /* parse the coma separated list of fields */
+        const size_t iComa = sFields.find(',');
+        if ( std::string::npos != iComa )
+        {
+            sFirstField = sFields.substr(0, iComa); 
+            sSecondField = sFields.substr( iComa + 1 );
+        }
+        else
+        {
+            sFirstField = sFields;
+        }
+    }
+
+    const char *pszGeomField = CSLFetchNameValue( papszOptions, "WASP_GEOM_FIELD" );
+    sGeomField = CPLString( pszGeomField ? pszGeomField : "" );
+
+    const bool bMerge = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "WASP_MERGE", "YES" ));
+
+    double * pdfTolerance = NULL;
+    const char *pszToler = CSLFetchNameValue( papszOptions, "WASP_TOLERANCE" );
+
+    if (pszToler)
+    {
+        if ( !OGRGeometryFactory::haveGEOS() )
+        {
+            CPLError( CE_Warning, 
+                    CPLE_IllegalArg, 
+                    "GEOS support not enabled, ignoring option WASP_TOLERANCE" );
+        }
+        else
+        {
+            pdfTolerance = new double;
+            if (!(std::istringstream( pszToler ) >> *pdfTolerance ))
+            {
+                delete pdfTolerance;
+                CPLError( CE_Failure, 
+                        CPLE_IllegalArg, 
+                        "cannot set tolerance from %s", pszToler );
+                return NULL;
+            }
+        }
+    }
+
+    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(pszName), 
+                                    hFile, 
+                                    poSpatialRef,
+                                    sFirstField, 
+                                    sSecondField,
+                                    sGeomField,
+                                    bMerge,
+                                    pdfTolerance ) );
+
+    char * ppszWktSpatialRef = NULL ;
+    if ( poSpatialRef 
+            && poSpatialRef->exportToProj4( &ppszWktSpatialRef ) == OGRERR_NONE )
+    {
+        VSIFPrintfL( hFile, "%s\n", ppszWktSpatialRef );
+        OGRFree( ppszWktSpatialRef );
+    }
+    else
+    {
+        VSIFPrintfL( hFile, "no spatial ref sys\n" );
+    }
+
+    VSIFPrintfL( hFile, "    0.0 0.0 0.0 0.0\n" );
+    VSIFPrintfL( hFile, "    1.0 0.0 1.0 0.0\n" );
+    VSIFPrintfL( hFile, "    1.0 0.0\n" );
+    return oLayer.get();
+}
+
+
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
new file mode 100644
index 0000000..7b0bc76
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * Project:  WAsP Translator
+ * Purpose:  Implements OGRWAsPDriver.
+ * Author:   Vincent Mora, vincent dot mora at oslandia dot com
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Oslandia <info at oslandia dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwasp.h"
+#include "cpl_conv.h"
+#include <cassert>
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRWAsPDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    if (bUpdate)
+    {
+        return NULL;
+    }
+
+    if (!EQUAL(CPLGetExtension(pszFilename), "map"))
+    {
+        return NULL;
+    }
+
+    VSILFILE * fh = VSIFOpenL( pszFilename, "r" );
+    if ( !fh )
+    {
+        /*CPLError( CE_Failure, CPLE_FileIO, "cannot open file %s", pszFilename );*/
+        return NULL;
+    }
+    std::auto_ptr<OGRWAsPDataSource> pDataSource( new OGRWAsPDataSource( pszFilename, fh ));
+
+    if ( pDataSource->Load(true) != OGRERR_NONE )
+    {
+        return NULL;
+    }
+    return pDataSource.release();
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRWAsPDriver::TestCapability( const char * pszCap )
+
+{
+    return EQUAL(pszCap,ODrCCreateDataSource) 
+        || EQUAL(pszCap,ODrCDeleteDataSource);
+}
+
+/************************************************************************/
+/*                           CreateDataSource()                           */
+/************************************************************************/
+
+OGRDataSource * OGRWAsPDriver::CreateDataSource( const char *pszName, char ** )
+
+{
+    VSILFILE * fh = VSIFOpenL( pszName, "w" );
+    if ( !fh )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "cannot open file %s", pszName );
+        return NULL;
+    }
+    return new OGRWAsPDataSource( pszName, fh );
+}
+
+/************************************************************************/
+/*                           DeleteDataSource()                         */
+/************************************************************************/
+
+OGRErr OGRWAsPDriver::DeleteDataSource (const char *pszName)
+
+{
+    return VSIUnlink( pszName ) == 0 ? OGRERR_NONE : OGRERR_FAILURE;  	
+}
+
+/************************************************************************/
+/*                           RegisterOGRWAsP()                           */
+/************************************************************************/
+
+void RegisterOGRWAsP()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRWAsPDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
new file mode 100644
index 0000000..f06bf36
--- /dev/null
+++ b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
@@ -0,0 +1,827 @@
+/******************************************************************************
+ *
+ * Project:  WAsP Translator
+ * Purpose:  Implements OGRWAsPLayer class.
+ * Author:   Vincent Mora, vincent dot mora at oslandia dot com
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Oslandia <info at oslandia dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrwasp.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogrsf_frmts.h"
+
+#include <cassert>
+#include <sstream>
+#include <map>
+
+/************************************************************************/
+/*                            OGRWAsPLayer()                             */
+/************************************************************************/
+
+OGRWAsPLayer::OGRWAsPLayer( const char * pszName, 
+                            VSILFILE * hFileHandle,
+                            OGRSpatialReference * poSpatialRef )
+    : bMerge( false )
+    , iFeatureCount(0)
+    , sName( pszName )
+    , hFile( hFileHandle )
+    , iFirstFieldIdx( 0 )
+    , iSecondFieldIdx( 1 )
+    , iGeomFieldIdx( 0 )
+    , poLayerDefn( new OGRFeatureDefn( pszName ) )
+    , poSpatialReference( poSpatialRef )
+    , iOffsetFeatureBegin( VSIFTellL( hFile ) )
+    , eMode( READ_ONLY )
+
+{
+    poLayerDefn->Reference();
+    poLayerDefn->SetGeomType( wkbLineString25D );
+    poLayerDefn->GetGeomFieldDefn(0)->SetType( wkbLineString25D );
+    poLayerDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSpatialReference );
+    if (poSpatialReference) poSpatialReference->Reference();
+}
+
+OGRWAsPLayer::OGRWAsPLayer( const char * pszName, 
+                            VSILFILE * hFileHandle,
+                            OGRSpatialReference * poSpatialRef,
+                            const CPLString & sFirstFieldParam,
+                            const CPLString & sSecondFieldParam,
+                            const CPLString & sGeomFieldParam,
+                            bool bMergeParam,
+                            double * pdfToleranceParam )
+    : bMerge( bMergeParam )
+    , iFeatureCount(0)
+    , sName( pszName )
+    , hFile( hFileHandle )
+    , sFirstField( sFirstFieldParam )
+    , sSecondField( sSecondFieldParam )
+    , sGeomField( sGeomFieldParam )
+    , iFirstFieldIdx( -1 )
+    , iSecondFieldIdx( -1 )
+    , iGeomFieldIdx( sGeomFieldParam.empty() ? 0 : -1 )
+    , poLayerDefn( new OGRFeatureDefn( pszName ) )
+    , poSpatialReference( poSpatialRef )
+    , iOffsetFeatureBegin( VSIFTellL( hFile ) ) /* avoids coverity warning */
+    , eMode( WRITE_ONLY )
+    , pdfTolerance( pdfToleranceParam )
+
+{
+    poLayerDefn->Reference();
+    if (poSpatialReference) poSpatialReference->Reference();
+}
+
+/************************************************************************/
+/*                            ~OGRWAsPLayer()                            */
+/************************************************************************/
+
+OGRWAsPLayer::~OGRWAsPLayer()
+
+{    
+    if ( bMerge )
+    {
+        /* If polygon where used, we have to merge lines before output */
+        /* lines must be merged if they have the same left/right values */
+        /* and touch at end points. */
+        /* Those lines appear when polygon with the same roughness touch */
+        /* since the boundary between them is not wanted */
+        /* We do it here since we are sure we have all polygons */
+        /* We first detect touching lines, then the kind of touching, */
+        /* candidates for merging are pairs of neighbors with corresponding */
+        /* left/right values. Finally we merge */
+
+        typedef std::map< std::pair<double,double>, std::vector<int> > PointMap;
+        PointMap oMap;
+        for ( size_t i = 0; i < oBoundaries.size(); i++)
+        {
+            const Boundary & p = oBoundaries[i]; 
+            OGRPoint startP, endP;
+            p.poLine->StartPoint( &startP );
+            p.poLine->EndPoint( &endP );
+            oMap[ std::make_pair(startP.getX(), startP.getY()) ].push_back( i );
+            oMap[ std::make_pair(endP.getX(), endP.getY()) ].push_back( i ); 
+        }
+
+        std::vector<int> endNeighbors( oBoundaries.size(), -1 );
+        std::vector<int> startNeighbors( oBoundaries.size(), -1 );
+        for ( PointMap::const_iterator it = oMap.begin(); it != oMap.end(); it++ )
+        {
+            if ( it->second.size() != 2 ) continue;
+            int i = it->second[0];
+            int j = it->second[1];
+
+            const Boundary & p = oBoundaries[i]; 
+            OGRPoint startP, endP;
+            p.poLine->StartPoint( &startP );
+            p.poLine->EndPoint( &endP );
+            const Boundary & q = oBoundaries[j]; 
+            OGRPoint startQ, endQ;
+            q.poLine->StartPoint( &startQ );
+            q.poLine->EndPoint( &endQ );
+            if ( isEqual( p.dfRight, q.dfRight) && isEqual( p.dfLeft, q.dfLeft ) )
+            {
+                if ( endP.Equals( &startQ ) )
+                {
+                    endNeighbors[i] = j;
+                    startNeighbors[j] = i;
+                }
+                if ( endQ.Equals( &startP ) )
+                {
+                    endNeighbors[j] = i;
+                    startNeighbors[i] = j;
+                }
+            }
+            if ( isEqual( p.dfRight, q.dfLeft) && isEqual( p.dfRight, q.dfLeft ) )
+            {
+                if ( startP.Equals( &startQ ) )
+                {
+                    startNeighbors[i] = j;
+                    startNeighbors[j] = i;
+                }
+                if ( endP.Equals( &endQ ) )
+                {
+                    endNeighbors[j] = i;
+                    endNeighbors[i] = j;
+                }
+            }
+        }
+
+        /* output all end lines (one neighbor only) and all their neighbors*/
+        std::vector<bool> oHasBeenMerged( oBoundaries.size(), false);
+        for ( size_t i = 0; i < oBoundaries.size(); i++)
+        {
+            if ( !oHasBeenMerged[i] && ( startNeighbors[i] < 0 || endNeighbors[i] < 0 ) )
+            {
+                oHasBeenMerged[i] = true;
+                Boundary * p = &oBoundaries[i];
+                int j =  startNeighbors[i] < 0 ? endNeighbors[i] : startNeighbors[i];
+                if ( startNeighbors[i] >= 0 )
+                {
+                    /* reverse the line and left/right */
+                    p->poLine->reversePoints();
+                    std::swap( p->dfLeft, p->dfRight );
+                }
+                while ( j >= 0 )
+                {
+                    assert( !oHasBeenMerged[j] );
+                    oHasBeenMerged[j] = true;
+
+                    OGRLineString * other = oBoundaries[j].poLine;
+                    OGRPoint endP, startOther;
+                    p->poLine->EndPoint( &endP );
+                    other->StartPoint( &startOther );
+                    if ( !endP.Equals( &startOther ) ) other->reversePoints();
+                    p->poLine->addSubLineString( other, 1 );
+
+                    /* next neighbor */
+                    if ( endNeighbors[j] >= 0 && !oHasBeenMerged[endNeighbors[j]] )
+                        j = endNeighbors[j];
+                    else if ( startNeighbors[j] >= 0 && !oHasBeenMerged[startNeighbors[j]] )
+                        j = startNeighbors[j];
+                    else
+                        j = -1;
+                }
+                WriteRoughness( p->poLine, p->dfLeft, p->dfRight );
+            }
+        }
+        /* output all rings */
+        for ( size_t i = 0; i < oBoundaries.size(); i++)
+        {
+            if ( oHasBeenMerged[i] ) continue;
+            oHasBeenMerged[i] = true;
+            Boundary * p = &oBoundaries[i];
+            int j =  startNeighbors[i] < 0 ? endNeighbors[i] : startNeighbors[i];
+            assert( j != -1 );
+            if ( startNeighbors[i] >= 0 )
+            {
+                /* reverse the line and left/right */
+                p->poLine->reversePoints();
+                std::swap( p->dfLeft, p->dfRight );
+            }
+            while ( !oHasBeenMerged[j] )
+            {
+                oHasBeenMerged[j] = true;
+
+                OGRLineString * other = oBoundaries[j].poLine;
+                OGRPoint endP, startOther;
+                p->poLine->EndPoint( &endP );
+                other->StartPoint( &startOther );
+                if ( !endP.Equals( &startOther ) ) other->reversePoints();
+                p->poLine->addSubLineString( other, 1 );
+
+                /* next neighbor */
+                if ( endNeighbors[j] >= 0  )
+                    j = endNeighbors[j];
+                else if ( startNeighbors[j] >= 0 )
+                    j = startNeighbors[j];
+                else
+                    assert(false); /* there must be a neighbor since it's a ring */
+            }
+            WriteRoughness( p->poLine, p->dfLeft, p->dfRight );
+        }
+    }
+    else
+    {
+        for ( size_t i = 0; i < oBoundaries.size(); i++)
+        {
+            Boundary * p = &oBoundaries[i];
+            WriteRoughness( p->poLine, p->dfLeft, p->dfRight );
+        }
+    }
+    poLayerDefn->Release();
+    if (poSpatialReference) poSpatialReference->Release();
+    for ( size_t i=0; i<oZones.size(); i++) delete oZones[i].poPolygon;
+    for ( size_t i = 0; i < oBoundaries.size(); i++) delete oBoundaries[i].poLine;
+}
+
+/************************************************************************/
+/*                            WriteElevation()                          */
+/************************************************************************/
+
+OGRErr OGRWAsPLayer::WriteElevation( OGRLineString * poGeom, const double & dfZ )
+
+{
+    OGRLineString * poLine = pdfTolerance.get() 
+        ? static_cast<OGRLineString *>(poGeom->Simplify( *pdfTolerance )) 
+        : poGeom; 
+
+    const int iNumPoints = poLine->getNumPoints();
+    if ( !iNumPoints ) return OGRERR_NONE; /* empty geom */
+
+    VSIFPrintfL( hFile, "    %g %d", dfZ, iNumPoints );
+
+    for (int v=0; v<iNumPoints; v++)
+    {
+        if (!(v%3)) VSIFPrintfL( hFile, "\n  " );
+        VSIFPrintfL( hFile, "%.16g %.16g ", poLine->getX(v), poLine->getY(v) );
+    }
+    VSIFPrintfL( hFile, "\n" );
+
+    if ( poLine != poGeom ) delete poLine;
+
+    return OGRERR_NONE;
+}
+
+OGRErr OGRWAsPLayer::WriteElevation( OGRGeometry * poGeom, const double & dfZ )
+
+{
+    switch ( poGeom->getGeometryType() )
+    {
+    case wkbLineString:
+    case wkbLineString25D:
+        return WriteElevation( static_cast<OGRLineString *>(poGeom), dfZ );
+    case wkbMultiLineString25D:
+    case wkbMultiLineString:
+    {
+        OGRGeometryCollection * collection =  static_cast<OGRGeometryCollection *>(poGeom);
+        for ( int i=0; i<collection->getNumGeometries(); i++ )
+        {
+            const OGRErr err = WriteElevation( collection->getGeometryRef(i), dfZ );
+            if ( OGRERR_NONE != err ) return err;
+        }
+        return OGRERR_NONE;
+    }
+    default: 
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot handle geometry of type %s", 
+                 OGRGeometryTypeToName( poGeom->getGeometryType() ) );
+        break;
+    }
+    }
+    return OGRERR_FAILURE; /* avoid visual warning */
+}
+
+
+/************************************************************************/
+/*                            WriteRoughness()                          */
+/************************************************************************/
+
+
+OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
+
+{
+    /* text intersection with polygons in the stack */
+    /* for linestrings intersections, write linestring */
+    /* for polygon intersection error */
+    /* for point intersection do nothing */
+
+    OGRErr err = OGRERR_NONE;
+    OGREnvelope oEnvelope;
+    poGeom->getEnvelope( &oEnvelope );
+    for ( size_t i=0; i<oZones.size(); i++)
+    {
+        const bool bIntersects = oEnvelope.Intersects( oZones[i].oEnvelope );
+        if ( bIntersects && ( !bMerge || !isEqual( dfZ, oZones[i].dfZ ) ) ) /* boundary */
+        {
+            OGRGeometry * poIntersection = oZones[i].poPolygon->Intersection( poGeom );
+            if ( poIntersection )
+            {
+                switch (poIntersection->getGeometryType())
+                {
+                case wkbLineString:
+                case wkbLineString25D:
+                {
+                    Boundary oB = {static_cast<OGRLineString *>(poIntersection->clone()), dfZ, oZones[i].dfZ };
+                    oBoundaries.push_back( oB );
+                }
+                break;
+                case wkbMultiLineString:
+                case wkbMultiLineString25D:
+                {
+                    /*TODO join the multilinestring into linestring*/
+                    OGRGeometryCollection * collection = static_cast<OGRGeometryCollection *>(poIntersection);
+                    OGRLineString * oLine = NULL;
+                    OGRPoint * oStart = new OGRPoint;
+                    OGRPoint * oEnd   = new OGRPoint;
+                    for ( int j=0; j<collection->getNumGeometries(); j++ )
+                    {
+                        OGRLineString * poLine = static_cast<OGRLineString *>(collection->getGeometryRef(j));
+                        assert(poLine);
+                        poLine->StartPoint( oStart );
+
+                        if ( !oLine || !oLine->getNumPoints() || oStart->Equals( oEnd ) )
+                        {
+                            if (oLine) oLine->addSubLineString ( poLine, 1 );
+                            else oLine = static_cast<OGRLineString *>( poLine->clone() );
+                            oLine->EndPoint( oEnd );
+                        }
+                        else
+                        {
+                            Boundary oB = {oLine, dfZ, oZones[i].dfZ};
+                            oBoundaries.push_back( oB );
+                            oLine = static_cast<OGRLineString *>( poLine->clone() );
+                            oLine->EndPoint( oEnd );
+                        }
+                    }
+                    Boundary oB = {oLine, dfZ, oZones[i].dfZ};
+                    oBoundaries.push_back( oB );
+                    delete oStart;
+                    delete oEnd;
+                }
+                break;
+                case wkbPolygon:
+                case wkbPolygon25D:
+                {
+                            OGREnvelope oErrorRegion = oZones[i].oEnvelope;
+                            oErrorRegion.Intersect( oEnvelope );
+                            CPLError(CE_Failure, CPLE_NotSupported, 
+                                    "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
+                                    oErrorRegion.MinX, 
+                                    oErrorRegion.MinY, 
+                                    oErrorRegion.MaxX, 
+                                    oErrorRegion.MaxY );
+                            err = OGRERR_FAILURE;
+                }
+                break;
+                case wkbGeometryCollection:
+                case wkbGeometryCollection25D:
+                {
+                    OGRGeometryCollection * collection = static_cast<OGRGeometryCollection *>(poIntersection);
+                    for ( int j=0; j<collection->getNumGeometries(); j++ )
+                    {   
+                        const OGRwkbGeometryType eType = collection->getGeometryRef(j)->getGeometryType();
+                        if ( wkbFlatten(eType) == wkbPolygon )
+                        {
+                            OGREnvelope oErrorRegion = oZones[i].oEnvelope;
+                            oErrorRegion.Intersect( oEnvelope );
+                            CPLError(CE_Failure, CPLE_NotSupported, 
+                                    "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
+                                    oErrorRegion.MinX, 
+                                    oErrorRegion.MinY, 
+                                    oErrorRegion.MaxX, 
+                                    oErrorRegion.MaxY );
+                            err = OGRERR_FAILURE;
+                        }
+                    }
+                }
+                break;
+                case wkbPoint:
+                case wkbPoint25D:
+                    /* do nothing */
+                break;
+                default:
+                    CPLError(CE_Failure, CPLE_NotSupported, 
+                            "Unhandled polygon intersection of type %s",
+                            OGRGeometryTypeToName( poIntersection->getGeometryType() ) );
+                    err = OGRERR_FAILURE;
+                }
+            }
+            delete poIntersection;
+        }
+    }
+
+    Zone oZ =  { oEnvelope, static_cast<OGRPolygon *>(poGeom->clone()), dfZ };
+    oZones.push_back( oZ ); 
+    return err;
+}
+
+OGRErr OGRWAsPLayer::WriteRoughness( OGRLineString * poGeom, const double & dfZleft,  const double & dfZright )
+
+{
+    OGRLineString * poLine = pdfTolerance.get() 
+        ? static_cast<OGRLineString *>(poGeom->Simplify( *pdfTolerance ))
+        : poGeom; 
+
+    const int iNumPoints = poLine->getNumPoints();
+    if ( !iNumPoints ) return OGRERR_NONE; /* empty geom */
+
+    VSIFPrintfL( hFile, "    %g %g %d", dfZleft, dfZright, iNumPoints );
+
+    for (int v=0; v<iNumPoints; v++)
+    {
+        if (!(v%3)) VSIFPrintfL( hFile, "\n  " );
+        VSIFPrintfL( hFile, "%.16g %.16g ", poLine->getX(v), poLine->getY(v) );
+    }
+    VSIFPrintfL( hFile, "\n" );
+
+    if ( poGeom != poLine ) delete poLine;
+
+    return OGRERR_NONE;
+}
+
+OGRErr OGRWAsPLayer::WriteRoughness( OGRGeometry * poGeom, const double & dfZleft,  const double & dfZright )
+
+{
+    switch ( poGeom->getGeometryType() )
+    {
+    case wkbLineString:
+    case wkbLineString25D:
+        return WriteRoughness( static_cast<OGRLineString *>(poGeom), dfZleft, dfZright );
+    case wkbPolygon:
+    case wkbPolygon25D:
+        return WriteRoughness( static_cast<OGRPolygon *>(poGeom), dfZleft );
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+    case wkbMultiLineString25D:
+    case wkbMultiLineString:
+    {
+        OGRGeometryCollection * collection =  static_cast<OGRGeometryCollection *>(poGeom);
+        for ( int i=0; i<collection->getNumGeometries(); i++ )
+        {
+            const OGRErr err = WriteRoughness( collection->getGeometryRef(i), dfZleft, dfZright );
+            if ( OGRERR_NONE != err ) return err;
+        }
+        return OGRERR_NONE;
+    }
+    default:
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot handle geometry of type %s", 
+                 OGRGeometryTypeToName( poGeom->getGeometryType() ) );
+        break;
+    }
+    }
+    return OGRERR_FAILURE; /* avoid visual warning */
+}
+
+/************************************************************************/
+/*                            CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRWAsPLayer::CreateFeature( OGRFeature * poFeature )
+
+{
+    if ( WRITE_ONLY != eMode)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg , "Layer is open read only" );
+        return OGRERR_FAILURE;
+    }
+
+    /* This mainly checks for errors or inconsistencies */
+    /* the real work is done by WriteElevation or WriteRoughness */
+    if ( -1 == iFirstFieldIdx && !sFirstField.empty() )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg , "Cannot find field %s", sFirstField.c_str() );
+        return OGRERR_FAILURE;
+    }
+    if ( -1 == iSecondFieldIdx && !sSecondField.empty() )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Cannot find field %s", sSecondField.c_str() );
+        return OGRERR_FAILURE;
+    }
+    if ( -1 == iGeomFieldIdx && !sGeomField.empty() )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Cannot find field %s", sSecondField.c_str() );
+        return OGRERR_FAILURE;
+    }
+    OGRGeometry * geom = poFeature->GetGeomFieldRef(iGeomFieldIdx);
+    if ( !geom ) return OGRERR_NONE; /* null geom, nothing to do */
+
+    const OGRwkbGeometryType geomType = geom->getGeometryType();
+    const double bPolygon = (geomType == wkbPolygon)
+                         || (geomType == wkbPolygon25D)
+                         || (geomType == wkbMultiPolygon)
+                         || (geomType == wkbMultiPolygon25D);
+    const bool bRoughness = (-1 != iSecondFieldIdx) || bPolygon ;
+
+
+    double z1;
+    if ( -1 != iFirstFieldIdx )
+    {
+        if (!poFeature->IsFieldSet(iFirstFieldIdx))
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iFirstFieldIdx, sFirstField.c_str() );
+            return OGRERR_FAILURE;
+        } 
+        z1 = poFeature->GetFieldAsDouble(iFirstFieldIdx);
+    }
+    else
+    {
+        /* Case of z value for elevation or roughness, so we compute it */
+        OGRPoint centroid;
+        if ( geom->getCoordinateDimension() != 3 )
+        {
+
+            CPLError(CE_Failure, CPLE_NotSupported, "No field defined and no Z coordinate" );
+            return OGRERR_FAILURE;
+        }
+        z1 = AvgZ( geom );
+    }
+
+    double z2;
+    if ( -1 != iSecondFieldIdx )
+    {
+        if (!poFeature->IsFieldSet(iSecondFieldIdx))
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iSecondFieldIdx, sSecondField.c_str() );
+            return OGRERR_FAILURE;
+        } 
+        z2 = poFeature->GetFieldAsDouble(iSecondFieldIdx);
+    }
+    else if ( bRoughness && !bPolygon )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "No right roughness field" );
+        return OGRERR_FAILURE;
+    }
+
+    return bRoughness ? WriteRoughness( geom, z1, z2 ) : WriteElevation( geom, z1 );
+}
+
+/************************************************************************/
+/*                            CreateField()                            */
+/************************************************************************/
+
+OGRErr OGRWAsPLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
+
+{
+    poLayerDefn->AddFieldDefn( poField );
+    
+    /* Update field indexes */
+    if ( -1 == iFirstFieldIdx && ! sFirstField.empty() )
+        iFirstFieldIdx = poLayerDefn->GetFieldIndex( sFirstField.c_str() );
+    if ( -1 == iSecondFieldIdx && ! sSecondField.empty() )
+        iSecondFieldIdx = poLayerDefn->GetFieldIndex( sSecondField.c_str() );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRWAsPLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
+                                      int bApproxOK )
+{
+    poLayerDefn->AddGeomFieldDefn( poGeomFieldIn, FALSE );
+
+    /* Update geom field index */
+    if ( -1 == iGeomFieldIdx )
+    {
+        iGeomFieldIdx = poLayerDefn->GetGeomFieldIndex( sGeomField.c_str() );
+    }
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRWAsPLayer::GetNextFeature()
+{
+    if ( READ_ONLY != eMode)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg , "Layer is open write only" );
+        return NULL;
+    }
+
+    OGRFeature  *poFeature;
+
+    GetLayerDefn();
+
+    while(TRUE)
+    {
+        poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+            return NULL;
+
+        if((m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            return poFeature;
+        }
+        else
+            delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           GetNextRawFeature()                        */
+/************************************************************************/
+
+OGRFeature *OGRWAsPLayer::GetNextRawFeature()
+
+{
+    const char * pszLine = CPLReadLineL( hFile );
+    if ( !pszLine ) return NULL;
+
+    double dfValues[4];
+    int iNumValues = 0;
+    {
+        std::istringstream iss(pszLine);
+        while ( iNumValues < 4 && (iss >> dfValues[iNumValues] ) ){ ++iNumValues ;}
+
+        if ( iNumValues < 2 )
+        {
+            if (iNumValues) CPLError(CE_Failure, CPLE_FileIO, "No enough values" );
+            return NULL;
+        }
+    }
+
+    if( poLayerDefn->GetFieldCount() != iNumValues-1 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "looking for %d values and found %d on line: %s", poLayerDefn->GetFieldCount(), iNumValues-1, pszLine );
+        return NULL;
+    }
+
+    std::auto_ptr< OGRFeature > poFeature( new OGRFeature( poLayerDefn ) );
+    poFeature->SetFID( ++iFeatureCount );
+    for ( int i=0; i<iNumValues-1; i++ ) poFeature->SetField( i, dfValues[i] );
+
+    const int iNumValuesToRead = 2*dfValues[iNumValues-1];
+    int iReadValues = 0;
+    std::vector<double> values(iNumValuesToRead);
+    for ( pszLine = CPLReadLineL( hFile ); 
+            pszLine; 
+            pszLine = iNumValuesToRead > iReadValues ? CPLReadLineL( hFile ) : NULL )
+    {
+        std::istringstream iss(pszLine);
+        while ( iNumValuesToRead > iReadValues && (iss >> values[iReadValues] ) ){++iReadValues;}
+    }
+    if ( iNumValuesToRead != iReadValues )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "No enough values for linestring" );
+        return NULL;
+    }
+    std::auto_ptr< OGRLineString > poLine( new OGRLineString );
+    poLine->setCoordinateDimension(3);
+    poLine->assignSpatialReference( poSpatialReference );
+    for ( int i=0; i<iNumValuesToRead; i+=2 )
+    {
+        poLine->addPoint( values[i], values[i+1], 0 );
+    }
+    poFeature->SetGeomFieldDirectly(0, poLine.release() );
+
+    return poFeature.release();
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRWAsPLayer::TestCapability( const char * pszCap )
+
+{
+    return ( WRITE_ONLY == eMode &&
+       (EQUAL(pszCap,OLCSequentialWrite) ||
+        EQUAL(pszCap,OLCCreateField) ||
+        EQUAL(pszCap,OLCCreateGeomField) ) );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+void OGRWAsPLayer::ResetReading()
+{
+    iFeatureCount = 0;
+    VSIFSeekL( hFile, iOffsetFeatureBegin, SEEK_SET );	
+}
+
+
+/************************************************************************/
+/*                           AvgZ()                                     */
+/************************************************************************/
+
+double OGRWAsPLayer::AvgZ( OGRLineString * poGeom )
+
+{
+    const int iNumPoints = poGeom->getNumPoints();
+    double sum = 0;
+    for (int v=0; v<iNumPoints; v++)
+    {
+        sum += poGeom->getZ(v);
+    }
+    return iNumPoints ? sum/iNumPoints : 0;
+}
+
+double OGRWAsPLayer::AvgZ( OGRPolygon * poGeom )
+
+{
+    return AvgZ( poGeom->getExteriorRing() );
+}
+
+double OGRWAsPLayer::AvgZ( OGRGeometryCollection * poGeom )
+
+{
+    return poGeom->getNumGeometries() ? AvgZ( poGeom->getGeometryRef(0) ) : 0;
+}
+
+double OGRWAsPLayer::AvgZ( OGRGeometry * poGeom )
+
+{
+    switch ( poGeom->getGeometryType() )
+    {
+    case wkbLineString:
+    case wkbLineString25D:
+        return AvgZ( static_cast< OGRLineString * >(poGeom) );
+    case wkbPolygon:
+    case wkbPolygon25D:
+        return AvgZ( static_cast< OGRPolygon * >(poGeom) );
+    case wkbMultiLineString:
+    case wkbMultiLineString25D:
+
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+        return AvgZ( static_cast< OGRGeometryCollection * >(poGeom) );
+    default: 
+        CPLError( CE_Warning, CPLE_NotSupported, "Unsuported geometry type in OGRWAsPLayer::AvgZ()");
+        break;
+    }
+    return 0; /* avoid warning */
+}
+
+
+
+/************************************************************************/
+/*                           DouglasPeucker()                           */
+/************************************************************************/
+
+//void DouglasPeucker(PointList[], epsilon)
+//
+//{
+//    // Find the point with the maximum distance
+//    double dmax = 0;
+//    int index = 0;
+//    int end = length(PointList).
+//    for (int i = 1; i<end; i++)
+//    {
+//        const double d = shortestDistanceToSegment(PointList[i], Line(PointList[0], PointList[end])) 
+//        if ( d > dmax )
+//        {
+//            index = i
+//            dmax = d
+//        }
+//    }
+//    // If max distance is greater than epsilon, recursively simplify
+//    if ( dmax > epsilon ) 
+//    {
+//        // Recursive call
+//        recResults1[] = DouglasPeucker(PointList[1...index], epsilon)
+//        recResults2[] = DouglasPeucker(PointList[index...end], epsilon)
+// 
+//        // Build the result list
+//        ResultList[] = {recResults1[1...end-1] recResults2[1...end]}
+//    } 
+//    else 
+//    {
+//        ResultList[] = {PointList[1], PointList[end]}
+//    }
+//    // Return the result
+//    return ResultList[]
+//}
+
diff --git a/ogr/ogrsf_frmts/wfs/ogr_wfs.h b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
index 1561315..cc822d3 100644
--- a/ogr/ogrsf_frmts/wfs/ogr_wfs.h
+++ b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_wfs.h 25517 2013-01-17 21:10:41Z rouault $
+ * $Id: ogr_wfs.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Definition of classes for OGR WFS driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -52,6 +52,7 @@ const char* FindSubStringInsensitive(const char* pszStr,
                                      const char* pszSubStr);
 
 CPLString WFS_EscapeURL(const char* pszURL);
+CPLString WFS_DecodeURL(const CPLString &osSrc);
 
 /************************************************************************/
 /*                             OGRWFSLayer                              */
@@ -149,12 +150,8 @@ class OGRWFSLayer : public OGRLayer
 
     virtual OGRFeatureDefn *    GetLayerDefn();
 
-    virtual const char *GetGeometryColumn() { return osGeometryColumnName; }
-
     virtual int                 TestCapability( const char * );
 
-    virtual OGRSpatialReference *GetSpatialRef();
-
     virtual void        SetSpatialFilter( OGRGeometry * );
 
     virtual OGRErr      SetAttributeFilter( const char * );
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
index 483f9c8..d687e52 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrwfsdatasource.cpp 25727 2013-03-10 14:56:33Z rouault $
+ * $Id: ogrwfsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsdatasource.cpp 25727 2013-03-10 14:56:33Z rouault $");
+CPL_CVSID("$Id: ogrwfsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define DEFAULT_BASE_START_INDEX     0
 #define DEFAULT_PAGE_SIZE            100
@@ -685,7 +685,10 @@ CPLHTTPResult* OGRWFSDataSource::SendGetCapabilities(const char* pszBaseURL,
     osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
     osTypeName = CPLURLGetValue(osURL, "TYPENAME");
+    if( osTypeName.size() == 0 )
+        osTypeName = CPLURLGetValue(osURL, "TYPENAMES");
     osURL = CPLURLAddKVP(osURL, "TYPENAME", NULL);
+    osURL = CPLURLAddKVP(osURL, "TYPENAMES", NULL);
     osURL = CPLURLAddKVP(osURL, "FILTER", NULL);
     osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", NULL);
     osURL = CPLURLAddKVP(osURL, "MAXFEATURES", NULL);
@@ -751,8 +754,9 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             strncmp(pszBaseURL, "https://", 8) != 0)
             return FALSE;
 
-        CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL,
-                                                      osTypeName);
+        CPLString strOriginalTypeName = "";
+        CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL, strOriginalTypeName);
+        osTypeName = WFS_DecodeURL(strOriginalTypeName);
         if (psResult == NULL)
         {
             return FALSE;
@@ -852,13 +856,17 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
         if( pszParm )
             nBaseStartIndex = atoi(pszParm);
 
-        osTypeName = CPLURLGetValue(pszBaseURL, "TYPENAME");
+        CPLString strOriginalTypeName = CPLURLGetValue(pszBaseURL, "TYPENAME");
+        if( strOriginalTypeName.size() == 0 )
+            strOriginalTypeName = CPLURLGetValue(pszBaseURL, "TYPENAMES");
+        osTypeName = WFS_DecodeURL(strOriginalTypeName);
 
         psWFSCapabilities = WFSFindNode( psRoot, "WFS_Capabilities" );
         if (psWFSCapabilities == NULL)
         {
-            CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL,
-                                                          osTypeName);
+            CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL, strOriginalTypeName);
+            osTypeName = WFS_DecodeURL(strOriginalTypeName);
+
             if (psResult == NULL)
             {
                 CPLDestroyXMLNode( psXML );
@@ -1796,6 +1804,32 @@ CPLString WFS_EscapeURL(const char* pszURL)
 }
 
 /************************************************************************/
+/*                         WFS_DecodeURL()                              */
+/************************************************************************/
+
+CPLString WFS_DecodeURL(const CPLString &osSrc)
+{
+    CPLString ret;
+    char ch;
+    int ii;
+    for (size_t i=0; i<osSrc.length(); i++) 
+    {
+        if (osSrc[i]=='%' && i+2 < osSrc.length())
+        {
+            sscanf(osSrc.substr(i+1,2).c_str(), "%x", &ii);
+            ch=static_cast<char>(ii);
+            ret+=ch;
+            i=i+2;
+        }
+        else 
+        {
+            ret+=osSrc[i];
+        }
+    }
+    return (ret);
+}
+
+/************************************************************************/
 /*                            HTTPFetch()                               */
 /************************************************************************/
 
@@ -1851,9 +1885,9 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
 /* -------------------------------------------------------------------- */
-/*      Use generic implementation for OGRSQL dialect.                  */
+/*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
-    if( pszDialect != NULL && (EQUAL(pszDialect,"OGRSQL") || EQUAL(pszDialect, "SQLITE")) )
+    if( IsGenericSQLDialect(pszDialect) )
     {
         OGRLayer* poResLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
                                                           poSpatialFilter,
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
index 105ed85..c66c78d 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/wfs/*.cpp -shared -o ogr_WFS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gml -Iogr/ogrsf_frmts/wfs -L. -lgdal
 
-CPL_CVSID("$Id: ogrwfsdriver.cpp 20280 2010-08-14 18:56:08Z rouault $");
+CPL_CVSID("$Id: ogrwfsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRWFS();
 
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
index 83b3516..f5eb724 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrwfsfilter.cpp 24791 2012-08-15 20:48:55Z rouault $
+ * $Id: ogrwfsfilter.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGR SQL into OGC Filter translation.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 
 #include "cpl_list.h"
 
-CPL_CVSID("$Id: ogrwfsfilter.cpp 24791 2012-08-15 20:48:55Z rouault $");
+CPL_CVSID("$Id: ogrwfsfilter.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef enum
 {
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index 6e68527..081d0b0 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 25760 2013-03-15 21:53:45Z rouault $
+ * $Id: ogrwfslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 25760 2013-03-15 21:53:45Z rouault $");
+CPL_CVSID("$Id: ogrwfslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /************************************************************************/
@@ -319,7 +319,9 @@ OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poC
     this->poGMLFeatureClass = poClass;
 
     OGRFeatureDefn* poFDefn = new OGRFeatureDefn( pszName );
-    poFDefn->SetGeomType( (OGRwkbGeometryType)poGMLFeatureClass->GetGeometryType() );
+    poFDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+    if( poGMLFeatureClass->GetGeometryPropertyCount() > 0 )
+        poFDefn->SetGeomType( (OGRwkbGeometryType)poGMLFeatureClass->GetGeometryProperty(0)->GetType() );
 
 /* -------------------------------------------------------------------- */
 /*      Added attributes (properties).                                  */
@@ -360,9 +362,16 @@ OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poC
         poFDefn->AddFieldDefn( &oField );
     }
 
-    const char* pszGeometryColumnName = poGMLFeatureClass->GetGeometryElement();
-    if (pszGeometryColumnName)
-        osGeometryColumnName = pszGeometryColumnName;
+    if( poGMLFeatureClass->GetGeometryPropertyCount() > 0 )
+    {
+        const char* pszGeometryColumnName = poGMLFeatureClass->GetGeometryProperty(0)->GetSrcElement();
+        if (pszGeometryColumnName[0] != '\0')
+        {
+            osGeometryColumnName = pszGeometryColumnName;
+            if( poFDefn->GetGeomFieldCount() > 0 )
+                poFDefn->GetGeomFieldDefn(0)->SetName(pszGeometryColumnName);
+        }
+    }
 
     return poFDefn;
 }
@@ -377,7 +386,10 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
     osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
     osURL = CPLURLAddKVP(osURL, "VERSION", poDS->GetVersion());
     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetFeature");
-    osURL = CPLURLAddKVP(osURL, "TYPENAME", WFS_EscapeURL(pszName));
+    if( atoi(poDS->GetVersion()) >= 2 )
+        osURL = CPLURLAddKVP(osURL, "TYPENAMES", WFS_EscapeURL(pszName));
+    else
+        osURL = CPLURLAddKVP(osURL, "TYPENAME", WFS_EscapeURL(pszName));
     if (pszRequiredOutputFormat)
         osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", WFS_EscapeURL(pszRequiredOutputFormat));
 
@@ -970,6 +982,7 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
     int bUnsetWidthPrecision = FALSE;
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     poFeatureDefn->Reference();
 
     OGRDataSource* poDS = NULL;
@@ -1025,16 +1038,6 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRWFSLayer::GetSpatialRef()
-{
-    GetLayerDefn();
-    return poSRS;
-}
-
-/************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
 
@@ -1691,7 +1694,8 @@ OGRErr OGRWFSLayer::CreateFeature( OGRFeature *poFeature )
     int i;
     for(i=1; i <= poFeature->GetFieldCount(); i++)
     {
-        if (poGMLFeatureClass->GetGeometryAttributeIndex() == i - 1)
+        if (poGMLFeatureClass->GetGeometryPropertyCount() == 1 &&
+            poGMLFeatureClass->GetGeometryProperty(0)->GetAttributeIndex() == i - 1)
         {
             OGRGeometry* poGeom = poFeature->GetGeometryRef();
             if (poGeom != NULL && osGeometryColumnName.size() != 0)
diff --git a/ogr/ogrsf_frmts/xls/ogr_xls.h b/ogr/ogrsf_frmts/xls/ogr_xls.h
index ebdc91f..3271f1c 100644
--- a/ogr/ogrsf_frmts/xls/ogr_xls.h
+++ b/ogr/ogrsf_frmts/xls/ogr_xls.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_xls.h 23694 2012-01-03 22:03:47Z rouault $
+ * $Id: ogr_xls.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Definition of classes for OGR .xls driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
index 2a38a6e..dc945f4 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrxlsdatasource.cpp 25307 2012-12-15 09:04:40Z rouault $
+ * $Id: ogrxlsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlsdatasource.cpp 25307 2012-12-15 09:04:40Z rouault $");
+CPL_CVSID("$Id: ogrxlsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRXLSDataSource()                          */
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
index fe21385..abd7529 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrxlsdriver.cpp 23381 2011-11-17 21:55:45Z rouault $
+ * $Id: ogrxlsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_xls.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsdriver.cpp 23381 2011-11-17 21:55:45Z rouault $");
+CPL_CVSID("$Id: ogrxlsdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRXLSDriver()                            */
diff --git a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
index 8a935ea..4840110 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrxlslayer.cpp 24172 2012-03-29 19:16:09Z rouault $
+ * $Id: ogrxlslayer.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlslayer.cpp 24172 2012-03-29 19:16:09Z rouault $");
+CPL_CVSID("$Id: ogrxlslayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRXLSLayer()                             */
diff --git a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
index dc47717..eab13e1 100644
--- a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
+++ b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_xlsx.h 24173 2012-03-29 21:09:52Z rouault $
+ * $Id: ogr_xlsx.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
index 406ab92..091ff46 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrxlsxdatasource.cpp 24173 2012-03-29 21:09:52Z rouault $
+ * $Id: ogrxlsxdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: ogrxlsxdatasource.cpp 24173 2012-03-29 21:09:52Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRXLSXLayer()                            */
@@ -1154,10 +1154,11 @@ void OGRXLSXDataSource::startElementWBCbk(const char *pszName,
     if (strcmp(pszName,"sheet") == 0)
     {
         const char* pszSheetName = GetAttributeValue(ppszAttr, "name", NULL);
-        const char* pszSheetId = GetAttributeValue(ppszAttr, "sheetId", NULL);
-        if (pszSheetName && pszSheetId)
+        /*const char* pszSheetId = GetAttributeValue(ppszAttr, "sheetId", NULL);*/
+        if (pszSheetName /*&& pszSheetId*/)
         {
-            int nSheetId = atoi(pszSheetId);
+            /*int nSheetId = atoi(pszSheetId);*/
+            int nSheetId = nLayers + 1;
             papoLayers = (OGRLayer**)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
             papoLayers[nLayers++] = new OGRXLSXLayer(this, nSheetId, pszSheetName);
         }
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
index 654589b..ee8af9f 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogrxlsxdriver.cpp 23816 2012-01-28 17:37:33Z rouault $
+ * $Id: ogrxlsxdriver.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_xlsx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsxdriver.cpp 23816 2012-01-28 17:37:33Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdriver.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 extern "C" void RegisterOGRXLSX();
 
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane.h b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
index f52ec62..693179d 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -73,7 +73,6 @@ class OGRXPlaneLayer : public OGRLayer
     virtual OGRFeature *      GetFeature( long nFID );
     virtual OGRErr            SetNextByIndex( long nIndex );
     virtual int               GetFeatureCount( int bForce = TRUE );
-    virtual OGRSpatialReference * GetSpatialRef() { return poSRS; }
 
     virtual OGRFeatureDefn *  GetLayerDefn();
     virtual int               TestCapability( const char * pszCap );
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
index 1d2d542..e41ac76 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_xplane_apt_reader.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 22627 2011-07-01 19:36:15Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 27118 2014-04-02 20:52:00Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAptFileReader                       */
@@ -182,7 +182,8 @@ void OGRXPlaneAptReader::Rewind()
 int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 {
     return EQUALN(pszVersionString, "850 Version", 11) ||
-           EQUALN(pszVersionString, "810 Version", 11);
+           EQUALN(pszVersionString, "810 Version", 11) ||
+           EQUALN(pszVersionString, "1000 Version", 12);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
index d380050..aeab6eb 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
index 7f301c2..1c46aef 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_awy_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAwyFileReader                       */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
index 5a5218d..78f07fa 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
index c474c79..373128e 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_fix_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateFixFileReader                       */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
index 02e9403..8772eda 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
index 0424906..2727322 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include <math.h>
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 18430 2010-01-03 15:10:02Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef M_PI
 # define M_PI  3.1415926535897932384626433832795
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
index 2d62b00..3220fd8 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
index 962ec57..7032e1a 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_nav_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateNavFileReader                       */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
index f3470b3..45b6d9b 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
index c414522..40aa20a 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $
+ * $Id: ogr_xplane_reader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /***********************************************************************/
 /*                       OGRXPlaneReader()                             */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
index d94785c..5bbb7ef 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
index 80232a7..dce05b4 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanedatasource.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogrxplanedatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                          OGRXPlaneDataSource()                          */
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
index 1f0117e..6acbdf5 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
index 722c733..fa93cea 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
@@ -6,7 +6,7 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanelayer.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogrxplanelayer.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRXPlaneLayer()                          */
@@ -52,6 +52,7 @@ OGRXPlaneLayer::OGRXPlaneLayer( const char* pszLayerName )
 
     poSRS = new OGRSpatialReference();
     poSRS->SetWellKnownGeogCS("WGS84");
+    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     poReader = NULL;
 }
diff --git a/ogr/ogrspatialreference.cpp b/ogr/ogrspatialreference.cpp
index b37c9d9..5f7e498 100644
--- a/ogr/ogrspatialreference.cpp
+++ b/ogr/ogrspatialreference.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrspatialreference.cpp 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: ogrspatialreference.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSpatialReference class.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_http.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: ogrspatialreference.cpp 25627 2013-02-10 10:17:19Z rouault $");
+CPL_CVSID("$Id: ogrspatialreference.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // The current opinion is that WKT longitudes like central meridian
 // should be relative to greenwich, not the prime meridian in use. 
@@ -1972,7 +1973,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
 
                 CPLString osName = poHorizSRS->GetChild(0)->GetValue();
                 osName += " + ";
-                osName += oVertSRS.GetRoot()->GetValue();
+                osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
 
                 SetNode( "COMPD_CS", osName );
                 GetRoot()->AddChild( poHorizSRS );
@@ -2452,7 +2453,7 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 
             CPLString osName = poHorizSRS->GetChild(0)->GetValue();
             osName += " + ";
-            osName += oVertSRS.GetRoot()->GetValue();
+            osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
 
             SetNode( "COMPD_CS", osName );
             GetRoot()->AddChild( poHorizSRS );
diff --git a/ogr/ogrutils.cpp b/ogr/ogrutils.cpp
index 09c40ad..98f3a0c 100644
--- a/ogr/ogrutils.cpp
+++ b/ogr/ogrutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrutils.cpp 25496 2013-01-13 21:20:35Z rouault $
+ * $Id: ogrutils.cpp 27121 2014-04-03 22:08:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility functions for OGR classes, including some related to
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,6 +29,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_conv.h"
 #include "cpl_vsi.h"
 
 #include <ctype.h>
@@ -39,7 +41,7 @@
 # include "ogrsf_frmts.h"
 #endif /* OGR_ENABLED */
 
-CPL_CVSID("$Id: ogrutils.cpp 25496 2013-01-13 21:20:35Z rouault $");
+CPL_CVSID("$Id: ogrutils.cpp 27121 2014-04-03 22:08:55Z rouault $");
 
 /************************************************************************/
 /*                        OGRFormatDouble()                             */
@@ -60,7 +62,7 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
         return;
     }
 
-    while(TRUE)
+    while(nPrecision > 0)
     {
         i = 0;
         int nCountBeforeDot = 0;
@@ -728,7 +730,7 @@ int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
         {
-            setlocale( LC_ALL, papszArgv[++iArg] );
+            CPLsetlocale( LC_ALL, papszArgv[++iArg] );
         }
 
 /* -------------------------------------------------------------------- */
@@ -1423,3 +1425,69 @@ OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
     CPLFree(panCheck);
     return eErr;
 }
+
+
+OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbGeometryType *peGeometryType, OGRBoolean *pbIs3D )
+{
+    if ( ! (peGeometryType && pbIs3D) )
+        return OGRERR_FAILURE;
+    
+/* -------------------------------------------------------------------- */
+/*      Get the byte order byte.                                        */
+/* -------------------------------------------------------------------- */
+    OGRwkbByteOrder eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
+    if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
+        return OGRERR_CORRUPT_DATA;
+
+/* -------------------------------------------------------------------- */
+/*      Get the geometry feature type.  For now we assume that          */
+/*      geometry type is between 0 and 255 so we only have to fetch     */
+/*      one byte.                                                       */
+/* -------------------------------------------------------------------- */
+    int bIs3D = FALSE;
+    int iRawType;
+    
+    memcpy(&iRawType, pabyData + 1, 4);
+    if ( OGR_SWAP(eByteOrder))
+    {
+        CPL_SWAP32PTR(&iRawType);
+    }
+    
+    /* Old-style OGC z-bit is flipped? */
+    if ( wkb25DBit & iRawType )
+    {
+        /* Clean off top 3 bytes */
+        iRawType &= 0x000000FF;
+        bIs3D = TRUE;        
+    }
+    
+    /* ISO SQL/MM style Z types (between 1001 and 1007)? */
+    if ( iRawType >= 1001 && iRawType <= 1007 )
+    {
+        /* Remove the ISO padding */
+        iRawType -= 1000;
+        bIs3D = TRUE;
+    }
+    
+    /* Sometimes the Z flag is in the 2nd byte? */
+    if ( iRawType & (wkb25DBit >> 16) )
+    {
+        /* Clean off top 3 bytes */
+        iRawType &= 0x000000FF;
+        bIs3D = TRUE;        
+    }
+
+    /* Nothing left but (hopefully) basic 2D types */
+
+    /* What if what we have is still out of range? */
+    if ( iRawType < 1 || iRawType > (int)wkbGeometryCollection )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported WKB type %d", iRawType);            
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+    }
+
+    *pbIs3D = bIs3D;
+    *peGeometryType = (OGRwkbGeometryType)iRawType;
+    
+    return OGRERR_NONE;
+}
diff --git a/ogr/osr_cs_wkt.c b/ogr/osr_cs_wkt.c
new file mode 100644
index 0000000..bbca2c2
--- /dev/null
+++ b/ogr/osr_cs_wkt.c
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * $Id: osr_cs_wkt.c 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  CS WKT parser
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#define EQUALN_CST(x,y)  (strncmp(x, y, strlen(y)) == 0)
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#include "osr_cs_wkt.h"
+
+/************************************************************************/
+/*                        osr_cs_wkt_error()                            */
+/************************************************************************/
+
+void osr_cs_wkt_error( osr_cs_wkt_parse_context *context, const char *msg )
+{
+    int i, n;
+    char* szPtr;
+    sprintf(context->szErrorMsg,
+            "Parsing error : %s. Error occured around:\n", msg );
+    n = context->pszLastSuccess - context->pszInput;
+
+    szPtr = context->szErrorMsg + strlen(context->szErrorMsg);
+    for( i = MAX(0,n-40); i < n + 40 && context->pszInput[i]; i ++ )
+        *(szPtr ++) = context->pszInput[i];
+    *(szPtr ++) = '\n';
+    for(i=0;i<MIN(n,40);i++)
+        *(szPtr ++) = ' ';
+    *(szPtr ++) = '^';
+    *(szPtr ++) = '\0';
+}
+
+typedef struct
+{
+    const char* pszToken;
+    int         nTokenVal;
+} osr_cs_wkt_tokens;
+
+#define PAIR(X) { #X, T_ ##X }
+
+static const osr_cs_wkt_tokens tokens[] =
+{
+    PAIR(PARAM_MT),
+    PAIR(PARAMETER),
+    PAIR(CONCAT_MT),
+    PAIR(INVERSE_MT),
+    PAIR(PASSTHROUGH_MT),
+
+    PAIR(PROJCS),
+    PAIR(PROJECTION),
+    PAIR(GEOGCS),
+    PAIR(DATUM),
+    PAIR(SPHEROID),
+    PAIR(PRIMEM),
+    PAIR(UNIT),
+    PAIR(GEOCCS),
+    PAIR(AUTHORITY),
+    PAIR(VERT_CS),
+    PAIR(VERT_DATUM),
+    PAIR(COMPD_CS),
+    PAIR(AXIS),
+    PAIR(TOWGS84),
+    PAIR(FITTED_CS),
+    PAIR(LOCAL_CS),
+    PAIR(LOCAL_DATUM),
+
+    PAIR(EXTENSION)
+};
+
+/************************************************************************/
+/*                         osr_cs_wkt_lex()                             */
+/************************************************************************/
+
+int osr_cs_wkt_lex(YYSTYPE* pNode, osr_cs_wkt_parse_context *context)
+{
+    size_t i;
+    const char *pszInput = context->pszNext;
+
+/* -------------------------------------------------------------------- */
+/*      Skip white space.                                               */
+/* -------------------------------------------------------------------- */
+    while( *pszInput == ' ' || *pszInput == '\t'
+           || *pszInput == 10 || *pszInput == 13 )
+        pszInput++;
+
+    context->pszLastSuccess = pszInput;
+
+    if( *pszInput == '\0' )
+    {
+        context->pszNext = pszInput;
+        return EOF; 
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recognize node names.                                           */
+/* -------------------------------------------------------------------- */
+    for(i = 0; i < sizeof(tokens) / sizeof(tokens[0]); i++)
+    {
+        if( EQUALN_CST(pszInput, tokens[i].pszToken) )
+        {
+            context->pszNext = pszInput + strlen(tokens[i].pszToken);
+            return tokens[i].nTokenVal;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recognize double quoted strings.                                */
+/* -------------------------------------------------------------------- */
+    if( *pszInput == '"' )
+    {
+        pszInput ++;
+        while( *pszInput != '\0' && *pszInput != '"' )
+            pszInput ++;
+        if(  *pszInput == '\0' )
+        {
+            context->pszNext = pszInput;
+            return EOF; 
+        }
+        context->pszNext = pszInput + 1;
+        return T_STRING;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recognize numerical values.                                     */
+/* -------------------------------------------------------------------- */
+
+    if( ((*pszInput == '-' || *pszInput == '+') &&
+            pszInput[1] >= '0' && pszInput[1] <= '9' ) ||
+        (*pszInput >= '0' && *pszInput <= '9') )
+    {
+        if( *pszInput == '-' || *pszInput == '+' )
+            pszInput ++;
+
+        // collect non-decimal part of number
+        while( *pszInput >= '0' && *pszInput <= '9' )
+            pszInput++;
+
+        // collect decimal places.
+        if( *pszInput == '.' )
+        {
+            pszInput++;
+            while( *pszInput >= '0' && *pszInput <= '9' )
+                pszInput++;
+        }
+
+        // collect exponent
+        if( *pszInput == 'e' || *pszInput == 'E' )
+        {
+            pszInput++;
+            if( *pszInput == '-' || *pszInput == '+' )
+                pszInput++;
+            while( *pszInput >= '0' && *pszInput <= '9' )
+                pszInput++;
+        }
+
+        context->pszNext = pszInput;
+
+        return T_NUMBER;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recognize identifiers.                                          */
+/* -------------------------------------------------------------------- */
+    if( (*pszInput >= 'A' && *pszInput <= 'Z') ||
+        (*pszInput >= 'a' && *pszInput <= 'z'))
+    {
+        pszInput ++;
+        while( (*pszInput >= 'A' && *pszInput <= 'Z') ||
+               (*pszInput >= 'a' && *pszInput <= 'z') )
+            pszInput ++;
+        context->pszNext = pszInput;
+        return T_IDENTIFIER;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle special tokens.                                          */
+/* -------------------------------------------------------------------- */
+    context->pszNext = pszInput+1;
+    return *pszInput;
+}
diff --git a/ogr/osr_cs_wkt.h b/ogr/osr_cs_wkt.h
new file mode 100644
index 0000000..4e3decc
--- /dev/null
+++ b/ogr/osr_cs_wkt.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * $Id: osr_cs_wkt.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  CS WKT parser
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _OSR_CS_WKT_H_INCLUDED_
+#define _OSR_CS_WKT_H_INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+    const char *pszInput;
+    const char *pszLastSuccess;
+    const char *pszNext;
+    char        szErrorMsg[512];
+} osr_cs_wkt_parse_context;
+
+#include "osr_cs_wkt_parser.h"
+
+void osr_cs_wkt_error( osr_cs_wkt_parse_context *context, const char *msg );
+int osr_cs_wkt_lex(YYSTYPE* pNode, osr_cs_wkt_parse_context *context);
+int osr_cs_wkt_parse(osr_cs_wkt_parse_context *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*  _OSR_CS_WKT_H_INCLUDED_ */
diff --git a/ogr/osr_cs_wkt_grammar.y b/ogr/osr_cs_wkt_grammar.y
new file mode 100644
index 0000000..ff13f31
--- /dev/null
+++ b/ogr/osr_cs_wkt_grammar.y
@@ -0,0 +1,304 @@
+%{
+/******************************************************************************
+ * $Id: osr_cs_wkt_grammar.y 26439 2013-09-11 11:10:48Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  CS WKT parser grammar
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013 Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "osr_cs_wkt.h"
+
+%}
+
+%define api.pure
+/* if the next %define is commented out, Bison 2.4 should be sufficient */
+/* but will produce less prettier error messages */
+%define parse.error verbose
+%require "3.0"
+
+%parse-param {osr_cs_wkt_parse_context *context}
+%lex-param {osr_cs_wkt_parse_context *context}
+
+%token T_PARAM_MT               "PARAM_MT"
+%token T_CONCAT_MT              "CONCAT_MT"
+%token T_INVERSE_MT             "INVERSE_MT"
+%token T_PASSTHROUGH_MT         "PASSTHROUGH_MT"
+%token T_PROJCS                 "PROJCS"
+%token T_PROJECTION             "PROJECTION"
+%token T_GEOGCS                 "GEOGCS"
+%token T_DATUM                  "DATUM"
+%token T_SPHEROID               "SPHEROID"
+%token T_PRIMEM                 "PRIMEM"
+%token T_UNIT                   "UNIT"
+%token T_GEOCCS                 "GEOCCS"
+%token T_AUTHORITY              "AUTHORITY"
+%token T_VERT_CS                "VERT_CS"
+%token T_VERT_DATUM             "VERT_DATUM"
+%token T_COMPD_CS               "COMPD_CS"
+%token T_AXIS                   "AXIS"
+%token T_TOWGS84                "TOWGS84"
+%token T_FITTED_CS              "FITTED_CS"
+%token T_LOCAL_CS               "LOCAL_CS"
+%token T_LOCAL_DATUM            "LOCAL_DATUM"
+%token T_PARAMETER              "PARAMETER"
+
+%token T_EXTENSION              "EXTENSION"
+
+%token T_STRING                 "string"
+%token T_NUMBER                 "number"
+%token T_IDENTIFIER             "identifier"
+
+%token END 0                    "end of string"
+
+%%
+
+input:
+    coordinate_system
+
+/* Derived from BNF grammar in OGC 01-009 OpenGIS Implementation */
+/* Coordinate Transformation Services Revision 1.00 */
+/* with the following additions : */
+/* - accept an EXTENSION node at the end of GEOGCS, PROJCS, COMPD_CS, VERT_DATUM */
+/* - accept 3 parameters in TOWGS84 */
+
+/* 7.1 Math Transform WKT */
+
+begin_node:
+    '['
+
+begin_node_name:
+    begin_node T_STRING
+
+end_node:
+    ']'
+
+math_transform:
+    param_mt | concat_mt | inv_mt | passthrough_mt
+
+param_mt:
+    T_PARAM_MT begin_node_name opt_parameter_list end_node
+
+parameter:
+    T_PARAMETER begin_node_name ',' T_NUMBER end_node
+
+opt_parameter_list:
+    ',' parameter
+    | ',' parameter opt_parameter_list
+
+concat_mt:
+    T_CONCAT_MT begin_node math_transform opt_math_transform_list end_node
+
+opt_math_transform_list:
+  | math_transform
+  | math_transform ',' opt_math_transform_list
+
+inv_mt:
+    T_INVERSE_MT begin_node math_transform end_node
+
+passthrough_mt:
+    T_PASSTHROUGH_MT begin_node integer ',' math_transform end_node
+
+/* FIXME */
+integer:
+    T_NUMBER
+
+/* 7.2 Coordinate System WKT */
+
+coordinate_system:
+    horz_cs | geocentric_cs | vert_cs | compd_cs | fitted_cs | local_cs
+
+horz_cs:
+    geographic_cs | projected_cs
+
+/* opt_extension is an extension of the CT spec */
+projected_cs:
+    T_PROJCS begin_node_name ',' geographic_cs ',' projection ','
+                    opt_parameter_list_linear_unit opt_twin_axis_authority_extension end_node
+
+opt_parameter_list_linear_unit:
+    linear_unit
+  | parameter_list_linear_unit
+
+parameter_list_linear_unit:
+    parameter ',' parameter_list_linear_unit
+  | parameter ',' linear_unit
+
+opt_twin_axis_authority_extension:
+    | ',' twin_axis opt_authority_extension
+    | ',' authority opt_extension
+    | ',' extension
+
+opt_extension:
+    | ',' extension
+
+extension:
+    T_EXTENSION begin_node_name ',' T_STRING end_node
+
+projection:
+    T_PROJECTION begin_node_name opt_authority end_node
+
+opt_authority:
+    | ',' authority
+
+geographic_cs:
+    T_GEOGCS begin_node_name',' datum ',' prime_meridian ','
+                    angular_unit opt_twin_axis_authority_extension end_node
+
+datum:
+    T_DATUM begin_node_name ',' spheroid opt_towgs84_authority_extension end_node
+
+opt_towgs84_authority_extension:
+    | ',' towgs84 opt_authority_extension
+    | ',' authority opt_extension
+    | ',' extension
+
+spheroid:
+    T_SPHEROID begin_node_name ',' semi_major_axis ','
+                        inverse_flattening opt_authority end_node
+
+semi_major_axis:
+    T_NUMBER
+
+inverse_flattening:
+    T_NUMBER
+
+prime_meridian:
+    T_PRIMEM begin_node_name ',' longitude opt_authority end_node
+
+longitude:
+    T_NUMBER
+
+angular_unit:
+    unit
+
+linear_unit:
+    unit
+
+unit:
+    T_UNIT begin_node_name ',' conversion_factor opt_authority end_node
+
+conversion_factor:
+    T_NUMBER
+
+geocentric_cs:
+    T_GEOCCS begin_node_name ',' datum ',' prime_meridian ','
+                        linear_unit opt_three_axis_authority end_node
+
+opt_three_axis_authority:
+    | ',' three_axis opt_authority
+    | ',' authority
+
+three_axis:
+    axis ',' axis ',' axis
+
+authority:
+    T_AUTHORITY begin_node_name ',' T_STRING end_node
+
+vert_cs:
+    T_VERT_CS begin_node_name ',' vert_datum ',' linear_unit opt_axis_authority end_node
+
+opt_axis_authority:
+    | ',' axis opt_authority
+    | ',' authority
+
+vert_datum:
+    T_VERT_DATUM begin_node_name ',' datum_type opt_authority_extension end_node
+
+opt_authority_extension:
+    | ',' authority opt_extension
+    | ',' extension
+
+datum_type:
+    T_NUMBER
+
+compd_cs:
+    T_COMPD_CS begin_node_name ',' head_cs ',' tail_cs opt_authority_extension end_node
+
+head_cs:
+    coordinate_system
+
+tail_cs:
+    coordinate_system
+
+twin_axis: axis ',' axis
+
+axis:
+    T_AXIS begin_node_name ',' T_IDENTIFIER end_node
+/* Extension of the CT spec */
+/*    | T_AXIS '[' T_STRING ',' T_STRING ']'*/
+
+towgs84:
+    T_TOWGS84 begin_node towgs84_parameters end_node
+
+towgs84_parameters:
+    seven_parameters
+/* Extension of the CT spec */
+  | three_parameters
+
+three_parameters:
+    dx ',' dy ',' dz
+
+seven_parameters:
+    dx ',' dy ',' dz ',' ex ',' ey ',' ez ',' ppm
+
+dx:
+    T_NUMBER
+
+dy:
+    T_NUMBER
+
+dz:
+    T_NUMBER
+
+ex:
+    T_NUMBER
+
+ey:
+    T_NUMBER
+
+ez:
+    T_NUMBER
+
+ppm:
+    T_NUMBER
+
+fitted_cs:
+    T_FITTED_CS begin_node_name ',' to_base ',' base_cs end_node
+
+to_base:
+    math_transform
+
+base_cs:
+    coordinate_system
+
+local_cs:
+    T_LOCAL_CS begin_node_name ',' local_datum ',' unit ',' axis opt_axis_list_authority end_node
+
+opt_axis_list_authority:
+    | ',' authority
+    | ',' axis opt_axis_list_authority
+
+local_datum:
+    T_LOCAL_DATUM begin_node_name ',' datum_type opt_authority end_node
diff --git a/ogr/osr_cs_wkt_parser.c b/ogr/osr_cs_wkt_parser.c
new file mode 100644
index 0000000..b0c1021
--- /dev/null
+++ b/ogr/osr_cs_wkt_parser.c
@@ -0,0 +1,1642 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         osr_cs_wkt_parse
+#define yylex           osr_cs_wkt_lex
+#define yyerror         osr_cs_wkt_error
+#define yydebug         osr_cs_wkt_debug
+#define yynerrs         osr_cs_wkt_nerrs
+
+
+/* Copy the first part of user declarations.  */
+
+
+/******************************************************************************
+ * $Id: osr_cs_wkt_parser.c 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  CS WKT parser grammar
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013 Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "osr_cs_wkt.h"
+
+
+
+
+# ifndef YY_NULL
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULL nullptr
+#  else
+#   define YY_NULL 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "osr_cs_wkt_parser.h".  */
+#ifndef YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED
+# define YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int osr_cs_wkt_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    END = 0,
+    T_PARAM_MT = 258,
+    T_CONCAT_MT = 259,
+    T_INVERSE_MT = 260,
+    T_PASSTHROUGH_MT = 261,
+    T_PROJCS = 262,
+    T_PROJECTION = 263,
+    T_GEOGCS = 264,
+    T_DATUM = 265,
+    T_SPHEROID = 266,
+    T_PRIMEM = 267,
+    T_UNIT = 268,
+    T_GEOCCS = 269,
+    T_AUTHORITY = 270,
+    T_VERT_CS = 271,
+    T_VERT_DATUM = 272,
+    T_COMPD_CS = 273,
+    T_AXIS = 274,
+    T_TOWGS84 = 275,
+    T_FITTED_CS = 276,
+    T_LOCAL_CS = 277,
+    T_LOCAL_DATUM = 278,
+    T_PARAMETER = 279,
+    T_EXTENSION = 280,
+    T_STRING = 281,
+    T_NUMBER = 282,
+    T_IDENTIFIER = 283
+  };
+#endif
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int osr_cs_wkt_parse (osr_cs_wkt_parse_context *context);
+
+#endif /* !YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+#  define __attribute__(Spec) /* empty */
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  27
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   198
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  32
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  67
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  98
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  254
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   283
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    31,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    29,     2,    30,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    78,    78,    89,    92,    95,    98,    98,    98,    98,
+     101,   104,   107,   108,   111,   113,   114,   115,   118,   121,
+     125,   130,   130,   130,   130,   130,   130,   133,   133,   137,
+     141,   142,   145,   146,   148,   149,   150,   151,   153,   154,
+     157,   160,   162,   163,   166,   170,   172,   173,   174,   175,
+     178,   182,   185,   188,   191,   194,   197,   200,   203,   206,
+     209,   210,   211,   214,   217,   220,   222,   223,   224,   227,
+     229,   230,   231,   234,   237,   240,   243,   245,   248,   253,
+     256,   258,   261,   264,   267,   270,   273,   276,   279,   282,
+     285,   288,   291,   294,   297,   299,   300,   301,   304
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "\"end of string\"", "error", "$undefined", "\"PARAM_MT\"",
+  "\"CONCAT_MT\"", "\"INVERSE_MT\"", "\"PASSTHROUGH_MT\"", "\"PROJCS\"",
+  "\"PROJECTION\"", "\"GEOGCS\"", "\"DATUM\"", "\"SPHEROID\"",
+  "\"PRIMEM\"", "\"UNIT\"", "\"GEOCCS\"", "\"AUTHORITY\"", "\"VERT_CS\"",
+  "\"VERT_DATUM\"", "\"COMPD_CS\"", "\"AXIS\"", "\"TOWGS84\"",
+  "\"FITTED_CS\"", "\"LOCAL_CS\"", "\"LOCAL_DATUM\"", "\"PARAMETER\"",
+  "\"EXTENSION\"", "\"string\"", "\"number\"", "\"identifier\"", "'['",
+  "']'", "','", "$accept", "input", "begin_node", "begin_node_name",
+  "end_node", "math_transform", "param_mt", "parameter",
+  "opt_parameter_list", "concat_mt", "opt_math_transform_list", "inv_mt",
+  "passthrough_mt", "integer", "coordinate_system", "horz_cs",
+  "projected_cs", "opt_parameter_list_linear_unit",
+  "parameter_list_linear_unit", "opt_twin_axis_authority_extension",
+  "opt_extension", "extension", "projection", "opt_authority",
+  "geographic_cs", "datum", "opt_towgs84_authority_extension", "spheroid",
+  "semi_major_axis", "inverse_flattening", "prime_meridian", "longitude",
+  "angular_unit", "linear_unit", "unit", "conversion_factor",
+  "geocentric_cs", "opt_three_axis_authority", "three_axis", "authority",
+  "vert_cs", "opt_axis_authority", "vert_datum", "opt_authority_extension",
+  "datum_type", "compd_cs", "head_cs", "tail_cs", "twin_axis", "axis",
+  "towgs84", "towgs84_parameters", "three_parameters", "seven_parameters",
+  "dx", "dy", "dz", "ex", "ey", "ez", "ppm", "fitted_cs", "to_base",
+  "base_cs", "local_cs", "opt_axis_list_authority", "local_datum", YY_NULL
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,    91,
+      93,    44
+};
+# endif
+
+#define YYPACT_NINF -148
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-148)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
+{
+      80,    -5,    -5,    -5,    -5,    -5,    -5,    -5,    27,  -148,
+    -148,  -148,  -148,  -148,  -148,  -148,  -148,  -148,  -148,     3,
+      -1,    11,    28,    34,    35,    39,    41,  -148,  -148,    49,
+      63,    63,    58,    80,   116,    54,    50,    -5,    57,    61,
+      -5,    64,  -148,    66,    -5,    -5,    -5,    -5,  -148,  -148,
+    -148,  -148,  -148,    68,    -5,    73,    72,    74,    95,    95,
+      77,    98,    80,    82,   116,   116,    87,    80,    92,    98,
+      -5,    93,   114,    -5,    96,    99,   104,    -5,   101,  -148,
+    -148,   102,   113,   108,   116,   108,  -148,   109,  -148,   108,
+     104,   112,   118,    10,    -5,   119,   120,    98,    98,  -148,
+     102,   121,    36,   108,    16,   108,    -5,    82,  -148,  -148,
+     122,   108,  -148,   116,  -148,   118,   126,   124,   108,   123,
+     125,  -148,  -148,   127,    37,   108,   128,   125,  -148,   129,
+     108,   130,    -5,    -5,  -148,   118,  -148,    -5,  -148,   131,
+    -148,   132,  -148,   116,  -148,   108,   108,   133,  -148,  -148,
+      10,    13,   108,   134,    -5,  -148,   131,   102,  -148,  -148,
+     118,   108,    36,   108,  -148,  -148,   118,   135,   136,  -148,
+     137,   140,  -148,   142,  -148,  -148,  -148,    36,   108,  -148,
+    -148,  -148,   131,   102,   139,  -148,  -148,   141,   144,  -148,
+    -148,   108,  -148,   118,  -148,   143,  -148,   108,   147,   148,
+     149,  -148,   108,  -148,   133,  -148,  -148,  -148,   126,   150,
+    -148,   108,  -148,  -148,   151,  -148,  -148,   126,  -148,   108,
+     108,   108,  -148,  -148,  -148,  -148,   118,  -148,   152,   153,
+    -148,  -148,  -148,   108,  -148,   154,   126,  -148,   156,  -148,
+    -148,   155,   160,  -148,   157,   162,  -148,   159,   164,  -148,
+     161,   166,  -148,  -148
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     2,
+      21,    28,    27,    22,    23,    24,    25,    26,     3,     0,
+       0,     0,     0,     0,     0,     0,     0,     1,     4,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    75,     0,     0,     0,     0,     0,    92,     6,
+       7,     8,     9,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    66,    56,
+      76,    70,     0,     0,    15,     0,    20,     0,    93,     0,
+       0,     0,    42,     0,     0,    46,     0,     0,     0,    73,
+      70,     0,     0,     0,     0,     0,     0,    12,     5,    10,
+      16,     0,    18,     0,    91,    42,     0,     0,     0,     0,
+      34,    31,    30,     0,     0,     0,     0,    34,    55,    60,
+       0,     0,     0,     0,    68,    42,    65,     0,    72,    38,
+      74,     0,    13,    15,    14,     0,     0,    95,    43,    41,
+       0,     0,     0,     0,     0,    49,    38,    70,    45,    54,
+      42,     0,     0,     0,    69,    58,    42,     0,     0,    67,
+       0,     0,    71,     0,    17,    19,    98,     0,     0,    32,
+      33,    37,    38,    70,     0,    29,    51,     0,     0,    48,
+      47,     0,    44,    42,    62,     0,    59,     0,     0,     0,
+       0,    39,     0,    96,    95,    94,    36,    35,     0,     0,
+      84,     0,    81,    80,     0,    53,    61,     0,    57,     0,
+       0,     0,    11,    97,    77,    52,    42,    79,     0,     0,
+      64,    78,    40,     0,    85,     0,     0,    50,     0,    63,
+      86,    82,     0,    87,     0,     0,    88,     0,     0,    89,
+       0,     0,    90,    83
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -148,  -148,   -44,     9,   -85,   -28,  -148,    65,    52,  -148,
+      38,  -148,  -148,  -148,   -23,  -148,  -148,  -148,    30,    51,
+    -147,  -103,  -148,  -110,   165,   167,  -148,  -148,  -148,  -148,
+     138,  -148,  -148,   -76,   -50,  -148,  -148,  -148,  -148,   -33,
+    -148,  -148,  -148,   -93,   105,  -148,  -148,  -148,  -148,  -108,
+    -148,  -148,  -148,  -148,  -148,  -148,  -148,  -148,  -148,  -148,
+    -148,  -148,  -148,  -148,  -148,    -8,  -148
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     8,    19,    20,   109,   110,    49,   119,    83,    50,
+     111,    51,    52,    87,     9,    10,    11,   120,   121,   152,
+     172,   138,    71,   118,    12,    38,   125,    95,   187,   226,
+      74,   160,   127,    78,    79,   166,    13,   163,   193,   134,
+      14,   103,    41,   105,   100,    15,    43,    81,   183,   135,
+     157,   211,   212,   213,   214,   235,   241,   244,   247,   250,
+     253,    16,    53,    89,    17,   178,    55
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+     112,    64,    65,    66,   114,   146,    48,   130,   147,   189,
+      42,    21,    22,    23,    24,    25,    26,   122,   136,    91,
+     140,   155,   129,    77,    18,   169,   144,    27,   132,    28,
+      29,   132,   133,   149,   106,   206,    84,    85,   137,    80,
+     158,   137,    30,   184,    88,   164,    57,   128,   181,    60,
+     191,   132,   132,    63,   195,   133,   197,   154,     2,    31,
+     175,   176,   137,    68,   190,    32,    33,   185,   201,   204,
+      34,   139,    35,    37,   180,    40,   192,    54,   196,    92,
+      70,    56,    96,   216,   148,   145,   101,     1,    58,     2,
+     207,   156,    59,   205,     3,    61,     4,    62,     5,    67,
+     224,     6,     7,   123,    69,    72,   215,    73,    76,   229,
+     188,    77,   218,    82,    86,   141,   233,   222,   182,    44,
+      45,    46,    47,    90,    93,    94,   227,    97,   239,   194,
+      98,    99,   102,   104,   230,   231,   232,   106,   108,   132,
+     113,   167,   168,   116,   203,   133,   170,   107,   237,   117,
+     124,   126,   131,   143,   150,   159,   151,   165,   153,   142,
+     162,   186,   171,   173,   177,   137,   198,   199,   200,   202,
+     208,   210,   209,   219,   217,   221,   220,   225,   161,   234,
+     179,   174,   228,   240,   236,   238,   242,   243,   245,   246,
+     248,   249,   251,   252,    36,   115,   223,    75,    39
+};
+
+static const yytype_uint8 yycheck[] =
+{
+      85,    45,    46,    47,    89,   115,    34,   100,   116,   156,
+      33,     2,     3,     4,     5,     6,     7,    93,   103,    69,
+     105,   124,    98,    13,    29,   135,   111,     0,    15,    26,
+      31,    15,    19,   118,    24,   182,    64,    65,    25,    62,
+     125,    25,    31,   151,    67,   130,    37,    97,   151,    40,
+     160,    15,    15,    44,   162,    19,   166,    20,     9,    31,
+     145,   146,    25,    54,   157,    31,    31,   152,   171,   177,
+      31,   104,    31,    10,   150,    17,   161,    23,   163,    70,
+       8,    31,    73,   193,   117,   113,    77,     7,    31,     9,
+     183,   124,    31,   178,    14,    31,    16,    31,    18,    31,
+     208,    21,    22,    94,    31,    31,   191,    12,    31,   217,
+     154,    13,   197,    31,    27,   106,   226,   202,   151,     3,
+       4,     5,     6,    31,    31,    11,   211,    31,   236,   162,
+      31,    27,    31,    31,   219,   220,   221,    24,    30,    15,
+      31,   132,   133,    31,   177,    19,   137,    82,   233,    31,
+      31,    31,    31,    31,    31,    27,    31,    27,    31,   107,
+      31,    27,    31,    31,    31,    25,    31,    31,    31,    27,
+      31,    27,    31,    26,    31,    26,    28,    27,   127,    27,
+     150,   143,    31,    27,    31,    31,    31,    27,    31,    27,
+      31,    27,    31,    27,    29,    90,   204,    59,    31
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     7,     9,    14,    16,    18,    21,    22,    33,    46,
+      47,    48,    56,    68,    72,    77,    93,    96,    29,    34,
+      35,    35,    35,    35,    35,    35,    35,     0,    26,    31,
+      31,    31,    31,    31,    31,    31,    56,    10,    57,    57,
+      17,    74,    46,    78,     3,     4,     5,     6,    37,    38,
+      41,    43,    44,    94,    23,    98,    31,    35,    31,    31,
+      35,    31,    31,    35,    34,    34,    34,    31,    35,    31,
+       8,    54,    31,    12,    62,    62,    31,    13,    65,    66,
+      46,    79,    31,    40,    37,    37,    27,    45,    46,    95,
+      31,    66,    35,    31,    11,    59,    35,    31,    31,    27,
+      76,    35,    31,    73,    31,    75,    24,    39,    30,    36,
+      37,    42,    36,    31,    36,    76,    31,    31,    55,    39,
+      49,    50,    65,    35,    31,    58,    31,    64,    66,    65,
+      75,    31,    15,    19,    71,    81,    36,    25,    53,    71,
+      36,    35,    40,    31,    36,    37,    55,    81,    71,    36,
+      31,    31,    51,    31,    20,    53,    71,    82,    36,    27,
+      63,    51,    31,    69,    36,    27,    67,    35,    35,    55,
+      35,    31,    52,    31,    42,    36,    36,    31,    97,    50,
+      65,    53,    71,    80,    81,    36,    27,    60,    34,    52,
+      75,    55,    36,    70,    71,    81,    36,    55,    31,    31,
+      31,    53,    27,    71,    81,    36,    52,    75,    31,    31,
+      27,    83,    84,    85,    86,    36,    55,    31,    36,    26,
+      28,    26,    36,    97,    81,    27,    61,    36,    31,    81,
+      36,    36,    36,    55,    27,    87,    31,    36,    31,    81,
+      27,    88,    31,    27,    89,    31,    27,    90,    31,    27,
+      91,    31,    27,    92
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    32,    33,    34,    35,    36,    37,    37,    37,    37,
+      38,    39,    40,    40,    41,    42,    42,    42,    43,    44,
+      45,    46,    46,    46,    46,    46,    46,    47,    47,    48,
+      49,    49,    50,    50,    51,    51,    51,    51,    52,    52,
+      53,    54,    55,    55,    56,    57,    58,    58,    58,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    69,    69,    70,    71,    72,    73,    73,    73,    74,
+      75,    75,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    97,    97,    98
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     2,     1,     1,     1,     1,     1,
+       4,     5,     2,     3,     5,     0,     1,     3,     4,     6,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,    10,
+       1,     1,     3,     3,     0,     3,     3,     2,     0,     2,
+       5,     4,     0,     2,    10,     6,     0,     3,     3,     2,
+       8,     1,     1,     6,     1,     1,     1,     6,     1,    10,
+       0,     3,     2,     5,     5,     8,     0,     3,     2,     6,
+       0,     3,     2,     1,     8,     1,     1,     3,     5,     4,
+       1,     1,     5,    13,     1,     1,     1,     1,     1,     1,
+       1,     7,     1,     1,    10,     0,     2,     3,     6
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (context, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, osr_cs_wkt_parse_context *context)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (context);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, osr_cs_wkt_parse_context *context)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, osr_cs_wkt_parse_context *context)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , context);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, context); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULL;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, osr_cs_wkt_parse_context *context)
+{
+  YYUSE (yyvaluep);
+  YYUSE (context);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (osr_cs_wkt_parse_context *context)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, context);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+      
+
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (context, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (context, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, context);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, context);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (context, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, context);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, context);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
diff --git a/ogr/osr_cs_wkt_parser.h b/ogr/osr_cs_wkt_parser.h
new file mode 100644
index 0000000..412c907
--- /dev/null
+++ b/ogr/osr_cs_wkt_parser.h
@@ -0,0 +1,90 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED
+# define YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int osr_cs_wkt_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    END = 0,
+    T_PARAM_MT = 258,
+    T_CONCAT_MT = 259,
+    T_INVERSE_MT = 260,
+    T_PASSTHROUGH_MT = 261,
+    T_PROJCS = 262,
+    T_PROJECTION = 263,
+    T_GEOGCS = 264,
+    T_DATUM = 265,
+    T_SPHEROID = 266,
+    T_PRIMEM = 267,
+    T_UNIT = 268,
+    T_GEOCCS = 269,
+    T_AUTHORITY = 270,
+    T_VERT_CS = 271,
+    T_VERT_DATUM = 272,
+    T_COMPD_CS = 273,
+    T_AXIS = 274,
+    T_TOWGS84 = 275,
+    T_FITTED_CS = 276,
+    T_LOCAL_CS = 277,
+    T_LOCAL_DATUM = 278,
+    T_PARAMETER = 279,
+    T_EXTENSION = 280,
+    T_STRING = 281,
+    T_NUMBER = 282,
+    T_IDENTIFIER = 283
+  };
+#endif
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int osr_cs_wkt_parse (osr_cs_wkt_parse_context *context);
+
+#endif /* !YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED  */
diff --git a/ogr/swq.cpp b/ogr/swq.cpp
index 4e7ad37..f8af473 100644
--- a/ogr/swq.cpp
+++ b/ogr/swq.cpp
@@ -6,6 +6,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2001 Information Interoperability Institute (3i)
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission to use, copy, modify and distribute this software and
  * its documentation for any purpose and without fee is hereby granted,
@@ -24,11 +25,35 @@
 #include "cpl_multiproc.h"
 #include "swq.h"
 #include "swq_parser.hpp"
+#include "cpl_time.h"
 
 #define YYSTYPE  swq_expr_node*
 
 /************************************************************************/
 /*                               swqlex()                               */
+/************************************************************************/
+
+void swqerror( swq_parse_context *context, const char *msg )
+{
+    CPLString osMsg;
+    osMsg.Printf( "SQL Expression Parsing Error: %s. Occured around :\n", msg );
+
+    int i;
+    int n = context->pszLastValid - context->pszInput;
+
+    for( i = MAX(0,n-40); i < n + 40 && context->pszInput[i] != '\0'; i ++ )
+        osMsg += context->pszInput[i];
+    osMsg += "\n";
+    for(i=0;i<MIN(n, 40);i++)
+        osMsg += " ";
+    osMsg += "^";
+
+    CPLError( CE_Failure, CPLE_AppDefined, "%s", osMsg.c_str() );
+}
+
+
+/************************************************************************/
+/*                               swqlex()                               */
 /*                                                                      */
 /*      Read back a token from the input.                               */
 /************************************************************************/
@@ -56,6 +81,8 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
            || *pszInput == 10 || *pszInput == 13 )
         pszInput++;
 
+    context->pszLastValid = pszInput;
+
     if( *pszInput == '\0' )
     {
         context->pszNext = pszInput;
@@ -151,13 +178,13 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
             || strstr(osToken,"E") )
         {
             *ppNode = new swq_expr_node( CPLAtof(osToken) );
+            return SWQT_FLOAT_NUMBER;
         }
         else
         {
             *ppNode = new swq_expr_node( atoi(osToken) );
+            return SWQT_INTEGER_NUMBER;
         }
-
-        return SWQT_NUMBER;
     }
 
 /* -------------------------------------------------------------------- */
@@ -228,6 +255,13 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
             nReturn = SWQT_UNION;
         else if( EQUAL(osToken,"ALL") )
             nReturn = SWQT_ALL;
+
+        /* Unhandled by OGR SQL */
+        else if( EQUAL(osToken,"LIMIT") ||
+                 EQUAL(osToken,"OUTER") ||
+                 EQUAL(osToken,"INNER") )
+            nReturn = SWQT_RESERVED_KEYWORD;
+
         else
         {
             *ppNode = new swq_expr_node( osToken );
@@ -288,6 +322,8 @@ swq_select_summarize( swq_select *select_info,
         {
             select_info->column_summary[i].min = 1e20;
             select_info->column_summary[i].max = -1e20;
+            strcpy(select_info->column_summary[i].szMin, "9999/99/99 99:99:99");
+            strcpy(select_info->column_summary[i].szMax, "0000/00/00 00:00:00");
         }
     }
 
@@ -341,25 +377,73 @@ swq_select_summarize( swq_select *select_info,
       case SWQCF_MIN:
         if( value != NULL && value[0] != '\0' )
         {
-            double df_val = CPLAtof(value);
-            if( df_val < summary->min )
-                summary->min = df_val;
+            if(def->field_type == SWQ_DATE ||
+               def->field_type == SWQ_TIME ||
+               def->field_type == SWQ_TIMESTAMP)
+            {
+                if( strcmp( value, summary->szMin ) < 0 )
+                {
+                    strncpy( summary->szMin, value, sizeof(summary->szMin) );
+                    summary->szMin[sizeof(summary->szMin) - 1] = '\0';
+                }
+            }
+            else
+            {
+                double df_val = CPLAtof(value);
+                if( df_val < summary->min )
+                    summary->min = df_val;
+            }
         }
         break;
       case SWQCF_MAX:
         if( value != NULL && value[0] != '\0' )
         {
-            double df_val = CPLAtof(value);
-            if( df_val > summary->max )
-                summary->max = df_val;
+            if(def->field_type == SWQ_DATE ||
+               def->field_type == SWQ_TIME ||
+               def->field_type == SWQ_TIMESTAMP)
+            {
+                if( strcmp( value, summary->szMax ) > 0 )
+                {
+                    strncpy( summary->szMax, value, sizeof(summary->szMax) );
+                    summary->szMax[sizeof(summary->szMax) - 1] = '\0';
+                }
+            }
+            else
+            {
+                double df_val = CPLAtof(value);
+                if( df_val > summary->max )
+                    summary->max = df_val;
+            }
         }
         break;
       case SWQCF_AVG:
       case SWQCF_SUM:
         if( value != NULL && value[0] != '\0' )
         {
-            summary->count++;
-            summary->sum += CPLAtof(value);
+            if(def->field_type == SWQ_DATE ||
+               def->field_type == SWQ_TIME ||
+               def->field_type == SWQ_TIMESTAMP)
+            {
+                int nYear, nMonth, nDay, nHour, nMin, nSec;
+                if( sscanf(value, "%04d/%02d/%02d %02d:%02d:%02d",
+                           &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec) == 6 )
+                {
+                    struct tm brokendowntime;
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon = nMonth - 1;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = nHour;
+                    brokendowntime.tm_min = nMin;
+                    brokendowntime.tm_sec = nSec;
+                    summary->count++;
+                    summary->sum += CPLYMDHMSToUnixTime(&brokendowntime);
+                }
+            }
+            else
+            {
+                summary->count++;
+                summary->sum += CPLAtof(value);
+            }
         }
         break;
 
@@ -691,10 +775,11 @@ CPLErr swq_expr_compile2( const char *where_clause,
 
     context.pszInput = where_clause;
     context.pszNext = where_clause;
+    context.pszLastValid = where_clause;
     context.nStartToken = SWQT_LOGICAL_START;
     
     if( swqparse( &context ) == 0 
-        && context.poRoot->Check( field_list ) != SWQ_ERROR )
+        && context.poRoot->Check( field_list, FALSE ) != SWQ_ERROR )
     {
         *expr_out = context.poRoot;
 
@@ -748,3 +833,24 @@ int swq_is_reserved_keyword(const char* pszStr)
     }
     return FALSE;
 }
+
+/************************************************************************/
+/*                          SWQFieldTypeToString()                      */
+/************************************************************************/
+
+const char* SWQFieldTypeToString( swq_field_type field_type )
+{
+    switch(field_type)
+    {
+        case SWQ_INTEGER:   return "integer";
+        case SWQ_FLOAT:     return "float";
+        case SWQ_STRING:    return "string";
+        case SWQ_BOOLEAN:   return "boolean";
+        case SWQ_DATE:      return "date";
+        case SWQ_TIME:      return "time";
+        case SWQ_TIMESTAMP: return "timestamp";
+        case SWQ_GEOMETRY:  return "geometry";
+        case SWQ_NULL:      return "null";
+        default: return "unknown";
+    }
+}
diff --git a/ogr/swq.h b/ogr/swq.h
index 2118851..c0114cb 100644
--- a/ogr/swq.h
+++ b/ogr/swq.h
@@ -6,6 +6,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2001 Information Interoperability Institute (3i)
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Permission to use, copy, modify and distribute this software and
  * its documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies, that
@@ -22,6 +23,7 @@
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_core.h"
 
 #if defined(_WIN32) && !defined(_WIN32_WCE)
 #  define strcasecmp stricmp
@@ -68,6 +70,7 @@ typedef enum {
     SWQ_DATE,     // string
     SWQ_TIME,     // string
     SWQ_TIMESTAMP,// string
+    SWQ_GEOMETRY,
     SWQ_NULL,
     SWQ_OTHER,
     SWQ_ERROR
@@ -83,6 +86,7 @@ typedef enum {
 class swq_field_list;
 class swq_expr_node;
 class swq_select;
+class OGRGeometry;
 
 typedef swq_expr_node *(*swq_field_fetcher)( swq_expr_node *op,
                                              void *record_handle );
@@ -98,6 +102,7 @@ public:
     swq_expr_node( const char * );
     swq_expr_node( int );
     swq_expr_node( double );
+    swq_expr_node( OGRGeometry* );
     swq_expr_node( swq_op );
 
     ~swq_expr_node();
@@ -105,7 +110,7 @@ public:
     void           Initialize();
     char          *Unparse( swq_field_list *, char chColumnQuote );
     void           Dump( FILE *fp, int depth );
-    swq_field_type Check( swq_field_list * );
+    swq_field_type Check( swq_field_list *, int bAllowFieldsInSecondaryTables );
     swq_expr_node* Evaluate( swq_field_fetcher pfnFetcher, 
                              void *record );
 
@@ -128,28 +133,20 @@ public:
     char        *string_value;
     int         int_value;
     double      float_value;
+    OGRGeometry *geometry_value;
 };
 
-class swq_operation {
-public:
-    swq_operation() {}
-    ~swq_operation() {}
-
+typedef struct {
+    const char*      pszName;
     swq_op           eOperation;
-    CPLString        osName;
     swq_op_evaluator pfnEvaluator;
     swq_op_checker   pfnChecker;
-};
+} swq_operation;
 
 class swq_op_registrar {
 public:
     static const swq_operation *GetOperator( const char * );
     static const swq_operation *GetOperator( swq_op eOperation );
-    static void  Initialize();
-    static void  DeInitialize();
-    static void  AddOperator( const char *pszName, swq_op eOpCode,
-                              swq_op_evaluator pfnEvaluator = NULL,
-                              swq_op_checker pfnChecker = NULL );
 };
 
 typedef struct {
@@ -177,6 +174,7 @@ public:
     int        nStartToken;
     const char *pszInput;
     const char *pszNext;
+    const char *pszLastValid;
 
     swq_expr_node *poRoot;
 
@@ -189,6 +187,7 @@ public:
 */
 int swqparse( swq_parse_context *context );
 int swqlex( swq_expr_node **ppNode, swq_parse_context *context );
+void swqerror( swq_parse_context *context, const char *msg );
 
 int swq_identify_field( const char *token, swq_field_list *field_list,
                         swq_field_type *this_type, int *table_id );
@@ -212,6 +211,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *, swq_expr_node **);
 swq_field_type SWQGeneralChecker( swq_expr_node *node );
 swq_expr_node *SWQCastEvaluator( swq_expr_node *, swq_expr_node **);
 swq_field_type SWQCastChecker( swq_expr_node *node );
+const char*    SWQFieldTypeToString( swq_field_type field_type );
 
 /****************************************************************************/
 
@@ -242,6 +242,8 @@ typedef struct {
     int          field_length;
     int          field_precision;
     int          distinct_flag;
+    OGRwkbGeometryType eGeomType;
+    int          nSRID;
     swq_expr_node *expr;
 } swq_col_def;
 
@@ -252,6 +254,8 @@ typedef struct {
     double      sum;
     double      min;
     double      max;
+    char        szMin[32];
+    char        szMax[32];
 } swq_summary;
 
 typedef struct {
diff --git a/ogr/swq_expr_node.cpp b/ogr/swq_expr_node.cpp
index 40a4b13..53a1ca7 100644
--- a/ogr/swq_expr_node.cpp
+++ b/ogr/swq_expr_node.cpp
@@ -7,6 +7,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,6 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 #include "swq.h"
+#include "ogr_geometry.h"
 #include <vector>
 
 /************************************************************************/
@@ -82,6 +84,20 @@ swq_expr_node::swq_expr_node( const char *pszValueIn )
 }
 
 /************************************************************************/
+/*                      swq_expr_node(OGRGeometry *)                    */
+/************************************************************************/
+
+swq_expr_node::swq_expr_node( OGRGeometry *poGeomIn )
+
+{
+    Initialize();
+
+    field_type = SWQ_GEOMETRY;
+    geometry_value = poGeomIn ? poGeomIn->clone() : NULL;
+    is_null = poGeomIn == NULL;
+}
+
+/************************************************************************/
 /*                        swq_expr_node(swq_op)                         */
 /************************************************************************/
 
@@ -110,6 +126,7 @@ void swq_expr_node::Initialize()
 
     is_null = FALSE;
     string_value = NULL;
+    geometry_value = NULL;
     papoSubExpr = NULL;
     nSubExprCount = 0;
 }
@@ -127,6 +144,7 @@ swq_expr_node::~swq_expr_node()
     for( i = 0; i < nSubExprCount; i++ )
         delete papoSubExpr[i];
     CPLFree( papoSubExpr );
+    delete geometry_value;
 }
 
 /************************************************************************/
@@ -167,7 +185,8 @@ void swq_expr_node::ReverseSubExpressions()
 /*      Check argument types, etc.                                      */
 /************************************************************************/
 
-swq_field_type swq_expr_node::Check( swq_field_list *poFieldList )
+swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
+                                     int bAllowFieldsInSecondaryTables )
 
 {
 /* -------------------------------------------------------------------- */
@@ -180,9 +199,12 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList )
         int wrk_field_index, wrk_table_index;
         swq_field_type wrk_field_type;
 
-        wrk_field_index = 
-            swq_identify_field( string_value, poFieldList,
-                                &wrk_field_type, &wrk_table_index );
+        if( is_null )
+            wrk_field_index = -1;
+        else
+            wrk_field_index = 
+                swq_identify_field( string_value, poFieldList,
+                                    &wrk_field_type, &wrk_table_index );
         
         if( wrk_field_index >= 0 )
         {
@@ -215,7 +237,14 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList )
                       string_value );
 
             return SWQ_ERROR;
-            
+        }
+
+        if( !bAllowFieldsInSecondaryTables && table_index != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot use field '%s' of a secondary table in this context",
+                      string_value );
+            return SWQ_ERROR;
         }
     }
     
@@ -243,7 +272,7 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList )
 
     for( i = 0; i < nSubExprCount; i++ )
     {
-        if( papoSubExpr[i]->Check(poFieldList) == SWQ_ERROR )
+        if( papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables) == SWQ_ERROR )
             return SWQ_ERROR;
     }
     
@@ -265,7 +294,7 @@ void swq_expr_node::Dump( FILE * fp, int depth )
     char        spaces[60];
     int         i;
 
-    for( i = 0; i < depth*2 && i < (int) sizeof(spaces); i++ )
+    for( i = 0; i < depth*2 && i < (int) sizeof(spaces) - 1; i++ )
         spaces[i] = ' ';
     spaces[i] = '\0';
 
@@ -281,6 +310,18 @@ void swq_expr_node::Dump( FILE * fp, int depth )
             fprintf( fp, "%s  %d\n", spaces, int_value );
         else if( field_type == SWQ_FLOAT )
             fprintf( fp, "%s  %.15g\n", spaces, float_value );
+        else if( field_type == SWQ_GEOMETRY )
+        {
+            if( geometry_value == NULL )
+                fprintf( fp, "%s  (null)\n", spaces );
+            else
+            {
+                char* pszWKT = NULL;
+                geometry_value->exportToWkt(&pszWKT);
+                fprintf( fp, "%s  %s\n", spaces, pszWKT );
+                CPLFree(pszWKT);
+            }
+        }
         else
             fprintf( fp, "%s  %s\n", spaces, string_value );
         return;
@@ -291,7 +332,7 @@ void swq_expr_node::Dump( FILE * fp, int depth )
     const swq_operation *op_def = 
         swq_op_registrar::GetOperator( (swq_op) nOperation );
 
-    fprintf( fp, "%s%s\n", spaces, op_def->osName.c_str() );
+    fprintf( fp, "%s%s\n", spaces, op_def->pszName );
 
     for( i = 0; i < nSubExprCount; i++ )
         papoSubExpr[i]->Dump( fp, depth+1 );
@@ -371,12 +412,36 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         if( field_index != -1 
             && table_index < field_list->table_count 
             && table_index > 0 )
-            osExpr.Printf( "%s.%s", 
-                           field_list->table_defs[table_index].table_name,
-                           field_list->names[field_index] );
+        {
+            for(int i = 0; i < field_list->count; i++ )
+            {
+                if( field_list->table_ids[i] == table_index &&
+                    field_list->ids[i] == field_index )
+                {
+                    osExpr.Printf( "%s.%s",
+                                   field_list->table_defs[table_index].table_name,
+                                   field_list->names[i] );
+                    break;
+                }
+            }
+        }
         else if( field_index != -1 )
-            osExpr.Printf( "%s", field_list->names[field_index] );
+        {
+            for(int i = 0; i < field_list->count; i++ )
+            {
+                if( field_list->table_ids[i] == table_index &&
+                    field_list->ids[i] == field_index )
+                {
+                    osExpr.Printf( "%s", field_list->names[i] );
+                    break;
+                }
+            }
+        }
 
+        if( osExpr.size() == 0 )
+        {
+            return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote));
+        }
 
         for( int i = 0; i < (int) osExpr.size(); i++ )
         {
@@ -449,7 +514,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
             osExpr += ")";
         }
         osExpr += " ";
-        osExpr += poOp->osName;
+        osExpr += poOp->pszName;
         osExpr += " ";
         if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
             papoSubExpr[1]->eNodeType == SNT_CONSTANT)
@@ -493,7 +558,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         CPLAssert( nSubExprCount == 3 );
         osExpr.Printf( "%s %s (%s) AND (%s)",
                        apszSubExpr[0],
-                       poOp->osName.c_str(),
+                       poOp->pszName,
                        apszSubExpr[1],
                        apszSubExpr[2] );
         break;
@@ -508,14 +573,15 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
                 osExpr += ", ";
 
             int nLen = (int)strlen(apszSubExpr[i]);
-            if( i != 1 ||
-                !(apszSubExpr[i][0] == '\'' && nLen > 2 && apszSubExpr[i][nLen-1] == '\'') )
-                osExpr += apszSubExpr[i];
-            else
+            if( (i == 1 &&
+                (apszSubExpr[i][0] == '\'' && nLen > 2 && apszSubExpr[i][nLen-1] == '\'')) ||
+                (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")) )
             {
                 apszSubExpr[i][nLen-1] = '\0';
                 osExpr += apszSubExpr[i] + 1;
             }
+            else
+                osExpr += apszSubExpr[i];
 
             if( i == 1 && nSubExprCount > 2)
                 osExpr += "(";
@@ -526,7 +592,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         break;
 
       default: // function style.
-        osExpr.Printf( "%s(", poOp->osName.c_str() );
+        osExpr.Printf( "%s(", poOp->pszName );
         for( i = 0; i < nSubExprCount; i++ )
         {
             if( i > 0 )
@@ -575,6 +641,11 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
         else
             poRetNode->string_value = NULL;
 
+        if( geometry_value )
+            poRetNode->geometry_value = geometry_value->clone();
+        else
+            poRetNode->geometry_value = NULL;
+
         poRetNode->is_null = is_null;
 
         return poRetNode;
diff --git a/ogr/swq_op_general.cpp b/ogr/swq_op_general.cpp
index 2cc2c99..a9ffabd 100644
--- a/ogr/swq_op_general.cpp
+++ b/ogr/swq_op_general.cpp
@@ -8,6 +8,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,6 +31,7 @@
 
 #include "cpl_conv.h"
 #include "swq.h"
+#include "ogr_geometry.h"
 
 /************************************************************************/
 /*                           swq_test_like()                            */
@@ -720,8 +722,7 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
                              poSubNode->string_value);
                     continue;
                 }
-                                
-                poSubNode->float_value = atof(poSubNode->string_value);
+
                 /* we should also fill the integer value in this case */
                 poSubNode->int_value = (int)poSubNode->float_value;
                 poSubNode->field_type = SWQ_FLOAT;
@@ -731,6 +732,24 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
 }
 
 /************************************************************************/
+/*                   SWQCheckSubExprAreNotGeometries()                  */
+/************************************************************************/
+
+static int SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
+{
+    for( int i = 0; i < poNode->nSubExprCount; i++ )
+    {
+        if( poNode->papoSubExpr[i]->field_type == SWQ_GEOMETRY )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                        "Cannot use geometry field in this operation." );
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/************************************************************************/
 /*                         SWQGeneralChecker()                          */
 /*                                                                      */
 /*      Check the general purpose functions have appropriate types,     */
@@ -750,6 +769,8 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
       case SWQ_AND:
       case SWQ_OR:
       case SWQ_NOT:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_BOOLEAN;
         break;
 
@@ -761,6 +782,8 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
       case SWQ_LE:
       case SWQ_IN:
       case SWQ_BETWEEN:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_BOOLEAN;
         SWQAutoConvertStringToNumeric( poNode );
         SWQAutoPromoteIntegerToFloat( poNode );
@@ -773,16 +796,22 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
         break;
 
       case SWQ_LIKE:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_BOOLEAN;
         eArgType = SWQ_STRING;
         break;
 
       case SWQ_MODULUS:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_INTEGER;
         eArgType = SWQ_INTEGER;
         break;
 
       case SWQ_ADD:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         SWQAutoPromoteIntegerToFloat( poNode );
         if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
             eRetType = eArgType = SWQ_STRING;
@@ -795,6 +824,8 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
       case SWQ_SUBTRACT:
       case SWQ_MULTIPLY:
       case SWQ_DIVIDE:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         SWQAutoPromoteIntegerToFloat( poNode );
         if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
             eRetType = eArgType = SWQ_FLOAT;
@@ -803,11 +834,15 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
         break;
 
       case SWQ_CONCAT:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_STRING;
         eArgType = SWQ_STRING;
         break;
 
       case SWQ_SUBSTR:
+        if( !SWQCheckSubExprAreNotGeometries(poNode) )
+            return SWQ_ERROR;
         eRetType = SWQ_STRING;
         if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
         {
@@ -834,7 +869,7 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
           
           CPLError( CE_Failure, CPLE_AppDefined,
                     "SWQGeneralChecker() called on unsupported operation %s.",
-                    poOp->osName.c_str());
+                    poOp->pszName);
           return SWQ_ERROR;
       }
     }
@@ -861,7 +896,7 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
                 
                 CPLError( CE_Failure, CPLE_AppDefined, 
                           "Type mismatch or improper type of arguments to %s operator.",
-                          poOp->osName.c_str() );
+                          poOp->pszName );
                 return SWQ_ERROR;
             }
         }
@@ -879,7 +914,7 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Expected %d arguments to %s, but got %d arguments.",
                   nArgCount,
-                  poOp->osName.c_str(),
+                  poOp->pszName,
                   poNode->nSubExprCount );
         return SWQ_ERROR;
     }
@@ -946,6 +981,38 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
         }
         break;
 
+        case SWQ_GEOMETRY:
+        {
+            poRetNode = new swq_expr_node( (OGRGeometry*) NULL );
+            if( !poSrcNode->is_null )
+            {
+                switch( poSrcNode->field_type )
+                {
+                    case SWQ_GEOMETRY:
+                    {
+                        poRetNode->geometry_value =
+                            poSrcNode->geometry_value->clone();
+                        poRetNode->is_null = FALSE;
+                        break;
+                    }
+
+                    case SWQ_STRING:
+                    {
+                        char* pszTmp = poSrcNode->string_value;
+                        OGRGeometryFactory::createFromWkt(&pszTmp, NULL,
+                            &(poRetNode->geometry_value));
+                        if( poRetNode->geometry_value != NULL )
+                            poRetNode->is_null = FALSE;
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+            }
+            break;
+        }
+
         // everything else is a string.
         default:
         {
@@ -962,6 +1029,20 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                     osRet.Printf( "%.15g", poSrcNode->float_value );
                     break;
 
+                case SWQ_GEOMETRY:
+                {
+                    if( poSrcNode->geometry_value != NULL )
+                    {
+                        char* pszWKT;
+                        poSrcNode->geometry_value->exportToWkt(&pszWKT);
+                        osRet = pszWKT;
+                        CPLFree(pszWKT);
+                    }
+                    else
+                        osRet = "";
+                    break;
+                }
+
                 default:
                     osRet = poSrcNode->string_value;
                     break;
@@ -994,20 +1075,39 @@ swq_field_type SWQCastChecker( swq_expr_node *poNode )
     swq_field_type eType = SWQ_ERROR;
     const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
 
-    if( EQUAL(pszTypeName,"character") )
+    if( poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY &&
+        !(EQUAL(pszTypeName,"character") ||
+          EQUAL(pszTypeName,"geometry")) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast geometry to %s",
+                  pszTypeName );
+    }
+
+    else if( EQUAL(pszTypeName,"character") )
         eType = SWQ_STRING;
-    else if( strcasecmp(pszTypeName,"integer") == 0 )
+    else if( EQUAL(pszTypeName,"integer") )
         eType = SWQ_INTEGER;
-    else if( strcasecmp(pszTypeName,"float") == 0 )
+    else if( EQUAL(pszTypeName,"float") )
         eType = SWQ_FLOAT;
-    else if( strcasecmp(pszTypeName,"numeric") == 0 )
+    else if( EQUAL(pszTypeName,"numeric") )
         eType = SWQ_FLOAT;
-    else if( strcasecmp(pszTypeName,"timestamp") == 0 )
+    else if( EQUAL(pszTypeName,"timestamp") )
         eType = SWQ_TIMESTAMP;
-    else if( strcasecmp(pszTypeName,"date") == 0 )
+    else if( EQUAL(pszTypeName,"date") )
         eType = SWQ_DATE;
-    else if( strcasecmp(pszTypeName,"time") == 0 )
+    else if( EQUAL(pszTypeName,"time") )
         eType = SWQ_TIME;
+    else if( EQUAL(pszTypeName,"geometry") )
+    {
+        if( !(poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY ||
+              poNode->papoSubExpr[0]->field_type == SWQ_STRING) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry",
+                      SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type) );
+        }
+        else
+            eType = SWQ_GEOMETRY;
+    }
     else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
diff --git a/ogr/swq_op_registrar.cpp b/ogr/swq_op_registrar.cpp
index af05de1..d9f7a54 100644
--- a/ogr/swq_op_registrar.cpp
+++ b/ogr/swq_op_registrar.cpp
@@ -7,6 +7,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,12 +29,43 @@
  ****************************************************************************/
 
 #include "cpl_conv.h"
-#include "cpl_multiproc.h"
 #include "swq.h"
-#include <vector>
 
-static void *hOperationsMutex = NULL;
-static std::vector<swq_operation*>* papoOperations = NULL;
+static swq_field_type SWQColumnFuncChecker( swq_expr_node *poNode );
+
+static const swq_operation swq_apsOperations[] =
+{
+    { "OR", SWQ_OR, SWQGeneralEvaluator, SWQGeneralChecker },
+    { "AND", SWQ_AND, SWQGeneralEvaluator, SWQGeneralChecker },
+    { "NOT", SWQ_NOT , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "=", SWQ_EQ , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "<>", SWQ_NE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { ">=", SWQ_GE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "<=", SWQ_LE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "<", SWQ_LT , SWQGeneralEvaluator, SWQGeneralChecker },
+    { ">", SWQ_GT , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "LIKE", SWQ_LIKE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "IS NULL", SWQ_ISNULL , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "IN", SWQ_IN , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "BETWEEN", SWQ_BETWEEN , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "+", SWQ_ADD , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "-", SWQ_SUBTRACT , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "*", SWQ_MULTIPLY , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "/", SWQ_DIVIDE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "%", SWQ_MODULUS , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "CONCAT", SWQ_CONCAT , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "SUBSTR", SWQ_SUBSTR , SWQGeneralEvaluator, SWQGeneralChecker },
+
+    { "AVG", SWQ_AVG, SWQGeneralEvaluator, SWQColumnFuncChecker },
+    { "MIN", SWQ_MIN, SWQGeneralEvaluator, SWQColumnFuncChecker },
+    { "MAX", SWQ_MAX, SWQGeneralEvaluator, SWQColumnFuncChecker },
+    { "COUNT", SWQ_COUNT, SWQGeneralEvaluator, SWQColumnFuncChecker },
+    { "SUM", SWQ_SUM, SWQGeneralEvaluator, SWQColumnFuncChecker },
+
+    { "CAST", SWQ_CAST, SWQCastEvaluator, SWQCastChecker }
+};
+
+#define N_OPERATIONS (sizeof(swq_apsOperations) / sizeof(swq_apsOperations[0]))
 
 /************************************************************************/
 /*                            GetOperator()                             */
@@ -43,13 +75,10 @@ const swq_operation *swq_op_registrar::GetOperator( const char *pszName )
 
 {
     unsigned int i;
-
-    Initialize();
-
-    for( i = 0; i < papoOperations->size(); i++ )
+    for( i = 0; i < N_OPERATIONS; i++ )
     {
-        if( EQUAL(pszName,(*papoOperations)[i]->osName.c_str()) )
-            return (*papoOperations)[i];
+        if( EQUAL(pszName,swq_apsOperations[i].pszName) )
+            return &(swq_apsOperations[i]);
     }
 
     return NULL;
@@ -64,47 +93,15 @@ const swq_operation *swq_op_registrar::GetOperator( swq_op eOperator )
 {
     unsigned int i;
 
-    Initialize();
-
-    for( i = 0; i < papoOperations->size(); i++ )
+    for( i = 0; i < N_OPERATIONS; i++ )
     {
-        if( eOperator == (*papoOperations)[i]->eOperation )
-            return (*papoOperations)[i];
+        if( eOperator == swq_apsOperations[i].eOperation )
+            return &(swq_apsOperations[i]);
     }
 
     return NULL;
 }
 
-
-/************************************************************************/
-/*                            AddOperator()                             */
-/************************************************************************/
-
-void swq_op_registrar::AddOperator( const char *pszName, swq_op eOpCode,
-                                    swq_op_evaluator pfnEvaluator,
-                                    swq_op_checker pfnChecker )
-
-{
-    if( GetOperator( pszName ) != NULL )
-        return;
-
-    if( pfnEvaluator == NULL )
-        pfnEvaluator = SWQGeneralEvaluator;
-    if( pfnChecker == NULL )
-        pfnChecker = SWQGeneralChecker;
-
-    swq_operation *poOp = new swq_operation();
-
-    poOp->eOperation = eOpCode;
-    poOp->osName = pszName;
-    poOp->pfnEvaluator = pfnEvaluator;
-    poOp->pfnChecker = pfnChecker;
-
-    papoOperations->push_back( poOp );
-}
-
-
-
 /************************************************************************/
 /*                        SWQColumnFuncChecker()                        */
 /*                                                                      */
@@ -120,75 +117,6 @@ static swq_field_type SWQColumnFuncChecker( swq_expr_node *poNode )
             swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
     CPLError( CE_Failure, CPLE_AppDefined,
               "Column Summary Function '%s' found in an inappropriate context.",
-              (poOp) ? poOp->osName.c_str() : "" );
+              (poOp) ? poOp->pszName : "" );
     return SWQ_ERROR;
 }
-
-
-/************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void swq_op_registrar::Initialize()
-
-{
-    CPLMutexHolderD( &hOperationsMutex );
-
-    if( papoOperations )
-        return;
-
-    papoOperations = new std::vector<swq_operation*>;
-
-    AddOperator( "OR", SWQ_OR );
-    AddOperator( "AND", SWQ_AND );
-    AddOperator( "NOT", SWQ_NOT );
-    AddOperator( "=", SWQ_EQ );
-    AddOperator( "<>", SWQ_NE );
-    AddOperator( ">=", SWQ_GE );
-    AddOperator( "<=", SWQ_LE );
-    AddOperator( "<", SWQ_LT );
-    AddOperator( ">", SWQ_GT );
-    AddOperator( "LIKE", SWQ_LIKE );
-    AddOperator( "IS NULL", SWQ_ISNULL );
-    AddOperator( "IN", SWQ_IN );
-    AddOperator( "BETWEEN", SWQ_BETWEEN );
-    AddOperator( "+", SWQ_ADD );
-    AddOperator( "-", SWQ_SUBTRACT );
-    AddOperator( "*", SWQ_MULTIPLY );
-    AddOperator( "/", SWQ_DIVIDE );
-    AddOperator( "%", SWQ_MODULUS );
-    AddOperator( "CONCAT", SWQ_CONCAT );
-    AddOperator( "SUBSTR", SWQ_SUBSTR );
-
-    AddOperator( "AVG", SWQ_AVG, NULL, SWQColumnFuncChecker );
-    AddOperator( "MIN", SWQ_MIN, NULL, SWQColumnFuncChecker );
-    AddOperator( "MAX", SWQ_MAX, NULL, SWQColumnFuncChecker );
-    AddOperator( "COUNT", SWQ_COUNT, NULL, SWQColumnFuncChecker );
-    AddOperator( "SUM", SWQ_SUM, NULL, SWQColumnFuncChecker );
-
-    AddOperator( "CAST", SWQ_CAST, SWQCastEvaluator, SWQCastChecker );
-}
-
-/************************************************************************/
-/*                            DeInitialize()                            */
-/************************************************************************/
-
-void swq_op_registrar::DeInitialize()
-
-{
-    {
-        CPLMutexHolderD( &hOperationsMutex );
-        
-        if( papoOperations != NULL)
-        {
-            for( unsigned int i=0; i < papoOperations->size(); i++ )
-                delete (*papoOperations)[i];
-            
-            delete papoOperations;
-            papoOperations = NULL;
-        }
-    }
-
-    CPLDestroyMutex( hOperationsMutex );
-    hOperationsMutex = NULL;
-}
diff --git a/ogr/swq_parser.cpp b/ogr/swq_parser.cpp
index 4ac23d2..ac107c5 100644
--- a/ogr/swq_parser.cpp
+++ b/ogr/swq_parser.cpp
@@ -1,21 +1,20 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
 
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -28,7 +27,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -46,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "3.0"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -60,23 +59,17 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
 #define yyparse         swqparse
 #define yylex           swqlex
 #define yyerror         swqerror
-#define yylval          swqlval
-#define yychar          swqchar
 #define yydebug         swqdebug
 #define yynerrs         swqnerrs
 
 
 /* Copy the first part of user declarations.  */
-
-/* Line 189 of yacc.c  */
-#line 1 "swq_parser.y"
+#line 1 "swq_parser.y" /* yacc.c:339  */
 
 /******************************************************************************
  *
@@ -110,6 +103,7 @@
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_geometry.h"
 #include "swq.h"
 
 #define YYSTYPE  swq_expr_node*
@@ -121,91 +115,95 @@
 /* it appears to be a non documented feature of Bison */ 
 #define YYSTYPE_IS_TRIVIAL 1
 
-static void swqerror( swq_parse_context *context, const char *msg )
-{
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "SQL Expression Parsing Error: %s", msg );
-}
-
 
+#line 119 "swq_parser.cpp" /* yacc.c:339  */
 
-/* Line 189 of yacc.c  */
-#line 134 "swq_parser.cpp"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# ifndef YY_NULL
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULL nullptr
+#  else
+#   define YY_NULL 0
+#  endif
+# endif
 
 /* Enabling verbose error messages.  */
 #ifdef YYERROR_VERBOSE
 # undef YYERROR_VERBOSE
 # define YYERROR_VERBOSE 1
 #else
-# define YYERROR_VERBOSE 0
+# define YYERROR_VERBOSE 1
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* In a future release of Bison, this section will be replaced
+   by #include "swq_parser.hpp".  */
+#ifndef YY_SWQ_SWQ_PARSER_HPP_INCLUDED
+# define YY_SWQ_SWQ_PARSER_HPP_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int swqdebug;
 #endif
 
-
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     SWQT_NUMBER = 258,
-     SWQT_STRING = 259,
-     SWQT_IDENTIFIER = 260,
-     SWQT_IN = 261,
-     SWQT_LIKE = 262,
-     SWQT_ESCAPE = 263,
-     SWQT_BETWEEN = 264,
-     SWQT_NULL = 265,
-     SWQT_IS = 266,
-     SWQT_SELECT = 267,
-     SWQT_LEFT = 268,
-     SWQT_JOIN = 269,
-     SWQT_WHERE = 270,
-     SWQT_ON = 271,
-     SWQT_ORDER = 272,
-     SWQT_BY = 273,
-     SWQT_FROM = 274,
-     SWQT_AS = 275,
-     SWQT_ASC = 276,
-     SWQT_DESC = 277,
-     SWQT_DISTINCT = 278,
-     SWQT_CAST = 279,
-     SWQT_UNION = 280,
-     SWQT_ALL = 281,
-     SWQT_LOGICAL_START = 282,
-     SWQT_VALUE_START = 283,
-     SWQT_SELECT_START = 284,
-     SWQT_NOT = 285,
-     SWQT_OR = 286,
-     SWQT_AND = 287,
-     SWQT_UMINUS = 288
-   };
+  enum yytokentype
+  {
+    END = 0,
+    SWQT_INTEGER_NUMBER = 258,
+    SWQT_FLOAT_NUMBER = 259,
+    SWQT_STRING = 260,
+    SWQT_IDENTIFIER = 261,
+    SWQT_IN = 262,
+    SWQT_LIKE = 263,
+    SWQT_ESCAPE = 264,
+    SWQT_BETWEEN = 265,
+    SWQT_NULL = 266,
+    SWQT_IS = 267,
+    SWQT_SELECT = 268,
+    SWQT_LEFT = 269,
+    SWQT_JOIN = 270,
+    SWQT_WHERE = 271,
+    SWQT_ON = 272,
+    SWQT_ORDER = 273,
+    SWQT_BY = 274,
+    SWQT_FROM = 275,
+    SWQT_AS = 276,
+    SWQT_ASC = 277,
+    SWQT_DESC = 278,
+    SWQT_DISTINCT = 279,
+    SWQT_CAST = 280,
+    SWQT_UNION = 281,
+    SWQT_ALL = 282,
+    SWQT_LOGICAL_START = 283,
+    SWQT_VALUE_START = 284,
+    SWQT_SELECT_START = 285,
+    SWQT_NOT = 286,
+    SWQT_OR = 287,
+    SWQT_AND = 288,
+    SWQT_UMINUS = 289,
+    SWQT_RESERVED_KEYWORD = 290
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-/* Copy the second part of user declarations.  */
 
+int swqparse (swq_parse_context *context);
 
-/* Line 264 of yacc.c  */
-#line 209 "swq_parser.cpp"
+#endif /* !YY_SWQ_SWQ_PARSER_HPP_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 206 "swq_parser.cpp" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -219,11 +217,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -243,8 +238,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -255,41 +249,51 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+#  define __attribute__(Spec) /* empty */
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
 #else
-static int
-YYID (yyi)
-    int yyi;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
 #endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
 
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
@@ -308,11 +312,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
 #     endif
 #    endif
 #   endif
@@ -320,8 +324,8 @@ YYID (yyi)
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -335,25 +339,23 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
+             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -363,7 +365,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -381,73 +383,79 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
+# define YYCOPY_NEEDED 1
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
 
 #endif
 
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  22
+#define YYFINAL  23
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   294
+#define YYLAST   328
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  47
+#define YYNTOKENS  49
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  20
+#define YYNNTS  21
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  84
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  186
+#define YYNRULES  89
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  191
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   288
+#define YYMAXUTOK   290
 
-#define YYTRANSLATE(YYX)						\
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    44,     2,     2,     2,    37,     2,     2,
-      39,    40,    35,    33,    45,    34,    46,    36,     2,     2,
+       2,     2,     2,    46,     2,     2,     2,    38,     2,     2,
+      41,    42,    36,    34,    47,    35,    48,    37,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      42,    41,    43,     2,     2,     2,     2,     2,     2,     2,
+      44,    43,    45,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -469,396 +477,307 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    38
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    39,
+      40
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     6,     9,    12,    16,    20,    23,    27,
-      31,    36,    41,    45,    49,    54,    59,    64,    69,    73,
-      78,    84,    91,    97,   104,   110,   117,   121,   126,   130,
-     132,   134,   138,   140,   142,   144,   148,   150,   153,   157,
-     161,   165,   169,   173,   178,   185,   187,   192,   199,   202,
-     207,   215,   216,   219,   222,   224,   228,   231,   234,   236,
-     241,   245,   247,   251,   256,   263,   269,   277,   278,   281,
-     282,   290,   299,   300,   304,   308,   310,   312,   315,   318,
-     320,   322,   324,   327,   331
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      48,     0,    -1,    27,    49,    -1,    28,    52,    -1,    29,
-      54,    -1,    49,    32,    49,    -1,    49,    31,    49,    -1,
-      30,    49,    -1,    39,    49,    40,    -1,    52,    41,    52,
-      -1,    52,    42,    43,    52,    -1,    52,    44,    41,    52,
-      -1,    52,    42,    52,    -1,    52,    43,    52,    -1,    52,
-      42,    41,    52,    -1,    52,    41,    42,    52,    -1,    52,
-      41,    43,    52,    -1,    52,    43,    41,    52,    -1,    52,
-       7,    52,    -1,    52,    30,     7,    52,    -1,    52,     7,
-      52,     8,    52,    -1,    52,    30,     7,    52,     8,    52,
-      -1,    52,     6,    39,    50,    40,    -1,    52,    30,     6,
-      39,    50,    40,    -1,    52,     9,    52,    32,    52,    -1,
-      52,    30,     9,    52,    32,    52,    -1,    52,    11,    10,
-      -1,    52,    11,    30,    10,    -1,    52,    45,    50,    -1,
-      52,    -1,     5,    -1,     5,    46,     5,    -1,     3,    -1,
-       4,    -1,    51,    -1,    39,    52,    40,    -1,    10,    -1,
-      34,    52,    -1,    52,    33,    52,    -1,    52,    34,    52,
-      -1,    52,    35,    52,    -1,    52,    36,    52,    -1,    52,
-      37,    52,    -1,     5,    39,    50,    40,    -1,    24,    39,
-      52,    20,    53,    40,    -1,     5,    -1,     5,    39,     3,
-      40,    -1,     5,    39,     3,    45,     3,    40,    -1,    55,
-      56,    -1,    39,    55,    40,    56,    -1,    12,    58,    19,
-      66,    61,    60,    62,    -1,    -1,    57,    54,    -1,    25,
-      26,    -1,    59,    -1,    59,    45,    58,    -1,    23,    51,
-      -1,    23,     4,    -1,    52,    -1,    23,    51,    20,    65,
-      -1,    52,    20,    65,    -1,    35,    -1,     5,    46,    35,
-      -1,     5,    39,    35,    40,    -1,     5,    39,    35,    40,
-      20,    65,    -1,     5,    39,    23,    51,    40,    -1,     5,
-      39,    23,    51,    40,    20,    65,    -1,    -1,    15,    49,
-      -1,    -1,    14,    66,    16,    51,    41,    51,    61,    -1,
-      13,    14,    66,    16,    51,    41,    51,    61,    -1,    -1,
-      17,    18,    63,    -1,    64,    45,    63,    -1,    64,    -1,
-      51,    -1,    51,    21,    -1,    51,    22,    -1,     5,    -1,
-       4,    -1,    65,    -1,    65,     5,    -1,     4,    46,    65,
-      -1,     4,    46,    65,     5,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   104,   104,   109,   114,   120,   128,   136,   143,   148,
-     156,   164,   172,   180,   188,   196,   204,   212,   220,   228,
-     241,   250,   264,   273,   288,   297,   311,   318,   332,   338,
-     345,   352,   368,   373,   377,   382,   387,   392,   408,   415,
-     422,   429,   436,   443,   467,   475,   481,   488,   497,   498,
-     501,   506,   507,   509,   517,   518,   521,   530,   539,   548,
-     560,   571,   585,   607,   637,   671,   695,   723,   724,   729,
-     730,   739,   749,   750,   753,   754,   757,   763,   769,   777,
-     781,   787,   797,   808,   819
+       0,   111,   111,   116,   121,   127,   135,   143,   150,   155,
+     163,   171,   179,   187,   195,   203,   211,   219,   227,   235,
+     248,   257,   271,   280,   295,   304,   318,   325,   339,   345,
+     352,   359,   375,   380,   385,   389,   394,   399,   404,   420,
+     427,   434,   441,   448,   455,   479,   487,   493,   500,   509,
+     527,   547,   548,   551,   556,   557,   559,   567,   568,   571,
+     580,   589,   598,   610,   621,   635,   657,   687,   721,   745,
+     774,   780,   783,   784,   789,   790,   799,   809,   810,   813,
+     814,   817,   823,   829,   837,   841,   847,   857,   868,   879
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 1
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "SWQT_NUMBER", "SWQT_STRING",
-  "SWQT_IDENTIFIER", "SWQT_IN", "SWQT_LIKE", "SWQT_ESCAPE", "SWQT_BETWEEN",
-  "SWQT_NULL", "SWQT_IS", "SWQT_SELECT", "SWQT_LEFT", "SWQT_JOIN",
-  "SWQT_WHERE", "SWQT_ON", "SWQT_ORDER", "SWQT_BY", "SWQT_FROM", "SWQT_AS",
-  "SWQT_ASC", "SWQT_DESC", "SWQT_DISTINCT", "SWQT_CAST", "SWQT_UNION",
-  "SWQT_ALL", "SWQT_LOGICAL_START", "SWQT_VALUE_START",
-  "SWQT_SELECT_START", "SWQT_NOT", "SWQT_OR", "SWQT_AND", "'+'", "'-'",
-  "'*'", "'/'", "'%'", "SWQT_UMINUS", "'('", "')'", "'='", "'<'", "'>'",
-  "'!'", "','", "'.'", "$accept", "input", "logical_expr",
-  "value_expr_list", "field_value", "value_expr", "type_def",
-  "select_statement", "select_core", "opt_union_all", "union_all",
-  "select_field_list", "column_spec", "opt_where", "opt_joins",
-  "opt_order_by", "sort_spec_list", "sort_spec", "string_or_identifier",
-  "table_def", 0
+  "\"end of string\"", "error", "$undefined", "\"integer number\"",
+  "\"floating point number\"", "\"string\"", "\"identifier\"", "\"IN\"",
+  "\"LIKE\"", "\"ESCAPE\"", "\"BETWEEN\"", "\"NULL\"", "\"IS\"",
+  "\"SELECT\"", "\"LEFT\"", "\"JOIN\"", "\"WHERE\"", "\"ON\"", "\"ORDER\"",
+  "\"BY\"", "\"FROM\"", "\"AS\"", "\"ASC\"", "\"DESC\"", "\"DISTINCT\"",
+  "\"CAST\"", "\"UNION\"", "\"ALL\"", "SWQT_LOGICAL_START",
+  "SWQT_VALUE_START", "SWQT_SELECT_START", "\"NOT\"", "\"OR\"", "\"AND\"",
+  "'+'", "'-'", "'*'", "'/'", "'%'", "SWQT_UMINUS", "\"reserved keyword\"",
+  "'('", "')'", "'='", "'<'", "'>'", "'!'", "','", "'.'", "$accept",
+  "input", "logical_expr", "value_expr_list", "field_value", "value_expr",
+  "type_def", "select_statement", "select_core", "opt_union_all",
+  "union_all", "select_field_list", "column_spec", "as_clause",
+  "opt_where", "opt_joins", "opt_order_by", "sort_spec_list", "sort_spec",
+  "string_or_identifier", "table_def", YY_NULL
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,    43,    45,    42,    47,    37,   288,    40,
-      41,    61,    60,    62,    33,    44,    46
+     285,   286,   287,   288,    43,    45,    42,    47,    37,   289,
+     290,    40,    41,    61,    60,    62,    33,    44,    46
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    47,    48,    48,    48,    49,    49,    49,    49,    49,
-      49,    49,    49,    49,    49,    49,    49,    49,    49,    49,
-      49,    49,    49,    49,    49,    49,    49,    49,    50,    50,
-      51,    51,    52,    52,    52,    52,    52,    52,    52,    52,
-      52,    52,    52,    52,    52,    53,    53,    53,    54,    54,
-      55,    56,    56,    57,    58,    58,    59,    59,    59,    59,
-      59,    59,    59,    59,    59,    59,    59,    60,    60,    61,
-      61,    61,    62,    62,    63,    63,    64,    64,    64,    65,
-      65,    66,    66,    66,    66
-};
+#define YYPACT_NINF -170
 
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-170)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
 {
-       0,     2,     2,     2,     2,     3,     3,     2,     3,     3,
-       4,     4,     3,     3,     4,     4,     4,     4,     3,     4,
-       5,     6,     5,     6,     5,     6,     3,     4,     3,     1,
-       1,     3,     1,     1,     1,     3,     1,     2,     3,     3,
-       3,     3,     3,     4,     6,     1,     4,     6,     2,     4,
-       7,     0,     2,     2,     1,     3,     2,     2,     1,     4,
-       3,     1,     3,     4,     6,     5,     7,     0,     2,     0,
-       7,     8,     0,     3,     3,     1,     1,     2,     2,     1,
-       1,     1,     2,     3,     4
+      72,   243,   260,    -8,    16,  -170,  -170,  -170,   -10,  -170,
+      -1,   243,   260,   243,    56,  -170,   181,   260,   290,   217,
+      23,  -170,    18,  -170,   260,    36,   260,    56,  -170,   -25,
+     165,   243,   243,    22,   260,   260,    -5,    54,   260,   260,
+     260,   260,   260,    62,   126,   149,    31,    44,    -9,    99,
+    -170,   144,    39,    29,    43,    65,  -170,    -8,    53,   252,
+    -170,   105,  -170,  -170,    87,  -170,   260,   268,   279,  -170,
+     112,    84,   260,   260,    75,    75,  -170,  -170,  -170,   260,
+     260,   290,   260,   260,   290,   260,   290,   260,   226,    -2,
+    -170,    79,     4,  -170,  -170,   103,  -170,  -170,   111,   217,
+      18,  -170,  -170,  -170,   260,   127,   114,   260,   260,  -170,
+     260,   273,   285,   290,   290,   290,   290,   290,   290,   151,
+     116,  -170,  -170,  -170,   115,   153,   121,  -170,  -170,  -170,
+     125,   120,  -170,   290,   290,   122,   260,   260,   128,     4,
+     103,  -170,   161,   111,   152,    69,  -170,  -170,   290,   290,
+       4,  -170,   177,   111,   168,   243,   169,   -20,     1,  -170,
+    -170,   178,   151,    56,   167,  -170,  -170,   191,  -170,   194,
+     151,   155,   151,   162,   163,   170,   151,   123,  -170,   159,
+    -170,  -170,   151,   121,  -170,  -170,   151,   121,  -170,  -170,
+    -170
 };
 
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     0,     0,    32,    33,    30,    36,     0,
-       0,     0,     0,     2,    34,     0,     0,     3,     0,     0,
-       4,    51,     1,     0,     0,     0,     7,    37,     0,     0,
+       0,     0,     0,     0,     0,    32,    33,    34,    30,    37,
+       0,     0,     0,     0,     2,    35,     0,     0,     3,     0,
+       0,     4,    54,     1,     0,     0,     0,     7,    38,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    30,     0,    61,
-      58,     0,    54,     0,     0,    48,     0,     0,    29,    31,
-       0,     8,    35,     6,     5,     0,    18,     0,    26,     0,
-       0,     0,     0,    38,    39,    40,    41,    42,     0,     0,
-       9,     0,     0,    12,     0,    13,     0,     0,     0,    57,
-      30,    56,     0,     0,     0,    51,    53,    52,    43,     0,
-       0,     0,     0,     0,    27,     0,    19,     0,    15,    16,
-      14,    10,    17,    11,     0,     0,    62,     0,    80,    79,
-      60,    80,    81,    69,    55,    49,    28,    45,     0,    22,
-      20,    24,     0,     0,     0,     0,    63,    59,     0,    82,
-       0,     0,    67,     0,    44,    23,    21,    25,    65,     0,
-      83,     0,     0,     0,    72,     0,     0,    64,    84,     0,
-       0,    68,     0,    50,    46,     0,    66,     0,     0,     0,
-       0,     0,     0,    76,    73,    75,    47,     0,    69,    77,
-      78,     0,    69,    70,    74,    71
+       0,     0,     0,     0,     0,     0,     0,     0,    30,     0,
+      64,    61,     0,    57,     0,     0,    51,     0,     0,    29,
+      31,     0,     8,    36,     6,     5,     0,    18,     0,    26,
+       0,     0,     0,     0,    39,    40,    41,    42,    43,     0,
+       0,     9,     0,     0,    12,     0,    13,     0,     0,     0,
+      60,    30,    59,    85,    84,     0,    63,    71,     0,     0,
+      54,    56,    55,    44,     0,     0,     0,     0,     0,    27,
+       0,    19,     0,    15,    16,    14,    10,    17,    11,     0,
+       0,    65,    62,    70,    85,    86,    74,    58,    52,    28,
+      46,     0,    22,    20,    24,     0,     0,     0,     0,    66,
+       0,    87,     0,     0,    72,     0,    45,    23,    21,    25,
+      68,    67,    88,     0,     0,     0,    77,     0,     0,    69,
+      89,     0,     0,    73,     0,    53,    47,     0,    49,     0,
+       0,     0,     0,     0,     0,     0,     0,    81,    78,    80,
+      48,    50,     0,    74,    82,    83,     0,    74,    75,    79,
+      76
 };
 
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     4,    13,    57,    14,    15,   128,    20,    21,    55,
-      56,    51,    52,   154,   142,   163,   174,   175,   122,   123
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -156
-static const yytype_int16 yypact[] =
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
 {
-     100,   214,   218,    -1,    10,  -156,  -156,   -30,  -156,   -26,
-     214,   218,   214,    44,  -156,   151,   218,   257,   173,     3,
-    -156,    12,  -156,   218,    23,   218,    44,  -156,    26,   112,
-     214,   214,    13,   218,   218,    -4,    54,   218,   218,   218,
-     218,   218,    31,    92,   165,     1,   237,   -14,    94,  -156,
-     200,    37,    19,    28,    60,  -156,    -1,    32,   231,  -156,
-     226,  -156,  -156,    57,  -156,   218,    46,   246,  -156,    81,
-      55,   218,   218,   136,   136,  -156,  -156,  -156,   218,   218,
-     257,   218,   218,   257,   218,   257,   218,   206,    -2,  -156,
-      64,    97,    99,   102,   173,    12,  -156,  -156,  -156,   218,
-      96,    72,   218,   218,  -156,   218,   130,   252,   257,   257,
-     257,   257,   257,   257,   119,   104,  -156,    99,  -156,  -156,
-    -156,    86,   145,   101,  -156,  -156,  -156,   120,   111,  -156,
-     257,   257,   121,   218,   218,   134,   159,  -156,    99,  -156,
-     127,   102,   167,   177,  -156,  -156,   257,   257,   170,    99,
-     186,   102,   182,   214,   183,   -33,    99,  -156,  -156,   185,
-     119,    44,   184,  -156,  -156,   202,  -156,   119,   162,   119,
-     174,   172,   119,   115,  -156,   180,  -156,   119,   101,  -156,
-    -156,   119,   101,  -156,  -156,  -156
+    -170,  -170,   -11,   -63,   -48,    11,  -170,   157,   213,   134,
+    -170,   136,  -170,   -81,  -170,  -169,  -170,    50,  -170,   -83,
+    -124
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
 {
-    -156,  -156,   -10,   -46,   -47,     6,  -156,   171,   196,   131,
-    -156,   137,  -156,  -156,  -155,  -156,    51,  -156,   -87,  -137
+      -1,     4,    14,    58,    15,    16,   131,    21,    22,    56,
+      57,    52,    53,    96,   156,   144,   165,   178,   179,    97,
+     126
 };
 
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      26,    91,    28,    59,   152,   120,    68,   164,    17,    23,
-      22,    18,   165,    25,   159,    18,    24,    27,    29,   101,
-      63,    64,    46,   183,    50,    87,    69,   185,    59,    58,
-     137,    60,    88,   116,     5,     6,     7,    54,    19,    66,
-      67,     8,    86,    73,    74,    75,    76,    77,    80,    83,
-      85,   150,    65,   126,   102,     9,    93,    30,    31,   132,
-      70,    71,   157,    72,    94,    11,    61,   135,    95,   166,
-      16,    58,    98,    78,    79,    30,    31,   106,   107,    37,
-      38,    39,    40,    41,   108,   109,    96,   110,   111,    31,
-     112,   104,   113,    58,   105,     5,     6,     7,    89,    90,
-      50,   127,     8,   118,   119,    58,   121,   119,   130,   131,
-      24,    58,   129,   168,   140,   141,     9,   117,    32,    33,
-     171,    34,   173,    35,    90,   178,    11,     1,     2,     3,
-     182,    16,   138,    81,   173,    82,   179,   180,   133,   146,
-     147,   151,    36,   161,   136,    37,    38,    39,    40,    41,
-     139,   144,    62,    42,    43,    44,    45,    32,    33,   143,
-      34,   145,    35,    37,    38,    39,    40,    41,     5,     6,
-       7,    39,    40,    41,   148,     8,     5,     6,    47,   149,
-     155,    36,   153,     8,    37,    38,    39,    40,    41,     9,
-     156,   158,    42,    43,    44,    45,    48,     9,   160,    11,
-     162,   167,   169,   172,    16,   170,    84,    11,    49,     5,
-       6,     7,    16,   177,   176,    53,     8,     5,     6,     7,
-      92,     5,     6,     7,     8,   181,   125,    97,     8,   114,
-       9,   124,   184,    37,    38,    39,    40,    41,     9,     0,
-      11,   115,     9,     0,    10,    16,   100,     0,    11,     0,
-       0,     0,    11,    12,     0,     0,     0,    16,     0,    37,
-      38,    39,    40,    41,    37,    38,    39,    40,    41,     0,
-      37,    38,    39,    40,    41,     0,    99,    62,   103,    37,
-      38,    39,    40,    41,   134,    37,    38,    39,    40,    41,
-      37,    38,    39,    40,    41
+      27,    92,    29,   106,    60,    19,    69,    31,    32,    93,
+      94,   122,   123,    18,   188,   125,    23,    62,   190,   154,
+      64,    65,   166,    28,    30,    95,    70,   167,    47,   161,
+      51,    24,    88,    20,   121,    59,    19,    61,    25,    89,
+      26,   129,    60,   168,    55,    67,    68,   135,   169,    74,
+      75,    76,    77,    78,    81,    84,    86,   152,   151,    98,
+     125,    71,    72,    66,    73,     5,     6,     7,     8,   159,
+     125,   138,   157,     9,    87,   158,    99,    59,    38,    39,
+      40,    41,    42,   111,   112,   100,    63,    10,    31,    32,
+     113,   114,   101,   115,   116,   103,   117,    12,   118,    59,
+       1,     2,     3,    17,    90,    91,    79,    80,    93,    94,
+      51,    40,    41,    42,   171,    59,   124,    94,   133,   134,
+      32,    59,   175,   109,   177,   110,   105,    25,   183,     5,
+       6,     7,     8,   130,   187,   142,   143,     9,   177,    38,
+      39,    40,    41,    42,   163,   184,   185,   148,   149,    93,
+      94,    10,     5,     6,     7,     8,   132,    91,   139,   141,
+       9,    12,   146,   140,   147,    95,   145,    17,   155,    82,
+     150,    83,    33,    34,    10,    35,   153,    36,    38,    39,
+      40,    41,    42,   160,    12,   162,   172,   164,    33,    34,
+      17,    35,    85,    36,   173,   170,    37,   174,   176,    38,
+      39,    40,    41,    42,   180,   181,   186,    63,    43,    44,
+      45,    46,    37,   182,   102,    38,    39,    40,    41,    42,
+       5,     6,     7,    48,    43,    44,    45,    46,     9,     5,
+       6,     7,     8,    54,   128,   127,   189,     9,     0,     0,
+       0,    49,    10,     0,     0,     0,     5,     6,     7,     8,
+     119,    10,    12,    50,     9,     0,     0,     0,    17,     0,
+       0,    12,   120,     5,     6,     7,     8,    17,    10,     0,
+       0,     9,     0,     0,    11,     0,     0,   107,    12,     0,
+       0,     0,   136,     0,    13,    10,    38,    39,    40,    41,
+      42,     0,     0,     0,     0,    12,     0,     0,     0,   104,
+       0,    17,    38,    39,    40,    41,    42,    38,    39,    40,
+      41,    42,   108,    38,    39,    40,    41,    42,   137,    38,
+      39,    40,    41,    42,    38,    39,    40,    41,    42
 };
 
 static const yytype_int16 yycheck[] =
 {
-      10,    48,    12,     5,   141,    92,    10,    40,     2,    39,
-       0,    12,    45,    39,   151,    12,    46,    11,    12,    65,
-      30,    31,    16,   178,    18,    39,    30,   182,     5,    23,
-     117,    25,    46,    35,     3,     4,     5,    25,    39,    33,
-      34,    10,    41,    37,    38,    39,    40,    41,    42,    43,
-      44,   138,    39,    99,     8,    24,    19,    31,    32,   105,
-       6,     7,   149,     9,    45,    34,    40,   114,    40,   156,
-      39,    65,    40,    42,    43,    31,    32,    71,    72,    33,
-      34,    35,    36,    37,    78,    79,    26,    81,    82,    32,
-      84,    10,    86,    87,    39,     3,     4,     5,     4,     5,
-      94,     5,    10,     4,     5,    99,     4,     5,   102,   103,
-      46,   105,    40,   160,    13,    14,    24,    20,     6,     7,
-     167,     9,   169,    11,     5,   172,    34,    27,    28,    29,
-     177,    39,    46,    41,   181,    43,    21,    22,     8,   133,
-     134,    14,    30,   153,    40,    33,    34,    35,    36,    37,
-       5,    40,    40,    41,    42,    43,    44,     6,     7,    39,
-       9,    40,    11,    33,    34,    35,    36,    37,     3,     4,
-       5,    35,    36,    37,    40,    10,     3,     4,     5,    20,
-       3,    30,    15,    10,    33,    34,    35,    36,    37,    24,
-      20,     5,    41,    42,    43,    44,    23,    24,    16,    34,
-      17,    16,    18,    41,    39,     3,    41,    34,    35,     3,
-       4,     5,    39,    41,    40,    19,    10,     3,     4,     5,
-      20,     3,     4,     5,    10,    45,    95,    56,    10,    23,
-      24,    94,   181,    33,    34,    35,    36,    37,    24,    -1,
-      34,    35,    24,    -1,    30,    39,    20,    -1,    34,    -1,
-      -1,    -1,    34,    39,    -1,    -1,    -1,    39,    -1,    33,
-      34,    35,    36,    37,    33,    34,    35,    36,    37,    -1,
-      33,    34,    35,    36,    37,    -1,    45,    40,    32,    33,
-      34,    35,    36,    37,    32,    33,    34,    35,    36,    37,
-      33,    34,    35,    36,    37
+      11,    49,    13,    66,     6,    13,    11,    32,    33,     5,
+       6,    92,    95,     2,   183,    98,     0,    42,   187,   143,
+      31,    32,    42,    12,    13,    21,    31,    47,    17,   153,
+      19,    41,    41,    41,    36,    24,    13,    26,    48,    48,
+      41,   104,     6,    42,    26,    34,    35,   110,    47,    38,
+      39,    40,    41,    42,    43,    44,    45,   140,   139,    20,
+     143,     7,     8,    41,    10,     3,     4,     5,     6,   150,
+     153,   119,     3,    11,    43,     6,    47,    66,    34,    35,
+      36,    37,    38,    72,    73,    42,    42,    25,    32,    33,
+      79,    80,    27,    82,    83,    42,    85,    35,    87,    88,
+      28,    29,    30,    41,     5,     6,    44,    45,     5,     6,
+      99,    36,    37,    38,   162,   104,     5,     6,   107,   108,
+      33,   110,   170,    11,   172,    41,    21,    48,   176,     3,
+       4,     5,     6,     6,   182,    14,    15,    11,   186,    34,
+      35,    36,    37,    38,   155,    22,    23,   136,   137,     5,
+       6,    25,     3,     4,     5,     6,    42,     6,    42,     6,
+      11,    35,    42,    48,    42,    21,    41,    41,    16,    43,
+      42,    45,     7,     8,    25,    10,    15,    12,    34,    35,
+      36,    37,    38,     6,    35,    17,    19,    18,     7,     8,
+      41,    10,    43,    12,     3,    17,    31,     3,    43,    34,
+      35,    36,    37,    38,    42,    42,    47,    42,    43,    44,
+      45,    46,    31,    43,    57,    34,    35,    36,    37,    38,
+       3,     4,     5,     6,    43,    44,    45,    46,    11,     3,
+       4,     5,     6,    20,   100,    99,   186,    11,    -1,    -1,
+      -1,    24,    25,    -1,    -1,    -1,     3,     4,     5,     6,
+      24,    25,    35,    36,    11,    -1,    -1,    -1,    41,    -1,
+      -1,    35,    36,     3,     4,     5,     6,    41,    25,    -1,
+      -1,    11,    -1,    -1,    31,    -1,    -1,     9,    35,    -1,
+      -1,    -1,     9,    -1,    41,    25,    34,    35,    36,    37,
+      38,    -1,    -1,    -1,    -1,    35,    -1,    -1,    -1,    47,
+      -1,    41,    34,    35,    36,    37,    38,    34,    35,    36,
+      37,    38,    33,    34,    35,    36,    37,    38,    33,    34,
+      35,    36,    37,    38,    34,    35,    36,    37,    38
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    27,    28,    29,    48,     3,     4,     5,    10,    24,
-      30,    34,    39,    49,    51,    52,    39,    52,    12,    39,
-      54,    55,     0,    39,    46,    39,    49,    52,    49,    52,
-      31,    32,     6,     7,     9,    11,    30,    33,    34,    35,
-      36,    37,    41,    42,    43,    44,    52,     5,    23,    35,
-      52,    58,    59,    55,    25,    56,    57,    50,    52,     5,
-      52,    40,    40,    49,    49,    39,    52,    52,    10,    30,
-       6,     7,     9,    52,    52,    52,    52,    52,    42,    43,
-      52,    41,    43,    52,    41,    52,    41,    39,    46,     4,
-       5,    51,    20,    19,    45,    40,    26,    54,    40,    45,
-      20,    50,     8,    32,    10,    39,    52,    52,    52,    52,
-      52,    52,    52,    52,    23,    35,    35,    20,     4,     5,
-      65,     4,    65,    66,    58,    56,    50,     5,    53,    40,
-      52,    52,    50,     8,    32,    51,    40,    65,    46,     5,
-      13,    14,    61,    39,    40,    40,    52,    52,    40,    20,
-      65,    14,    66,    15,    60,     3,    20,    65,     5,    66,
-      16,    49,    17,    62,    40,    45,    65,    16,    51,    18,
-       3,    51,    41,    51,    63,    64,    40,    41,    51,    21,
-      22,    45,    51,    61,    63,    61
+       0,    28,    29,    30,    50,     3,     4,     5,     6,    11,
+      25,    31,    35,    41,    51,    53,    54,    41,    54,    13,
+      41,    56,    57,     0,    41,    48,    41,    51,    54,    51,
+      54,    32,    33,     7,     8,    10,    12,    31,    34,    35,
+      36,    37,    38,    43,    44,    45,    46,    54,     6,    24,
+      36,    54,    60,    61,    57,    26,    58,    59,    52,    54,
+       6,    54,    42,    42,    51,    51,    41,    54,    54,    11,
+      31,     7,     8,    10,    54,    54,    54,    54,    54,    44,
+      45,    54,    43,    45,    54,    43,    54,    43,    41,    48,
+       5,     6,    53,     5,     6,    21,    62,    68,    20,    47,
+      42,    27,    56,    42,    47,    21,    52,     9,    33,    11,
+      41,    54,    54,    54,    54,    54,    54,    54,    54,    24,
+      36,    36,    62,    68,     5,    68,    69,    60,    58,    52,
+       6,    55,    42,    54,    54,    52,     9,    33,    53,    42,
+      48,     6,    14,    15,    64,    41,    42,    42,    54,    54,
+      42,    62,    68,    15,    69,    16,    63,     3,     6,    62,
+       6,    69,    17,    51,    18,    65,    42,    47,    42,    47,
+      17,    53,    19,     3,     3,    53,    43,    53,    66,    67,
+      42,    42,    43,    53,    22,    23,    47,    53,    64,    66,
+      64
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    49,    50,    50,    50,    51,    51,    51,    51,    51,
+      51,    51,    51,    51,    51,    51,    51,    51,    51,    51,
+      51,    51,    51,    51,    51,    51,    51,    51,    52,    52,
+      53,    53,    54,    54,    54,    54,    54,    54,    54,    54,
+      54,    54,    54,    54,    54,    54,    55,    55,    55,    55,
+      55,    56,    56,    57,    58,    58,    59,    60,    60,    61,
+      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
+      62,    62,    63,    63,    64,    64,    64,    65,    65,    66,
+      66,    67,    67,    67,    68,    68,    69,    69,    69,    69
 };
 
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     2,     2,     3,     3,     2,     3,     3,
+       4,     4,     3,     3,     4,     4,     4,     4,     3,     4,
+       5,     6,     5,     6,     5,     6,     3,     4,     3,     1,
+       1,     3,     1,     1,     1,     1,     3,     1,     2,     3,
+       3,     3,     3,     3,     4,     6,     1,     4,     6,     4,
+       6,     2,     4,     7,     0,     2,     2,     1,     3,     2,
+       2,     1,     3,     2,     1,     3,     4,     5,     5,     6,
+       2,     1,     0,     2,     0,     7,     8,     0,     3,     3,
+       1,     1,     2,     2,     1,     1,     1,     2,     3,     4
+};
 
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
 
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
 
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
 
-#define YYFAIL		goto yyerrlab
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
       yyerror (context, YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
 
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)			\
-     fprintf (File, "%d.%d-%d.%d",			\
-	      (Loc).first_line, (Loc).first_column,	\
-	      (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
 
 
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, context)
-#endif
-
 /* Enable debugging if requested.  */
 #if YYDEBUG
 
@@ -867,56 +786,47 @@ while (YYID (0))
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
 
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value, context); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, swq_parse_context *context)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    swq_parse_context *context;
-#endif
 {
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (context);
   if (!yyvaluep)
     return;
-  YYUSE (context);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -924,23 +834,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, swq_parse_context *context)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    swq_parse_context *context;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
   YYFPRINTF (yyoutput, ")");
@@ -951,16 +849,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, context)
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -971,50 +861,42 @@ yy_stack_print (yybottom, yytop)
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule, swq_parse_context *context)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule, context)
-    YYSTYPE *yyvsp;
-    int yyrule;
-    swq_parse_context *context;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, swq_parse_context *context)
 {
+  unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  unsigned long int yylno = yyrline[yyrule];
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
+             yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       , context);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , context);
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule, context); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, context); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -1028,7 +910,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -1043,7 +925,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
-

 
 #if YYERROR_VERBOSE
 
@@ -1052,15 +933,8 @@ int yydebug;
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -1076,16 +950,8 @@ yystrlen (yystr)
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -1115,27 +981,27 @@ yytnamerr (char *yyres, const char *yystr)
       char const *yyp = yystr;
 
       for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
     do_not_strip_quotes: ;
     }
 
@@ -1146,289 +1012,250 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
 {
-  int yyn = yypact[yystate];
+  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULL;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
     {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-	 constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-		    + sizeof yyexpecting - 1
-		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-		       * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-	 YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	  {
-	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-	      {
-		yycount = 1;
-		yysize = yysize0;
-		yyformat[sizeof yyunexpected - 1] = '\0';
-		break;
-	      }
-	    yyarg[yycount++] = yytname[yyx];
-	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-	    yysize_overflow |= (yysize1 < yysize);
-	    yysize = yysize1;
-	    yyfmt = yystpcpy (yyfmt, yyprefix);
-	    yyprefix = yyor;
-	  }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-	return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-	{
-	  /* Avoid sprintf, as that infringes on the user's name space.
-	     Don't have undefined behavior even if the translation
-	     produced a string with the wrong number of "%s"s.  */
-	  char *yyp = yyresult;
-	  int yyi = 0;
-	  while ((*yyp = *yyf) != '\0')
-	    {
-	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-		{
-		  yyp += yytnamerr (yyp, yyarg[yyi++]);
-		  yyf += 2;
-		}
-	      else
-		{
-		  yyp++;
-		  yyf++;
-		}
-	    }
-	}
-      return yysize;
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
     }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
 }
 #endif /* YYERROR_VERBOSE */
-

 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, swq_parse_context *context)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, context)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    swq_parse_context *context;
-#endif
 {
   YYUSE (yyvaluep);
   YYUSE (context);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   switch (yytype)
     {
-      case 3: /* "SWQT_NUMBER" */
-
-/* Line 1000 of yacc.c  */
-#line 98 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1294 "swq_parser.cpp"
-	break;
-      case 4: /* "SWQT_STRING" */
-
-/* Line 1000 of yacc.c  */
-#line 98 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1303 "swq_parser.cpp"
-	break;
-      case 5: /* "SWQT_IDENTIFIER" */
-
-/* Line 1000 of yacc.c  */
-#line 98 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1312 "swq_parser.cpp"
-	break;
-      case 49: /* "logical_expr" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1321 "swq_parser.cpp"
-	break;
-      case 50: /* "value_expr_list" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1330 "swq_parser.cpp"
-	break;
-      case 51: /* "field_value" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1339 "swq_parser.cpp"
-	break;
-      case 52: /* "value_expr" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1348 "swq_parser.cpp"
-	break;
-      case 53: /* "type_def" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1357 "swq_parser.cpp"
-	break;
-      case 65: /* "string_or_identifier" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1366 "swq_parser.cpp"
-	break;
-      case 66: /* "table_def" */
-
-/* Line 1000 of yacc.c  */
-#line 99 "swq_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1375 "swq_parser.cpp"
-	break;
+          case 3: /* "integer number"  */
+#line 105 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1170 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 4: /* "floating point number"  */
+#line 105 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1176 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 5: /* "string"  */
+#line 105 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1182 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 6: /* "identifier"  */
+#line 105 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1188 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 51: /* logical_expr  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1194 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 52: /* value_expr_list  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1200 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 53: /* field_value  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1206 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 54: /* value_expr  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1212 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 55: /* type_def  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1218 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 68: /* string_or_identifier  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1224 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 69: /* table_def  */
+#line 106 "swq_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1230 "swq_parser.cpp" /* yacc.c:1257  */
+        break;
+
 
       default:
-	break;
+        break;
     }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
-/* Prevent warnings from -Wmissing-prototypes.  */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (swq_parse_context *context);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
 
 
 
+/*----------.
+| yyparse.  |
+`----------*/
 
-/*-------------------------.
-| yyparse or yypush_parse.  |
-`-------------------------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (swq_parse_context *context)
-#else
-int
-yyparse (context)
-    swq_parse_context *context;
-#endif
-#endif
 {
 /* The lookahead symbol.  */
 int yychar;
 
+
 /* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
 
     /* Number of syntax errors so far.  */
     int yynerrs;
@@ -1438,10 +1265,10 @@ YYSTYPE yylval;
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
 
-       Refer to the stacks thru separate pointers, to allow yyoverflow
+       Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
 
     /* The state stack.  */
@@ -1459,7 +1286,7 @@ YYSTYPE yylval;
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1477,9 +1304,8 @@ YYSTYPE yylval;
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1488,14 +1314,6 @@ YYSTYPE yylval;
   yyerrstatus = 0;
   yynerrs = 0;
   yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1516,23 +1334,23 @@ YYSTYPE yylval;
 
 #ifdef yyoverflow
       {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -1540,22 +1358,22 @@ YYSTYPE yylval;
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
+        yystacksize = YYMAXDEPTH;
 
       {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -1564,10 +1382,10 @@ YYSTYPE yylval;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1587,7 +1405,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1596,7 +1414,7 @@ yybackup:
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, context);
     }
 
   if (yychar <= YYEOF)
@@ -1618,8 +1436,8 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1636,7 +1454,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1659,7 +1479,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1673,438 +1493,409 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-
-/* Line 1455 of yacc.c  */
-#line 105 "swq_parser.y"
+#line 112 "swq_parser.y" /* yacc.c:1646  */
     {
-			context->poRoot = (yyvsp[(2) - (2)]);
-		;}
+            context->poRoot = (yyvsp[0]);
+        }
+#line 1500 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 3:
-
-/* Line 1455 of yacc.c  */
-#line 110 "swq_parser.y"
+#line 117 "swq_parser.y" /* yacc.c:1646  */
     {
-			context->poRoot = (yyvsp[(2) - (2)]);
-		;}
+            context->poRoot = (yyvsp[0]);
+        }
+#line 1508 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 4:
-
-/* Line 1455 of yacc.c  */
-#line 115 "swq_parser.y"
+#line 122 "swq_parser.y" /* yacc.c:1646  */
     {
-			context->poRoot = (yyvsp[(2) - (2)]);
-		;}
+            context->poRoot = (yyvsp[0]);
+        }
+#line 1516 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 5:
-
-/* Line 1455 of yacc.c  */
-#line 121 "swq_parser.y"
+#line 128 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_AND );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_AND );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1527 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 6:
-
-/* Line 1455 of yacc.c  */
-#line 129 "swq_parser.y"
+#line 136 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_OR );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_OR );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1538 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-
-/* Line 1455 of yacc.c  */
-#line 137 "swq_parser.y"
+#line 144 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_NOT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(2) - (2)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_NOT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1548 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-
-/* Line 1455 of yacc.c  */
-#line 144 "swq_parser.y"
+#line 151 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(2) - (3)]);
-		     ;}
+            (yyval) = (yyvsp[-1]);
+        }
+#line 1556 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-
-/* Line 1455 of yacc.c  */
-#line 149 "swq_parser.y"
+#line 156 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_EQ );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_EQ );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1567 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-
-/* Line 1455 of yacc.c  */
-#line 157 "swq_parser.y"
+#line 164 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_NE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_NE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1578 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-
-/* Line 1455 of yacc.c  */
-#line 165 "swq_parser.y"
+#line 172 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_NE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_NE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1589 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-
-/* Line 1455 of yacc.c  */
-#line 173 "swq_parser.y"
+#line 180 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_LT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_LT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1600 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-
-/* Line 1455 of yacc.c  */
-#line 181 "swq_parser.y"
+#line 188 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_GT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_GT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1611 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-
-/* Line 1455 of yacc.c  */
-#line 189 "swq_parser.y"
+#line 196 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_LE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_LE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1622 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-
-/* Line 1455 of yacc.c  */
-#line 197 "swq_parser.y"
+#line 204 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_LE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_LE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1633 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-
-/* Line 1455 of yacc.c  */
-#line 205 "swq_parser.y"
+#line 212 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_LE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_LE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1644 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-
-/* Line 1455 of yacc.c  */
-#line 213 "swq_parser.y"
+#line 220 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_GE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-			(yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_GE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1655 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-
-/* Line 1455 of yacc.c  */
-#line 221 "swq_parser.y"
+#line 228 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_LIKE );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_LIKE );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1666 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-
-/* Line 1455 of yacc.c  */
-#line 229 "swq_parser.y"
+#line 236 "swq_parser.y" /* yacc.c:1646  */
     {
-		        swq_expr_node *like;
-			like = new swq_expr_node( SWQ_LIKE );
-			like->field_type = SWQ_BOOLEAN;
-			like->PushSubExpression( (yyvsp[(1) - (4)]) );
-			like->PushSubExpression( (yyvsp[(4) - (4)]) );
+            swq_expr_node *like;
+            like = new swq_expr_node( SWQ_LIKE );
+            like->field_type = SWQ_BOOLEAN;
+            like->PushSubExpression( (yyvsp[-3]) );
+            like->PushSubExpression( (yyvsp[0]) );
 
-			(yyval) = new swq_expr_node( SWQ_NOT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( like );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_NOT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( like );
+        }
+#line 1682 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-
-/* Line 1455 of yacc.c  */
-#line 242 "swq_parser.y"
+#line 249 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LIKE );
             (yyval)->field_type = SWQ_BOOLEAN;
-            (yyval)->PushSubExpression( (yyvsp[(1) - (5)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (5)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (5)]) );
-       ;}
+            (yyval)->PushSubExpression( (yyvsp[-4]) );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1694 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-
-/* Line 1455 of yacc.c  */
-#line 251 "swq_parser.y"
+#line 258 "swq_parser.y" /* yacc.c:1646  */
     {
-                swq_expr_node *like;
+            swq_expr_node *like;
             like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
-            like->PushSubExpression( (yyvsp[(1) - (6)]) );
-            like->PushSubExpression( (yyvsp[(4) - (6)]) );
-            like->PushSubExpression( (yyvsp[(6) - (6)]) );
+            like->PushSubExpression( (yyvsp[-5]) );
+            like->PushSubExpression( (yyvsp[-2]) );
+            like->PushSubExpression( (yyvsp[0]) );
 
             (yyval) = new swq_expr_node( SWQ_NOT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( like );
-      ;}
+        }
+#line 1711 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-
-/* Line 1455 of yacc.c  */
-#line 265 "swq_parser.y"
+#line 272 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(4) - (5)]);
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->nOperation = SWQ_IN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (5)]) );
-			(yyval)->ReverseSubExpressions();
-		     ;}
+            (yyval) = (yyvsp[-1]);
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->nOperation = SWQ_IN;
+            (yyval)->PushSubExpression( (yyvsp[-4]) );
+            (yyval)->ReverseSubExpressions();
+        }
+#line 1723 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-
-/* Line 1455 of yacc.c  */
-#line 274 "swq_parser.y"
+#line 281 "swq_parser.y" /* yacc.c:1646  */
     {
-		        swq_expr_node *in;
+            swq_expr_node *in;
 
-			in = (yyvsp[(5) - (6)]);
-			in->field_type = SWQ_BOOLEAN;
-			in->nOperation = SWQ_IN;
-			in->PushSubExpression( (yyvsp[(1) - (6)]) );
-			in->ReverseSubExpressions();
-			
-			(yyval) = new swq_expr_node( SWQ_NOT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( in );
-		     ;}
+            in = (yyvsp[-1]);
+            in->field_type = SWQ_BOOLEAN;
+            in->nOperation = SWQ_IN;
+            in->PushSubExpression( (yyvsp[-5]) );
+            in->ReverseSubExpressions();
+            
+            (yyval) = new swq_expr_node( SWQ_NOT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( in );
+        }
+#line 1741 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-
-/* Line 1455 of yacc.c  */
-#line 289 "swq_parser.y"
+#line 296 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_BETWEEN );
             (yyval)->field_type = SWQ_BOOLEAN;
-            (yyval)->PushSubExpression( (yyvsp[(1) - (5)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (5)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (5)]) );
-             ;}
+            (yyval)->PushSubExpression( (yyvsp[-4]) );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1753 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-
-/* Line 1455 of yacc.c  */
-#line 298 "swq_parser.y"
+#line 305 "swq_parser.y" /* yacc.c:1646  */
     {
             swq_expr_node *between;
             between = new swq_expr_node( SWQ_BETWEEN );
             between->field_type = SWQ_BOOLEAN;
-            between->PushSubExpression( (yyvsp[(1) - (6)]) );
-            between->PushSubExpression( (yyvsp[(4) - (6)]) );
-            between->PushSubExpression( (yyvsp[(6) - (6)]) );
+            between->PushSubExpression( (yyvsp[-5]) );
+            between->PushSubExpression( (yyvsp[-2]) );
+            between->PushSubExpression( (yyvsp[0]) );
 
             (yyval) = new swq_expr_node( SWQ_NOT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( between );
-             ;}
+        }
+#line 1770 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-
-/* Line 1455 of yacc.c  */
-#line 312 "swq_parser.y"
+#line 319 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_ISNULL );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_ISNULL );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+        }
+#line 1780 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-
-/* Line 1455 of yacc.c  */
-#line 319 "swq_parser.y"
+#line 326 "swq_parser.y" /* yacc.c:1646  */
     {
-		        swq_expr_node *isnull;
+        swq_expr_node *isnull;
 
-			isnull = new swq_expr_node( SWQ_ISNULL );
-			isnull->field_type = SWQ_BOOLEAN;
-			isnull->PushSubExpression( (yyvsp[(1) - (4)]) );
+            isnull = new swq_expr_node( SWQ_ISNULL );
+            isnull->field_type = SWQ_BOOLEAN;
+            isnull->PushSubExpression( (yyvsp[-3]) );
 
-			(yyval) = new swq_expr_node( SWQ_NOT );
-			(yyval)->field_type = SWQ_BOOLEAN;
-			(yyval)->PushSubExpression( isnull );
-		     ;}
+            (yyval) = new swq_expr_node( SWQ_NOT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( isnull );
+        }
+#line 1796 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-
-/* Line 1455 of yacc.c  */
-#line 333 "swq_parser.y"
+#line 340 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(3) - (3)]);
-			(yyvsp[(3) - (3)])->PushSubExpression( (yyvsp[(1) - (3)]) );
-		;}
+            (yyval) = (yyvsp[0]);
+            (yyvsp[0])->PushSubExpression( (yyvsp[-2]) );
+        }
+#line 1805 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-
-/* Line 1455 of yacc.c  */
-#line 339 "swq_parser.y"
+#line 346 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_UNKNOWN ); /* list */
-			(yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
-		;}
+            (yyval) = new swq_expr_node( SWQ_UNKNOWN ); /* list */
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1814 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-
-/* Line 1455 of yacc.c  */
-#line 346 "swq_parser.y"
+#line 353 "swq_parser.y" /* yacc.c:1646  */
     {
-		        (yyval) = (yyvsp[(1) - (1)]);  // validation deferred.
-			(yyval)->eNodeType = SNT_COLUMN;
-			(yyval)->field_index = (yyval)->table_index = -1;
-		;}
+            (yyval) = (yyvsp[0]);  // validation deferred.
+            (yyval)->eNodeType = SNT_COLUMN;
+            (yyval)->field_index = (yyval)->table_index = -1;
+        }
+#line 1824 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-
-/* Line 1455 of yacc.c  */
-#line 353 "swq_parser.y"
+#line 360 "swq_parser.y" /* yacc.c:1646  */
     {
-		        (yyval) = (yyvsp[(1) - (3)]);  // validation deferred.
-			(yyval)->eNodeType = SNT_COLUMN;
-			(yyval)->field_index = (yyval)->table_index = -1;
-			(yyval)->string_value = (char *) 
+            (yyval) = (yyvsp[-2]);  // validation deferred.
+            (yyval)->eNodeType = SNT_COLUMN;
+            (yyval)->field_index = (yyval)->table_index = -1;
+            (yyval)->string_value = (char *) 
                             CPLRealloc( (yyval)->string_value, 
                                         strlen((yyval)->string_value) 
-                                        + strlen((yyvsp[(3) - (3)])->string_value) + 2 );
-			strcat( (yyval)->string_value, "." );
-			strcat( (yyval)->string_value, (yyvsp[(3) - (3)])->string_value );
-			delete (yyvsp[(3) - (3)]);
-			(yyvsp[(3) - (3)]) = NULL;
-		;}
+                                        + strlen((yyvsp[0])->string_value) + 2 );
+            strcat( (yyval)->string_value, "." );
+            strcat( (yyval)->string_value, (yyvsp[0])->string_value );
+            delete (yyvsp[0]);
+            (yyvsp[0]) = NULL;
+        }
+#line 1842 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-
-/* Line 1455 of yacc.c  */
-#line 369 "swq_parser.y"
+#line 376 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(1) - (1)]);
-		;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1850 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-
-/* Line 1455 of yacc.c  */
-#line 374 "swq_parser.y"
+#line 381 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(1) - (1)]);
-		;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1858 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-
-/* Line 1455 of yacc.c  */
-#line 378 "swq_parser.y"
+#line 386 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(1) - (1)]);
-		;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1866 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-
-/* Line 1455 of yacc.c  */
-#line 383 "swq_parser.y"
+#line 390 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = (yyvsp[(2) - (3)]);
-		;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1874 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-
-/* Line 1455 of yacc.c  */
-#line 388 "swq_parser.y"
+#line 395 "swq_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = new swq_expr_node((const char*)NULL);
-        ;}
+            (yyval) = (yyvsp[-1]);
+        }
+#line 1882 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
+#line 400 "swq_parser.y" /* yacc.c:1646  */
+    {
+            (yyval) = new swq_expr_node((const char*)NULL);
+        }
+#line 1890 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 393 "swq_parser.y"
+  case 38:
+#line 405 "swq_parser.y" /* yacc.c:1646  */
     {
-            if ((yyvsp[(2) - (2)])->eNodeType == SNT_CONSTANT)
+            if ((yyvsp[0])->eNodeType == SNT_CONSTANT)
             {
-                (yyval) = (yyvsp[(2) - (2)]);
+                (yyval) = (yyvsp[0]);
                 (yyval)->int_value *= -1;
                 (yyval)->float_value *= -1;
             }
@@ -2112,559 +1903,585 @@ yyreduce:
             {
                 (yyval) = new swq_expr_node( SWQ_MULTIPLY );
                 (yyval)->PushSubExpression( new swq_expr_node(-1) );
-                (yyval)->PushSubExpression( (yyvsp[(2) - (2)]) );
+                (yyval)->PushSubExpression( (yyvsp[0]) );
             }
-        ;}
-    break;
-
-  case 38:
-
-/* Line 1455 of yacc.c  */
-#line 409 "swq_parser.y"
-    {
-			(yyval) = new swq_expr_node( SWQ_ADD );
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		;}
+        }
+#line 1909 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-
-/* Line 1455 of yacc.c  */
-#line 416 "swq_parser.y"
+#line 421 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_SUBTRACT );
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		;}
+            (yyval) = new swq_expr_node( SWQ_ADD );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1919 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-
-/* Line 1455 of yacc.c  */
-#line 423 "swq_parser.y"
+#line 428 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_MULTIPLY );
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		;}
+            (yyval) = new swq_expr_node( SWQ_SUBTRACT );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1929 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-
-/* Line 1455 of yacc.c  */
-#line 430 "swq_parser.y"
+#line 435 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_DIVIDE );
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		;}
+            (yyval) = new swq_expr_node( SWQ_MULTIPLY );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1939 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-
-/* Line 1455 of yacc.c  */
-#line 437 "swq_parser.y"
+#line 442 "swq_parser.y" /* yacc.c:1646  */
     {
-			(yyval) = new swq_expr_node( SWQ_MODULUS );
-			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-			(yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-		;}
+            (yyval) = new swq_expr_node( SWQ_DIVIDE );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1949 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-
-/* Line 1455 of yacc.c  */
-#line 444 "swq_parser.y"
-    {
-		    const swq_operation *poOp = 
-                      swq_op_registrar::GetOperator( (yyvsp[(1) - (4)])->string_value );
-
-		    if( poOp == NULL )
-		    {
-		        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Undefined function '%s' used.",
-                                  (yyvsp[(1) - (4)])->string_value );
-                delete (yyvsp[(1) - (4)]);
-                delete (yyvsp[(3) - (4)]);
-		        YYERROR;
-		    }
-		    else
-		    {
-			(yyval) = (yyvsp[(3) - (4)]);
-                        (yyval)->eNodeType = SNT_OPERATION;
-                        (yyval)->nOperation = poOp->eOperation;
-			(yyval)->ReverseSubExpressions();
-			delete (yyvsp[(1) - (4)]);
-		    }
-		;}
+#line 449 "swq_parser.y" /* yacc.c:1646  */
+    {
+            (yyval) = new swq_expr_node( SWQ_MODULUS );
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1959 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-
-/* Line 1455 of yacc.c  */
-#line 468 "swq_parser.y"
+#line 456 "swq_parser.y" /* yacc.c:1646  */
     {
-		    (yyval) = (yyvsp[(5) - (6)]);
-		    (yyval)->PushSubExpression( (yyvsp[(3) - (6)]) );
-		    (yyval)->ReverseSubExpressions();
-		;}
+            const swq_operation *poOp = 
+                    swq_op_registrar::GetOperator( (yyvsp[-3])->string_value );
+
+            if( poOp == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                                "Undefined function '%s' used.",
+                                (yyvsp[-3])->string_value );
+                delete (yyvsp[-3]);
+                delete (yyvsp[-1]);
+                YYERROR;
+            }
+            else
+            {
+                (yyval) = (yyvsp[-1]);
+                            (yyval)->eNodeType = SNT_OPERATION;
+                            (yyval)->nOperation = poOp->eOperation;
+                (yyval)->ReverseSubExpressions();
+                delete (yyvsp[-3]);
+            }
+        }
+#line 1986 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-
-/* Line 1455 of yacc.c  */
-#line 476 "swq_parser.y"
+#line 480 "swq_parser.y" /* yacc.c:1646  */
     {
-	    (yyval) = new swq_expr_node( SWQ_CAST );
-	    (yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
-	;}
+            (yyval) = (yyvsp[-1]);
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->ReverseSubExpressions();
+        }
+#line 1996 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-
-/* Line 1455 of yacc.c  */
-#line 482 "swq_parser.y"
+#line 488 "swq_parser.y" /* yacc.c:1646  */
     {
-	    (yyval) = new swq_expr_node( SWQ_CAST );
-	    (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-	    (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-	;}
+        (yyval) = new swq_expr_node( SWQ_CAST );
+        (yyval)->PushSubExpression( (yyvsp[0]) );
+    }
+#line 2005 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
+#line 494 "swq_parser.y" /* yacc.c:1646  */
+    {
+        (yyval) = new swq_expr_node( SWQ_CAST );
+        (yyval)->PushSubExpression( (yyvsp[-1]) );
+        (yyval)->PushSubExpression( (yyvsp[-3]) );
+    }
+#line 2015 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 489 "swq_parser.y"
+  case 48:
+#line 501 "swq_parser.y" /* yacc.c:1646  */
     {
-	    (yyval) = new swq_expr_node( SWQ_CAST );
-	    (yyval)->PushSubExpression( (yyvsp[(5) - (6)]) );
-	    (yyval)->PushSubExpression( (yyvsp[(3) - (6)]) );
-	    (yyval)->PushSubExpression( (yyvsp[(1) - (6)]) );
-	;}
+        (yyval) = new swq_expr_node( SWQ_CAST );
+        (yyval)->PushSubExpression( (yyvsp[-1]) );
+        (yyval)->PushSubExpression( (yyvsp[-3]) );
+        (yyval)->PushSubExpression( (yyvsp[-5]) );
+    }
+#line 2026 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 50:
+  case 49:
+#line 510 "swq_parser.y" /* yacc.c:1646  */
+    {
+        OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-1])->string_value);
+        if( !EQUAL((yyvsp[-3])->string_value,"GEOMETRY") || 
+            (wkbFlatten(eType) == wkbUnknown &&
+            !EQUALN((yyvsp[-1])->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+        {
+            yyerror (context, "syntax error");
+            delete (yyvsp[-3]);
+            delete (yyvsp[-1]);
+            YYERROR;
+        }
+        (yyval) = new swq_expr_node( SWQ_CAST );
+        (yyval)->PushSubExpression( (yyvsp[-1]) );
+        (yyval)->PushSubExpression( (yyvsp[-3]) );
+    }
+#line 2046 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 502 "swq_parser.y"
+  case 50:
+#line 528 "swq_parser.y" /* yacc.c:1646  */
     {
-        delete (yyvsp[(4) - (7)]);
-    ;}
+        OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-3])->string_value);
+        if( !EQUAL((yyvsp[-5])->string_value,"GEOMETRY") || 
+            (wkbFlatten(eType) == wkbUnknown &&
+            !EQUALN((yyvsp[-3])->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+        {
+            yyerror (context, "syntax error");
+            delete (yyvsp[-5]);
+            delete (yyvsp[-3]);
+            delete (yyvsp[-1]);
+            YYERROR;
+        }
+        (yyval) = new swq_expr_node( SWQ_CAST );
+        (yyval)->PushSubExpression( (yyvsp[-1]) );
+        (yyval)->PushSubExpression( (yyvsp[-3]) );
+        (yyval)->PushSubExpression( (yyvsp[-5]) );
+    }
+#line 2068 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 53:
+#line 552 "swq_parser.y" /* yacc.c:1646  */
+    {
+        delete (yyvsp[-3]);
+    }
+#line 2076 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 510 "swq_parser.y"
+  case 56:
+#line 560 "swq_parser.y" /* yacc.c:1646  */
     {
         swq_select* poNewSelect = new swq_select();
         context->poCurSelect->PushUnionAll(poNewSelect);
         context->poCurSelect = poNewSelect;
-    ;}
+    }
+#line 2086 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 56:
-
-/* Line 1455 of yacc.c  */
-#line 522 "swq_parser.y"
+  case 59:
+#line 572 "swq_parser.y" /* yacc.c:1646  */
     {
-		if( !context->poCurSelect->PushField( (yyvsp[(2) - (2)]), NULL, TRUE ) )
-        {
-            delete (yyvsp[(2) - (2)]);
-		    YYERROR;
+            if( !context->poCurSelect->PushField( (yyvsp[0]), NULL, TRUE ) )
+            {
+                delete (yyvsp[0]);
+                YYERROR;
+            }
         }
-	    ;}
+#line 2098 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 57:
-
-/* Line 1455 of yacc.c  */
-#line 531 "swq_parser.y"
+  case 60:
+#line 581 "swq_parser.y" /* yacc.c:1646  */
     {
-        if( !context->poCurSelect->PushField( (yyvsp[(2) - (2)]), NULL, TRUE ) )
-        {
-            delete (yyvsp[(2) - (2)]);
-            YYERROR;
+            if( !context->poCurSelect->PushField( (yyvsp[0]), NULL, TRUE ) )
+            {
+                delete (yyvsp[0]);
+                YYERROR;
+            }
         }
-        ;}
+#line 2110 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 58:
-
-/* Line 1455 of yacc.c  */
-#line 540 "swq_parser.y"
+  case 61:
+#line 590 "swq_parser.y" /* yacc.c:1646  */
     {
-		if( !context->poCurSelect->PushField( (yyvsp[(1) - (1)]) ) )
-        {
-            delete (yyvsp[(1) - (1)]);
-		    YYERROR;
+            if( !context->poCurSelect->PushField( (yyvsp[0]) ) )
+            {
+                delete (yyvsp[0]);
+                YYERROR;
+            }
         }
-	    ;}
+#line 2122 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 59:
-
-/* Line 1455 of yacc.c  */
-#line 549 "swq_parser.y"
+  case 62:
+#line 599 "swq_parser.y" /* yacc.c:1646  */
     {
-		if( !context->poCurSelect->PushField( (yyvsp[(2) - (4)]), (yyvsp[(4) - (4)])->string_value, TRUE ))
-        {
-            delete (yyvsp[(2) - (4)]);
-            delete (yyvsp[(4) - (4)]);
-		    YYERROR;
-        }
+            if( !context->poCurSelect->PushField( (yyvsp[-1]), (yyvsp[0])->string_value, TRUE ))
+            {
+                delete (yyvsp[-1]);
+                delete (yyvsp[0]);
+                YYERROR;
+            }
 
-		delete (yyvsp[(4) - (4)]);
-	    ;}
+            delete (yyvsp[0]);
+        }
+#line 2137 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 60:
-
-/* Line 1455 of yacc.c  */
-#line 561 "swq_parser.y"
+  case 63:
+#line 611 "swq_parser.y" /* yacc.c:1646  */
     {
-		if( !context->poCurSelect->PushField( (yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])->string_value ) )
-        {
-            delete (yyvsp[(1) - (3)]);
-            delete (yyvsp[(3) - (3)]);
-		    YYERROR;
+            if( !context->poCurSelect->PushField( (yyvsp[-1]), (yyvsp[0])->string_value ) )
+            {
+                delete (yyvsp[-1]);
+                delete (yyvsp[0]);
+                YYERROR;
+            }
+            delete (yyvsp[0]);
         }
-		delete (yyvsp[(3) - (3)]);
-	    ;}
+#line 2151 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 61:
-
-/* Line 1455 of yacc.c  */
-#line 572 "swq_parser.y"
+  case 64:
+#line 622 "swq_parser.y" /* yacc.c:1646  */
     {
-	        swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
 
-		if( !context->poCurSelect->PushField( poNode ) )
-        {
-            delete poNode;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( poNode ) )
+            {
+                delete poNode;
+                YYERROR;
+            }
         }
-	    ;}
+#line 2168 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 62:
-
-/* Line 1455 of yacc.c  */
-#line 586 "swq_parser.y"
+  case 65:
+#line 636 "swq_parser.y" /* yacc.c:1646  */
     {
-                CPLString osQualifiedField;
+            CPLString osQualifiedField;
 
-                osQualifiedField = (yyvsp[(1) - (3)])->string_value;
-                osQualifiedField += ".*";
+            osQualifiedField = (yyvsp[-2])->string_value;
+            osQualifiedField += ".*";
 
-                delete (yyvsp[(1) - (3)]);
-                (yyvsp[(1) - (3)]) = NULL;
+            delete (yyvsp[-2]);
+            (yyvsp[-2]) = NULL;
 
-	        swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( osQualifiedField );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( osQualifiedField );
+            poNode->table_index = poNode->field_index = -1;
 
-		if( !context->poCurSelect->PushField( poNode ) )
-        {
-            delete poNode;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( poNode ) )
+            {
+                delete poNode;
+                YYERROR;
+            }
         }
-	    ;}
+#line 2193 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 63:
+  case 66:
+#line 658 "swq_parser.y" /* yacc.c:1646  */
+    {
+                // special case for COUNT(*), confirm it.
+            if( !EQUAL((yyvsp[-3])->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Syntax Error with %s(*).", 
+                    (yyvsp[-3])->string_value );
+                delete (yyvsp[-3]);
+                    YYERROR;
+            }
 
-/* Line 1455 of yacc.c  */
-#line 608 "swq_parser.y"
-    {
-	        // special case for COUNT(*), confirm it.
-		if( !EQUAL((yyvsp[(1) - (4)])->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "Syntax Error with %s(*).", 
-			      (yyvsp[(1) - (4)])->string_value );
-            delete (yyvsp[(1) - (4)]);
-	            YYERROR;
-		}
-
-        delete (yyvsp[(1) - (4)]);
-        (yyvsp[(1) - (4)]) = NULL;
-                
-		swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+            delete (yyvsp[-3]);
+            (yyvsp[-3]) = NULL;
+                    
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
 
-		swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
-		count->PushSubExpression( poNode );
+            swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
+            count->PushSubExpression( poNode );
 
-		if( !context->poCurSelect->PushField( count ) )
-        {
-            delete count;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( count ) )
+            {
+                delete count;
+                YYERROR;
+            }
         }
-	    ;}
+#line 2226 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 64:
-
-/* Line 1455 of yacc.c  */
-#line 638 "swq_parser.y"
+  case 67:
+#line 688 "swq_parser.y" /* yacc.c:1646  */
     {
-	        // special case for COUNT(*), confirm it.
-		if( !EQUAL((yyvsp[(1) - (6)])->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "Syntax Error with %s(*).", 
-			      (yyvsp[(1) - (6)])->string_value );
-            delete (yyvsp[(1) - (6)]);
-            delete (yyvsp[(6) - (6)]);
-	            YYERROR;
-		}
+                // special case for COUNT(*), confirm it.
+            if( !EQUAL((yyvsp[-4])->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Syntax Error with %s(*).", 
+                        (yyvsp[-4])->string_value );
+                delete (yyvsp[-4]);
+                delete (yyvsp[0]);
+                YYERROR;
+            }
 
-        delete (yyvsp[(1) - (6)]);
-        (yyvsp[(1) - (6)]) = NULL;
+            delete (yyvsp[-4]);
+            (yyvsp[-4]) = NULL;
 
-		swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
 
-		swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
-		count->PushSubExpression( poNode );
+            swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
+            count->PushSubExpression( poNode );
 
-		if( !context->poCurSelect->PushField( count, (yyvsp[(6) - (6)])->string_value ) )
-        {
-            delete count;
-            delete (yyvsp[(6) - (6)]);
-		    YYERROR;
-        }
+            if( !context->poCurSelect->PushField( count, (yyvsp[0])->string_value ) )
+            {
+                delete count;
+                delete (yyvsp[0]);
+                YYERROR;
+            }
 
-                delete (yyvsp[(6) - (6)]);
-	    ;}
+            delete (yyvsp[0]);
+        }
+#line 2263 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 65:
-
-/* Line 1455 of yacc.c  */
-#line 672 "swq_parser.y"
+  case 68:
+#line 722 "swq_parser.y" /* yacc.c:1646  */
     {
-	        // special case for COUNT(DISTINCT x), confirm it.
-		if( !EQUAL((yyvsp[(1) - (5)])->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "DISTINCT keyword can only be used in COUNT() operator." );
-            delete (yyvsp[(1) - (5)]);
-            delete (yyvsp[(4) - (5)]);
-	            YYERROR;
-		}
+                // special case for COUNT(DISTINCT x), confirm it.
+            if( !EQUAL((yyvsp[-4])->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "DISTINCT keyword can only be used in COUNT() operator." );
+                delete (yyvsp[-4]);
+                delete (yyvsp[-1]);
+                    YYERROR;
+            }
 
-                delete (yyvsp[(1) - (5)]);
-                
-                swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
-                count->PushSubExpression( (yyvsp[(4) - (5)]) );
+            delete (yyvsp[-4]);
+            
+            swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
+            count->PushSubExpression( (yyvsp[-1]) );
                 
-		if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
-        {
-            delete count;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
+            {
+                delete count;
+                YYERROR;
+            }
         }
-	    ;}
+#line 2290 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 66:
-
-/* Line 1455 of yacc.c  */
-#line 696 "swq_parser.y"
-    {
-	        // special case for COUNT(DISTINCT x), confirm it.
-		if( !EQUAL((yyvsp[(1) - (7)])->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "DISTINCT keyword can only be used in COUNT() operator." );
-            delete (yyvsp[(1) - (7)]);
-            delete (yyvsp[(4) - (7)]);
-            delete (yyvsp[(7) - (7)]);
-	            YYERROR;
-		}
-
-                swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
-                count->PushSubExpression( (yyvsp[(4) - (7)]) );
-                
-		if( !context->poCurSelect->PushField( count, (yyvsp[(7) - (7)])->string_value, TRUE ) )
-        {
-            delete (yyvsp[(1) - (7)]);
-            delete count;
-            delete (yyvsp[(7) - (7)]);
-		    YYERROR;
-        }
+  case 69:
+#line 746 "swq_parser.y" /* yacc.c:1646  */
+    {
+            // special case for COUNT(DISTINCT x), confirm it.
+            if( !EQUAL((yyvsp[-5])->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "DISTINCT keyword can only be used in COUNT() operator." );
+                delete (yyvsp[-5]);
+                delete (yyvsp[-2]);
+                delete (yyvsp[0]);
+                YYERROR;
+            }
 
-                delete (yyvsp[(1) - (7)]);
-                delete (yyvsp[(7) - (7)]);
-	    ;}
-    break;
+            swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
+            count->PushSubExpression( (yyvsp[-2]) );
 
-  case 68:
+            if( !context->poCurSelect->PushField( count, (yyvsp[0])->string_value, TRUE ) )
+            {
+                delete (yyvsp[-5]);
+                delete count;
+                delete (yyvsp[0]);
+                YYERROR;
+            }
 
-/* Line 1455 of yacc.c  */
-#line 725 "swq_parser.y"
-    {	     
-	    	 context->poCurSelect->where_expr = (yyvsp[(2) - (2)]);
-	    ;}
+            delete (yyvsp[-5]);
+            delete (yyvsp[0]);
+        }
+#line 2321 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 70:
-
-/* Line 1455 of yacc.c  */
-#line 731 "swq_parser.y"
+#line 775 "swq_parser.y" /* yacc.c:1646  */
     {
-	        context->poCurSelect->PushJoin( (yyvsp[(2) - (7)])->int_value,
-					     (yyvsp[(4) - (7)])->string_value, 
-					     (yyvsp[(6) - (7)])->string_value );
-                delete (yyvsp[(2) - (7)]);
-	        delete (yyvsp[(4) - (7)]);
-	        delete (yyvsp[(6) - (7)]);
-	    ;}
+            delete (yyvsp[-1]);
+            (yyval) = (yyvsp[0]);
+        }
+#line 2330 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 71:
+  case 73:
+#line 785 "swq_parser.y" /* yacc.c:1646  */
+    {
+            context->poCurSelect->where_expr = (yyvsp[0]);
+        }
+#line 2338 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 740 "swq_parser.y"
+  case 75:
+#line 791 "swq_parser.y" /* yacc.c:1646  */
     {
-	        context->poCurSelect->PushJoin( (yyvsp[(3) - (8)])->int_value,
-					     (yyvsp[(5) - (8)])->string_value, 
-					     (yyvsp[(7) - (8)])->string_value );
-                delete (yyvsp[(3) - (8)]);
-	        delete (yyvsp[(5) - (8)]);
-	        delete (yyvsp[(7) - (8)]);
-	    ;}
+            context->poCurSelect->PushJoin( (yyvsp[-5])->int_value,
+                                            (yyvsp[-3])->string_value, 
+                                            (yyvsp[-1])->string_value );
+            delete (yyvsp[-5]);
+            delete (yyvsp[-3]);
+            delete (yyvsp[-1]);
+        }
+#line 2351 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 76:
+#line 800 "swq_parser.y" /* yacc.c:1646  */
+    {
+            context->poCurSelect->PushJoin( (yyvsp[-5])->int_value,
+                                            (yyvsp[-3])->string_value, 
+                                            (yyvsp[-1])->string_value );
+            delete (yyvsp[-5]);
+            delete (yyvsp[-3]);
+            delete (yyvsp[-1]);
+	    }
+#line 2364 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
 
-/* Line 1455 of yacc.c  */
-#line 758 "swq_parser.y"
+  case 81:
+#line 818 "swq_parser.y" /* yacc.c:1646  */
     {
-                context->poCurSelect->PushOrderBy( (yyvsp[(1) - (1)])->string_value, TRUE );
-                delete (yyvsp[(1) - (1)]);
-                (yyvsp[(1) - (1)]) = NULL;
-            ;}
+            context->poCurSelect->PushOrderBy( (yyvsp[0])->string_value, TRUE );
+            delete (yyvsp[0]);
+            (yyvsp[0]) = NULL;
+        }
+#line 2374 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 77:
-
-/* Line 1455 of yacc.c  */
-#line 764 "swq_parser.y"
+  case 82:
+#line 824 "swq_parser.y" /* yacc.c:1646  */
     {
-                context->poCurSelect->PushOrderBy( (yyvsp[(1) - (2)])->string_value, TRUE );
-                delete (yyvsp[(1) - (2)]);
-                (yyvsp[(1) - (2)]) = NULL;
-            ;}
+            context->poCurSelect->PushOrderBy( (yyvsp[-1])->string_value, TRUE );
+            delete (yyvsp[-1]);
+            (yyvsp[-1]) = NULL;
+        }
+#line 2384 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 78:
-
-/* Line 1455 of yacc.c  */
-#line 770 "swq_parser.y"
+  case 83:
+#line 830 "swq_parser.y" /* yacc.c:1646  */
     {
-                context->poCurSelect->PushOrderBy( (yyvsp[(1) - (2)])->string_value, FALSE );
-                delete (yyvsp[(1) - (2)]);
-                (yyvsp[(1) - (2)]) = NULL;
-            ;}
+            context->poCurSelect->PushOrderBy( (yyvsp[-1])->string_value, FALSE );
+            delete (yyvsp[-1]);
+            (yyvsp[-1]) = NULL;
+        }
+#line 2394 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 79:
-
-/* Line 1455 of yacc.c  */
-#line 778 "swq_parser.y"
+  case 84:
+#line 838 "swq_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (1)]);
-        ;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 2402 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 80:
-
-/* Line 1455 of yacc.c  */
-#line 782 "swq_parser.y"
+  case 85:
+#line 842 "swq_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (1)]);
-        ;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 2410 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 81:
-
-/* Line 1455 of yacc.c  */
-#line 788 "swq_parser.y"
+  case 86:
+#line 848 "swq_parser.y" /* yacc.c:1646  */
     {
-	    int iTable;
-	    iTable =context->poCurSelect->PushTableDef( NULL, (yyvsp[(1) - (1)])->string_value,
-	    	   				     	   NULL );
-	    delete (yyvsp[(1) - (1)]);
+        int iTable;
+        iTable =context->poCurSelect->PushTableDef( NULL, (yyvsp[0])->string_value,
+                                                    NULL );
+        delete (yyvsp[0]);
 
-	    (yyval) = new swq_expr_node( iTable );
-	;}
+        (yyval) = new swq_expr_node( iTable );
+    }
+#line 2423 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 82:
-
-/* Line 1455 of yacc.c  */
-#line 798 "swq_parser.y"
+  case 87:
+#line 858 "swq_parser.y" /* yacc.c:1646  */
     {
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( NULL, (yyvsp[(1) - (2)])->string_value,
-	    					      (yyvsp[(2) - (2)])->string_value );
-	    delete (yyvsp[(1) - (2)]);
-	    delete (yyvsp[(2) - (2)]);
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( NULL, (yyvsp[-1])->string_value,
+                                                     (yyvsp[0])->string_value );
+        delete (yyvsp[-1]);
+        delete (yyvsp[0]);
 
-	    (yyval) = new swq_expr_node( iTable );
-	;}
+        (yyval) = new swq_expr_node( iTable );
+    }
+#line 2437 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 83:
-
-/* Line 1455 of yacc.c  */
-#line 809 "swq_parser.y"
+  case 88:
+#line 869 "swq_parser.y" /* yacc.c:1646  */
     {
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( (yyvsp[(1) - (3)])->string_value,
-	    					      (yyvsp[(3) - (3)])->string_value, NULL );
-	    delete (yyvsp[(1) - (3)]);
-	    delete (yyvsp[(3) - (3)]);
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( (yyvsp[-2])->string_value,
+                                                     (yyvsp[0])->string_value, NULL );
+        delete (yyvsp[-2]);
+        delete (yyvsp[0]);
 
-	    (yyval) = new swq_expr_node( iTable );
-	;}
+        (yyval) = new swq_expr_node( iTable );
+    }
+#line 2451 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 84:
-
-/* Line 1455 of yacc.c  */
-#line 820 "swq_parser.y"
+  case 89:
+#line 880 "swq_parser.y" /* yacc.c:1646  */
     {
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( (yyvsp[(1) - (4)])->string_value,
-	    				     	      (yyvsp[(3) - (4)])->string_value, 
-					     	      (yyvsp[(4) - (4)])->string_value );
-	    delete (yyvsp[(1) - (4)]);
-	    delete (yyvsp[(3) - (4)]);
-	    delete (yyvsp[(4) - (4)]);
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
+                                                     (yyvsp[-1])->string_value, 
+                                                     (yyvsp[0])->string_value );
+        delete (yyvsp[-3]);
+        delete (yyvsp[-1]);
+        delete (yyvsp[0]);
 
-	    (yyval) = new swq_expr_node( iTable );
-	;}
+        (yyval) = new swq_expr_node( iTable );
+    }
+#line 2467 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
 
-
-/* Line 1455 of yacc.c  */
-#line 2666 "swq_parser.cpp"
+#line 2471 "swq_parser.cpp" /* yacc.c:1646  */
       default: break;
     }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
   YYPOPSTACK (yylen);
@@ -2673,7 +2490,7 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -2688,10 +2505,14 @@ yyreduce:
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
 yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
   /* If not already recovering from an error, report this error.  */
   if (!yyerrstatus)
     {
@@ -2699,37 +2520,36 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (context, YY_("syntax error"));
 #else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-	  {
-	    YYSIZE_T yyalloc = 2 * yysize;
-	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
-	    if (yymsg != yymsgbuf)
-	      YYSTACK_FREE (yymsg);
-	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-	    if (yymsg)
-	      yymsg_alloc = yyalloc;
-	    else
-	      {
-		yymsg = yymsgbuf;
-		yymsg_alloc = sizeof yymsgbuf;
-	      }
-	  }
-
-	if (0 < yysize && yysize <= yymsg_alloc)
-	  {
-	    (void) yysyntax_error (yymsg, yystate, yychar);
-	    yyerror (context, yymsg);
-	  }
-	else
-	  {
-	    yyerror (context, YY_("syntax error"));
-	    if (yysize != 0)
-	      goto yyexhaustedlab;
-	  }
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (context, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
       }
+# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2738,20 +2558,20 @@ yyerrlab:
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
+         error, discard it.  */
 
       if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
       else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval, context);
-	  yychar = YYEMPTY;
-	}
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, context);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -2770,7 +2590,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -2783,35 +2603,37 @@ yyerrorlab:
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
 
       /* Pop the current state because it cannot handle the error token.  */
       if (yyssp == yyss)
-	YYABORT;
+        YYABORT;
 
 
       yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp, context);
+                  yystos[yystate], yyvsp, context);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2835,7 +2657,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2847,16 +2669,21 @@ yyexhaustedlab:
 
 yyreturn:
   if (yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-		 yytoken, &yylval, context);
-  /* Do not reclaim the symbols of the rule which action triggered
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, context);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp, context);
+                  yystos[*yyssp], yyvsp, context);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -2867,9 +2694,5 @@ yyreturn:
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
-
-
-
diff --git a/ogr/swq_parser.hpp b/ogr/swq_parser.hpp
index efb7d65..894cf17 100644
--- a/ogr/swq_parser.hpp
+++ b/ogr/swq_parser.hpp
@@ -1,21 +1,20 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -28,60 +27,71 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+#ifndef YY_SWQ_SWQ_PARSER_HPP_INCLUDED
+# define YY_SWQ_SWQ_PARSER_HPP_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int swqdebug;
+#endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     SWQT_NUMBER = 258,
-     SWQT_STRING = 259,
-     SWQT_IDENTIFIER = 260,
-     SWQT_IN = 261,
-     SWQT_LIKE = 262,
-     SWQT_ESCAPE = 263,
-     SWQT_BETWEEN = 264,
-     SWQT_NULL = 265,
-     SWQT_IS = 266,
-     SWQT_SELECT = 267,
-     SWQT_LEFT = 268,
-     SWQT_JOIN = 269,
-     SWQT_WHERE = 270,
-     SWQT_ON = 271,
-     SWQT_ORDER = 272,
-     SWQT_BY = 273,
-     SWQT_FROM = 274,
-     SWQT_AS = 275,
-     SWQT_ASC = 276,
-     SWQT_DESC = 277,
-     SWQT_DISTINCT = 278,
-     SWQT_CAST = 279,
-     SWQT_UNION = 280,
-     SWQT_ALL = 281,
-     SWQT_LOGICAL_START = 282,
-     SWQT_VALUE_START = 283,
-     SWQT_SELECT_START = 284,
-     SWQT_NOT = 285,
-     SWQT_OR = 286,
-     SWQT_AND = 287,
-     SWQT_UMINUS = 288
-   };
+  enum yytokentype
+  {
+    END = 0,
+    SWQT_INTEGER_NUMBER = 258,
+    SWQT_FLOAT_NUMBER = 259,
+    SWQT_STRING = 260,
+    SWQT_IDENTIFIER = 261,
+    SWQT_IN = 262,
+    SWQT_LIKE = 263,
+    SWQT_ESCAPE = 264,
+    SWQT_BETWEEN = 265,
+    SWQT_NULL = 266,
+    SWQT_IS = 267,
+    SWQT_SELECT = 268,
+    SWQT_LEFT = 269,
+    SWQT_JOIN = 270,
+    SWQT_WHERE = 271,
+    SWQT_ON = 272,
+    SWQT_ORDER = 273,
+    SWQT_BY = 274,
+    SWQT_FROM = 275,
+    SWQT_AS = 276,
+    SWQT_ASC = 277,
+    SWQT_DESC = 278,
+    SWQT_DISTINCT = 279,
+    SWQT_CAST = 280,
+    SWQT_UNION = 281,
+    SWQT_ALL = 282,
+    SWQT_LOGICAL_START = 283,
+    SWQT_VALUE_START = 284,
+    SWQT_SELECT_START = 285,
+    SWQT_NOT = 286,
+    SWQT_OR = 287,
+    SWQT_AND = 288,
+    SWQT_UMINUS = 289,
+    SWQT_RESERVED_KEYWORD = 290
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
 
+int swqparse (swq_parse_context *context);
 
+#endif /* !YY_SWQ_SWQ_PARSER_HPP_INCLUDED  */
diff --git a/ogr/swq_parser.y b/ogr/swq_parser.y
index 5b84861..cdc2877 100644
--- a/ogr/swq_parser.y
+++ b/ogr/swq_parser.y
@@ -31,6 +31,7 @@
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_geometry.h"
 #include "swq.h"
 
 #define YYSTYPE  swq_expr_node*
@@ -42,49 +43,53 @@
 /* it appears to be a non documented feature of Bison */ 
 #define YYSTYPE_IS_TRIVIAL 1
 
-static void swqerror( swq_parse_context *context, const char *msg )
-{
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "SQL Expression Parsing Error: %s", msg );
-}
-
 %}
 
 %define api.pure
-%require "2.4.0"
+/* if the next %define is commented out, Bison 2.4 should be sufficient */
+/* but will produce less prettier error messages */
+%define parse.error verbose
+%require "3.0"
 
 %parse-param {swq_parse_context *context}
 %lex-param {swq_parse_context *context}
 
-%token SWQT_NUMBER
-%token SWQT_STRING
-%token SWQT_IDENTIFIER
-%token SWQT_IN
-%token SWQT_LIKE
-%token SWQT_ESCAPE
-%token SWQT_BETWEEN
-%token SWQT_NULL
-%token SWQT_IS
-%token SWQT_SELECT
-%token SWQT_LEFT
-%token SWQT_JOIN
-%token SWQT_WHERE
-%token SWQT_ON
-%token SWQT_ORDER
-%token SWQT_BY
-%token SWQT_FROM
-%token SWQT_AS
-%token SWQT_ASC
-%token SWQT_DESC
-%token SWQT_DISTINCT
-%token SWQT_CAST
-%token SWQT_UNION
-%token SWQT_ALL
+%token SWQT_INTEGER_NUMBER      "integer number"
+%token SWQT_FLOAT_NUMBER        "floating point number"
+%token SWQT_STRING              "string"
+%token SWQT_IDENTIFIER          "identifier"
+%token SWQT_IN                  "IN"
+%token SWQT_LIKE                "LIKE"
+%token SWQT_ESCAPE              "ESCAPE"
+%token SWQT_BETWEEN             "BETWEEN"
+%token SWQT_NULL                "NULL"
+%token SWQT_IS                  "IS"
+%token SWQT_SELECT              "SELECT"
+%token SWQT_LEFT                "LEFT"
+%token SWQT_JOIN                "JOIN"
+%token SWQT_WHERE               "WHERE"
+%token SWQT_ON                  "ON"
+%token SWQT_ORDER               "ORDER"
+%token SWQT_BY                  "BY"
+%token SWQT_FROM                "FROM"
+%token SWQT_AS                  "AS"
+%token SWQT_ASC                 "ASC"
+%token SWQT_DESC                "DESC"
+%token SWQT_DISTINCT            "DISTINCT"
+%token SWQT_CAST                "CAST"
+%token SWQT_UNION               "UNION"
+%token SWQT_ALL                 "ALL"
 
 %token SWQT_LOGICAL_START
 %token SWQT_VALUE_START
 %token SWQT_SELECT_START
 
+%token END 0                    "end of string"
+
+%token SWQT_NOT                 "NOT"
+%token SWQT_OR                  "OR"
+%token SWQT_AND                 "AND"
+
 %left SWQT_NOT
 %left SWQT_OR
 %left SWQT_AND
@@ -93,163 +98,165 @@ static void swqerror( swq_parse_context *context, const char *msg )
 %left '*' '/' '%'
 %left SWQT_UMINUS
 
+%token SWQT_RESERVED_KEYWORD    "reserved keyword"
+
 /* Any grammar rule that does $$ =  must be listed afterwards */
-/* as well as SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */
-%destructor { delete $$; } SWQT_NUMBER SWQT_STRING SWQT_IDENTIFIER
+/* as well as SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */
+%destructor { delete $$; } SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER
 %destructor { delete $$; } logical_expr value_expr_list field_value value_expr type_def string_or_identifier table_def
 
 %%
 
 input:  
-	SWQT_LOGICAL_START logical_expr
-		{
-			context->poRoot = $2;
-		}
+    SWQT_LOGICAL_START logical_expr
+        {
+            context->poRoot = $2;
+        }
 
-	| SWQT_VALUE_START value_expr
-		{
-			context->poRoot = $2;
-		}
+    | SWQT_VALUE_START value_expr
+        {
+            context->poRoot = $2;
+        }
 
-	| SWQT_SELECT_START select_statement
-		{
-			context->poRoot = $2;
-		}
+    | SWQT_SELECT_START select_statement
+        {
+            context->poRoot = $2;
+        }
 
 logical_expr:
-	logical_expr SWQT_AND logical_expr 
-		     {
-			$$ = new swq_expr_node( SWQ_AND );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| logical_expr SWQT_OR logical_expr
-		     {
-			$$ = new swq_expr_node( SWQ_OR );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| SWQT_NOT logical_expr
-		     {
-			$$ = new swq_expr_node( SWQ_NOT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $2 );
-		     }
-
-	| '(' logical_expr ')'
-	             {
-			$$ = $2;
-		     }
-
-	| value_expr '=' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_EQ );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| value_expr '<' '>' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_NE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr '!' '=' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_NE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr '<' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_LT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| value_expr '>' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_GT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| value_expr '<' '=' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_LE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr '=' '<' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_LE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr '=' '>' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_LE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr '>' '=' value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_GE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $4 );
-		     }
-
-	| value_expr SWQT_LIKE value_expr
-	             {
-			$$ = new swq_expr_node( SWQ_LIKE );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		     }
-
-	| value_expr SWQT_NOT SWQT_LIKE value_expr
-	             {
-		        swq_expr_node *like;
-			like = new swq_expr_node( SWQ_LIKE );
-			like->field_type = SWQ_BOOLEAN;
-			like->PushSubExpression( $1 );
-			like->PushSubExpression( $4 );
-
-			$$ = new swq_expr_node( SWQ_NOT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( like );
-		     }
+    logical_expr SWQT_AND logical_expr 
+        {
+            $$ = new swq_expr_node( SWQ_AND );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | logical_expr SWQT_OR logical_expr
+        {
+            $$ = new swq_expr_node( SWQ_OR );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | SWQT_NOT logical_expr
+        {
+            $$ = new swq_expr_node( SWQ_NOT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $2 );
+        }
+
+    | '(' logical_expr ')'
+        {
+            $$ = $2;
+        }
+
+    | value_expr '=' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_EQ );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '<' '>' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_NE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr '!' '=' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_NE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr '<' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_LT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '>' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_GT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '<' '=' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_LE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr '=' '<' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_LE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr '=' '>' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_LE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr '>' '=' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_GE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $4 );
+        }
+
+    | value_expr SWQT_LIKE value_expr
+        {
+            $$ = new swq_expr_node( SWQ_LIKE );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr SWQT_NOT SWQT_LIKE value_expr
+        {
+            swq_expr_node *like;
+            like = new swq_expr_node( SWQ_LIKE );
+            like->field_type = SWQ_BOOLEAN;
+            like->PushSubExpression( $1 );
+            like->PushSubExpression( $4 );
+
+            $$ = new swq_expr_node( SWQ_NOT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( like );
+        }
 
     | value_expr SWQT_LIKE value_expr SWQT_ESCAPE value_expr
-      {
+        {
             $$ = new swq_expr_node( SWQ_LIKE );
             $$->field_type = SWQ_BOOLEAN;
             $$->PushSubExpression( $1 );
             $$->PushSubExpression( $3 );
             $$->PushSubExpression( $5 );
-       }
+        }
 
     | value_expr SWQT_NOT SWQT_LIKE value_expr SWQT_ESCAPE value_expr
-      {
-                swq_expr_node *like;
+        {
+            swq_expr_node *like;
             like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
             like->PushSubExpression( $1 );
@@ -259,43 +266,43 @@ logical_expr:
             $$ = new swq_expr_node( SWQ_NOT );
             $$->field_type = SWQ_BOOLEAN;
             $$->PushSubExpression( like );
-      }
-
-	| value_expr SWQT_IN '(' value_expr_list ')'
-	             {
-			$$ = $4;
-			$$->field_type = SWQ_BOOLEAN;
-			$$->nOperation = SWQ_IN;
-			$$->PushSubExpression( $1 );
-			$$->ReverseSubExpressions();
-		     }
-
-	| value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
-	             {
-		        swq_expr_node *in;
-
-			in = $5;
-			in->field_type = SWQ_BOOLEAN;
-			in->nOperation = SWQ_IN;
-			in->PushSubExpression( $1 );
-			in->ReverseSubExpressions();
-			
-			$$ = new swq_expr_node( SWQ_NOT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( in );
-		     }
+        }
+
+    | value_expr SWQT_IN '(' value_expr_list ')'
+        {
+            $$ = $4;
+            $$->field_type = SWQ_BOOLEAN;
+            $$->nOperation = SWQ_IN;
+            $$->PushSubExpression( $1 );
+            $$->ReverseSubExpressions();
+        }
+
+    | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
+        {
+            swq_expr_node *in;
+
+            in = $5;
+            in->field_type = SWQ_BOOLEAN;
+            in->nOperation = SWQ_IN;
+            in->PushSubExpression( $1 );
+            in->ReverseSubExpressions();
+            
+            $$ = new swq_expr_node( SWQ_NOT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( in );
+        }
 
     | value_expr SWQT_BETWEEN value_expr SWQT_AND value_expr
-                 {
+        {
             $$ = new swq_expr_node( SWQ_BETWEEN );
             $$->field_type = SWQ_BOOLEAN;
             $$->PushSubExpression( $1 );
             $$->PushSubExpression( $3 );
             $$->PushSubExpression( $5 );
-             }
+        }
 
     | value_expr SWQT_NOT SWQT_BETWEEN value_expr SWQT_AND value_expr
-                 {
+        {
             swq_expr_node *between;
             between = new swq_expr_node( SWQ_BETWEEN );
             between->field_type = SWQ_BOOLEAN;
@@ -306,83 +313,88 @@ logical_expr:
             $$ = new swq_expr_node( SWQ_NOT );
             $$->field_type = SWQ_BOOLEAN;
             $$->PushSubExpression( between );
-             }
+        }
 
-	| value_expr SWQT_IS SWQT_NULL
-	             {
-			$$ = new swq_expr_node( SWQ_ISNULL );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( $1 );
-		     }
+    | value_expr SWQT_IS SWQT_NULL
+        {
+            $$ = new swq_expr_node( SWQ_ISNULL );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( $1 );
+        }
 
-	| value_expr SWQT_IS SWQT_NOT SWQT_NULL
-	             {
-		        swq_expr_node *isnull;
+    | value_expr SWQT_IS SWQT_NOT SWQT_NULL
+        {
+        swq_expr_node *isnull;
 
-			isnull = new swq_expr_node( SWQ_ISNULL );
-			isnull->field_type = SWQ_BOOLEAN;
-			isnull->PushSubExpression( $1 );
+            isnull = new swq_expr_node( SWQ_ISNULL );
+            isnull->field_type = SWQ_BOOLEAN;
+            isnull->PushSubExpression( $1 );
 
-			$$ = new swq_expr_node( SWQ_NOT );
-			$$->field_type = SWQ_BOOLEAN;
-			$$->PushSubExpression( isnull );
-		     }
+            $$ = new swq_expr_node( SWQ_NOT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( isnull );
+        }
 
 value_expr_list:
-	value_expr ',' value_expr_list
-		{
-			$$ = $3;
-			$3->PushSubExpression( $1 );
-		}
-
-	| value_expr
-	        {
-			$$ = new swq_expr_node( SWQ_UNKNOWN ); /* list */
-			$$->PushSubExpression( $1 );
-		}
+    value_expr ',' value_expr_list
+        {
+            $$ = $3;
+            $3->PushSubExpression( $1 );
+        }
+
+    | value_expr
+            {
+            $$ = new swq_expr_node( SWQ_UNKNOWN ); /* list */
+            $$->PushSubExpression( $1 );
+        }
 
 field_value:
-	SWQT_IDENTIFIER
-		{
-		        $$ = $1;  // validation deferred.
-			$$->eNodeType = SNT_COLUMN;
-			$$->field_index = $$->table_index = -1;
-		}
-
-	| SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
-		{
-		        $$ = $1;  // validation deferred.
-			$$->eNodeType = SNT_COLUMN;
-			$$->field_index = $$->table_index = -1;
-			$$->string_value = (char *) 
+    SWQT_IDENTIFIER
+        {
+            $$ = $1;  // validation deferred.
+            $$->eNodeType = SNT_COLUMN;
+            $$->field_index = $$->table_index = -1;
+        }
+
+    | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
+        {
+            $$ = $1;  // validation deferred.
+            $$->eNodeType = SNT_COLUMN;
+            $$->field_index = $$->table_index = -1;
+            $$->string_value = (char *) 
                             CPLRealloc( $$->string_value, 
                                         strlen($$->string_value) 
                                         + strlen($3->string_value) + 2 );
-			strcat( $$->string_value, "." );
-			strcat( $$->string_value, $3->string_value );
-			delete $3;
-			$3 = NULL;
-		}
+            strcat( $$->string_value, "." );
+            strcat( $$->string_value, $3->string_value );
+            delete $3;
+            $3 = NULL;
+        }
 
 value_expr:
-	SWQT_NUMBER 
-	        {
-			$$ = $1;
-		}
-
-	| SWQT_STRING
-		{
-			$$ = $1;
-		}
-	| field_value
-		{
-			$$ = $1;
-		}
-
-	| '(' value_expr ')'
-		{
-			$$ = $2;
-		}
+    SWQT_INTEGER_NUMBER 
+        {
+            $$ = $1;
+        }
+
+    | SWQT_FLOAT_NUMBER 
+        {
+            $$ = $1;
+        }
+
+    | SWQT_STRING
+        {
+            $$ = $1;
+        }
+    | field_value
+        {
+            $$ = $1;
+        }
+
+    | '(' value_expr ')'
+        {
+            $$ = $2;
+        }
 
     | SWQT_NULL
         {
@@ -405,96 +417,134 @@ value_expr:
             }
         }
 
-	| value_expr '+' value_expr
-		{
-			$$ = new swq_expr_node( SWQ_ADD );
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		}
-
-	| value_expr '-' value_expr
-		{
-			$$ = new swq_expr_node( SWQ_SUBTRACT );
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		}
-
-	| value_expr '*' value_expr
-		{
-			$$ = new swq_expr_node( SWQ_MULTIPLY );
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		}
-
-	| value_expr '/' value_expr
-		{
-			$$ = new swq_expr_node( SWQ_DIVIDE );
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		}
-
-	| value_expr '%' value_expr
-		{
-			$$ = new swq_expr_node( SWQ_MODULUS );
-			$$->PushSubExpression( $1 );
-			$$->PushSubExpression( $3 );
-		}
-
-	| SWQT_IDENTIFIER '(' value_expr_list ')'
-		{
-		    const swq_operation *poOp = 
-                      swq_op_registrar::GetOperator( $1->string_value );
-
-		    if( poOp == NULL )
-		    {
-		        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Undefined function '%s' used.",
-                                  $1->string_value );
+    | value_expr '+' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_ADD );
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '-' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_SUBTRACT );
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '*' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_MULTIPLY );
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '/' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_DIVIDE );
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | value_expr '%' value_expr
+        {
+            $$ = new swq_expr_node( SWQ_MODULUS );
+            $$->PushSubExpression( $1 );
+            $$->PushSubExpression( $3 );
+        }
+
+    | SWQT_IDENTIFIER '(' value_expr_list ')'
+        {
+            const swq_operation *poOp = 
+                    swq_op_registrar::GetOperator( $1->string_value );
+
+            if( poOp == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                                "Undefined function '%s' used.",
+                                $1->string_value );
                 delete $1;
                 delete $3;
-		        YYERROR;
-		    }
-		    else
-		    {
-			$$ = $3;
-                        $$->eNodeType = SNT_OPERATION;
-                        $$->nOperation = poOp->eOperation;
-			$$->ReverseSubExpressions();
-			delete $1;
-		    }
-		}
-
-	| SWQT_CAST '(' value_expr SWQT_AS type_def ')'
-	        {
-		    $$ = $5;
-		    $$->PushSubExpression( $3 );
-		    $$->ReverseSubExpressions();
-		}
-		
+                YYERROR;
+            }
+            else
+            {
+                $$ = $3;
+                            $$->eNodeType = SNT_OPERATION;
+                            $$->nOperation = poOp->eOperation;
+                $$->ReverseSubExpressions();
+                delete $1;
+            }
+        }
+
+    | SWQT_CAST '(' value_expr SWQT_AS type_def ')'
+        {
+            $$ = $5;
+            $$->PushSubExpression( $3 );
+            $$->ReverseSubExpressions();
+        }
+
 type_def:
-	SWQT_IDENTIFIER
-	{
-	    $$ = new swq_expr_node( SWQ_CAST );
-	    $$->PushSubExpression( $1 );
-	}
-
-	| SWQT_IDENTIFIER '(' SWQT_NUMBER ')' 
-	{
-	    $$ = new swq_expr_node( SWQ_CAST );
-	    $$->PushSubExpression( $3 );
-	    $$->PushSubExpression( $1 );
-	}
-
-	| SWQT_IDENTIFIER '(' SWQT_NUMBER ',' SWQT_NUMBER ')' 
-	{
-	    $$ = new swq_expr_node( SWQ_CAST );
-	    $$->PushSubExpression( $5 );
-	    $$->PushSubExpression( $3 );
-	    $$->PushSubExpression( $1 );
-	}
+    SWQT_IDENTIFIER
+    {
+        $$ = new swq_expr_node( SWQ_CAST );
+        $$->PushSubExpression( $1 );
+    }
+
+    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ')' 
+    {
+        $$ = new swq_expr_node( SWQ_CAST );
+        $$->PushSubExpression( $3 );
+        $$->PushSubExpression( $1 );
+    }
+
+    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ',' SWQT_INTEGER_NUMBER ')' 
+    {
+        $$ = new swq_expr_node( SWQ_CAST );
+        $$->PushSubExpression( $5 );
+        $$->PushSubExpression( $3 );
+        $$->PushSubExpression( $1 );
+    }
+
+    /* e.g. GEOMETRY(POINT) */
+    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ')' 
+    {
+        OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
+        if( !EQUAL($1->string_value,"GEOMETRY") || 
+            (wkbFlatten(eType) == wkbUnknown &&
+            !EQUALN($3->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+        {
+            yyerror (context, "syntax error");
+            delete $1;
+            delete $3;
+            YYERROR;
+        }
+        $$ = new swq_expr_node( SWQ_CAST );
+        $$->PushSubExpression( $3 );
+        $$->PushSubExpression( $1 );
+    }
+
+    /* e.g. GEOMETRY(POINT,4326) */
+    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ',' SWQT_INTEGER_NUMBER ')' 
+    {
+        OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
+        if( !EQUAL($1->string_value,"GEOMETRY") || 
+            (wkbFlatten(eType) == wkbUnknown &&
+            !EQUALN($3->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+        {
+            yyerror (context, "syntax error");
+            delete $1;
+            delete $3;
+            delete $5;
+            YYERROR;
+        }
+        $$ = new swq_expr_node( SWQ_CAST );
+        $$->PushSubExpression( $5 );
+        $$->PushSubExpression( $3 );
+        $$->PushSubExpression( $1 );
+    }
 
 select_statement: 
-	select_core opt_union_all
+    select_core opt_union_all
     | '(' select_core ')' opt_union_all
 
 select_core:
@@ -514,317 +564,327 @@ union_all: SWQT_UNION SWQT_ALL
     }
 
 select_field_list:
-	column_spec
-	| column_spec ',' select_field_list
+    column_spec
+    | column_spec ',' select_field_list
 
 column_spec: 
-	 SWQT_DISTINCT field_value
-	    {
-		if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
+    SWQT_DISTINCT field_value
         {
-            delete $2;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
+            {
+                delete $2;
+                YYERROR;
+            }
         }
-	    }
 
     | SWQT_DISTINCT SWQT_STRING
         {
-        if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
-        {
-            delete $2;
-            YYERROR;
-        }
+            if( !context->poCurSelect->PushField( $2, NULL, TRUE ) )
+            {
+                delete $2;
+                YYERROR;
+            }
         }
 
     | value_expr
-	    {
-		if( !context->poCurSelect->PushField( $1 ) )
         {
-            delete $1;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( $1 ) )
+            {
+                delete $1;
+                YYERROR;
+            }
         }
-	    }
 
-	| SWQT_DISTINCT field_value SWQT_AS string_or_identifier
-	    {
-		if( !context->poCurSelect->PushField( $2, $4->string_value, TRUE ))
+    | SWQT_DISTINCT field_value as_clause
         {
-            delete $2;
-            delete $4;
-		    YYERROR;
-        }
-
-		delete $4;
-	    }
+            if( !context->poCurSelect->PushField( $2, $3->string_value, TRUE ))
+            {
+                delete $2;
+                delete $3;
+                YYERROR;
+            }
 
-	| value_expr SWQT_AS string_or_identifier
-	    {
-		if( !context->poCurSelect->PushField( $1, $3->string_value ) )
-        {
-            delete $1;
             delete $3;
-		    YYERROR;
         }
-		delete $3;
-	    }
 
-        | '*'
-	    {
-	        swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+    | value_expr as_clause
+        {
+            if( !context->poCurSelect->PushField( $1, $2->string_value ) )
+            {
+                delete $1;
+                delete $2;
+                YYERROR;
+            }
+            delete $2;
+        }
 
-		if( !context->poCurSelect->PushField( poNode ) )
+    | '*'
         {
-            delete poNode;
-		    YYERROR;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
+
+            if( !context->poCurSelect->PushField( poNode ) )
+            {
+                delete poNode;
+                YYERROR;
+            }
         }
-	    }
-		
-        | SWQT_IDENTIFIER '.' '*'
-	    {
-                CPLString osQualifiedField;
 
-                osQualifiedField = $1->string_value;
-                osQualifiedField += ".*";
+    | SWQT_IDENTIFIER '.' '*'
+        {
+            CPLString osQualifiedField;
 
-                delete $1;
-                $1 = NULL;
+            osQualifiedField = $1->string_value;
+            osQualifiedField += ".*";
+
+            delete $1;
+            $1 = NULL;
 
-	        swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( osQualifiedField );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( osQualifiedField );
+            poNode->table_index = poNode->field_index = -1;
 
-		if( !context->poCurSelect->PushField( poNode ) )
-        {
-            delete poNode;
-		    YYERROR;
+            if( !context->poCurSelect->PushField( poNode ) )
+            {
+                delete poNode;
+                YYERROR;
+            }
         }
-	    }
-		
-        | SWQT_IDENTIFIER '(' '*' ')'
-	    {
-	        // special case for COUNT(*), confirm it.
-		if( !EQUAL($1->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "Syntax Error with %s(*).", 
-			      $1->string_value );
+
+    | SWQT_IDENTIFIER '(' '*' ')'
+        {
+                // special case for COUNT(*), confirm it.
+            if( !EQUAL($1->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Syntax Error with %s(*).", 
+                    $1->string_value );
+                delete $1;
+                    YYERROR;
+            }
+
             delete $1;
-	            YYERROR;
-		}
+            $1 = NULL;
+                    
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
 
-        delete $1;
-        $1 = NULL;
-                
-		swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
+            count->PushSubExpression( poNode );
 
-		swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
-		count->PushSubExpression( poNode );
+            if( !context->poCurSelect->PushField( count ) )
+            {
+                delete count;
+                YYERROR;
+            }
+        }
 
-		if( !context->poCurSelect->PushField( count ) )
+    | SWQT_IDENTIFIER '(' '*' ')' as_clause
         {
-            delete count;
-		    YYERROR;
-        }
-	    }
+                // special case for COUNT(*), confirm it.
+            if( !EQUAL($1->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Syntax Error with %s(*).", 
+                        $1->string_value );
+                delete $1;
+                delete $5;
+                YYERROR;
+            }
 
-        | SWQT_IDENTIFIER '(' '*' ')' SWQT_AS string_or_identifier
-	    {
-	        // special case for COUNT(*), confirm it.
-		if( !EQUAL($1->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "Syntax Error with %s(*).", 
-			      $1->string_value );
             delete $1;
-            delete $6;
-	            YYERROR;
-		}
+            $1 = NULL;
 
-        delete $1;
-        $1 = NULL;
+            swq_expr_node *poNode = new swq_expr_node();
+            poNode->eNodeType = SNT_COLUMN;
+            poNode->string_value = CPLStrdup( "*" );
+            poNode->table_index = poNode->field_index = -1;
 
-		swq_expr_node *poNode = new swq_expr_node();
-		poNode->eNodeType = SNT_COLUMN;
-		poNode->string_value = CPLStrdup( "*" );
-		poNode->table_index = poNode->field_index = -1;
+            swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
+            count->PushSubExpression( poNode );
+
+            if( !context->poCurSelect->PushField( count, $5->string_value ) )
+            {
+                delete count;
+                delete $5;
+                YYERROR;
+            }
 
-		swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
-		count->PushSubExpression( poNode );
+            delete $5;
+        }
 
-		if( !context->poCurSelect->PushField( count, $6->string_value ) )
+    | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
         {
-            delete count;
-            delete $6;
-		    YYERROR;
+                // special case for COUNT(DISTINCT x), confirm it.
+            if( !EQUAL($1->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "DISTINCT keyword can only be used in COUNT() operator." );
+                delete $1;
+                delete $4;
+                    YYERROR;
+            }
+
+            delete $1;
+            
+            swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
+            count->PushSubExpression( $4 );
+                
+            if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
+            {
+                delete count;
+                YYERROR;
+            }
         }
 
+    | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' as_clause
+        {
+            // special case for COUNT(DISTINCT x), confirm it.
+            if( !EQUAL($1->string_value,"COUNT") )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "DISTINCT keyword can only be used in COUNT() operator." );
+                delete $1;
+                delete $4;
                 delete $6;
-	    }
+                YYERROR;
+            }
 
-	| SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
-	    {
-	        // special case for COUNT(DISTINCT x), confirm it.
-		if( !EQUAL($1->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "DISTINCT keyword can only be used in COUNT() operator." );
-            delete $1;
-            delete $4;
-	            YYERROR;
-		}
+            swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
+            count->PushSubExpression( $4 );
 
+            if( !context->poCurSelect->PushField( count, $6->string_value, TRUE ) )
+            {
                 delete $1;
-                
-                swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
-                count->PushSubExpression( $4 );
-                
-		if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
-        {
-            delete count;
-		    YYERROR;
-        }
-	    }
+                delete count;
+                delete $6;
+                YYERROR;
+            }
 
-	| SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' SWQT_AS string_or_identifier
-	    {
-	        // special case for COUNT(DISTINCT x), confirm it.
-		if( !EQUAL($1->string_value,"COUNT") )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined,
-		    	      "DISTINCT keyword can only be used in COUNT() operator." );
             delete $1;
-            delete $4;
-            delete $7;
-	            YYERROR;
-		}
+            delete $6;
+        }
 
-                swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
-                count->PushSubExpression( $4 );
-                
-		if( !context->poCurSelect->PushField( count, $7->string_value, TRUE ) )
+as_clause:
+    SWQT_AS string_or_identifier
         {
             delete $1;
-            delete count;
-            delete $7;
-		    YYERROR;
+            $$ = $2;
         }
 
-                delete $1;
-                delete $7;
-	    }
+    | string_or_identifier
+
 
 opt_where:  
-	| SWQT_WHERE logical_expr
-	    {	     
-	    	 context->poCurSelect->where_expr = $2;
-	    }
+    | SWQT_WHERE logical_expr
+        {
+            context->poCurSelect->where_expr = $2;
+        }
 
 opt_joins:
-        | SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
-	    {
-	        context->poCurSelect->PushJoin( $2->int_value,
-					     $4->string_value, 
-					     $6->string_value );
-                delete $2;
-	        delete $4;
-	        delete $6;
-	    }
-        | SWQT_LEFT SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
-	    {
-	        context->poCurSelect->PushJoin( $3->int_value,
-					     $5->string_value, 
-					     $7->string_value );
-                delete $3;
-	        delete $5;
-	        delete $7;
+    | SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
+        {
+            context->poCurSelect->PushJoin( $2->int_value,
+                                            $4->string_value, 
+                                            $6->string_value );
+            delete $2;
+            delete $4;
+            delete $6;
+        }
+    | SWQT_LEFT SWQT_JOIN table_def SWQT_ON field_value '=' field_value opt_joins
+        {
+            context->poCurSelect->PushJoin( $3->int_value,
+                                            $5->string_value, 
+                                            $7->string_value );
+            delete $3;
+            delete $5;
+            delete $7;
 	    }
 
 opt_order_by:
-	| SWQT_ORDER SWQT_BY sort_spec_list
+    | SWQT_ORDER SWQT_BY sort_spec_list
 
 sort_spec_list:
-	sort_spec ',' sort_spec_list
-	| sort_spec 
+    sort_spec ',' sort_spec_list
+    | sort_spec 
 
 sort_spec:
-	field_value
-            {
-                context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
-                delete $1;
-                $1 = NULL;
-            }
-	| field_value SWQT_ASC
-            {
-                context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
-                delete $1;
-                $1 = NULL;
-            }
-	| field_value SWQT_DESC
-            {
-                context->poCurSelect->PushOrderBy( $1->string_value, FALSE );
-                delete $1;
-                $1 = NULL;
-            }
+    field_value
+        {
+            context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
+            delete $1;
+            $1 = NULL;
+        }
+    | field_value SWQT_ASC
+        {
+            context->poCurSelect->PushOrderBy( $1->string_value, TRUE );
+            delete $1;
+            $1 = NULL;
+        }
+    | field_value SWQT_DESC
+        {
+            context->poCurSelect->PushOrderBy( $1->string_value, FALSE );
+            delete $1;
+            $1 = NULL;
+        }
 
 string_or_identifier:
-        SWQT_IDENTIFIER
+    SWQT_IDENTIFIER
         {
             $$ = $1;
         }
-        | SWQT_STRING
+    | SWQT_STRING
         {
             $$ = $1;
         }
 
 table_def:
-	string_or_identifier
-	{
-	    int iTable;
-	    iTable =context->poCurSelect->PushTableDef( NULL, $1->string_value,
-	    	   				     	   NULL );
-	    delete $1;
-
-	    $$ = new swq_expr_node( iTable );
-	}
-
-	| string_or_identifier SWQT_IDENTIFIER
-	{
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( NULL, $1->string_value,
-	    					      $2->string_value );
-	    delete $1;
-	    delete $2;
-
-	    $$ = new swq_expr_node( iTable );
-	}
-
-	| SWQT_STRING '.' string_or_identifier
-	{
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( $1->string_value,
-	    					      $3->string_value, NULL );
-	    delete $1;
-	    delete $3;
-
-	    $$ = new swq_expr_node( iTable );
-	}
-
-	| SWQT_STRING '.' string_or_identifier SWQT_IDENTIFIER
-	{
-	    int iTable;
-	    iTable = context->poCurSelect->PushTableDef( $1->string_value,
-	    				     	      $3->string_value, 
-					     	      $4->string_value );
-	    delete $1;
-	    delete $3;
-	    delete $4;
-
-	    $$ = new swq_expr_node( iTable );
-	}
+    string_or_identifier
+    {
+        int iTable;
+        iTable =context->poCurSelect->PushTableDef( NULL, $1->string_value,
+                                                    NULL );
+        delete $1;
+
+        $$ = new swq_expr_node( iTable );
+    }
+
+    | string_or_identifier SWQT_IDENTIFIER
+    {
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( NULL, $1->string_value,
+                                                     $2->string_value );
+        delete $1;
+        delete $2;
+
+        $$ = new swq_expr_node( iTable );
+    }
+
+    | SWQT_STRING '.' string_or_identifier
+    {
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( $1->string_value,
+                                                     $3->string_value, NULL );
+        delete $1;
+        delete $3;
+
+        $$ = new swq_expr_node( iTable );
+    }
+
+    | SWQT_STRING '.' string_or_identifier SWQT_IDENTIFIER
+    {
+        int iTable;
+        iTable = context->poCurSelect->PushTableDef( $1->string_value,
+                                                     $3->string_value, 
+                                                     $4->string_value );
+        delete $1;
+        delete $3;
+        delete $4;
+
+        $$ = new swq_expr_node( iTable );
+    }
diff --git a/ogr/swq_select.cpp b/ogr/swq_select.cpp
index f705036..922a369 100644
--- a/ogr/swq_select.cpp
+++ b/ogr/swq_select.cpp
@@ -6,6 +6,7 @@
  * 
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,6 +29,7 @@
 
 #include "swq.h"
 #include "swq_parser.hpp"
+#include "ogr_geometry.h"
 
 /************************************************************************/
 /*                             swq_select()                             */
@@ -137,6 +139,7 @@ CPLErr swq_select::preparse( const char *select_statement )
 
     context.pszInput = select_statement;
     context.pszNext = select_statement;
+    context.pszLastValid = select_statement;
     context.nStartToken = SWQT_SELECT_START;
     context.poCurSelect = this;
 
@@ -344,6 +347,9 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         col_def->field_name = 
             CPLStrdup(poExpr->string_value);
     else if( poExpr->eNodeType == SNT_OPERATION
+             && (poExpr->nOperation == SWQ_CAST ||
+                 (poExpr->nOperation >= SWQ_AVG &&
+                  poExpr->nOperation <= SWQ_SUM))
              && poExpr->nSubExprCount >= 1
              && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
         col_def->field_name = 
@@ -356,6 +362,18 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
     if( pszAlias != NULL )
         col_def->field_alias = CPLStrdup( pszAlias );
+    else if( pszAlias == NULL && poExpr->eNodeType == SNT_OPERATION
+             && poExpr->nSubExprCount >= 1
+             && ( poExpr->nOperation == SWQ_CONCAT ||
+                  poExpr->nOperation == SWQ_SUBSTR )
+             && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
+    {
+        const swq_operation *op = swq_op_registrar::GetOperator( 
+                (swq_op) poExpr->nOperation );
+
+        col_def->field_alias = CPLStrdup( CPLSPrintf("%s_%s", op->pszName, 
+                                    poExpr->papoSubExpr[0]->string_value));
+    }
 
     col_def->table_index = -1;
     col_def->field_index = -1;
@@ -404,6 +422,10 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         {
             col_def->target_type = SWQ_TIME;
         }
+        else if( strcasecmp(pszTypeName,"geometry") == 0 )
+        {
+            col_def->target_type = SWQ_GEOMETRY;
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -416,17 +438,57 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
             result_columns--;
             return FALSE;
         }
-
-        // field width.
-        if( poExpr->nSubExprCount > 2 )
+        
+        if( col_def->target_type == SWQ_GEOMETRY ) 
         {
-            col_def->field_length = poExpr->papoSubExpr[2]->int_value;
-        }
+            if( poExpr->nSubExprCount > 2 )
+            {
+                if( poExpr->papoSubExpr[2]->field_type != SWQ_STRING )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                      "First argument of CAST operator should be an geometry type identifier." );
+                    CPLFree(col_def->field_name);
+                    col_def->field_name = NULL;
+                    CPLFree(col_def->field_alias);
+                    col_def->field_alias = NULL;
+                    result_columns--;
+                    return FALSE;
+                }
+
+                col_def->eGeomType =
+                    OGRFromOGCGeomType(poExpr->papoSubExpr[2]->string_value);
 
-        // field width.
-        if( poExpr->nSubExprCount > 3 && parse_precision )
+                // SRID
+                if( poExpr->nSubExprCount > 3 )
+                {
+                    col_def->nSRID = poExpr->papoSubExpr[3]->int_value;
+                }
+            }
+        }
+        else
         {
-            col_def->field_precision = poExpr->papoSubExpr[3]->int_value;
+            // field width.
+            if( poExpr->nSubExprCount > 2 )
+            {
+                if( poExpr->papoSubExpr[2]->field_type != SWQ_INTEGER )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                      "First argument of CAST operator should be of integer type." );
+                    CPLFree(col_def->field_name);
+                    col_def->field_name = NULL;
+                    CPLFree(col_def->field_alias);
+                    col_def->field_alias = NULL;
+                    result_columns--;
+                    return FALSE;
+                }
+                col_def->field_length = poExpr->papoSubExpr[2]->int_value;
+            }
+
+            // field width.
+            if( poExpr->nSubExprCount > 3 && parse_precision )
+            {
+                col_def->field_precision = poExpr->papoSubExpr[3]->int_value;
+            }
         }
     }
 
@@ -439,9 +501,25 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
     {
         if( poExpr->nSubExprCount != 1 )
         {
+            const swq_operation *poOp = 
+                    swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Column Summary Function '%s' has wrong number of arguments.", 
-                      poExpr->string_value ? poExpr->string_value : "(null)");
+                      poOp->pszName );
+            CPLFree(col_def->field_name);
+            col_def->field_name = NULL;
+            CPLFree(col_def->field_alias);
+            col_def->field_alias = NULL;
+            result_columns--;
+            return FALSE;
+        }
+        else if( poExpr->papoSubExpr[0]->eNodeType != SNT_COLUMN )
+        {
+            const swq_operation *poOp = 
+                    swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Argument of column Summary Function '%s' should be a column.", 
+                      poOp->pszName );
             CPLFree(col_def->field_name);
             col_def->field_name = NULL;
             CPLFree(col_def->field_alias);
@@ -686,8 +764,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
             int compose = itable != -1;
 
             /* skip this field if it isn't in the target table.  */
-            if( itable != -1 && field_list->table_ids != NULL 
-                && itable != field_list->table_ids[i] )
+            if( itable != -1 && itable != field_list->table_ids[i] )
                 continue;
 
             /* set up some default values. */
@@ -696,8 +773,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
             def->target_type = SWQ_OTHER;
 
             /* does this field duplicate an earlier one? */
-            if( field_list->table_ids != NULL 
-                && field_list->table_ids[i] != 0 
+            if( field_list->table_ids[i] != 0 
                 && !compose )
             {
                 int other;
@@ -713,23 +789,20 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
                 }
             }
 
-            if( !compose )
-                def->field_name = CPLStrdup( field_list->names[i] );
-            else
-            {
-                int itable = field_list->table_ids[i];
-                char *composed_name;
-                const char *field_name = field_list->names[i];
-                const char *table_alias = 
-                    field_list->table_defs[itable].table_alias;
+            int itable = field_list->table_ids[i];
+            char *composed_name;
+            const char *field_name = field_list->names[i];
+            const char *table_alias = 
+                field_list->table_defs[itable].table_alias;
 
-                composed_name = (char *) 
-                    CPLMalloc(strlen(field_name)+strlen(table_alias)+2);
+            composed_name = (char *) 
+                CPLMalloc(strlen(field_name)+strlen(table_alias)+2);
 
-                sprintf( composed_name, "%s.%s", table_alias, field_name );
+            sprintf( composed_name, "%s.%s", table_alias, field_name );
 
-                def->field_name = composed_name;
-            }							
+            def->field_name = composed_name;
+            if( !compose )
+                def->field_alias = CPLStrdup( field_list->names[i] );
 
             iout++;
 
@@ -777,7 +850,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             def->field_index = -1;
             def->table_index = -1;
 
-            if( def->expr->Check( field_list ) == SWQ_ERROR )
+            if( def->expr->Check( field_list, TRUE ) == SWQ_ERROR )
                 return CE_Failure;
                 
             def->field_type = def->expr->field_type;
@@ -819,15 +892,17 @@ CPLErr swq_select::parse( swq_field_list *field_list,
              || def->col_func == SWQCF_MAX
              || def->col_func == SWQCF_AVG
              || def->col_func == SWQCF_SUM)
-            && def->field_type == SWQ_STRING )
+            && (def->field_type == SWQ_STRING ||
+                def->field_type == SWQ_GEOMETRY) )
         {
             // possibly this is already enforced by the checker?
             const swq_operation *op = swq_op_registrar::GetOperator( 
                 (swq_op) def->col_func );
-            
             CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Use of field function %s() on string field %s illegal.", 
-                          op->osName.c_str(), def->field_name );
+                      "Use of field function %s() on %s field %s illegal.", 
+                      op->pszName,
+                      SWQFieldTypeToString(def->field_type),
+                      def->field_name );
             return CE_Failure;
         }
     }
@@ -848,11 +923,29 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             || def->col_func == SWQCF_AVG
             || def->col_func == SWQCF_SUM
             || def->col_func == SWQCF_COUNT )
+        {
             this_indicator = SWQM_SUMMARY_RECORD;
+            if( def->col_func == SWQCF_COUNT &&
+                def->distinct_flag &&
+                def->field_type == SWQ_GEOMETRY )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "SELECT COUNT DISTINCT on a geometry not supported." );
+                return CE_Failure;
+            }
+        }
         else if( def->col_func == SWQCF_NONE )
         {
             if( def->distinct_flag )
+            {
                 this_indicator = SWQM_DISTINCT_LIST;
+                if( def->field_type == SWQ_GEOMETRY )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "SELECT DISTINCT on a geometry not supported." );
+                    return CE_Failure;
+                }
+            }
             else
                 this_indicator = SWQM_RECORDSET;
         }
@@ -940,8 +1033,9 @@ CPLErr swq_select::parse( swq_field_list *field_list,
         swq_order_def *def = order_defs + i;
 
         /* identify field */
+        swq_field_type field_type;
         def->field_index = swq_identify_field( def->field_name, field_list,
-                                               NULL, &(def->table_index) );
+                                               &field_type, &(def->table_index) );
         if( def->field_index == -1 )
         {
             CPLError( CE_Failure, CPLE_AppDefined, 
@@ -949,6 +1043,22 @@ CPLErr swq_select::parse( swq_field_list *field_list,
                      def->field_name );
             return CE_Failure;
         }
+
+        if( def->table_index != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot use field '%s' of a secondary table in a ORDER BY clause",
+                      def->field_name );
+            return CE_Failure;
+        }
+
+        if( field_type == SWQ_GEOMETRY )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot use geometry field '%s' in a ORDER BY clause",
+                      def->field_name );
+            return CE_Failure;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -956,7 +1066,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 /*      doing final validation.                                         */
 /* -------------------------------------------------------------------- */
     if( where_expr != NULL 
-        && where_expr->Check( field_list ) == SWQ_ERROR )
+        && where_expr->Check( field_list, FALSE ) == SWQ_ERROR )
     {
         return CE_Failure;
     }
diff --git a/port/GNUmakefile b/port/GNUmakefile
index cbe2eb6..6ad69b7 100644
--- a/port/GNUmakefile
+++ b/port/GNUmakefile
@@ -27,7 +27,7 @@ OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \
 	cpl_vsil_tar.o cpl_vsil_stdin.o cpl_vsil_buffered_reader.o \
 	cpl_base64.o cpl_vsil_curl.o cpl_vsil_curl_streaming.o \
 	cpl_vsil_cache.o cpl_xml_validate.o cpl_spawn.o \
-	cpl_google_oauth2.o cpl_progress.o
+	cpl_google_oauth2.o cpl_progress.o cpl_virtualmem.o
 
 ifeq ($(ODBC_SETTING),yes)
 OBJ	:= 	$(OBJ) cpl_odbc.o
diff --git a/port/cpl_atomic_ops.cpp b/port/cpl_atomic_ops.cpp
index 79306c2..fee48b5 100644
--- a/port/cpl_atomic_ops.cpp
+++ b/port/cpl_atomic_ops.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.cpp 19884 2010-06-17 22:01:19Z rouault $
+ * $Id: cpl_atomic_ops.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_atomic_ops.cpp
  * Project:  CPL - Common Portability Library
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_atomic_ops.h b/port/cpl_atomic_ops.h
index a1323bb..29416be 100644
--- a/port/cpl_atomic_ops.h
+++ b/port/cpl_atomic_ops.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.h 19884 2010-06-17 22:01:19Z rouault $
+ * $Id: cpl_atomic_ops.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_atomic_ops.h
  * Project:  CPL - Common Portability Library
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_base64.cpp b/port/cpl_base64.cpp
index de82465..b3946bc 100644
--- a/port/cpl_base64.cpp
+++ b/port/cpl_base64.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_base64.cpp 21954 2011-03-13 18:18:20Z warmerdam $
+ * $Id: cpl_base64.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Encoding/Decoding Base64 strings
@@ -11,6 +11,7 @@
  * Copyright (c) 2008 Paul Ramsey
  * Copyright (c) 2002 Refractions Research
  * Copyright (C) 2004-2008 René Nyffenegger
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * (see also part way down the file for license terms for René's code)
  *
@@ -35,7 +36,7 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_base64.cpp 21954 2011-03-13 18:18:20Z warmerdam $");
+CPL_CVSID("$Id: cpl_base64.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* Derived from MapServer's mappostgis.c */
 
@@ -129,11 +130,17 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
             b4 = CPLBase64DecodeChar[c4];
 
             *p++=((b1<<2)|(b2>>4) );
+            if( p - pszBase64 == i )
+                break;
             if (c3 != '=') {
                 *p++=(((b2&0xf)<<4)|(b3>>2) );
+                if( p - pszBase64 == i )
+                    break;
             }
             if (c4 != '=') {
                 *p++=(((b3&0x3)<<6)|b4 );
+                if( p - pszBase64 == i )
+                    break;
             }
         }
         return(p-pszBase64);
diff --git a/port/cpl_conv.cpp b/port/cpl_conv.cpp
index 28a3587..446e8d5 100644
--- a/port/cpl_conv.cpp
+++ b/port/cpl_conv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.cpp 25795 2013-03-24 13:16:52Z rouault $
+ * $Id: cpl_conv.cpp 27121 2014-04-03 22:08:55Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "cpl_vsi.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_conv.cpp 25795 2013-03-24 13:16:52Z rouault $");
+CPL_CVSID("$Id: cpl_conv.cpp 27121 2014-04-03 22:08:55Z rouault $");
 
 #if defined(WIN32CE)
 #  include "cpl_wince.h"
@@ -48,6 +49,9 @@ static void *hSharedFileMutex = NULL;
 static volatile int nSharedFileCount = 0;
 static volatile CPLSharedFileInfo *pasSharedFileList = NULL;
 
+/* Used by CPLsetlocale() */
+static void *hSetLocaleMutex = NULL;
+
 /* Note: ideally this should be added in CPLSharedFileInfo* */
 /* but CPLSharedFileInfo is exposed in the API, hence that trick */
 /* to hide this detail */
@@ -1295,9 +1299,9 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
     if ( pszLocale || EQUAL( pszLocale, "" ) )
     {
         // Save the current locale
-        pszCurLocale = setlocale(LC_ALL, NULL );
+        pszCurLocale = CPLsetlocale(LC_ALL, NULL );
         // Set locale to the specified value
-        setlocale( LC_ALL, pszLocale );
+        CPLsetlocale( LC_ALL, pszLocale );
     }
 #else
     (void) pszLocale;
@@ -1319,7 +1323,7 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
     // Restore stored locale back
     if ( pszCurLocale )
-        setlocale( LC_ALL, pszCurLocale );
+        CPLsetlocale( LC_ALL, pszCurLocale );
 #endif
 
     return CPLPrintString( pszBuffer, szTemp, 64 );
@@ -1379,9 +1383,9 @@ int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
     if ( pszLocale || EQUAL( pszLocale, "" ) )
     {
         // Save the current locale
-        pszCurLocale = setlocale(LC_ALL, NULL );
+        pszCurLocale = CPLsetlocale(LC_ALL, NULL );
         // Set locale to the specified value
-        setlocale( LC_ALL, pszLocale );
+        CPLsetlocale( LC_ALL, pszLocale );
     }
 #else
     (void) pszLocale;
@@ -1393,7 +1397,7 @@ int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
     // Restore stored locale back
     if ( pszCurLocale )
-        setlocale( LC_ALL, pszCurLocale );
+        CPLsetlocale( LC_ALL, pszCurLocale );
 #endif
 
     nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
@@ -2231,9 +2235,9 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
 /*      First, ensure there isn't any such file yet.                    */
 /* -------------------------------------------------------------------- */
-    VSIStatBuf sStatBuf;
+    VSIStatBufL sStatBuf;
 
-    if( VSIStat( pszPath, &sStatBuf ) != 0 )
+    if( VSIStatL( pszPath, &sStatBuf ) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "It seems no file system object called '%s' exists.",
@@ -2399,17 +2403,24 @@ int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
 /*                             CPLLocaleC()                             */
 /************************************************************************/
 
-CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
+CPLLocaleC::CPLLocaleC()
 
 {
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO"))
-        || EQUAL(pszOldLocale,"C")
-        || EQUAL(pszOldLocale,"POSIX")
-        || setlocale(LC_NUMERIC,"C") == NULL )
+    if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO")) )
     {
-        CPLFree( pszOldLocale );
         pszOldLocale = NULL;
     }
+    else
+    {
+        pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
+        if( EQUAL(pszOldLocale,"C")
+            || EQUAL(pszOldLocale,"POSIX")
+            || CPLsetlocale(LC_NUMERIC,"C") == NULL )
+        {
+            CPLFree( pszOldLocale );
+            pszOldLocale = NULL;
+        }
+    }
 }
 
 /************************************************************************/
@@ -2421,11 +2432,46 @@ CPLLocaleC::~CPLLocaleC()
 {
     if( pszOldLocale != NULL )
     {
-        setlocale( LC_NUMERIC, pszOldLocale );
+        CPLsetlocale( LC_NUMERIC, pszOldLocale );
         CPLFree( pszOldLocale );
     }
 }
 
+
+/************************************************************************/
+/*                          CPLsetlocale()                              */
+/************************************************************************/
+
+/**
+ * Prevents parallel executions of setlocale().
+ *
+ * Calling setlocale() concurrently from two or more threads is a 
+ * potential data race. A mutex is used to provide a critical region so
+ * that only one thread at a time can be executing setlocale().
+ *
+ * @param category See your compiler's documentation on setlocale.
+ * @param locale See your compiler's documentation on setlocale.
+ *
+ * @return See your compiler's documentation on setlocale.
+ */
+char* CPLsetlocale (int category, const char* locale)
+{
+    CPLMutexHolder oHolder(&hSetLocaleMutex);
+    return setlocale(category, locale);
+}
+
+
+/************************************************************************/
+/*                       CPLCleanupSetlocaleMutex()                     */
+/************************************************************************/
+
+void CPLCleanupSetlocaleMutex(void)
+{
+    if( hSetLocaleMutex != NULL )
+        CPLDestroyMutex(hSetLocaleMutex);
+    hSetLocaleMutex = NULL;
+}
+
 /************************************************************************/
 /*                          CPLCheckForFile()                           */
 /************************************************************************/
diff --git a/port/cpl_conv.h b/port/cpl_conv.h
index be33371..660652a 100644
--- a/port/cpl_conv.h
+++ b/port/cpl_conv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.h 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: cpl_conv.h 27121 2014-04-03 22:08:55Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions declarations.
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -190,7 +191,7 @@ FILE CPL_DLL    *CPLOpenShared( const char *, const char *, int );
 void CPL_DLL     CPLCloseShared( FILE * );
 CPLSharedFileInfo CPL_DLL *CPLGetSharedList( int * );
 void CPL_DLL     CPLDumpSharedList( FILE * );
-void CPL_DLL     CPLCleanupSharedFileMutex();
+void CPL_DLL     CPLCleanupSharedFileMutex( void );
 
 /* -------------------------------------------------------------------- */
 /*      DMS to Dec to DMS conversion.                                   */
@@ -239,6 +240,12 @@ void CPL_DLL *CPLZLibInflate( const void* ptr, size_t nBytes,
 int CPL_DLL CPLValidateXML(const char* pszXMLFilename,
                            const char* pszXSDFilename,
                            char** papszOptions);
+						   
+/* -------------------------------------------------------------------- */
+/*      Locale handling. Prevents parallel executions of setlocale().   */
+/* -------------------------------------------------------------------- */
+char* CPLsetlocale (int category, const char* locale);
+void CPLCleanupSetlocaleMutex(void);
 
 CPL_C_END
 
diff --git a/port/cpl_csv.cpp b/port/cpl_csv.cpp
index ba09678..72307e6 100644
--- a/port/cpl_csv.cpp
+++ b/port/cpl_csv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_csv.cpp 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: cpl_csv.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CSV (comma separated value) file access.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,7 +33,7 @@
 #include "cpl_multiproc.h"
 #include "gdal_csv.h"
 
-CPL_CVSID("$Id: cpl_csv.cpp 25340 2012-12-21 20:30:21Z rouault $");
+CPL_CVSID("$Id: cpl_csv.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* ==================================================================== */
 /*      The CSVTable is a persistant set of info about an open CSV      */
diff --git a/port/cpl_error.cpp b/port/cpl_error.cpp
index 15cc2e9..a379801 100644
--- a/port/cpl_error.cpp
+++ b/port/cpl_error.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.cpp 25781 2013-03-22 20:57:00Z warmerdam $
+ * $Id: cpl_error.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_error.cpp
  * Project:  CPL - Common Portability Library
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 1998, Daniel Morissette
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,8 +40,9 @@
 #endif
  
 #define TIMESTAMP_DEBUG
+//#define MEMORY_DEBUG
 
-CPL_CVSID("$Id: cpl_error.cpp 25781 2013-03-22 20:57:00Z warmerdam $");
+CPL_CVSID("$Id: cpl_error.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void *hErrorMutex = NULL;
 static void *pErrorHandlerUserData = NULL; 
@@ -314,6 +316,40 @@ void CPLEmergencyError( const char *pszMessage )
 }
 
 /************************************************************************/
+/*                    CPLGetProcessMemorySize()                         */
+/************************************************************************/
+
+#ifdef MEMORY_DEBUG
+
+#ifdef __linux
+static int CPLGetProcessMemorySize()
+{
+    FILE* fp = fopen("/proc/self/status", "r");
+    if( fp == NULL )
+        return -1;
+    int nRet = -1;
+    char szLine[128];
+    while (fgets(szLine, sizeof(szLine), fp) != NULL)
+    {
+        if (strncmp(szLine, "VmSize:", 7) == 0)
+        {
+            const char* pszPtr = szLine;
+            while( !(*pszPtr == '\0' || (*pszPtr >= '0' && *pszPtr <= '9')) )
+                 pszPtr ++;
+            nRet = atoi(pszPtr);
+            break;
+        }
+    }
+    fclose(fp);
+    return nRet;
+}
+#else
+#error CPLGetProcessMemorySize() unimplemented for this OS
+#endif
+
+#endif // def MEMORY_DEBUG
+
+/************************************************************************/
 /*                              CPLDebug()                              */
 /************************************************************************/
 
@@ -397,6 +433,16 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
         strcat( pszMessage, ": " );
     }
 #endif
+
+/* -------------------------------------------------------------------- */
+/*      Add the process memory size.                                    */
+/* -------------------------------------------------------------------- */
+#ifdef MEMORY_DEBUG
+    char szVmSize[32];
+    sprintf( szVmSize, "[VmSize: %d] ", CPLGetProcessMemorySize());
+    strcat( pszMessage, szVmSize );
+#endif
+
     //sprintf(pszMessage,"[%d] ", (int)getpid());
 
 /* -------------------------------------------------------------------- */
diff --git a/port/cpl_error.h b/port/cpl_error.h
index 3b354ac..bac9bc1 100644
--- a/port/cpl_error.h
+++ b/port/cpl_error.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.h 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: cpl_error.h 26282 2013-08-08 21:15:36Z rouault $
  *
  * Name:     cpl_error.h
  * Project:  CPL - Common Portability Library
@@ -62,7 +62,7 @@ int CPL_DLL CPL_STDCALL CPLGetLastErrorNo( void );
 CPLErr CPL_DLL CPL_STDCALL CPLGetLastErrorType( void );
 const char CPL_DLL * CPL_STDCALL CPLGetLastErrorMsg( void );
 void CPL_DLL * CPL_STDCALL CPLGetErrorHandlerUserData(void);
-void CPL_DLL CPLCleanupErrorMutex();
+void CPL_DLL CPLCleanupErrorMutex( void );
 
 typedef void (CPL_STDCALL *CPLErrorHandler)(CPLErr, int, const char*);
 
diff --git a/port/cpl_findfile.cpp b/port/cpl_findfile.cpp
index 7e07ea7..84184fe 100644
--- a/port/cpl_findfile.cpp
+++ b/port/cpl_findfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_findfile.cpp 20089 2010-07-17 20:42:03Z rouault $
+ * $Id: cpl_findfile.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Generic data file location finder, with application hooking.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_findfile.cpp 20089 2010-07-17 20:42:03Z rouault $");
+CPL_CVSID("$Id: cpl_findfile.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef struct
 {
diff --git a/port/cpl_hash_set.cpp b/port/cpl_hash_set.cpp
index 7c4dc09..01c1804 100644
--- a/port/cpl_hash_set.cpp
+++ b/port/cpl_hash_set.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_hash_set.cpp 19040 2010-03-10 17:28:41Z warmerdam $
+ * $Id: cpl_hash_set.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_hash_set.cpp
  * Project:  CPL - Common Portability Library
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2008, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_hash_set.h b/port/cpl_hash_set.h
index 336a579..fad62fe 100644
--- a/port/cpl_hash_set.h
+++ b/port/cpl_hash_set.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_hash_set.h 16029 2009-01-01 19:32:39Z rouault $
+ * $Id: cpl_hash_set.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_hash_set.h
  * Project:  CPL - Common Portability Library
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2008, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2008-2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp
index 0175770..36105bf 100644
--- a/port/cpl_http.cpp
+++ b/port/cpl_http.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.cpp 25668 2013-02-22 18:47:08Z rouault $
+ * $Id: cpl_http.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  libcurl based HTTP client
  * Purpose:  libcurl based HTTP client
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -43,7 +44,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
 
 #endif
 
-CPL_CVSID("$Id: cpl_http.cpp 25668 2013-02-22 18:47:08Z rouault $");
+CPL_CVSID("$Id: cpl_http.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // list of named persistent http sessions 
 
@@ -135,14 +136,16 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  *                form proxy.server.com:port_number
  * <li>PROXYUSERPWD=val, where val is of the form username:password
  * <li>PROXYAUTH=[BASIC/NTLM/DIGEST/ANY] to specify an proxy authentication scheme to use.
+ * <li>NETRC=[YES/NO] to enable or disable use of $HOME/.netrc, default YES.
  * <li>CUSTOMREQUEST=val, where val is GET, PUT, POST, DELETE, etc.. (GDAL >= 1.9.0)
  * </ul>
  *
  * Alternatively, if not defined in the papszOptions arguments, the PROXY,  
- * PROXYUSERPWD and PROXYAUTH values are searched in the configuration options named 
- * GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH, as proxy configuration belongs 
- * to networking setup and makes more sense at the configuration option level 
- * than at the connection level.
+ * PROXYUSERPWD, PROXYAUTH and NETRC values are searched in the configuration 
+ * options named GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD, GDAL_PROXY_AUTH and 
+ * GDAL_HTTP_NETRC, as proxy configuration belongs to networking setup and 
+ * makes more sense at the configuration option level than at the connection 
+ * level.
  *
  * @return a CPLHTTPResult* structure that must be freed by 
  * CPLHTTPDestroyResult(), or NULL if libcurl support is disabled
@@ -286,11 +289,9 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Fetch content-type if possible.                                 */
 /* -------------------------------------------------------------------- */
-    CURLcode err;
-
     psResult->pszContentType = NULL;
-    err = curl_easy_getinfo( http_handle, CURLINFO_CONTENT_TYPE, 
-                             &(psResult->pszContentType) );
+    curl_easy_getinfo( http_handle, CURLINFO_CONTENT_TYPE, 
+                       &(psResult->pszContentType) );
     if( psResult->pszContentType != NULL )
         psResult->pszContentType = CPLStrdup(psResult->pszContentType);
 
@@ -401,6 +402,13 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     }
 #endif
 
+    /* Support use of .netrc - default enabled */
+    const char *pszHttpNetrc = CSLFetchNameValue( papszOptions, "NETRC" );
+    if( pszHttpNetrc == NULL )
+        pszHttpNetrc = CPLGetConfigOption( "GDAL_HTTP_NETRC", "YES" );
+    if( pszHttpNetrc == NULL || CSLTestBoolean(pszHttpNetrc) )
+        curl_easy_setopt(http_handle, CURLOPT_NETRC, 1L);
+
     /* Support setting userid:password */
     const char *pszUserPwd = CSLFetchNameValue( papszOptions, "USERPWD" );
     if (pszUserPwd == NULL)
@@ -496,6 +504,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     const char* pszPost = CSLFetchNameValue( papszOptions, "POSTFIELDS" );
     if( pszPost != NULL )
     {
+        CPLDebug("HTTP", "These POSTFIELDS were sent:%.4000s", pszPost);
         curl_easy_setopt(http_handle, CURLOPT_POST, 1 );
         curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pszPost );
     }
diff --git a/port/cpl_http.h b/port/cpl_http.h
index 9244d19..6747853 100644
--- a/port/cpl_http.h
+++ b/port/cpl_http.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.h 25478 2013-01-10 00:28:54Z warmerdam $
+ * $Id: cpl_http.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Function wrapper for libcurl HTTP access.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_list.cpp b/port/cpl_list.cpp
index 401fce0..5059317 100644
--- a/port/cpl_list.cpp
+++ b/port/cpl_list.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_list.cpp 14693 2008-06-12 18:21:54Z rouault $
+ * $Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_list.cpp
  * Project:  CPL - Common Portability Library
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_list.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_list.cpp 14693 2008-06-12 18:21:54Z rouault $");
+CPL_CVSID("$Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /*=====================================================================
                     List manipulation functions.
diff --git a/port/cpl_list.h b/port/cpl_list.h
index cb4f478..be0f724 100644
--- a/port/cpl_list.h
+++ b/port/cpl_list.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_list.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: cpl_list.h 26927 2014-02-11 15:54:59Z goatbar $
  *
  * Name:     cpl_list.h
  * Project:  CPL - Common Portability Library
@@ -47,12 +47,12 @@ CPL_C_START
 /** List element structure. */
 typedef struct _CPLList
 {
-    /*! Pointer to the data object. Should be allocated and frred by the
+    /*! Pointer to the data object. Should be allocated and freed by the
      * caller.
      * */
     void        *pData;
     /*! Pointer to the next element in list. NULL, if current element is the
-     * last one
+     * last one.
      */
     struct _CPLList    *psNext;
 } CPLList;
@@ -70,4 +70,3 @@ void CPL_DLL *CPLListGetData( CPLList *psElement );
 CPL_C_END
 
 #endif /* _CPL_LIST_H_INCLUDED */
-
diff --git a/port/cpl_minixml.cpp b/port/cpl_minixml.cpp
index 082a399..721587b 100644
--- a/port/cpl_minixml.cpp
+++ b/port/cpl_minixml.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_minixml.cpp 25340 2012-12-21 20:30:21Z rouault $
+ * $Id: cpl_minixml.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of MiniXML Parser and handling.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -44,7 +45,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: cpl_minixml.cpp 25340 2012-12-21 20:30:21Z rouault $");
+CPL_CVSID("$Id: cpl_minixml.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 typedef enum {
     TNone,
@@ -1887,46 +1888,16 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
 CPLXMLNode *CPLParseXMLFile( const char *pszFilename )
 
 {
-    VSILFILE       *fp;
-    vsi_l_offset    nLen;
+    GByte           *pabyOut = NULL;
     char            *pszDoc;
     CPLXMLNode      *psTree;
 
 /* -------------------------------------------------------------------- */
-/*      Read the file.                                                  */
+/*      Ingest the file.                                                */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "rb" );
-    if( fp == NULL )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %.500s to read.", pszFilename );
-        return NULL;
-    }
-
-    VSIFSeekL( fp, 0, SEEK_END );
-    nLen = VSIFTellL( fp );
-    VSIFSeekL( fp, 0, SEEK_SET );
-    
-    pszDoc = (char *) VSIMalloc((size_t)nLen + 1);
-    if( pszDoc == NULL )
-    {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Out of memory allocating space for %d byte buffer in\n"
-                  "CPLParseXMLFile(%.500s).", 
-                  (int)nLen+1, pszFilename );
-        VSIFCloseL( fp );
+    if( !VSIIngestFile( NULL, pszFilename, &pabyOut, NULL, -1 ) )
         return NULL;
-    }
-    if( VSIFReadL( pszDoc, 1, (size_t)nLen, fp ) < nLen )
-    {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "VSIFRead() result short of expected %d bytes from %.500s.", 
-                  (int)nLen, pszFilename );
-        pszDoc[0] = '\0';
-    }
-    VSIFCloseL( fp );
-
-    pszDoc[nLen] = '\0';
+    pszDoc = (char*) pabyOut;
 
 /* -------------------------------------------------------------------- */
 /*      Parse it.                                                       */
diff --git a/port/cpl_minizip_ioapi.cpp b/port/cpl_minizip_ioapi.cpp
index e767a9c..56f878a 100644
--- a/port/cpl_minizip_ioapi.cpp
+++ b/port/cpl_minizip_ioapi.cpp
@@ -4,7 +4,7 @@
       - Remove old C style function prototypes
       - Add support for ZIP64
 
-   Copyright (C) 2007-2008 Even Rouault
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
 
    Original licence available in port/LICENCE_minizip
 */
diff --git a/port/cpl_minizip_ioapi.h b/port/cpl_minizip_ioapi.h
index 8237429..35156d2 100644
--- a/port/cpl_minizip_ioapi.h
+++ b/port/cpl_minizip_ioapi.h
@@ -2,7 +2,7 @@
       - change fill_fopen_filefunc to cpl_fill_fopen_filefunc
       - Add support for ZIP64
 
-   Copyright (C) 2007-2008 Even Rouault
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
 
    Original licence available in port/LICENCE_minizip
 */
diff --git a/port/cpl_minizip_unzip.cpp b/port/cpl_minizip_unzip.cpp
index 4e92234..e30b78c 100644
--- a/port/cpl_minizip_unzip.cpp
+++ b/port/cpl_minizip_unzip.cpp
@@ -4,8 +4,10 @@
      - Undef EXPORT so that we are sure the symbols are not exported
      - Remove old C style function prototypes
      - Add support for ZIP64
+     - Recode filename to UTF-8 if GP 11 is unset
+     - Use Info-ZIP Unicode Path Extra Field (0x7075) to get UTF-8 filenames
 
-   Copyright (C) 2007-2008 Even Rouault
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
 
    Original licence available in port/LICENCE_minizip
 */
@@ -54,6 +56,7 @@ woven in by Terry Thorsen 1/2003.
 
 #include "zlib.h"
 #include "cpl_minizip_unzip.h"
+#include "cpl_string.h"
 
 #ifdef STDC
 #  include <stddef.h>
@@ -822,6 +825,7 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
     uLong uMagic;
     long lSeek=0;
     uLong uL;
+    int bHasUTF8Filename = FALSE;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
@@ -904,8 +908,10 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
             uSizeRead = fileNameBufferSize;
 
         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+        {
             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
                 err=UNZ_ERRNO;
+        }
         lSeek -= uSizeRead;
     }
 
@@ -958,21 +964,89 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
             /* ZIP64 extra fields */
             if (headerId == 0x0001)
             {
-                if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
-                    err=UNZ_ERRNO;
-
-                if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
-                    err=UNZ_ERRNO;
+                uLong64 u64;
+                if( file_info.uncompressed_size == 0xFFFFFFFF )
+                {
+                    if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&u64) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                    file_info.uncompressed_size = u64;
+                }
+
+                if( file_info.compressed_size == 0xFFFFFFFF )
+                {
+                    if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&u64) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                    file_info.compressed_size = u64;
+                }
 
                 /* Relative Header offset */
-                uLong64 u64;
-                if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&u64) != UNZ_OK)
-                    err=UNZ_ERRNO;
+                if( file_info_internal.offset_curfile == 0xFFFFFFFF )
+                {
+                    if (unzlocal_getLong64(&s->z_filefunc, s->filestream,&u64) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                    file_info_internal.offset_curfile = u64;
+                }
 
                 /* Disk Start Number */
-                uLong uL;
-                if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                if( file_info.disk_num_start == 0xFFFF )
+                {
+                    uLong uL;
+                    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                        err=UNZ_ERRNO;
+                    file_info.disk_num_start = uL;
+                }
+            }
+            /* Info-ZIP Unicode Path Extra Field (0x7075) */
+            else if( headerId == 0x7075 && dataSize > 5 &&
+                     file_info.size_filename<=fileNameBufferSize &&
+                     szFileName != NULL )
+            {
+                int version;
+                if (unzlocal_getByte(&s->z_filefunc, s->filestream,&version) != UNZ_OK)
                     err=UNZ_ERRNO;
+                if( version != 1 )
+                {
+                    /* If version != 1, ignore that extra field */
+                    if (ZSEEK(s->z_filefunc, s->filestream,dataSize - 1,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+                        err=UNZ_ERRNO;
+                }
+                else
+                {
+                    uLong nameCRC32;
+                    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&nameCRC32) != UNZ_OK)
+                        err=UNZ_ERRNO;
+
+                    /* Check expected CRC for filename */
+                    if( nameCRC32 == crc32(0, (const Bytef*)szFileName, file_info.size_filename) )
+                    {
+                        uLong utf8Size = dataSize - 1 - 4;
+                        uLong uSizeRead ;
+
+                        bHasUTF8Filename = TRUE;
+
+                        if (utf8Size<fileNameBufferSize)
+                        {
+                            *(szFileName+utf8Size)='\0';
+                            uSizeRead = utf8Size;
+                        }
+                        else
+                            uSizeRead = fileNameBufferSize;
+
+                        if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+                            err=UNZ_ERRNO;
+                        else if( utf8Size > fileNameBufferSize )
+                        {
+                            if (ZSEEK(s->z_filefunc, s->filestream,utf8Size - fileNameBufferSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+                                err=UNZ_ERRNO;
+                        }
+                    }
+                    else
+                    {
+                        /* ignore unicode name if CRC mismatch */
+                        if (ZSEEK(s->z_filefunc, s->filestream,dataSize - 1- 4,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+                                err=UNZ_ERRNO;
+                    }
+                }
             }
             else
             {
@@ -983,6 +1057,25 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
             acc += 2 + 2 + dataSize;
         }
     }
+    
+    if( !bHasUTF8Filename && szFileName != NULL &&
+        (file_info.flag & (1 << 11)) == 0 &&
+        file_info.size_filename<fileNameBufferSize )
+    {
+        const char* pszSrcEncoding = CPLGetConfigOption("CPL_ZIP_ENCODING",
+#ifdef _WIN32
+                                                        "CP_OEMCP"
+#else
+                                                        "CP437"
+#endif
+                                                        );
+        char* pszRecoded = CPLRecode(szFileName, pszSrcEncoding, CPL_ENC_UTF8);
+        if( pszRecoded != NULL && strlen(pszRecoded) < fileNameBufferSize)
+        {
+            strcpy(szFileName, pszRecoded);
+        }
+        CPLFree(pszRecoded);
+    }
 
 #if 0
     if ((err==UNZ_OK) && (szComment!=NULL))
diff --git a/port/cpl_minizip_unzip.h b/port/cpl_minizip_unzip.h
index a2acd48..f60d617 100644
--- a/port/cpl_minizip_unzip.h
+++ b/port/cpl_minizip_unzip.h
@@ -4,7 +4,7 @@
      - Undef EXPORT so that we are sure the symbols are not exported
      - Add support for ZIP64
 
-   Copyright (C) 2007-2008 Even Rouault
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
 
    Original licence available in port/LICENCE_minizip
 */
diff --git a/port/cpl_minizip_zip.cpp b/port/cpl_minizip_zip.cpp
index 8cb10d5..5575ab8 100644
--- a/port/cpl_minizip_zip.cpp
+++ b/port/cpl_minizip_zip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.cpp 25401 2012-12-30 09:42:27Z rouault $
+ * $Id: cpl_minizip_zip.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -22,6 +22,7 @@
    Modification to zipOpen2 to support globalComment retrieval.
 
    Copyright (C) 1998-2005 Gilles Vollant
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
 
    Read zip.h for more info
 */
diff --git a/port/cpl_multiproc.cpp b/port/cpl_multiproc.cpp
index 4b5c36b..421a201 100644
--- a/port/cpl_multiproc.cpp
+++ b/port/cpl_multiproc.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.cpp 25780 2013-03-22 19:36:58Z warmerdam $
+ * $Id: cpl_multiproc.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,7 +41,7 @@
 #  include <wce_time.h>
 #endif
 
-CPL_CVSID("$Id: cpl_multiproc.cpp 25780 2013-03-22 19:36:58Z warmerdam $");
+CPL_CVSID("$Id: cpl_multiproc.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
 #  define MUTEX_NONE
@@ -89,6 +90,29 @@ CPLMutexHolder::CPLMutexHolder( void **phMutex, double dfWaitInSeconds,
 }
 
 /************************************************************************/
+/*                           CPLMutexHolder()                           */
+/************************************************************************/
+
+CPLMutexHolder::CPLMutexHolder( void *hMutexIn, double dfWaitInSeconds,
+                                const char *pszFileIn, 
+                                int nLineIn )
+
+{
+#ifndef MUTEX_NONE
+    pszFile = pszFileIn;
+    nLine = nLineIn;
+    hMutex = hMutexIn;
+
+    if( hMutex != NULL &&
+        !CPLAcquireMutex( hMutex, dfWaitInSeconds ) )
+    {
+        fprintf( stderr, "CPLMutexHolder: Failed to acquire mutex!\n" );
+        hMutex = NULL;
+    }
+#endif /* ndef MUTEX_NONE */
+}
+
+/************************************************************************/
 /*                          ~CPLMutexHolder()                           */
 /************************************************************************/
 
@@ -747,8 +771,9 @@ void  CPLCondWait( void *hCond, void* hClientMutex )
     /* Release the client mutex before waiting for the event being signaled */
     CPLReleaseMutex(hClientMutex);
 
-    DWORD nRet = WaitForSingleObject(hEvent, INFINITE);
-    CPLAssert (nRet != WAIT_FAILED);
+    // Ideally we would check that we do not get WAIT_FAILED but it is hard 
+    // to report a failure.
+    WaitForSingleObject(hEvent, INFINITE);
 
     /* Reacquire the client mutex */
     CPLAcquireMutex(hClientMutex, 1000.0);
diff --git a/port/cpl_multiproc.h b/port/cpl_multiproc.h
index 34733c3..ac78f99 100644
--- a/port/cpl_multiproc.h
+++ b/port/cpl_multiproc.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.h 25716 2013-03-09 12:09:29Z rouault $
+ * $Id: cpl_multiproc.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -58,35 +59,40 @@ typedef void (*CPLThreadFunc)(void *);
 void CPL_DLL *CPLLockFile( const char *pszPath, double dfWaitInSeconds );
 void  CPL_DLL CPLUnlockFile( void *hLock );
 
-void CPL_DLL *CPLCreateMutex();
+void CPL_DLL *CPLCreateMutex( void );
 int   CPL_DLL CPLCreateOrAcquireMutex( void **, double dfWaitInSeconds );
 int   CPL_DLL CPLAcquireMutex( void *hMutex, double dfWaitInSeconds );
 void  CPL_DLL CPLReleaseMutex( void *hMutex );
 void  CPL_DLL CPLDestroyMutex( void *hMutex );
-void  CPL_DLL CPLCleanupMasterMutex();
+void  CPL_DLL CPLCleanupMasterMutex( void );
 
-void  CPL_DLL *CPLCreateCond();
+void  CPL_DLL *CPLCreateCond( void );
 void  CPL_DLL  CPLCondWait( void *hCond, void* hMutex );
 void  CPL_DLL  CPLCondSignal( void *hCond );
 void  CPL_DLL  CPLCondBroadcast( void *hCond );
 void  CPL_DLL  CPLDestroyCond( void *hCond );
 
-GIntBig CPL_DLL CPLGetPID();
+GIntBig CPL_DLL CPLGetPID( void );
 int   CPL_DLL CPLCreateThread( CPLThreadFunc pfnMain, void *pArg );
 void  CPL_DLL* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pArg );
 void  CPL_DLL CPLJoinThread(void* hJoinableThread); 
 void  CPL_DLL CPLSleep( double dfWaitInSeconds );
 
-const char CPL_DLL *CPLGetThreadingModel();
+const char CPL_DLL *CPLGetThreadingModel( void );
 
-int CPL_DLL CPLGetNumCPUs();
+int CPL_DLL CPLGetNumCPUs( void );
 
 CPL_C_END
 
 #ifdef __cplusplus
 
+/* Instanciates the mutex if not already done */
 #define CPLMutexHolderD(x)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__);
 
+/* This variant assumes the the mutex has already been created. If not, it will */
+/* be a no-op */
+#define CPLMutexHolderOptionalLockD(x)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__);
+
 class CPL_DLL CPLMutexHolder
 {
   private:
@@ -96,9 +102,17 @@ class CPL_DLL CPLMutexHolder
 
   public:
 
+    /* Instanciates the mutex if not already done */
     CPLMutexHolder( void **phMutex, double dfWaitInSeconds = 1000.0,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__ );
+
+    /* This variant assumes the the mutex has already been created. If not, it will */
+    /* be a no-op */
+    CPLMutexHolder( void* hMutex, double dfWaitInSeconds = 1000.0,
+                    const char *pszFile = __FILE__,
+                    int nLine = __LINE__ );
+
     ~CPLMutexHolder();
 };
 #endif /* def __cplusplus */
@@ -134,7 +148,7 @@ void CPL_DLL CPLSetTLS( int nIndex, void *pData, int bFreeOnExit );
 typedef void (*CPLTLSFreeFunc)( void* pData );
 void CPL_DLL CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree );
 
-void CPL_DLL CPLCleanupTLS();
+void CPL_DLL CPLCleanupTLS( void );
 CPL_C_END
 
 #endif /* _CPL_MULTIPROC_H_INCLUDED_ */
diff --git a/port/cpl_odbc.cpp b/port/cpl_odbc.cpp
index f9d146b..e8a4376 100644
--- a/port/cpl_odbc.cpp
+++ b/port/cpl_odbc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_odbc.cpp 20862 2010-10-17 15:47:12Z tamas $
+ * $Id: cpl_odbc.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  OGR ODBC Driver
  * Purpose:  Declarations for ODBC Access Cover API.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam
+ * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +36,7 @@
 
 #ifndef WIN32CE /* ODBC is not supported on Windows CE. */
 
-CPL_CVSID("$Id: cpl_odbc.cpp 20862 2010-10-17 15:47:12Z tamas $");
+CPL_CVSID("$Id: cpl_odbc.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef SQLColumns_TABLE_CAT 
 #define SQLColumns_TABLE_CAT 1
diff --git a/port/cpl_path.cpp b/port/cpl_path.cpp
index f706309..a27f22b 100644
--- a/port/cpl_path.cpp
+++ b/port/cpl_path.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_path.cpp 25181 2012-10-27 11:52:46Z rouault $
+ * $Id: cpl_path.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Portable filename/path parsing, and forming ala "Glob API".
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_path.cpp 25181 2012-10-27 11:52:46Z rouault $");
+CPL_CVSID("$Id: cpl_path.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /* should be size of larged possible filename */
@@ -481,6 +482,8 @@ const char *CPLFormFilename( const char * pszPath,
         /* prefer as directory separator */
         if (strncmp(pszPath, "/vsicurl/", 9) == 0)
             pszAddedPathSep = "/";
+        else if (strncmp(pszPath, "/vsizip/", 8) == 0)
+            pszAddedPathSep = "/";
         else
             pszAddedPathSep = SEP_STRING;
     }
diff --git a/port/cpl_port.h b/port/cpl_port.h
index 44fd0db..00edcac 100644
--- a/port/cpl_port.h
+++ b/port/cpl_port.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_port.h 25450 2013-01-04 23:15:38Z rouault $
+ * $Id: cpl_port.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -168,7 +169,7 @@
 #  include <direct.h>
 #endif
 
-#ifdef _AIX
+#if !(defined(WIN32) || defined(WIN32CE))
 #  include <strings.h>
 #endif
 
@@ -554,6 +555,13 @@ static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
 #  define CPL_CVSID(string)
 #endif
 
+/* Null terminated variadic */
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+#   define CPL_NULL_TERMINATED     __attribute__((__sentinel__))
+#else
+#   define CPL_NULL_TERMINATED
+#endif
+
 #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
 #else
diff --git a/port/cpl_quad_tree.cpp b/port/cpl_quad_tree.cpp
index 838f98b..4cb4512 100644
--- a/port/cpl_quad_tree.cpp
+++ b/port/cpl_quad_tree.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_quad_tree.cpp 15067 2008-07-28 22:08:58Z rouault $
+ * $Id: cpl_quad_tree.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999-2008, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,7 @@
 #include "cpl_conv.h"
 #include "cpl_quad_tree.h"
 
-CPL_CVSID("$Id: cpl_quad_tree.cpp 15067 2008-07-28 22:08:58Z rouault $");
+CPL_CVSID("$Id: cpl_quad_tree.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define MAX_DEFAULT_TREE_DEPTH 12
 #define MAX_SUBNODES 4
@@ -46,11 +47,13 @@ struct _QuadTreeNode
   /* area covered by this psNode */
   CPLRectObj    rect;
 
-  /* list of shapes stored at this psNode. */
-  int           nFeatures;
-  void        **pahFeatures;
+  int           nFeatures;    /* number of shapes stored at this psNode. */
+
+  int           nNumSubNodes; /* number of active subnodes */
+
+  void        **pahFeatures; /* list of shapes stored at this psNode. */
+  CPLRectObj   *pasBounds;
 
-  int           nNumSubNodes;
   QuadTreeNode *apSubNode[MAX_SUBNODES];
 };
 
@@ -113,6 +116,7 @@ static QuadTreeNode *CPLQuadTreeNodeCreate(const CPLRectObj* pRect)
 
     psNode->nFeatures = 0;
     psNode->pahFeatures = NULL;
+    psNode->pasBounds = NULL;
 
     psNode->nNumSubNodes = 0;
 
@@ -131,7 +135,10 @@ static QuadTreeNode *CPLQuadTreeNodeCreate(const CPLRectObj* pRect)
  * @param pGlobalBounds a pointer to the global extent of all
  *                      the elements that will be inserted
  * @param pfnGetBounds  a user provided function to get the bounding box of
- *                      the inserted elements
+ *                      the inserted elements. If it is set to NULL, then
+ *                      CPLQuadTreeInsertWithBounds() must be used, and
+ *                      extra memory will be used to keep features bounds in the
+ *                      quad tree.
  *
  * @return a newly allocated quadtree
  */
@@ -143,7 +150,7 @@ CPLQuadTree *CPLQuadTreeCreate(const CPLRectObj* pGlobalBounds, CPLQuadTreeGetBo
     CPLAssert(pGlobalBounds);
 
     /* -------------------------------------------------------------------- */
-    /*      Allocate the hQuadTree object                                        */
+    /*      Allocate the hQuadTree object                                   */
     /* -------------------------------------------------------------------- */
     hQuadTree = (CPLQuadTree *) CPLMalloc(sizeof(CPLQuadTree));
 
@@ -155,7 +162,7 @@ CPLQuadTree *CPLQuadTreeCreate(const CPLRectObj* pGlobalBounds, CPLQuadTreeGetBo
     hQuadTree->dfSplitRatio = DEFAULT_SPLIT_RATIO;
 
     /* -------------------------------------------------------------------- */
-    /*      Allocate the psRoot psNode.                                         */
+    /*      Allocate the psRoot psNode.                                     */
     /* -------------------------------------------------------------------- */
     hQuadTree->psRoot = CPLQuadTreeNodeCreate(pGlobalBounds);
 
@@ -242,7 +249,8 @@ void CPLQuadTreeSetMaxDepth(CPLQuadTree *hQuadTree, int nMaxDepth)
 
 void CPLQuadTreeSetBucketCapacity(CPLQuadTree *hQuadTree, int nBucketCapacity)
 {
-    hQuadTree->nBucketCapacity = nBucketCapacity;
+    if( nBucketCapacity > 0 )
+        hQuadTree->nBucketCapacity = nBucketCapacity;
 }
 
 /************************************************************************/
@@ -259,12 +267,37 @@ void CPLQuadTreeSetBucketCapacity(CPLQuadTree *hQuadTree, int nBucketCapacity)
 void CPLQuadTreeInsert(CPLQuadTree * hQuadTree, void* hFeature)
 {
     CPLRectObj bounds;
+    if( hQuadTree->pfnGetBounds == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "hQuadTree->pfnGetBounds == NULL");
+        return;
+    }
     hQuadTree->nFeatures ++;
     hQuadTree->pfnGetBounds(hFeature, &bounds);
     CPLQuadTreeAddFeatureInternal(hQuadTree, hFeature, &bounds);
 }
 
 /************************************************************************/
+/*                        CPLQuadTreeInsertWithBounds()                 */
+/************************************************************************/
+
+/**
+ * Insert a feature into a quadtree
+ * 
+ * @param hQuadTree the quad tree
+ * @param hFeature the feature to insert
+ * @param psBounds bounds of the feature
+ */
+void CPLQuadTreeInsertWithBounds(CPLQuadTree *hQuadTree,
+                                 void* hFeature,
+                                 const CPLRectObj* psBounds)
+{
+    hQuadTree->nFeatures ++;
+    CPLQuadTreeAddFeatureInternal(hQuadTree, hFeature, psBounds);
+}
+
+/************************************************************************/
 /*                    CPLQuadTreeNodeDestroy()                          */
 /************************************************************************/
 
@@ -279,7 +312,10 @@ static void CPLQuadTreeNodeDestroy(QuadTreeNode *psNode)
     }
 
     if(psNode->pahFeatures)
+    {
         CPLFree(psNode->pahFeatures);
+        CPLFree(psNode->pasBounds);
+    }
 
     CPLFree(psNode);
 }
@@ -365,10 +401,14 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
             CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
             CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);
 
-            if (CPL_RectContained(pRect, &quad1) ||
+            if (memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
+                memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
+                memcmp(&psNode->rect, &quad3, sizeof(CPLRectObj)) != 0 &&
+                memcmp(&psNode->rect, &quad4, sizeof(CPLRectObj)) != 0 &&
+                (CPL_RectContained(pRect, &quad1) ||
                 CPL_RectContained(pRect, &quad2) ||
                 CPL_RectContained(pRect, &quad3) ||
-                CPL_RectContained(pRect, &quad4))
+                CPL_RectContained(pRect, &quad4)))
             {
                 psNode->nNumSubNodes = 4;
                 psNode->apSubNode[0] = CPLQuadTreeNodeCreate(&quad1);
@@ -378,19 +418,27 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
 
                 int oldNumFeatures = psNode->nFeatures;
                 void** oldFeatures = psNode->pahFeatures;
+                CPLRectObj* pasOldBounds = psNode->pasBounds;
                 psNode->nFeatures = 0;
                 psNode->pahFeatures = NULL;
+                psNode->pasBounds = NULL;
 
                 /* redispatch existing pahFeatures in apSubNodes */
                 int i;
                 for(i=0;i<oldNumFeatures;i++)
                 {
-                    CPLRectObj hFeatureBound;
-                    hQuadTree->pfnGetBounds(oldFeatures[i], &hFeatureBound);
-                    CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &hFeatureBound);
+                    if( hQuadTree->pfnGetBounds == NULL )
+                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &pasOldBounds[i]);
+                    else
+                    {
+                        CPLRectObj bounds;
+                        hQuadTree->pfnGetBounds(oldFeatures[i], &bounds);
+                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &bounds);
+                    }
                 }
 
                 CPLFree(oldFeatures);
+                CPLFree(pasOldBounds);
 
                 /* recurse back on this psNode now that it has apSubNodes */
                 CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, hFeature, pRect);
@@ -419,8 +467,22 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
 /* -------------------------------------------------------------------- */
     psNode->nFeatures++;
 
-    psNode->pahFeatures = (void**) CPLRealloc( psNode->pahFeatures, sizeof(void*) * psNode->nFeatures );
+    if( psNode->nFeatures == 1 )
+    {
+        CPLAssert( psNode->pahFeatures == NULL );
+        psNode->pahFeatures = (void**) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(void*) );
+        if( hQuadTree->pfnGetBounds == NULL )
+            psNode->pasBounds = (CPLRectObj*) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(CPLRectObj) );
+    }
+    else if( psNode->nFeatures > hQuadTree->nBucketCapacity )
+    {
+        psNode->pahFeatures = (void**) CPLRealloc( psNode->pahFeatures, sizeof(void*) * psNode->nFeatures );
+        if( hQuadTree->pfnGetBounds == NULL )
+            psNode->pasBounds = (CPLRectObj*) CPLRealloc( psNode->pasBounds, sizeof(CPLRectObj) * psNode->nFeatures );
+    }
     psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
+    if( hQuadTree->pfnGetBounds == NULL )
+        psNode->pasBounds[psNode->nFeatures-1] = *pRect;
 
     return ;
 }
@@ -467,10 +529,14 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
         CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
         CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);
 
-        if(CPL_RectContained(pRect, &quad1) ||
-        CPL_RectContained(pRect, &quad2) ||
-        CPL_RectContained(pRect, &quad3) ||
-        CPL_RectContained(pRect, &quad4))
+        if( memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
+            memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
+            memcmp(&psNode->rect, &quad3, sizeof(CPLRectObj)) != 0 &&
+            memcmp(&psNode->rect, &quad4, sizeof(CPLRectObj)) != 0 &&
+            (CPL_RectContained(pRect, &quad1) ||
+             CPL_RectContained(pRect, &quad2) ||
+             CPL_RectContained(pRect, &quad3) ||
+             CPL_RectContained(pRect, &quad4)) )
         {
             psNode->nNumSubNodes = 4;
             psNode->apSubNode[0] = CPLQuadTreeNodeCreate(&quad1);
@@ -492,7 +558,17 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
     psNode->pahFeatures =
             (void**) CPLRealloc( psNode->pahFeatures,
                                  sizeof(void*) * psNode->nFeatures );
+    if( hQuadTree->pfnGetBounds == NULL )
+    {
+        psNode->pasBounds =
+            (CPLRectObj*) CPLRealloc( psNode->pasBounds,
+                                 sizeof(CPLRectObj) * psNode->nFeatures );
+    }
     psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
+    if( hQuadTree->pfnGetBounds == NULL )
+    {
+        psNode->pasBounds[psNode->nFeatures-1] = *pRect;
+    }
 }
 
 
@@ -551,10 +627,18 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
   /* -------------------------------------------------------------------- */
   for(i=0; i<psNode->nFeatures; i++)
   {
-      CPLRectObj bounds;
-      hQuadTree->pfnGetBounds(psNode->pahFeatures[i], &bounds);
-      if (CPL_RectOverlap(&bounds, pAoi))
+      if( hQuadTree->pfnGetBounds == NULL )
+      {
+          if (CPL_RectOverlap(&psNode->pasBounds[i], pAoi))
+            (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
+      }
+      else
+      {
+          CPLRectObj bounds;
+          hQuadTree->pfnGetBounds(psNode->pahFeatures[i], &bounds);
+          if (CPL_RectOverlap(&bounds, pAoi))
             (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
+      }
   }
   
   /* -------------------------------------------------------------------- */
diff --git a/port/cpl_quad_tree.h b/port/cpl_quad_tree.h
index 74f5284..7b6bfc2 100644
--- a/port/cpl_quad_tree.h
+++ b/port/cpl_quad_tree.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_quad_tree.h 15067 2008-07-28 22:08:58Z rouault $
+ * $Id: cpl_quad_tree.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -9,6 +9,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999-2008, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -73,6 +74,9 @@ void        CPL_DLL   CPLQuadTreeSetMaxDepth(CPLQuadTree *hQuadtree,
 
 void        CPL_DLL   CPLQuadTreeInsert(CPLQuadTree *hQuadtree,
                                         void* hFeature);
+void        CPL_DLL   CPLQuadTreeInsertWithBounds(CPLQuadTree *hQuadtree,
+                                                  void* hFeature,
+                                                  const CPLRectObj* psBounds);
 
 void        CPL_DLL **CPLQuadTreeSearch(const CPLQuadTree *hQuadtree,
                                         const CPLRectObj* pAoi,
diff --git a/port/cpl_recode.cpp b/port/cpl_recode.cpp
index 09f38db..2a8e6aa 100644
--- a/port/cpl_recode.cpp
+++ b/port/cpl_recode.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode.cpp 24555 2012-06-10 09:49:55Z rouault $
+ * $Id: cpl_recode.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_recode.cpp
  * Project:  CPL - Common Portability Library
@@ -9,6 +9,7 @@
  **********************************************************************
  * Copyright (c) 2011, Andrey Kiselev <dron at ak4719.spb.edu>
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +26,7 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode.cpp 24555 2012-06-10 09:49:55Z rouault $");
+CPL_CVSID("$Id: cpl_recode.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifdef CPL_RECODE_ICONV
 extern void CPLClearRecodeIconvWarningFlags();
@@ -335,3 +336,28 @@ void CPLClearRecodeWarningFlags()
 #endif
     CPLClearRecodeStubWarningFlags();
 }
+
+
+/************************************************************************/
+/*                         CPLStrlenUTF8()                              */
+/************************************************************************/
+
+/**
+ * Return the number of UTF-8 characters of a nul-terminated string.
+ *
+ * This is different from strlen() which returns the number of bytes.
+ *
+ * @param pszUTF8Str a nul-terminated UTF-8 string
+ *
+ * @return the number of UTF-8 characters. 
+ */
+
+int CPLStrlenUTF8(const char *pszUTF8Str) {
+    int i = 0, j = 0;
+    while (pszUTF8Str[i]) {
+        if ((pszUTF8Str[i] & 0xc0) != 0x80) j++;
+        i++;
+    }
+    return j;
+}
+
diff --git a/port/cpl_recode_iconv.cpp b/port/cpl_recode_iconv.cpp
index 8c5d62f..9ed6b07 100644
--- a/port/cpl_recode_iconv.cpp
+++ b/port/cpl_recode_iconv.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode_iconv.cpp 24555 2012-06-10 09:49:55Z rouault $
+ * $Id: cpl_recode_iconv.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_recode_iconv.cpp
  * Project:  CPL - Common Portability Library
@@ -9,6 +9,7 @@
  *
  **********************************************************************
  * Copyright (c) 2011, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +26,7 @@
 
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: cpl_recode_iconv.cpp 24555 2012-06-10 09:49:55Z rouault $");
+CPL_CVSID("$Id: cpl_recode_iconv.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifdef CPL_RECODE_ICONV
 
diff --git a/port/cpl_recode_stub.cpp b/port/cpl_recode_stub.cpp
index dbd3225..97bd705 100644
--- a/port/cpl_recode_stub.cpp
+++ b/port/cpl_recode_stub.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode_stub.cpp 24557 2012-06-10 10:22:49Z rouault $
+ * $Id: cpl_recode_stub.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_recode_stub.cpp
  * Project:  CPL - Common Portability Library
@@ -15,6 +15,7 @@
  **********************************************************************
  * Copyright (c) 2008, Frank Warmerdam
  * Copyright 2006 by Bill Spitzak and others.
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -31,7 +32,7 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode_stub.cpp 24557 2012-06-10 10:22:49Z rouault $");
+CPL_CVSID("$Id: cpl_recode_stub.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifdef CPL_RECODE_STUB 
 
@@ -169,6 +170,8 @@ char *CPLRecodeStub( const char *pszSource,
         if( nCode > 0 ) {
            return CPLWin32Recode( pszSource, nCode, CP_UTF8 );
         }
+        else if( EQUAL(pszSrcEncoding, "CP_OEMCP") )
+            return CPLWin32Recode( pszSource, CP_OEMCP, CP_UTF8 );
     }
 
 /* ---------------------------------------------------------------------*/
diff --git a/port/cpl_spawn.cpp b/port/cpl_spawn.cpp
index d702594..77d43b8 100644
--- a/port/cpl_spawn.cpp
+++ b/port/cpl_spawn.cpp
@@ -1,12 +1,12 @@
 /**********************************************************************
- * $Id: cpl_spawn.cpp 26317 2013-08-14 08:17:37Z rouault $
+ * $Id: cpl_spawn.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLSystem().
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2012,Even Rouault
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -39,7 +39,7 @@
 #define IN_FOR_PARENT   0
 #define OUT_FOR_PARENT  1
 
-CPL_CVSID("$Id: cpl_spawn.cpp 26317 2013-08-14 08:17:37Z rouault $");
+CPL_CVSID("$Id: cpl_spawn.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout);
 
@@ -464,7 +464,7 @@ void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
     #ifdef __APPLE__
         #include <TargetConditionals.h>
     #endif
-    #if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+    #if defined(__APPLE__) && (!defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE==0)
         #include <crt_externs.h>
         #define environ (*_NSGetEnviron())
     #else
diff --git a/port/cpl_spawn.h b/port/cpl_spawn.h
index 8c11166..37036ba 100644
--- a/port/cpl_spawn.h
+++ b/port/cpl_spawn.h
@@ -1,12 +1,12 @@
 /**********************************************************************
- * $Id: cpl_spawn.h 25681 2013-02-24 18:22:20Z rouault $
+ * $Id: cpl_spawn.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLSystem().
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2013,Even Rouault
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp
index 17969e8..fc1264e 100644
--- a/port/cpl_string.cpp
+++ b/port/cpl_string.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.cpp 25044 2012-10-04 01:54:26Z rcoup $
+ * $Id: cpl_string.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_string.cpp
  * Project:  CPL - Common Portability Library
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 1998, Daniel Morissette
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -54,7 +55,7 @@
 #  include <wce_string.h>
 #endif
 
-CPL_CVSID("$Id: cpl_string.cpp 25044 2012-10-04 01:54:26Z rcoup $");
+CPL_CVSID("$Id: cpl_string.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /*=====================================================================
                     StringList manipulation functions.
@@ -918,7 +919,7 @@ char ** CSLTokenizeString2( const char * pszString,
     {
         // we prefer to return empty lists as a pointer to 
         // a null pointer since some client code might depend on this.
-        oRetList.Assign( (char**) CPLCalloc(sizeof(char**),1) );
+        oRetList.Assign( (char**) CPLCalloc(sizeof(char*),1) );
     }
 
     return oRetList.StealList();
diff --git a/port/cpl_string.h b/port/cpl_string.h
index 8644255..93cb844 100644
--- a/port/cpl_string.h
+++ b/port/cpl_string.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.h 25477 2013-01-10 00:27:30Z warmerdam $
+ * $Id: cpl_string.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_string.h
  * Project:  CPL - Common Portability Library
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 1998, Daniel Morissette
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -165,7 +166,7 @@ size_t CPL_DLL CPLStrnlen (const char *pszStr, size_t nMaxLen);
 #define CPL_ENC_ISO8859_1  "ISO-8859-1"
 
 int CPL_DLL  CPLEncodingCharSize( const char *pszEncoding );
-void CPL_DLL  CPLClearRecodeWarningFlags();
+void CPL_DLL  CPLClearRecodeWarningFlags( void );
 char CPL_DLL *CPLRecode( const char *pszSource, 
                          const char *pszSrcEncoding, 
                          const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
@@ -177,6 +178,7 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
                                    const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLIsUTF8(const char* pabyData, int nLen);
 char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL CPLStrlenUTF8(const char *pszUTF8Str);
 
 CPL_C_END
 
@@ -280,6 +282,9 @@ public:
     CPLString &tolower( void );
 };
 
+CPLString CPLOPrintf(const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (1, 2);
+CPLString CPLOvPrintf(const char *pszFormat, va_list args);
+
 /* -------------------------------------------------------------------- */
 /*      URL processing functions, here since they depend on CPLString.  */
 /* -------------------------------------------------------------------- */
diff --git a/port/cpl_strtod.cpp b/port/cpl_strtod.cpp
index 3b2daa8..c1d296d 100644
--- a/port/cpl_strtod.cpp
+++ b/port/cpl_strtod.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_strtod.cpp 24899 2012-09-03 11:42:58Z rouault $
+ * $Id: cpl_strtod.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Functions to convert ASCII string to floating point number.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2006, Andrey Kiselev
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_strtod.cpp 24899 2012-09-03 11:42:58Z rouault $");
+CPL_CVSID("$Id: cpl_strtod.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 // XXX: with GCC 2.95 strtof() function is only available when in c99 mode.
 // Fix it here not touching the compiler options.
diff --git a/port/cpl_time.h b/port/cpl_time.h
index 8c62413..b131b5c 100644
--- a/port/cpl_time.h
+++ b/port/cpl_time.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_time.h 18063 2009-11-21 21:11:49Z warmerdam $
+ * $Id: cpl_time.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     cpl_time.h
  * Project:  CPL - Common Portability Library
@@ -7,7 +7,7 @@
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_virtualmem.cpp b/port/cpl_virtualmem.cpp
new file mode 100644
index 0000000..022f01d
--- /dev/null
+++ b/port/cpl_virtualmem.cpp
@@ -0,0 +1,2059 @@
+/**********************************************************************
+ * $Id: cpl_virtualmem.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Name:     cpl_virtualmem.cpp
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Virtual memory
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "cpl_virtualmem.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
+
+#if defined(__linux) && defined(CPL_MULTIPROC_PTHREAD)
+
+#include <sys/mman.h>   /* mmap, munmap, mremap */
+#include <sys/select.h> /* select */
+#include <sys/stat.h>   /* open() */
+#include <sys/types.h>  /* open() */
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>      /* open() */
+#include <signal.h>     /* sigaction */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>     /* read, write, close, pipe */
+#include <pthread.h>
+
+#define HAVE_5ARGS_MREMAP
+
+#ifndef HAVE_5ARGS_MREMAP
+#include "cpl_atomic_ops.h"
+#endif
+
+/* Linux specific (i.e. non POSIX compliant) features used :
+   - returning from a SIGSEGV handler is clearly a POSIX violation, but in
+     practice most POSIX systems should be happy.
+   - mremap() with 5 args is Linux specific. It is used when the user callback is invited
+     to fill a page, we currently mmap() a writable page, let it filled it,
+     and afterwards mremap() that temporary page onto the location where the
+     fault occured.
+     If we have no mremap(), the workaround is to pause other threads that
+     consume the current view while we are updating the faulted page, otherwise
+     a non-paused thread could access a page that is in the middle of being
+     filled... The way we pause those threads is quite original : we send them
+     a SIGUSR1 and wait that they are stuck in the temporary SIGUSR1 handler...
+   - MAP_ANONYMOUS isn't documented in Posix, but very commonly found (sometimes called MAP_ANON)
+   - dealing with the limitation of number of memory mapping regions, and the 65536 limit.
+   - other things I've not identified
+*/
+
+
+#define ALIGN_DOWN(p,pagesize)  (void*)(((size_t)(p)) / (pagesize) * (pagesize))
+#define ALIGN_UP(p,pagesize)    (void*)(((size_t)(p) + (pagesize) - 1) / (pagesize) * (pagesize))
+
+#define DEFAULT_PAGE_SIZE       (256*256)
+#define MAXIMUM_PAGE_SIZE       (32*1024*1024)
+
+/* Linux Kernel limit */
+#define MAXIMUM_COUNT_OF_MAPPINGS   65536
+
+#define BYEBYE_ADDR             ((void*)(~(size_t)0))
+
+#define MAPPING_FOUND           "yeah"
+#define MAPPING_NOT_FOUND       "doh!"
+
+#define SET_BIT(ar,bitnumber)       ar[(bitnumber)/8] |= 1 << ((bitnumber) % 8)
+#define UNSET_BIT(ar,bitnumber)     ar[(bitnumber)/8] &= ~(1 << ((bitnumber) % 8))
+#define TEST_BIT(ar,bitnumber)      (ar[(bitnumber)/8] & (1 << ((bitnumber) % 8)))
+
+typedef enum
+{
+    OP_LOAD,
+    OP_STORE,
+    OP_MOVS_RSI_RDI,
+    OP_UNKNOWN
+} OpType;
+
+struct CPLVirtualMem
+{
+    struct CPLVirtualMem *pVMemBase;
+    int          nRefCount;
+
+    int          bFileMemoryMapped; /* if TRUE, only eAccessMode, pData, pDataToFree, nSize and nPageSize are valid */
+    CPLVirtualMemAccessMode eAccessMode;
+
+    size_t       nPageSize;
+    void        *pData;                  /* aligned on nPageSize */
+    void        *pDataToFree;            /* returned by mmap(), potentially lower than pData */
+    size_t       nSize;                  /* requested size (unrounded) */
+
+    GByte       *pabitMappedPages;
+    GByte       *pabitRWMappedPages;
+
+    int          nCacheMaxSizeInPages;   /* maximum size of page array */
+    int         *panLRUPageIndices;      /* array with indices of cached pages */
+    int          iLRUStart;              /* index in array where to write next page index */
+    int          nLRUSize;               /* current isze of the array */
+
+    int          iLastPage;              /* last page accessed */
+    int          nRetry;                 /* number of consecutive retries to that last page */
+    
+    int          bSingleThreadUsage;
+
+    CPLVirtualMemCachePageCbk     pfnCachePage;       /* called when a page is mapped */
+    CPLVirtualMemUnCachePageCbk   pfnUnCachePage;     /* called when a (writable) page is unmapped */
+    void                   *pCbkUserData;
+    CPLVirtualMemFreeUserData     pfnFreeUserData;
+#ifndef HAVE_5ARGS_MREMAP
+    void                   *hMutexThreadArray;
+    int                     nThreads;
+    pthread_t              *pahThreads;
+#endif
+};
+
+typedef struct
+{
+    /* hVirtualMemManagerMutex protects the 2 following variables */
+    CPLVirtualMem        **pasVirtualMem;
+    int              nVirtualMemCount;
+
+    int              pipefd_to_thread[2];
+    int              pipefd_from_thread[2];
+    int              pipefd_wait_thread[2];
+    void            *hHelperThread;
+
+    struct sigaction oldact;
+} CPLVirtualMemManager;
+
+typedef struct
+{
+    void            *pFaultAddr;
+    OpType           opType;
+    pthread_t        hRequesterThread;
+} CPLVirtualMemMsgToWorkerThread;
+
+static CPLVirtualMemManager* pVirtualMemManager = NULL;
+static void* hVirtualMemManagerMutex = NULL;
+
+static void CPLVirtualMemManagerInit();
+
+#ifdef DEBUG_VIRTUALMEM
+
+/************************************************************************/
+/*                           fprintfstderr()                            */
+/************************************************************************/
+
+static void fprintfstderr(const char* fmt, ...)
+{
+    char buffer[80];
+    va_list ap;
+    va_start(ap, fmt);
+    vsnprintf(buffer, sizeof(buffer), fmt, ap);
+    va_end(ap);
+    int offset = 0;
+    while(TRUE)
+    {
+        int ret = write(2, buffer + offset, strlen(buffer + offset));
+        if( ret < 0 && errno == EINTR )
+            ;
+        else
+        {
+            if( ret == (int)strlen(buffer + offset) )
+                break;
+            offset += ret;
+        }
+    }
+}
+
+#endif
+
+/************************************************************************/
+/*                         CPLGetPageSize()                             */
+/************************************************************************/
+
+size_t CPLGetPageSize(void)
+{
+    return (size_t) sysconf(_SC_PAGESIZE);
+}
+
+/************************************************************************/
+/*              CPLVirtualMemManagerRegisterVirtualMem()                */
+/************************************************************************/
+
+static void CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMem* ctxt)
+{
+    CPLVirtualMemManagerInit();
+
+    assert(ctxt);
+    CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
+    pVirtualMemManager->pasVirtualMem = (CPLVirtualMem**) CPLRealloc(
+        pVirtualMemManager->pasVirtualMem, sizeof(CPLVirtualMem*) * (pVirtualMemManager->nVirtualMemCount + 1) );
+    pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount] = ctxt;
+    pVirtualMemManager->nVirtualMemCount ++;
+    CPLReleaseMutex(hVirtualMemManagerMutex);
+}
+
+/************************************************************************/
+/*               CPLVirtualMemManagerUnregisterVirtualMem()             */
+/************************************************************************/
+
+static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMem* ctxt)
+{
+    int i;
+    CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
+    for(i=0;i<pVirtualMemManager->nVirtualMemCount;i++)
+    {
+        if( pVirtualMemManager->pasVirtualMem[i] == ctxt )
+        {
+            if( i < pVirtualMemManager->nVirtualMemCount - 1 )
+            {
+                memmove( pVirtualMemManager->pasVirtualMem + i,
+                         pVirtualMemManager->pasVirtualMem + i + 1,
+                    sizeof(CPLVirtualMem*) * (pVirtualMemManager->nVirtualMemCount - i - 1) );
+            }
+            pVirtualMemManager->nVirtualMemCount --;
+            break;
+        }
+    }
+    CPLReleaseMutex(hVirtualMemManagerMutex);
+}
+
+/************************************************************************/
+/*                           CPLVirtualMemNew()                         */
+/************************************************************************/
+
+CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
+                                size_t nCacheSize,
+                                size_t nPageSizeHint,
+                                int bSingleThreadUsage,
+                                CPLVirtualMemAccessMode eAccessMode,
+                                CPLVirtualMemCachePageCbk pfnCachePage,
+                                CPLVirtualMemUnCachePageCbk pfnUnCachePage,
+                                CPLVirtualMemFreeUserData pfnFreeUserData,
+                                void *pCbkUserData)
+{
+    CPLVirtualMem* ctxt;
+    void* pData;
+    size_t nMinPageSize = CPLGetPageSize();
+    size_t nPageSize = DEFAULT_PAGE_SIZE;
+    size_t nCacheMaxSizeInPages;
+    size_t nRoundedMappingSize;
+    FILE* f;
+    int nMappings = 0;
+
+    assert(nSize > 0);
+    assert(pfnCachePage != NULL);
+
+    if( nPageSizeHint >= nMinPageSize && nPageSizeHint <= MAXIMUM_PAGE_SIZE )
+    {
+        if( (nPageSizeHint % nMinPageSize) == 0 )
+            nPageSize = nPageSizeHint;
+        else
+        {
+            int nbits = 0;
+            nPageSize = (size_t)nPageSizeHint;
+            while(nPageSize > 0)
+            {
+                nPageSize >>= 1;
+                nbits ++;
+            }
+            nPageSize = (size_t)1 << (nbits - 1);
+            if( nPageSize < (size_t)nPageSizeHint )
+                nPageSize <<= 1;
+        }
+    }
+
+    if( (nPageSize % nMinPageSize) != 0 )
+        nPageSize = nMinPageSize;
+
+    if( nCacheSize > nSize )
+        nCacheSize = nSize;
+    else if( nCacheSize == 0 )
+        nCacheSize = 1;
+
+    /* Linux specific */
+    /* Count the number of existing memory mappings */
+    f = fopen("/proc/self/maps", "rb");
+    if( f != NULL )
+    {
+        char buffer[80];
+        while( fgets(buffer, sizeof(buffer), f) != NULL )
+            nMappings ++;
+        fclose(f);
+    }
+
+    while(TRUE)
+    {
+        /* /proc/self/maps must not have more than 65K lines */
+        nCacheMaxSizeInPages = (nCacheSize + 2 * nPageSize - 1) / nPageSize;
+        if( nCacheMaxSizeInPages >
+                    (size_t)((MAXIMUM_COUNT_OF_MAPPINGS * 9 / 10) - nMappings) )
+            nPageSize <<= 1;
+        else
+            break;
+    }
+    nRoundedMappingSize = ((nSize + 2 * nPageSize - 1) / nPageSize) * nPageSize;
+    pData = mmap(NULL, nRoundedMappingSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if( pData == MAP_FAILED )
+    {
+        perror("mmap");
+        return NULL;
+    }
+    ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
+    ctxt->nRefCount = 1;
+    ctxt->bFileMemoryMapped = FALSE;
+    ctxt->eAccessMode = eAccessMode;
+    ctxt->pDataToFree = pData;
+    ctxt->pData = ALIGN_UP(pData, nPageSize);
+    ctxt->nPageSize = nPageSize;
+    ctxt->pabitMappedPages = (GByte*)CPLCalloc(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    assert(ctxt->pabitMappedPages);
+    ctxt->pabitRWMappedPages = (GByte*)CPLCalloc(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    assert(ctxt->pabitRWMappedPages);
+    /* we need at least 2 pages in case for a rep movs instruction */
+    /* that operate in the view */
+    ctxt->nCacheMaxSizeInPages = nCacheMaxSizeInPages;
+    ctxt->panLRUPageIndices = (int*)CPLMalloc(ctxt->nCacheMaxSizeInPages * sizeof(int));
+    assert(ctxt->panLRUPageIndices);
+    ctxt->nSize = nSize;
+    ctxt->iLRUStart = 0;
+    ctxt->nLRUSize = 0;
+    ctxt->iLastPage = -1;
+    ctxt->nRetry = 0;
+    ctxt->bSingleThreadUsage = bSingleThreadUsage;
+    ctxt->pfnCachePage = pfnCachePage;
+    ctxt->pfnUnCachePage = pfnUnCachePage;
+    ctxt->pfnFreeUserData = pfnFreeUserData;
+    ctxt->pCbkUserData = pCbkUserData;
+#ifndef HAVE_5ARGS_MREMAP
+    if( !ctxt->bSingleThreadUsage )
+    {
+        ctxt->hMutexThreadArray = CPLCreateMutex();
+        assert(ctxt->hMutexThreadArray != NULL);
+        CPLReleaseMutex(ctxt->hMutexThreadArray);
+        ctxt->nThreads = 0;
+        ctxt->pahThreads = NULL;
+    }
+#endif
+
+    CPLVirtualMemManagerRegisterVirtualMem(ctxt);
+
+    return ctxt;
+}
+
+/************************************************************************/
+/*                   CPLIsVirtualMemFileMapAvailable()                  */
+/************************************************************************/
+
+int CPLIsVirtualMemFileMapAvailable(void)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       CPLVirtualMemFileMapNew()                      */
+/************************************************************************/
+
+CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
+                                        vsi_l_offset nOffset,
+                                        vsi_l_offset nLength,
+                                        CPLVirtualMemAccessMode eAccessMode,
+                                        CPLVirtualMemFreeUserData pfnFreeUserData,
+                                        void *pCbkUserData )
+{
+#if SIZEOF_VOIDP == 4
+    if( nLength != (size_t)nLength )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "nLength = " CPL_FRMT_GUIB " incompatible with 32 bit architecture",
+                 nLength);
+        return NULL;
+    }
+#endif
+
+    int fd = (int) (size_t) VSIFGetNativeFileDescriptorL(fp);
+    if( fd == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot operate on a virtual file");
+        return NULL;
+    }
+
+    off_t nAlignedOffset = (nOffset / CPLGetPageSize()) * CPLGetPageSize();
+    size_t nAligment = nOffset - nAlignedOffset;
+    size_t nMappingSize = nLength + nAligment;
+
+    /* We need to ensure that the requested extent fits into the file size */
+    /* otherwise SIGBUS errors will occur when using the mapping */
+    vsi_l_offset nCurPos = VSIFTellL(fp);
+    VSIFSeekL(fp, 0, SEEK_END);
+    vsi_l_offset nFileSize = VSIFTellL(fp);
+    if( nFileSize < nOffset + nLength )
+    {
+        if( eAccessMode != VIRTUALMEM_READWRITE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Trying to map an extent outside of the file");
+            VSIFSeekL(fp, nCurPos, SEEK_SET);
+            return NULL;
+        }
+        else
+        {
+            char ch = 0;
+            if( VSIFSeekL(fp, nOffset + nLength - 1, SEEK_SET) != 0 ||
+                VSIFWriteL(&ch, 1, 1, fp) != 1 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot extend file to mapping size");
+                VSIFSeekL(fp, nCurPos, SEEK_SET);
+                return NULL;
+            }
+        }
+    }
+    VSIFSeekL(fp, nCurPos, SEEK_SET);
+
+    void* addr = mmap(NULL, nMappingSize,
+                      (eAccessMode == VIRTUALMEM_READWRITE) ? PROT_READ | PROT_WRITE : PROT_READ,
+                      MAP_SHARED, fd, nAlignedOffset);
+    if( addr == MAP_FAILED )
+    {
+        int myerrno = errno;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "mmap() failed : %s", strerror(myerrno));
+        return NULL;
+    }
+
+    CPLVirtualMem* ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
+    ctxt->nRefCount = 1;
+    ctxt->eAccessMode = eAccessMode;
+    ctxt->bFileMemoryMapped = TRUE;
+    ctxt->pData = (GByte*) addr + nAligment;
+    ctxt->pDataToFree = addr;
+    ctxt->nSize = nLength;
+    ctxt->nPageSize = CPLGetPageSize();
+    ctxt->bSingleThreadUsage = FALSE;
+    ctxt->pfnFreeUserData = pfnFreeUserData;
+    ctxt->pCbkUserData = pCbkUserData;
+
+    return ctxt;
+}
+
+/************************************************************************/
+/*                       CPLVirtualMemDerivedNew()                      */
+/************************************************************************/
+
+CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
+                                       vsi_l_offset nOffset,
+                                       vsi_l_offset nSize,
+                                       CPLVirtualMemFreeUserData pfnFreeUserData,
+                                       void *pCbkUserData)
+{
+    if( nOffset + nSize > pVMemBase->nSize )
+        return NULL;
+
+    CPLVirtualMem* ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
+    ctxt->nRefCount = 1;
+    ctxt->pVMemBase = pVMemBase;
+    pVMemBase->nRefCount ++;
+    ctxt->eAccessMode = pVMemBase->eAccessMode;
+    ctxt->bFileMemoryMapped = pVMemBase->bFileMemoryMapped;
+    ctxt->pData = (GByte*) pVMemBase->pData + nOffset;
+    ctxt->pDataToFree = NULL;
+    ctxt->nSize = nSize;
+    ctxt->nPageSize = pVMemBase->nPageSize;
+    ctxt->bSingleThreadUsage = pVMemBase->bSingleThreadUsage;
+    ctxt->pfnFreeUserData = pfnFreeUserData;
+    ctxt->pCbkUserData = pCbkUserData;
+
+    return ctxt;
+}
+
+/************************************************************************/
+/*                        CPLVirtualMemFree()                           */
+/************************************************************************/
+
+void CPLVirtualMemFree(CPLVirtualMem* ctxt)
+{
+    size_t nRoundedMappingSize;
+
+    if( ctxt == NULL || --(ctxt->nRefCount) > 0 )
+        return;
+
+    if( ctxt->pVMemBase != NULL )
+    {
+        CPLVirtualMemFree(ctxt->pVMemBase);
+        if( ctxt->pfnFreeUserData != NULL )
+            ctxt->pfnFreeUserData(ctxt->pCbkUserData);
+        CPLFree(ctxt);
+        return;
+    }
+
+    if( ctxt->bFileMemoryMapped )
+    {
+        size_t nMappingSize = ctxt->nSize + (GByte*)ctxt->pData - (GByte*)ctxt->pDataToFree;
+        assert(munmap(ctxt->pDataToFree, nMappingSize) == 0);
+        if( ctxt->pfnFreeUserData != NULL )
+            ctxt->pfnFreeUserData(ctxt->pCbkUserData);
+        CPLFree(ctxt);
+        return;
+    }
+
+    CPLVirtualMemManagerUnregisterVirtualMem(ctxt);
+
+    nRoundedMappingSize = ((ctxt->nSize + 2 * ctxt->nPageSize - 1) /
+                                            ctxt->nPageSize) * ctxt->nPageSize;
+    if( ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+        ctxt->pfnUnCachePage != NULL )
+    {
+        size_t i;
+        for(i = 0; i < nRoundedMappingSize / ctxt->nPageSize; i++)
+        {
+            if( TEST_BIT(ctxt->pabitRWMappedPages, i) )
+            {
+                void* addr = (char*)ctxt->pData + i * ctxt->nPageSize;
+                ctxt->pfnUnCachePage(ctxt,
+                                 i * ctxt->nPageSize,
+                                 addr,
+                                 ctxt->nPageSize,
+                                 ctxt->pCbkUserData);
+            }
+        }
+    }
+    assert(munmap(ctxt->pDataToFree, nRoundedMappingSize) == 0);
+    CPLFree(ctxt->pabitMappedPages);
+    CPLFree(ctxt->pabitRWMappedPages);
+    CPLFree(ctxt->panLRUPageIndices);
+#ifndef HAVE_5ARGS_MREMAP
+    if( !ctxt->bSingleThreadUsage )
+    {
+        CPLFree(ctxt->pahThreads);
+        CPLDestroyMutex(ctxt->hMutexThreadArray);
+    }
+#endif
+    if( ctxt->pfnFreeUserData != NULL )
+        ctxt->pfnFreeUserData(ctxt->pCbkUserData);
+
+    CPLFree(ctxt);
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemGetAddr()                          */
+/************************************************************************/
+
+void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
+{
+    return ctxt->pData;
+}
+
+/************************************************************************/
+/*                     CPLVirtualMemIsFileMapping()                     */
+/************************************************************************/
+
+int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
+{
+    return ctxt->bFileMemoryMapped;
+}
+
+/************************************************************************/
+/*                     CPLVirtualMemGetAccessMode()                     */
+/************************************************************************/
+
+CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
+{
+    return ctxt->eAccessMode;
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemGetPageSize()                      */
+/************************************************************************/
+
+size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
+{
+    return ctxt->nPageSize;
+}
+
+/************************************************************************/
+/*                        CPLVirtualMemGetSize()                        */
+/************************************************************************/
+
+size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
+{
+    return ctxt->nSize;
+}
+
+#ifndef HAVE_5ARGS_MREMAP
+
+static volatile int nCountThreadsInSigUSR1 = 0;
+static volatile int nWaitHelperThread = 0;
+
+/************************************************************************/
+/*                   CPLVirtualMemSIGUSR1Handler()                      */
+/************************************************************************/
+
+static void CPLVirtualMemSIGUSR1Handler(int signum_unused, 
+                                     siginfo_t* the_info_unused,
+                                     void* the_ctxt_unused)
+{
+    /* fprintfstderr("entering CPLVirtualMemSIGUSR1Handler %X\n", pthread_self()); */
+    (void)signum_unused;
+    (void)the_info_unused;
+    (void)the_ctxt_unused;
+    /* I guess this is only POSIX correct if it is implemented by an intrinsic */
+    CPLAtomicInc(&nCountThreadsInSigUSR1);
+    while( nWaitHelperThread )
+        usleep(1); /* not explicitely indicated as signal-async-safe, but hopefully ok */
+    CPLAtomicDec(&nCountThreadsInSigUSR1);
+    /* fprintfstderr("leaving CPLVirtualMemSIGUSR1Handler %X\n", pthread_self()); */
+}
+#endif
+
+/************************************************************************/
+/*                   CPLVirtualMemIsAccessThreadSafe()                  */
+/************************************************************************/
+
+int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
+{
+    return !ctxt->bSingleThreadUsage;
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemDeclareThread()                    */
+/************************************************************************/
+
+void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
+{
+    if( ctxt->bFileMemoryMapped )
+        return;
+#ifndef HAVE_5ARGS_MREMAP
+    assert( !ctxt->bSingleThreadUsage );
+    CPLAcquireMutex(ctxt->hMutexThreadArray, 1000.0);
+    ctxt->pahThreads = (pthread_t*) CPLRealloc(ctxt->pahThreads,
+                                (ctxt->nThreads + 1) * sizeof(pthread_t));
+    ctxt->pahThreads[ctxt->nThreads] = pthread_self();
+    ctxt->nThreads ++;
+
+    CPLReleaseMutex(ctxt->hMutexThreadArray);
+#endif
+}
+
+/************************************************************************/
+/*                     CPLVirtualMemUnDeclareThread()                   */
+/************************************************************************/
+
+void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
+{
+    if( ctxt->bFileMemoryMapped )
+        return;
+#ifndef HAVE_5ARGS_MREMAP
+    int i;
+    pthread_t self = pthread_self();
+    assert( !ctxt->bSingleThreadUsage );
+    CPLAcquireMutex(ctxt->hMutexThreadArray, 1000.0);
+    for(i = 0; i < ctxt->nThreads; i++)
+    {
+        if( ctxt->pahThreads[i] == self )
+        {
+            if( i < ctxt->nThreads - 1 )
+                memmove(ctxt->pahThreads + i + 1,
+                        ctxt->pahThreads + i,
+                        (ctxt->nThreads - 1 - i) * sizeof(pthread_t));
+            ctxt->nThreads --;
+            break;
+        }
+    }
+
+    CPLReleaseMutex(ctxt->hMutexThreadArray);
+#endif
+}
+
+
+/************************************************************************/
+/*                     CPLVirtualMemGetPageToFill()                     */
+/************************************************************************/
+
+/* Must be paired with CPLVirtualMemAddPage */
+static
+void* CPLVirtualMemGetPageToFill(CPLVirtualMem* ctxt, void* start_page_addr)
+{
+    void* pPageToFill;
+
+    if( ctxt->bSingleThreadUsage )
+    {
+        pPageToFill = start_page_addr;
+        assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
+    }
+    else
+    {
+#ifndef HAVE_5ARGS_MREMAP
+        CPLAcquireMutex(ctxt->hMutexThreadArray, 1000.0);
+        if( ctxt->nThreads == 1 )
+        {
+            pPageToFill = start_page_addr;
+            assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
+        }
+        else
+#endif
+        {
+            /* Allocate a temporary writable page that the user */
+            /* callback can fill */
+            pPageToFill = mmap(NULL, ctxt->nPageSize,
+                                PROT_READ | PROT_WRITE,
+                                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+            assert(pPageToFill != MAP_FAILED);
+        }
+    }
+    return pPageToFill;
+}
+
+/************************************************************************/
+/*                        CPLVirtualMemAddPage()                        */
+/************************************************************************/
+
+static
+void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToFill,
+                       OpType opType, pthread_t hRequesterThread)
+{
+    size_t iPage = (int)(((char*)target_addr - (char*)ctxt->pData) / ctxt->nPageSize);
+    if( ctxt->nLRUSize == ctxt->nCacheMaxSizeInPages )
+    {
+        /* fprintfstderr("uncaching page %d\n", iPage); */
+        int nOldPage = ctxt->panLRUPageIndices[ctxt->iLRUStart];
+        void* addr = (char*)ctxt->pData + nOldPage * ctxt->nPageSize;
+        if( ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+            ctxt->pfnUnCachePage != NULL &&
+            TEST_BIT(ctxt->pabitRWMappedPages, nOldPage) )
+        {
+            size_t nToBeEvicted = ctxt->nPageSize;
+            if( (char*)addr + nToBeEvicted >= (char*) ctxt->pData + ctxt->nSize )
+                nToBeEvicted = (char*) ctxt->pData + ctxt->nSize - (char*)addr;
+
+            ctxt->pfnUnCachePage(ctxt,
+                                 nOldPage * ctxt->nPageSize,
+                                 addr,
+                                 nToBeEvicted,
+                                 ctxt->pCbkUserData);
+        }
+        /* "Free" the least recently used page */
+        UNSET_BIT(ctxt->pabitMappedPages, nOldPage);
+        UNSET_BIT(ctxt->pabitRWMappedPages, nOldPage);
+        /* Free the old page */
+        /* Not sure how portable it is to do that that way... */
+        assert(mmap(addr, ctxt->nPageSize, PROT_NONE,
+                    MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == addr);
+    }
+    ctxt->panLRUPageIndices[ctxt->iLRUStart] = iPage;
+    ctxt->iLRUStart = (ctxt->iLRUStart + 1) % ctxt->nCacheMaxSizeInPages;
+    if( ctxt->nLRUSize < ctxt->nCacheMaxSizeInPages )
+    {
+        ctxt->nLRUSize ++;
+    }
+    SET_BIT(ctxt->pabitMappedPages, iPage);
+
+    if( ctxt->bSingleThreadUsage )
+    {
+        if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+        {
+            /* let (and mark) the page writable since the instruction that triggered */
+            /* the fault is a store */
+            SET_BIT(ctxt->pabitRWMappedPages, iPage);
+        }
+        else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+        {
+            assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+        }
+    }
+    else
+    {
+#ifdef HAVE_5ARGS_MREMAP
+        (void)hRequesterThread;
+
+        if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+        {
+            /* let (and mark) the page writable since the instruction that triggered */
+            /* the fault is a store */
+            SET_BIT(ctxt->pabitRWMappedPages, iPage);
+        }
+        else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+        {
+            /* Turn the temporary page read-only before remapping it. We will only turn it */
+            /* writtable when a new fault occurs (and that the mapping is writable) */
+            assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ) == 0);
+        }
+        /* Can now remap the pPageToFill onto the target page */
+        assert(mremap(pPageToFill, ctxt->nPageSize, ctxt->nPageSize,
+                    MREMAP_MAYMOVE | MREMAP_FIXED, target_addr) == target_addr);
+
+#else
+        if (ctxt->nThreads > 1 )
+        {
+            int i;
+
+            /* Pause threads that share this mem view */
+            CPLAtomicInc(&nWaitHelperThread);
+
+            /* Install temporary SIGUSR1 signal handler */
+            struct sigaction act, oldact;
+            act.sa_sigaction = CPLVirtualMemSIGUSR1Handler;
+            sigemptyset (&act.sa_mask);
+            /* We don't want the sigsegv handler to be called when we are */
+            /* running the sigusr1 handler */
+            assert(sigaddset(&act.sa_mask, SIGSEGV) == 0);
+            act.sa_flags = 0;
+            assert(sigaction(SIGUSR1, &act, &oldact) == 0);
+
+            for(i = 0; i < ctxt->nThreads; i++)
+            {
+                if( ctxt->pahThreads[i] != hRequesterThread )
+                {
+                    /* fprintfstderr("stopping thread %X\n", ctxt->pahThreads[i]); */
+                    assert(pthread_kill( ctxt->pahThreads[i], SIGUSR1 ) == 0);
+                }
+            }
+
+            /* Wait that they are all paused */
+            while( nCountThreadsInSigUSR1 != ctxt->nThreads-1 )
+                usleep(1);
+
+            /* Restore old SIGUSR1 signal handler */
+            assert(sigaction(SIGUSR1, &oldact, NULL) == 0);
+
+            assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
+            /*fprintfstderr("memcpying page %d\n", iPage);*/
+            memcpy(target_addr, pPageToFill, ctxt->nPageSize);
+            
+            if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+            {
+                /* let (and mark) the page writable since the instruction that triggered */
+                /* the fault is a store */
+                SET_BIT(ctxt->pabitRWMappedPages, iPage);
+            }
+            else
+            {
+                assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+            }
+
+            /* Wake up sleeping threads */
+            CPLAtomicDec(&nWaitHelperThread);
+            while( nCountThreadsInSigUSR1 != 0 )
+                usleep(1);
+
+            assert(munmap(pPageToFill, ctxt->nPageSize) == 0);
+        }
+        else
+        {
+            if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+            {
+                /* let (and mark) the page writable since the instruction that triggered */
+                /* the fault is a store */
+                SET_BIT(ctxt->pabitRWMappedPages, iPage);
+            }
+            else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+            {
+                assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+            }
+        }
+
+        CPLReleaseMutex(ctxt->hMutexThreadArray);
+#endif
+    }
+}
+
+/************************************************************************/
+/*                    CPLVirtualMemGetOpTypeImm()                       */
+/************************************************************************/
+
+#if defined(__x86_64__) || defined(__i386__)
+static OpType CPLVirtualMemGetOpTypeImm(GByte val_rip)
+{
+    OpType opType = OP_UNKNOWN;
+    if( (/*val_rip >= 0x00 &&*/ val_rip <= 0x07) ||
+        (val_rip >= 0x40 && val_rip <= 0x47) ) /* add $,(X) */
+        opType = OP_STORE;
+    if( (val_rip >= 0x08 && val_rip <= 0x0f) ||
+        (val_rip >= 0x48 && val_rip <= 0x4f) ) /* or $,(X) */
+        opType = OP_STORE;
+    if( (val_rip >= 0x20 && val_rip <= 0x27) ||
+        (val_rip >= 0x60 && val_rip <= 0x67) ) /* and $,(X) */
+        opType = OP_STORE;
+    if( (val_rip >= 0x28 && val_rip <= 0x2f) ||
+        (val_rip >= 0x68 && val_rip <= 0x6f) ) /* sub $,(X) */
+        opType = OP_STORE;
+    if( (val_rip >= 0x30 && val_rip <= 0x37) ||
+        (val_rip >= 0x70 && val_rip <= 0x77) ) /* xor $,(X) */
+        opType = OP_STORE;
+    if( (val_rip >= 0x38 && val_rip <= 0x3f) ||
+        (val_rip >= 0x78 && val_rip <= 0x7f) ) /* cmp $,(X) */
+        opType = OP_LOAD;
+    return opType;
+}
+#endif
+
+/************************************************************************/
+/*                      CPLVirtualMemGetOpType()                        */
+/************************************************************************/
+
+/* We don't need exhaustivity. It is just a hint for an optimization : */
+/* if the fault occurs on a store operation, then we can directly put */
+/* the page in writable mode if the mapping allows it */
+
+static OpType CPLVirtualMemGetOpType(const GByte* rip)
+{
+    OpType opType = OP_UNKNOWN;
+
+#if defined(__x86_64__) || defined(__i386__)
+    switch(rip[0])
+    {
+        case 0x00: /* add %al,(%rax) */
+        case 0x01: /* add %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x02: /* add (%rax),%al */
+        case 0x03: /* add (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+
+        case 0x08: /* or %al,(%rax) */
+        case 0x09: /* or %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x0a: /* or (%rax),%al */
+        case 0x0b: /* or (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+
+        case 0x0f:
+        {
+            switch(rip[1])
+            {
+                case 0xb6: /* movzbl (%rax),%eax */
+                case 0xb7: /* movzwl (%rax),%eax */
+                case 0xbe: /* movsbl (%rax),%eax */
+                case 0xbf: /* movswl (%rax),%eax */
+                    opType = OP_LOAD;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        }
+        case 0xc6: /* movb $,(%rax) */
+        case 0xc7: /* movl $,(%rax) */
+            opType = OP_STORE;
+            break;
+
+        case 0x20: /* and %al,(%rax) */
+        case 0x21: /* and %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x22: /* and (%rax),%al */
+        case 0x23: /* and (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+
+        case 0x28: /* sub %al,(%rax) */
+        case 0x29: /* sub %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x2a: /* sub (%rax),%al */
+        case 0x2b: /* sub (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+
+        case 0x30: /* xor %al,(%rax) */
+        case 0x31: /* xor %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x32: /* xor (%rax),%al */
+        case 0x33: /* xor (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+
+        case 0x38: /* cmp %al,(%rax) */
+        case 0x39: /* cmp %eax,(%rax) */
+            opType = OP_LOAD;
+            break;
+        case 0x40:
+        {
+            switch(rip[1])
+            {
+                case 0x00: /* add %spl,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x02: /* add (%rax),%spl */
+                    opType = OP_LOAD;
+                    break;
+                case 0x28: /* sub %spl,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x2a: /* sub (%rax),%spl */
+                    opType = OP_LOAD;
+                    break;
+                case 0x3a: /* cmp (%rax),%spl */
+                    opType = OP_LOAD;
+                    break;
+                case 0x8a: /* mov (%rax),%spl */
+                    opType = OP_LOAD;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        }
+#if defined(__x86_64__)
+        case 0x41: /* reg=%al/%eax, X=%r8 */
+        case 0x42: /* reg=%al/%eax, X=%rax,%r8,1 */
+        case 0x43: /* reg=%al/%eax, X=%r8,%r8,1 */
+        case 0x44: /* reg=%r8b/%r8w, X = %rax */
+        case 0x45: /* reg=%r8b/%r8w, X = %r8 */
+        case 0x46: /* reg=%r8b/%r8w, X = %rax,%r8,1 */
+        case 0x47: /* reg=%r8b/%r8w, X = %r8,%r8,1 */
+        {
+            switch(rip[1])
+            {
+                case 0x00: /* add regb,(X) */
+                case 0x01: /* add regl,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x02: /* add (X),regb */
+                case 0x03: /* add (X),regl */
+                    opType = OP_LOAD;
+                    break;
+                case 0x0f:
+                {
+                    switch(rip[2])
+                    {
+                        case 0xb6: /* movzbl (X),regl */
+                        case 0xb7: /* movzwl (X),regl */
+                        case 0xbe: /* movsbl (X),regl */
+                        case 0xbf: /* movswl (X),regl */
+                            opType = OP_LOAD;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case 0x28: /* sub regb,(X) */
+                case 0x29: /* sub regl,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x2a: /* sub (X),regb */
+                case 0x2b: /* sub (X),regl */
+                    opType = OP_LOAD;
+                    break;
+                case 0x38: /* cmp  regb,(X) */
+                case 0x39: /* cmp  regl,(X) */
+                    opType = OP_LOAD;
+                    break;
+                case 0x80: /* cmpb,... $,(X) */
+                case 0x81: /* cmpl,... $,(X) */
+                case 0x83: /* cmpl,... $,(X) */
+                    opType = CPLVirtualMemGetOpTypeImm(rip[2]);
+                    break;
+                case 0x88: /* mov regb,(X) */
+                case 0x89: /* mov regl,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x8a: /* mov (X),regb */
+                case 0x8b: /* mov (X),regl */
+                    opType = OP_LOAD;
+                    break;
+                case 0xc6: /* movb $,(X) */
+                case 0xc7: /* movl $,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x84: /* test %al,(X) */
+                    opType = OP_LOAD;
+                    break;
+                case 0xf6: /* testb $,(X) or notb (X) */
+                case 0xf7: /* testl $,(X) or notl (X)*/
+                {
+                    if( rip[2] < 0x10 ) /* test (X) */
+                        opType = OP_LOAD;
+                    else /* not (X) */
+                        opType = OP_STORE;
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+        }
+        case 0x48: /* reg=%rax, X=%rax or %rax,%rax,1 */
+        case 0x49: /* reg=%rax, X=%r8 or %r8,%rax,1 */
+        case 0x4a: /* reg=%rax, X=%rax,%r8,1 */
+        case 0x4b: /* reg=%rax, X=%r8,%r8,1 */
+        case 0x4c: /* reg=%r8, X=%rax or %rax,%rax,1 */
+        case 0x4d: /* reg=%r8, X=%r8 or %r8,%rax,1 */
+        case 0x4e: /* reg=%r8, X=%rax,%r8,1 */
+        case 0x4f: /* reg=%r8, X=%r8,%r8,1 */
+        {
+            switch(rip[1])
+            {
+                case 0x01: /* add reg,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x03: /* add (X),reg */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x09: /* or reg,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x0b: /* or (%rax),reg */
+                    opType = OP_LOAD;
+                    break;
+                case 0x0f:
+                {
+                    switch(rip[2])
+                    {
+                        case 0xc3: /* movnti reg,(X) */
+                            opType = OP_STORE;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case 0x21: /* and reg,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x23: /* and (X),reg */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x29: /* sub reg,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x2b: /* sub (X),reg */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x31: /* xor reg,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x33: /* xor (X),reg */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x39: /* cmp reg,(X) */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x81:
+                case 0x83:
+                    opType = CPLVirtualMemGetOpTypeImm(rip[2]);
+                    break;
+
+                case 0x85: /* test reg,(X) */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0x89: /* mov reg,(X) */
+                    opType = OP_STORE;
+                    break;
+                case 0x8b: /* mov (X),reg */
+                    opType = OP_LOAD;
+                    break;
+
+                case 0xc7: /* movq $,(X) */
+                    opType = OP_STORE;
+                    break;
+
+                case 0xf7:
+                {
+                    if( rip[2] < 0x10 ) /* testq $,(X) */
+                        opType = OP_LOAD;
+                    else /* notq (X) */
+                        opType = OP_STORE;
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+        }
+#endif
+        case 0x66:
+        {
+            switch(rip[1])
+            {
+                case 0x01: /* add %ax,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x03: /* add (%rax),%ax */
+                    opType = OP_LOAD;
+                    break;
+                case 0x0f:
+                {
+                    switch(rip[2])
+                    {
+                        case 0x2e: /* ucomisd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x6f: /* movdqa (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x7f: /* movdqa %xmm0,(%rax) */
+                            opType = OP_STORE;
+                            break;
+                        case 0xb6: /* movzbw (%rax),%ax */
+                            opType = OP_LOAD;
+                            break;
+                        case 0xe7: /* movntdq %xmm0,(%rax) */
+                            opType = OP_STORE;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case 0x29: /* sub %ax,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x2b: /* sub (%rax),%ax */
+                    opType = OP_LOAD;
+                    break;
+                case 0x39: /* cmp %ax,(%rax) */
+                    opType = OP_LOAD;
+                    break;
+#if defined(__x86_64__)
+                case 0x41: /* reg = %ax (or %xmm0), X = %r8 */
+                case 0x42: /* reg = %ax (or %xmm0), X = %rax,%r8,1 */
+                case 0x43: /* reg = %ax (or %xmm0), X = %r8,%r8,1 */
+                case 0x44: /* reg = %r8w (or %xmm8), X = %rax */
+                case 0x45: /* reg = %r8w (or %xmm8), X = %r8 */
+                case 0x46: /* reg = %r8w (or %xmm8), X = %rax,%r8,1 */
+                case 0x47: /* reg = %r8w (or %xmm8), X = %r8,%r8,1 */
+                {
+                    switch(rip[2])
+                    {
+                        case 0x01: /* add reg,(X) */
+                            opType = OP_STORE;
+                            break;
+                        case 0x03: /* add (X),reg */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x0f:
+                        {
+                            switch(rip[3])
+                            {
+                                case 0x2e: /* ucomisd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x6f: /* movdqa (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x7f: /* movdqa reg,(X) */
+                                    opType = OP_STORE;
+                                    break;
+                                case 0xb6: /* movzbw (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0xe7: /* movntdq reg,(X) */
+                                    opType = OP_STORE;
+                                    break;
+                                default:
+                                    break;
+                            }
+                            break;
+                        }
+                        case 0x29: /* sub reg,(X) */
+                            opType = OP_STORE;
+                            break;
+                        case 0x2b: /* sub (X),reg */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x39: /* cmp reg,(X) */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x81: /* cmpw,... $,(X) */
+                        case 0x83: /* cmpw,... $,(X) */
+                            opType = CPLVirtualMemGetOpTypeImm(rip[3]);
+                            break;
+                        case 0x85: /* test reg,(X) */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x89: /* mov reg,(X) */
+                            opType = OP_STORE;
+                            break;
+                        case 0x8b: /* mov (X),reg */
+                            opType = OP_LOAD;
+                            break;
+                        case 0xc7: /* movw $,(X) */
+                            opType = OP_STORE;
+                            break;
+                        case 0xf7:
+                        {
+                            if( rip[3] < 0x10 ) /* testw $,(X) */
+                                opType = OP_LOAD;
+                            else /* notw (X) */
+                                opType = OP_STORE;
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                    break;
+                }
+#endif
+                case 0x81: /* cmpw,... $,(%rax) */
+                case 0x83: /* cmpw,... $,(%rax) */
+                    opType = CPLVirtualMemGetOpTypeImm(rip[2]);
+                    break;
+
+                case 0x85: /* test %ax,(%rax) */
+                    opType = OP_LOAD;
+                    break;
+                case 0x89: /* mov %ax,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0x8b: /* mov (%rax),%ax */
+                    opType = OP_LOAD;
+                    break;
+                case 0xc7: /* movw $,(%rax) */
+                    opType = OP_STORE;
+                    break;
+                case 0xf3:
+                {
+                    switch( rip[2] )
+                    {
+                        case 0xa5: /* rep movsw %ds:(%rsi),%es:(%rdi) */
+                            opType = OP_MOVS_RSI_RDI;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case 0xf7: /* testw $,(%rax) or notw (%rax) */
+                {
+                    if( rip[2] < 0x10 ) /* test */
+                        opType = OP_LOAD;
+                    else /* not */
+                        opType = OP_STORE;
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+        }
+        case 0x80: /* cmpb,... $,(%rax) */
+        case 0x81: /* cmpl,... $,(%rax) */
+        case 0x83: /* cmpl,... $,(%rax) */
+            opType = CPLVirtualMemGetOpTypeImm(rip[1]);
+            break;
+        case 0x84: /* test %al,(%rax) */
+        case 0x85: /* test %eax,(%rax) */
+            opType = OP_LOAD;
+            break;
+        case 0x88: /* mov %al,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x89: /* mov %eax,(%rax) */
+            opType = OP_STORE;
+            break;
+        case 0x8a: /* mov (%rax),%al */
+            opType = OP_LOAD;
+            break;
+        case 0x8b: /* mov (%rax),%eax */
+            opType = OP_LOAD;
+            break;
+        case 0xd9: /* 387 float */
+        {
+            if( rip[1] < 0x08 ) /* flds (%eax) */
+                opType = OP_LOAD;
+            else if( rip[1] >= 0x18 && rip[1] <= 0x20 ) /* fstps (%eax) */
+                opType = OP_STORE;
+            break;
+        }
+        case 0xf2: /* SSE 2 */
+        {
+            switch(rip[1])
+            {
+                case 0x0f:
+                {
+                    switch(rip[2])
+                    {
+                        case 0x10: /* movsd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x11: /* movsd %xmm0,(%rax) */
+                            opType = OP_STORE;
+                            break;
+                        case 0x58: /* addsd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x59: /* mulsd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x5c: /* subsd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x5e: /* divsd (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+#if defined(__x86_64__)
+                case 0x41: /* reg=%xmm0, X=%r8 or %r8,%rax,1 */
+                case 0x42: /* reg=%xmm0, X=%rax,%r8,1 */
+                case 0x43: /* reg=%xmm0, X=%r8,%r8,1 */
+                case 0x44: /* reg=%xmm8, X=%rax or %rax,%rax,1*/
+                case 0x45: /* reg=%xmm8, X=%r8 or %r8,%rax,1 */
+                case 0x46: /* reg=%xmm8, X=%rax,%r8,1 */
+                case 0x47: /* reg=%xmm8, X=%r8,%r8,1 */
+                {
+                    switch(rip[2])
+                    {
+                        case 0x0f:
+                        {
+                            switch(rip[3])
+                            {
+                                case 0x10: /* movsd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x11: /* movsd reg,(X) */
+                                    opType = OP_STORE;
+                                    break;
+                                case 0x58: /* addsd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                 case 0x59: /* mulsd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x5c: /* subsd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x5e: /* divsd (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                default:
+                                    break;
+                            }
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                    break;
+                }
+#endif
+                default:
+                    break;
+            }
+            break;
+        }
+        case 0xf3:
+        {
+            switch(rip[1])
+            {
+                case 0x0f: /* SSE 2 */
+                {
+                    switch(rip[2])
+                    {
+                        case 0x10: /* movss (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x11: /* movss %xmm0,(%rax) */
+                            opType = OP_STORE;
+                            break;
+                        case 0x6f: /* movdqu (%rax),%xmm0 */
+                            opType = OP_LOAD;
+                            break;
+                        case 0x7f: /* movdqu %xmm0,(%rax) */
+                            opType = OP_STORE;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+#if defined(__x86_64__)
+                case 0x41: /* reg=%xmm0, X=%r8 */
+                case 0x42: /* reg=%xmm0, X=%rax,%r8,1 */
+                case 0x43: /* reg=%xmm0, X=%r8,%r8,1 */
+                case 0x44: /* reg=%xmm8, X = %rax */
+                case 0x45: /* reg=%xmm8, X = %r8 */
+                case 0x46: /* reg=%xmm8, X = %rax,%r8,1 */
+                case 0x47: /* reg=%xmm8, X = %r8,%r8,1 */
+                {
+                    switch(rip[2])
+                    {
+                        case 0x0f: /* SSE 2 */
+                        {
+                            switch(rip[3])
+                            {
+                                case 0x10: /* movss (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x11: /* movss reg,(X) */
+                                    opType = OP_STORE;
+                                    break;
+                                case 0x6f: /* movdqu (X),reg */
+                                    opType = OP_LOAD;
+                                    break;
+                                case 0x7f: /* movdqu reg,(X) */
+                                    opType = OP_STORE;
+                                    break;
+                                default:
+                                    break;
+                            }
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case 0x48:
+                {
+                    switch(rip[2])
+                    {
+                        case 0xa5: /* rep movsq %ds:(%rsi),%es:(%rdi) */
+                            opType = OP_MOVS_RSI_RDI;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+#endif
+                case 0xa4: /* rep movsb %ds:(%rsi),%es:(%rdi) */
+                case 0xa5: /* rep movsl %ds:(%rsi),%es:(%rdi) */
+                    opType = OP_MOVS_RSI_RDI;
+                    break;
+                case 0xa6: /* repz cmpsb %es:(%rdi),%ds:(%rsi) */
+                    opType = OP_LOAD;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        }
+        case 0xf6: /* testb $,(%rax) or notb (%rax) */
+        case 0xf7: /* testl $,(%rax) or notl (%rax) */
+        {
+            if( rip[1] < 0x10 ) /* test */
+                opType = OP_LOAD;
+            else /* not */
+                opType = OP_STORE;
+            break;
+        }
+        default:
+            break;
+    }
+#endif
+    return opType;
+}
+
+/************************************************************************/
+/*                    CPLVirtualMemManagerPinAddrInternal()             */
+/************************************************************************/
+
+static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* msg)
+{
+    char wait_ready;
+    char response_buf[4];
+
+    /* Wait for the helper thread to be ready to process another request */
+    while(TRUE)
+    {
+        int ret = read(pVirtualMemManager->pipefd_wait_thread[0], &wait_ready, 1);
+        if( ret < 0 && errno == EINTR )
+            ;
+        else
+        {
+            assert(ret == 1);
+            break;
+        }
+    }
+
+    /* Pass the address that caused the fault to the helper thread */
+    assert(write(pVirtualMemManager->pipefd_to_thread[1], msg, sizeof(*msg))
+            == sizeof(*msg));
+
+    /* Wait that the helper thread has fixed the fault */
+    while(TRUE)
+    {
+        int ret = read(pVirtualMemManager->pipefd_from_thread[0], response_buf, 4);
+        if( ret < 0 && errno == EINTR )
+            ;
+        else
+        {
+            assert(ret == 4);
+            break;
+        }
+    }
+
+    /* In case the helper thread did not recognize the address as being */
+    /* one that it should take care of, just rely on the previous SIGSEGV */
+    /* handler (with might abort the process) */
+    return( memcmp(response_buf, MAPPING_FOUND, 4) == 0 );
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemPin()                              */
+/************************************************************************/
+
+void CPLVirtualMemPin(CPLVirtualMem* ctxt,
+                      void* pAddr, size_t nSize, int bWriteOp)
+{
+    if( ctxt->bFileMemoryMapped )
+        return;
+
+    CPLVirtualMemMsgToWorkerThread msg;
+    size_t i = 0, n;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.hRequesterThread = pthread_self();
+    msg.opType = (bWriteOp) ? OP_STORE : OP_LOAD;
+
+    char* pBase = (char*)ALIGN_DOWN(pAddr, ctxt->nPageSize);
+    n = ((char*)pAddr - pBase + nSize + ctxt->nPageSize - 1) / ctxt->nPageSize;
+    for(i=0; i<n; i++)
+    {
+        msg.pFaultAddr = (char*) pBase + i * ctxt->nPageSize;
+        CPLVirtualMemManagerPinAddrInternal(&msg);
+    }
+}
+
+/************************************************************************/
+/*                   CPLVirtualMemManagerSIGSEGVHandler()               */
+/************************************************************************/
+
+#if defined(__x86_64__)
+#define REG_IP      REG_RIP
+#define REG_SI      REG_RSI
+#define REG_DI      REG_RDI
+#elif defined(__i386__)
+#define REG_IP      REG_EIP
+#define REG_SI      REG_ESI
+#define REG_DI      REG_EDI
+#endif
+
+/* We must take care of only using "asynchronous-signal-safe" functions in a signal handler */
+/* pthread_self(), read() and write() are such. See */
+/* https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers */
+static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
+                                             siginfo_t* the_info,
+                                             void* the_ctxt)
+{
+    CPLVirtualMemMsgToWorkerThread msg;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.pFaultAddr = the_info->si_addr;
+    msg.hRequesterThread = pthread_self();
+    msg.opType = OP_UNKNOWN;
+
+#if defined(__x86_64__) || defined(__i386__)
+    ucontext_t* the_ucontext = (ucontext_t* )the_ctxt;
+    const GByte* rip = (const GByte*)the_ucontext->uc_mcontext.gregs[REG_IP];
+    msg.opType = CPLVirtualMemGetOpType(rip);
+    /*fprintfstderr("at rip %p, bytes: %02x %02x %02x %02x\n",
+                          rip, rip[0], rip[1], rip[2], rip[3]);*/
+    if( msg.opType == OP_MOVS_RSI_RDI )
+    {
+        void* rsi = (void*)the_ucontext->uc_mcontext.gregs[REG_SI];
+        void* rdi = (void*)the_ucontext->uc_mcontext.gregs[REG_DI];
+
+        /*fprintfstderr("fault=%p rsi=%p rsi=%p\n", msg.pFaultAddr, rsi, rdi);*/
+        if( msg.pFaultAddr == rsi )
+        {
+            /*fprintfstderr("load\n");*/
+            msg.opType = OP_LOAD;
+        }
+        else if( msg.pFaultAddr == rdi )
+        {
+            /*fprintfstderr("store\n");*/
+            msg.opType = OP_STORE;
+        }
+    }
+#ifdef DEBUG_VIRTUALMEM
+    else if( msg.opType == OP_UNKNOWN )
+    {
+        static int bHasWarned = FALSE;
+        if( !bHasWarned )
+        {
+            bHasWarned = TRUE;
+            fprintfstderr("at rip %p, unknown bytes: %02x %02x %02x %02x\n",
+                          rip, rip[0], rip[1], rip[2], rip[3]);
+        }
+    }
+#endif
+#endif
+
+    /*fprintfstderr("entering handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr); */
+
+    if( the_info->si_code != SEGV_ACCERR )
+    {
+        pVirtualMemManager->oldact.sa_sigaction(the_signal, the_info, the_ctxt);
+        return;
+    }
+
+    if( !CPLVirtualMemManagerPinAddrInternal(&msg) )
+    {
+        /* In case the helper thread did not recognize the address as being */
+        /* one that it should take care of, just rely on the previous SIGSEGV */
+        /* handler (with might abort the process) */
+        pVirtualMemManager->oldact.sa_sigaction(the_signal, the_info, the_ctxt);
+    }
+
+    /*fprintfstderr("leaving handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);*/
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemManagerThread()                    */
+/************************************************************************/
+
+static void CPLVirtualMemManagerThread(void* unused_param)
+{
+    (void)unused_param;
+
+    while(TRUE)
+    {
+        char i_m_ready = 1;
+        int i;
+        CPLVirtualMem* ctxt = NULL;
+        int bMappingFound = FALSE;
+        CPLVirtualMemMsgToWorkerThread msg;
+
+        /* Signal that we are ready to process a new request */
+        assert(write(pVirtualMemManager->pipefd_wait_thread[1], &i_m_ready, 1) == 1);
+
+        /* Fetch the address to process */
+        assert(read(pVirtualMemManager->pipefd_to_thread[0], &msg,
+                    sizeof(msg)) == sizeof(msg));
+
+        /* If CPLVirtualMemManagerTerminate() is called, it will use BYEBYE_ADDR as a */
+        /* means to ask for our termination */
+        if( msg.pFaultAddr == BYEBYE_ADDR )
+            break;
+
+        /* Lookup for a mapping that contains addr */
+        CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
+        for(i=0;i<pVirtualMemManager->nVirtualMemCount;i++)
+        {
+            ctxt = pVirtualMemManager->pasVirtualMem[i];
+            if( (char*)msg.pFaultAddr >= (char*) ctxt->pData &&
+                (char*)msg.pFaultAddr < (char*) ctxt->pData + ctxt->nSize )
+            {
+                bMappingFound = TRUE;
+                break;
+            }
+        }
+        CPLReleaseMutex(hVirtualMemManagerMutex);
+
+        if( bMappingFound )
+        {
+            char* start_page_addr = (char*)ALIGN_DOWN(msg.pFaultAddr, ctxt->nPageSize);
+            int iPage = (int)
+                (((char*)start_page_addr - (char*)ctxt->pData) / ctxt->nPageSize);
+
+            if( iPage == ctxt->iLastPage )
+            {
+                /* In case 2 threads try to access the same page */
+                /* concurrently it is possible that we are asked to mapped */
+                /* the page again whereas it is always mapped. However */
+                /* if that number of successive retries is too high, this */
+                /* is certainly a sign that something else happen, like */
+                /* trying to write-access a read-only page */
+                /* 100 is a bit of magic number. I believe it must be */
+                /* at least the number of concurrent threads. 100 seems */
+                /* to be really safe ! */
+                ctxt->nRetry ++;
+                /* fprintfstderr("retry on page %d : %d\n", (int)iPage, ctxt->nRetry); */
+                if( ctxt->nRetry >= 100 )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "CPLVirtualMemManagerThread: trying to "
+                             "write into read-only mapping");
+                    assert(write(pVirtualMemManager->pipefd_from_thread[1],
+                                    MAPPING_NOT_FOUND, 4) == 4);
+                    break;
+                }
+                else if( msg.opType != OP_LOAD &&
+                         ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+                         !TEST_BIT(ctxt->pabitRWMappedPages, iPage) )
+                {
+                    /* fprintfstderr("switching page %d to write mode\n", (int)iPage); */
+                    SET_BIT(ctxt->pabitRWMappedPages, iPage);
+                    assert(mprotect(start_page_addr, ctxt->nPageSize,
+                                    PROT_READ | PROT_WRITE) == 0);
+                }
+            }
+            else
+            {
+                ctxt->iLastPage = iPage;
+                ctxt->nRetry = 0;
+
+                if( TEST_BIT(ctxt->pabitMappedPages, iPage) )
+                {
+                    if( msg.opType != OP_LOAD &&
+                        ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+                        !TEST_BIT(ctxt->pabitRWMappedPages, iPage) )
+                    {
+                        /*fprintfstderr("switching page %d to write mode\n",
+                                iPage);*/
+                        SET_BIT(ctxt->pabitRWMappedPages, iPage);
+                        assert(mprotect(start_page_addr, ctxt->nPageSize,
+                                        PROT_READ | PROT_WRITE) == 0);
+                    }
+                    else
+                    {
+                        /*fprintfstderr("unexpected case for page %d\n",
+                                iPage);*/
+                    }
+                }
+                else
+                {
+                    void* pPageToFill;
+                    size_t nToFill;
+                    pPageToFill = CPLVirtualMemGetPageToFill(ctxt, start_page_addr);
+
+                    nToFill = ctxt->nPageSize;
+                    if( start_page_addr + nToFill >= (char*) ctxt->pData + ctxt->nSize )
+                        nToFill = (char*) ctxt->pData + ctxt->nSize - start_page_addr;
+
+                    ctxt->pfnCachePage(
+                            ctxt,
+                            start_page_addr - (char*) ctxt->pData,
+                            pPageToFill,
+                            nToFill,
+                            ctxt->pCbkUserData);
+
+                    /* Now remap this page to its target address and */
+                    /* register it in the LRU */
+                    CPLVirtualMemAddPage(ctxt, start_page_addr, pPageToFill,
+                                      msg.opType, msg.hRequesterThread);
+                }
+            }
+
+            /* Warn the segfault handler that we have finished our job */
+            assert(write(pVirtualMemManager->pipefd_from_thread[1],
+                            MAPPING_FOUND, 4) == 4);
+        }
+        else
+        {
+            /* Warn the segfault handler that we have finished our job */
+            /* but that the fault didn't occur in a memory range that is under */
+            /* our responsability */
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CPLVirtualMemManagerThread: no mapping found");
+            assert(write(pVirtualMemManager->pipefd_from_thread[1],
+                         MAPPING_NOT_FOUND, 4) == 4);
+        }
+    }
+}
+
+/************************************************************************/
+/*                       CPLVirtualMemManagerInit()                     */
+/************************************************************************/
+
+static void CPLVirtualMemManagerInit(void)
+{
+    CPLMutexHolderD(&hVirtualMemManagerMutex);
+    if( pVirtualMemManager != NULL )
+        return;
+
+    struct sigaction act;
+    pVirtualMemManager = (CPLVirtualMemManager*) CPLMalloc(sizeof(CPLVirtualMemManager));
+    pVirtualMemManager->pasVirtualMem = NULL;
+    pVirtualMemManager->nVirtualMemCount = 0;
+    assert(pipe(pVirtualMemManager->pipefd_to_thread) == 0);
+    assert(pipe(pVirtualMemManager->pipefd_from_thread) == 0);
+    assert(pipe(pVirtualMemManager->pipefd_wait_thread) == 0);
+
+    /* Install our custom SIGSEGV handler */
+    act.sa_sigaction = CPLVirtualMemManagerSIGSEGVHandler;
+    sigemptyset (&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    assert(sigaction(SIGSEGV, &act, &pVirtualMemManager->oldact) == 0);
+
+    /* Starts the helper thread */
+    pVirtualMemManager->hHelperThread =
+            CPLCreateJoinableThread(CPLVirtualMemManagerThread, NULL);
+    assert(pVirtualMemManager->hHelperThread != NULL);
+}
+
+/************************************************************************/
+/*                      CPLVirtualMemManagerTerminate()                 */
+/************************************************************************/
+
+void CPLVirtualMemManagerTerminate(void)
+{
+    char wait_ready;
+    CPLVirtualMemMsgToWorkerThread msg;
+
+    if( pVirtualMemManager == NULL )
+        return;
+
+    msg.pFaultAddr = BYEBYE_ADDR;
+    msg.opType = OP_UNKNOWN;
+    memset(&msg.hRequesterThread, 0, sizeof(msg.hRequesterThread));
+
+    /* Wait for the helper thread to be ready */
+    assert(read(pVirtualMemManager->pipefd_wait_thread[0],
+                &wait_ready, 1) == 1);
+
+    /* Ask it to terminate */
+    assert(write(pVirtualMemManager->pipefd_to_thread[1], &msg, sizeof(msg)) == sizeof(msg));
+
+    /* Wait for its termination */
+    CPLJoinThread(pVirtualMemManager->hHelperThread);
+
+    /* Cleanup everything */
+    while(pVirtualMemManager->nVirtualMemCount > 0)
+        CPLVirtualMemFree(pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount - 1]);
+    CPLFree(pVirtualMemManager->pasVirtualMem);
+
+    close(pVirtualMemManager->pipefd_to_thread[0]);
+    close(pVirtualMemManager->pipefd_to_thread[1]);
+    close(pVirtualMemManager->pipefd_from_thread[0]);
+    close(pVirtualMemManager->pipefd_from_thread[1]);
+    close(pVirtualMemManager->pipefd_wait_thread[0]);
+    close(pVirtualMemManager->pipefd_wait_thread[1]);
+
+    /* Restore previous handler */
+    sigaction(SIGSEGV, &pVirtualMemManager->oldact, NULL);
+
+    CPLFree(pVirtualMemManager);
+    pVirtualMemManager = NULL;
+
+    CPLDestroyMutex(hVirtualMemManagerMutex);
+    hVirtualMemManagerMutex = NULL;
+}
+
+#else /* defined(__linux) && defined(CPL_MULTIPROC_PTHREAD) */
+
+size_t CPLGetPageSize(void)
+{
+    return 0;
+}
+
+CPLVirtualMem *CPLVirtualMemNew(size_t nSize,
+                                size_t nCacheSize,
+                                size_t nPageSizeHint,
+                                int bSingleThreadUsage,
+                                CPLVirtualMemAccessMode eAccessMode,
+                                CPLVirtualMemCachePageCbk pfnCachePage,
+                                CPLVirtualMemUnCachePageCbk pfnUnCachePage,
+                                CPLVirtualMemFreeUserData pfnFreeUserData,
+                                void *pCbkUserData)
+{
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "CPLVirtualMemNew() unsupported on this operating system / configuration");
+    return NULL;
+}
+
+int CPLIsVirtualMemFileMapAvailable(void)
+{
+    return FALSE;
+}
+
+CPLVirtualMem *CPLVirtualMemFileMapNew(VSILFILE* fp,
+                                    vsi_l_offset nOffset,
+                                    vsi_l_offset nLength,
+                                    CPLVirtualMemAccessMode eAccessMode,
+                                    CPLVirtualMemFreeUserData pfnFreeUserData,
+                                    void *pCbkUserData)
+{
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "CPLVirtualMemFileMapNew() unsupported on this operating system / configuration");
+    return NULL;
+}
+
+CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
+                                       vsi_l_offset nOffset,
+                                       vsi_l_offset nSize,
+                                       CPLVirtualMemFreeUserData pfnFreeUserData,
+                                       void *pCbkUserData)
+{
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "CPLVirtualMemDerivedNew() unsupported on this operating system / configuration");
+    return NULL;
+}
+
+void CPLVirtualMemFree(CPLVirtualMem* ctxt)
+{
+}
+
+void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
+{
+    return NULL;
+}
+
+size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
+{
+    return 0;
+}
+
+int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
+{
+    return FALSE;
+}
+
+CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
+{
+    return VIRTUALMEM_READONLY;
+}
+
+size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
+{
+    return 0;
+}
+
+int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
+{
+    return FALSE;
+}
+
+void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
+{
+}
+
+void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
+{
+}
+
+void CPLVirtualMemPin(CPLVirtualMem* ctxt,
+                      void* pAddr, size_t nSize, int bWriteOp)
+{
+}
+
+void CPLVirtualMemManagerTerminate(void)
+{
+}
+
+#endif /* defined(__linux) && defined(CPL_MULTIPROC_PTHREAD) */
diff --git a/port/cpl_virtualmem.h b/port/cpl_virtualmem.h
new file mode 100644
index 0000000..95f63b7
--- /dev/null
+++ b/port/cpl_virtualmem.h
@@ -0,0 +1,389 @@
+/**********************************************************************
+ * $Id: cpl_virtualmem.h 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Name:     cpl_virtualmem.h
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Virtual memory
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef _CPL_VIRTUAL_MEM_INCLUDED
+#define _CPL_VIRTUAL_MEM_INCLUDED
+
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+CPL_C_START
+
+/**
+ * \file cpl_virtualmem.h
+ *
+ * Virtual memory management.
+ *
+ * This file provides mechanism to define virtual memory mappings, whose content
+ * is allocated transparently and filled on-the-fly. Those virtual memory mappings
+ * can be much larger than the available RAM, but only parts of the virtual
+ * memory mapping, in the limit of the allowed the cache size, will actually be
+ * physically allocated.
+ *
+ * This exploits low-level mechanisms of the operating system (virtual memory
+ * allocation, page protection and handler of virtual memory exceptions).
+ *
+ * It is also possible to create a virtual memory mapping from a file or part
+ * of a file.
+ *
+ * The current implementation is Linux only.
+ */
+
+/** Opaque type that represents a virtual memory mapping. */
+typedef struct CPLVirtualMem CPLVirtualMem;
+
+/** Callback triggered when a still unmapped page of virtual memory is accessed.
+  * The callback has the responsibility of filling the page with relevant values
+  *
+  * @param ctxt virtual memory handle.
+  * @param nOffset offset of the page in the memory mapping.
+  * @param pPageToFill address of the page to fill. Note that the address might
+  *                    be a temporary location, and not at CPLVirtualMemGetAddr() + nOffset.
+  * @param nToFill number of bytes of the page.
+  * @param pUserData user data that was passed to CPLVirtualMemNew().
+  */
+typedef void (*CPLVirtualMemCachePageCbk)(CPLVirtualMem* ctxt,
+                                    size_t nOffset,
+                                    void* pPageToFill,
+                                    size_t nToFill,
+                                    void* pUserData);
+
+/** Callback triggered when a dirty mapped page is going to be freed.
+  * (saturation of cache, or termination of the virtual memory mapping).
+  *
+  * @param ctxt virtual memory handle.
+  * @param nOffset offset of the page in the memory mapping.
+  * @param pPageToBeEvicted address of the page that will be flushed. Note that the address might
+  *                    be a temporary location, and not at CPLVirtualMemGetAddr() + nOffset.
+  * @param nToBeEvicted number of bytes of the page.
+  * @param pUserData user data that was passed to CPLVirtualMemNew().
+  */
+typedef void (*CPLVirtualMemUnCachePageCbk)(CPLVirtualMem* ctxt,
+                                      size_t nOffset,
+                                      const void* pPageToBeEvicted,
+                                      size_t nToBeEvicted,
+                                      void* pUserData);
+
+/** Callback triggered when a virtual memory mapping is destroyed.
+  * @param pUserData user data that was passed to CPLVirtualMemNew().
+ */
+typedef void (*CPLVirtualMemFreeUserData)(void* pUserData);
+
+/** Access mode of a virtual memory mapping. */
+typedef enum
+{
+    /*! The mapping is meant at being read-only, but writes will not be prevented.
+        Note that any content written will be lost. */
+    VIRTUALMEM_READONLY,
+    /*! The mapping is meant at being read-only, and this will be enforced 
+        through the operating system page protection mechanism. */
+    VIRTUALMEM_READONLY_ENFORCED,
+    /*! The mapping is meant at being read-write, and modified pages can be saved
+        thanks to the pfnUnCachePage callback */
+    VIRTUALMEM_READWRITE
+} CPLVirtualMemAccessMode;
+
+
+/** Return the size of a page of virtual memory.
+ *
+ * @return the page size.
+ *
+ * @since GDAL 2.0
+ */
+size_t CPL_DLL CPLGetPageSize(void);
+
+/** Create a new virtual memory mapping.
+ *
+ * This will reserve an area of virtual memory of size nSize, whose size
+ * might be potentially much larger than the physical memory available. Initially,
+ * no physical memory will be allocated. As soon as memory pages will be accessed,
+ * they will be allocated transparently and filled with the pfnCachePage callback.
+ * When the allowed cache size is reached, the least recently used pages will
+ * be unallocated.
+ *
+ * On Linux AMD64 platforms, the maximum value for nSize is 128 TB.
+ * On Linux x86 platforms, the maximum value for nSize is 2 GB.
+ *
+ * Only supported on Linux for now.
+ *
+ * Note that on Linux, this function will install a SIGSEGV handler. The
+ * original handler will be restored by CPLVirtualMemManagerTerminate().
+ *
+ * @param nSize size in bytes of the virtual memory mapping.
+ * @param nCacheSize   size in bytes of the maximum memory that will be really
+ *                     allocated (must ideally fit into RAM).
+ * @param nPageSizeHint hint for the page size. Must be a multiple of the
+ *                      system page size, returned by CPLGetPageSize().
+ *                      Minimum value is generally 4096. Might be set to 0 to
+ *                      let the function determine a default page size.
+ * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
+ *                           that will access the virtual memory mapping. This can
+ *                           optimize performance a bit.
+ * @param eAccessMode permission to use for the virtual memory mapping.
+ * @param pfnCachePage callback triggered when a still unmapped page of virtual
+ *                     memory is accessed. The callback has the responsibility
+ *                     of filling the page with relevant values.
+ * @param pfnUnCachePage callback triggered when a dirty mapped page is going to
+ *                       be freed (saturation of cache, or termination of the
+ *                       virtual memory mapping). Might be NULL.
+ * @param pfnFreeUserData callback that can be used to free pCbkUserData. Might be
+ *                        NULL
+ * @param pCbkUserData user data passed to pfnCachePage and pfnUnCachePage.
+ *
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 2.0
+ */
+
+CPLVirtualMem CPL_DLL *CPLVirtualMemNew(size_t nSize,
+                                        size_t nCacheSize,
+                                        size_t nPageSizeHint,
+                                        int bSingleThreadUsage,
+                                        CPLVirtualMemAccessMode eAccessMode,
+                                        CPLVirtualMemCachePageCbk pfnCachePage,
+                                        CPLVirtualMemUnCachePageCbk pfnUnCachePage,
+                                        CPLVirtualMemFreeUserData pfnFreeUserData,
+                                        void *pCbkUserData);
+
+
+/** Return if virtual memory mapping of a file is available.
+ *
+ * @return TRUE if virtual memory mapping of a file is available.
+ * @since GDAL 2.0
+ */
+int CPL_DLL CPLIsVirtualMemFileMapAvailable(void);
+
+/** Create a new virtual memory mapping from a file.
+ *
+ * The file must be a "real" file recognized by the operating system, and not
+ * a VSI extended virtual file.
+ *
+ * In VIRTUALMEM_READWRITE mode, updates to the memory mapping will be written
+ * in the file.
+ *
+ * On Linux AMD64 platforms, the maximum value for nLength is 128 TB.
+ * On Linux x86 platforms, the maximum value for nLength is 2 GB.
+ *
+ * Only supported on Linux for now.
+ *
+ * @param  fp       Virtual file handle.
+ * @param  nOffset  Offset in the file to start the mapping from.
+ * @param  nLength  Length of the portion of the file to map into memory.
+ * @param eAccessMode Permission to use for the virtual memory mapping. This must
+ *                    be consistant with how the file has been opened.
+ * @param pfnFreeUserData callback that is called when the object is destroyed.
+ * @param pCbkUserData user data passed to pfnFreeUserData.
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 2.0
+ */
+CPLVirtualMem CPL_DLL *CPLVirtualMemFileMapNew( VSILFILE* fp,
+                                                vsi_l_offset nOffset,
+                                                vsi_l_offset nLength,
+                                                CPLVirtualMemAccessMode eAccessMode,
+                                                CPLVirtualMemFreeUserData pfnFreeUserData,
+                                                void *pCbkUserData );
+
+/** Create a new virtual memory mapping derived from an other virtual memory
+ *  mapping.
+ *
+ * This may be usefull in case of creating mapping for pixel interleaved data.
+ *
+ * The new mapping takes a reference on the base mapping.
+ *
+ * @param pVMemBase Base virtual memory mapping
+ * @param nOffset   Offset in the base virtual memory mapping from which to start
+ *                  the new mapping.
+ * @param nSize     Size of the base virtual memory mapping to expose in the
+ *                  the new mapping.
+ * @param pfnFreeUserData callback that is called when the object is destroyed.
+ * @param pCbkUserData user data passed to pfnFreeUserData.
+ * @return a virtual memory object that must be freed by CPLVirtualMemFree(),
+ *         or NULL in case of failure.
+ *
+ * @since GDAL 2.0
+ */
+CPLVirtualMem CPL_DLL *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
+                                               vsi_l_offset nOffset,
+                                               vsi_l_offset nSize,
+                                               CPLVirtualMemFreeUserData pfnFreeUserData,
+                                               void *pCbkUserData);
+
+/** Free a virtual memory mapping.
+ *
+ * The pointer returned by CPLVirtualMemGetAddr() will no longer be valid.
+ * If the virtual memory mapping was created with read/write permissions and that
+ * they are dirty (i.e. modified) pages, they will be flushed through the
+ * pfnUnCachePage callback before being freed.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL CPLVirtualMemFree(CPLVirtualMem* ctxt);
+
+/** Return the pointer to the start of a virtual memory mapping.
+ *
+ * The bytes in the range [p:p+CPLVirtualMemGetSize()-1] where p is the pointer
+ * returned by this function will be valid, until CPLVirtualMemFree() is called.
+ *
+ * Note that if a range of bytes used as an argument of a system call
+ * (such as read() or write()) contains pages that have not been "realized", the
+ * system call will fail with EFAULT. CPLVirtualMemPin() can be used to work
+ * around this issue.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return the pointer to the start of a virtual memory mapping.
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL *CPLVirtualMemGetAddr(CPLVirtualMem* ctxt);
+
+/** Return the size of the virtual memory mapping.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return the size of the virtual memory mapping.
+ *
+ * @since GDAL 2.0
+ */
+size_t CPL_DLL CPLVirtualMemGetSize(CPLVirtualMem* ctxt);
+
+/** Return if the virtal memory mapping is a direct file mapping.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return TRUE if the virtal memory mapping is a direct file mapping.
+ *
+ * @since GDAL 2.0
+ */
+int CPL_DLL CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt);
+
+/** Return the access mode of the virtual memory mapping.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return the access mode of the virtual memory mapping.
+ *
+ * @since GDAL 2.0
+ */
+CPLVirtualMemAccessMode CPL_DLL CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt);
+
+/** Return the page size associated to a virtual memory mapping.
+ *
+ * The value returned will be at least CPLGetPageSize(), but potentially
+ * larger.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return the page size
+ *
+ * @since GDAL 2.0
+ */
+size_t CPL_DLL CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt);
+
+/** Return TRUE if this memory mapping can be accessed safely from concurrent
+ *  threads.
+ *
+ * The situation that can cause problems is when several threads try to access
+ * a page of the mapping that is not yet mapped.
+ *
+ * The return value of this function depends on whether bSingleThreadUsage has
+ * been set of not in CPLVirtualMemNew() and/or the implementation.
+ *
+ * On Linux, this will always return TRUE if bSingleThreadUsage = FALSE.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @return TRUE if this memory mapping can be accessed safely from concurrent
+ *         threads.
+ *
+ * @since GDAL 2.0
+ */
+int CPL_DLL CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt);
+
+/** Declare that a thread will access a virtual memory mapping.
+ *
+ * This function must be called by a thread that wants to access the
+ * content of a virtual memory mapping, except if the virtual memory mapping has
+ * been created with bSingleThreadUsage = TRUE.
+ *
+ * This function must be paired with CPLVirtualMemUnDeclareThread().
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt);
+
+/** Declare that a thread will stop accessing a virtual memory mapping.
+ *
+ * This function must be called by a thread that will no longer access the
+ * content of a virtual memory mapping, except if the virtual memory mapping has
+ * been created with bSingleThreadUsage = TRUE.
+ *
+ * This function must be paired with CPLVirtualMemDeclareThread().
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt);
+
+/** Make sure that a region of virtual memory will be realized.
+ *
+ * Calling this function is not required, but might be usefull when debugging
+ * a process with tools like gdb or valgrind that do not naturally like
+ * segmentation fault signals.
+ *
+ * It is also needed when wanting to provide part of virtual memory mapping
+ * to a system call such as read() or write(). If read() or write() is called
+ * on a memory region not yet realized, the call will fail with EFAULT.
+ *
+ * @param ctxt context returned by CPLVirtualMemNew().
+ * @param pAddr the memory region to pin.
+ * @param nSize the size of the memory region.
+ * @param bWriteOp set to TRUE if the memory are will be accessed in write mode.
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL CPLVirtualMemPin(CPLVirtualMem* ctxt,
+                              void* pAddr, size_t nSize, int bWriteOp);
+
+/** Cleanup any resource and handlers related to virtual memory.
+ *
+ * This function must be called after the last CPLVirtualMem object has
+ * been freed.
+ *
+ * @since GDAL 2.0
+ */
+void CPL_DLL CPLVirtualMemManagerTerminate(void);
+
+
+CPL_C_END
+
+#endif /* _CPL_VIRTUAL_MEM_INCLUDED */
diff --git a/port/cpl_vsi.h b/port/cpl_vsi.h
index 08ee665..86a8006 100644
--- a/port/cpl_vsi.h
+++ b/port/cpl_vsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi.h 24442 2012-05-18 15:47:54Z rouault $
+ * $Id: cpl_vsi.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -149,6 +150,12 @@ int CPL_DLL     VSIFFlushL( VSILFILE * );
 int CPL_DLL     VSIFPrintfL( VSILFILE *, const char *, ... ) CPL_PRINT_FUNC_FORMAT(2, 3);
 int CPL_DLL     VSIFPutcL( int, VSILFILE * );
 
+int CPL_DLL     VSIIngestFile( VSILFILE* fp,
+                               const char* pszFilename,
+                               GByte** ppabyRet,
+                               vsi_l_offset* pnSize,
+                               GIntBig nMaxSize );
+
 #if defined(VSI_STAT64_T)
 typedef struct VSI_STAT64_T VSIStatBufL;
 #else
@@ -165,6 +172,8 @@ int CPL_DLL     VSIStatExL( const char * pszFilename, VSIStatBufL * psStatBuf, i
 
 int CPL_DLL     VSIIsCaseSensitiveFS( const char * pszFilename );
 
+void CPL_DLL   *VSIFGetNativeFileDescriptorL( VSILFILE* );
+
 /* ==================================================================== */
 /*      Memory allocation                                               */
 /* ==================================================================== */
diff --git a/port/cpl_vsi_mem.cpp b/port/cpl_vsi_mem.cpp
index 099c7b6..f12093d 100644
--- a/port/cpl_vsi_mem.cpp
+++ b/port/cpl_vsi_mem.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_mem.cpp 24698 2012-07-23 09:10:33Z rouault $
+ * $Id: cpl_vsi_mem.cpp 27157 2014-04-12 12:59:41Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of Memory Buffer virtual IO functions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,7 @@
 #endif
 
 
-CPL_CVSID("$Id: cpl_vsi_mem.cpp 24698 2012-07-23 09:10:33Z rouault $");
+CPL_CVSID("$Id: cpl_vsi_mem.cpp 27157 2014-04-12 12:59:41Z rouault $");
 
 /*
 ** Notes on Multithreading:
@@ -281,9 +282,9 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
         if( !bUpdate ) // Read-only files cannot be extended by seek.
         {
             CPLDebug( "VSIMemHandle", 
-                      "Attempt to extend read-only file '%s' to length %d from %d, .", 
+                      "Attempt to extend read-only file '%s' to length " CPL_FRMT_GUIB " from " CPL_FRMT_GUIB ".",
                       poFile->osFilename.c_str(), 
-                      (int) this->nOffset, (int) poFile->nLength );
+                      this->nOffset, poFile->nLength );
 
             this->nOffset = poFile->nLength;
             errno = EACCES;
@@ -541,7 +542,7 @@ int VSIMemFilesystemHandler::Stat( const char * pszFilename,
     }
     else
     {
-        pStatBuf->st_size = (long)poFile->nLength;
+        pStatBuf->st_size = poFile->nLength;
         pStatBuf->st_mode = S_IFREG;
     }
 
diff --git a/port/cpl_vsi_virtual.h b/port/cpl_vsi_virtual.h
index 0557a33..8bcdd32 100644
--- a/port/cpl_vsi_virtual.h
+++ b/port/cpl_vsi_virtual.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_virtual.h 23995 2012-02-19 22:39:17Z rouault $
+ * $Id: cpl_vsi_virtual.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Declarations for classes related to the virtual filesystem.
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -61,6 +62,7 @@ class CPL_DLL VSIVirtualHandle {
     virtual int       Flush() {return 0;}
     virtual int       Close() = 0;
     virtual int       Truncate( vsi_l_offset nNewSize ) { return -1; }
+    virtual void     *GetNativeFileDescriptor() { return NULL; }
     virtual           ~VSIVirtualHandle() { }
 };
 
@@ -187,7 +189,7 @@ public:
 };
 
 VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
-VSIVirtualHandle* VSICreateCachedFile( VSIVirtualHandle* poBaseHandle );
+VSIVirtualHandle* VSICreateCachedFile( VSIVirtualHandle* poBaseHandle, size_t nChunkSize = 32768, size_t nCacheSize = 0 );
 VSIVirtualHandle* VSICreateGZipWritable( VSIVirtualHandle* poBaseHandle, int bRegularZLibIn, int bAutoCloseBaseHandle );
 
 #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */
diff --git a/port/cpl_vsil.cpp b/port/cpl_vsil.cpp
index e9335f2..e6435cd 100644
--- a/port/cpl_vsil.cpp
+++ b/port/cpl_vsil.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil.cpp 25627 2013-02-10 10:17:19Z rouault $
+ * $Id: cpl_vsil.cpp 27110 2014-03-28 21:29:20Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation VSI*L File API and other file system access
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cpl_vsil.cpp 25627 2013-02-10 10:17:19Z rouault $");
+CPL_CVSID("$Id: cpl_vsil.cpp 27110 2014-03-28 21:29:20Z rouault $");
 
 /************************************************************************/
 /*                             VSIReadDir()                             */
@@ -841,6 +842,200 @@ int VSIFPutcL( int nChar, VSILFILE * fp )
 }
 
 /************************************************************************/
+/*                           VSIIngestFile()                            */
+/************************************************************************/
+
+/**
+ * \brief Ingest a file into memory.
+ *
+ * Read the whole content of a file into a memory buffer.
+ *
+ * Either fp or pszFilename can be NULL, but not both at the same time.
+ *
+ * If fp is passed non-NULL, it is the responsibility of the caller to
+ * close it.
+ *
+ * If non-NULL, the returned buffer is guaranteed to be NUL-terminated.
+ *
+ * @param fp file handle opened with VSIFOpenL().
+ * @param pszFilename filename.
+ * @param ppabyRet pointer to the target buffer. *ppabyRet must be freed with
+ *                 VSIFree()
+ * @param pnSize pointer to variable to store the file size. May be NULL.
+ * @param nMaxSize maximum size of file allowed. If no limit, set to a negative
+ *                 value.
+ * 
+ * @return TRUE in case of success.
+ *
+ * @since GDAL 1.11
+ */
+
+int VSIIngestFile( VSILFILE* fp,
+                   const char* pszFilename,
+                   GByte** ppabyRet,
+                   vsi_l_offset* pnSize,
+                   GIntBig nMaxSize)
+{
+    vsi_l_offset nDataLen = 0;
+    int bFreeFP = FALSE;
+
+    if( fp == NULL && pszFilename == NULL )
+        return FALSE;
+    if( ppabyRet == NULL )
+        return FALSE;
+
+    *ppabyRet = NULL;
+    if( pnSize != NULL )
+        *pnSize = 0;
+
+    if( NULL == fp )
+    {
+        fp = VSIFOpenL( pszFilename, "rb" );
+        if( NULL == fp )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Cannot open file '%s'", pszFilename );
+            return FALSE;
+        }
+        bFreeFP = TRUE;
+    }
+    else
+        VSIFSeekL(fp, 0, SEEK_SET);
+
+    if( pszFilename == NULL ||
+        strcmp(pszFilename, "/vsistdin/") == 0 )
+    {
+        vsi_l_offset nDataAlloc = 0;
+        VSIFSeekL( fp, 0, SEEK_SET );
+        while(TRUE)
+        {
+            if( nDataLen + 8192 + 1 > nDataAlloc )
+            {
+                nDataAlloc = (nDataAlloc * 4) / 3 + 8192 + 1;
+                if( nDataAlloc > (vsi_l_offset)(size_t)nDataAlloc )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Input file too large to be opened" );
+                    VSIFree( *ppabyRet );
+                    *ppabyRet = NULL;
+                    if( bFreeFP )
+                        VSIFCloseL( fp );
+                    return FALSE;
+                }
+                GByte* pabyNew = (GByte*)VSIRealloc(*ppabyRet, nDataAlloc);
+                if( pabyNew == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_OutOfMemory,
+                              "Cannot allocated " CPL_FRMT_GIB " bytes",
+                              nDataAlloc );
+                    VSIFree( *ppabyRet );
+                    *ppabyRet = NULL;
+                    if( bFreeFP )
+                        VSIFCloseL( fp );
+                    return FALSE;
+                }
+                *ppabyRet = pabyNew;
+            }
+            int nRead = (int)VSIFReadL( *ppabyRet + nDataLen, 1, 8192, fp );
+            nDataLen += nRead;
+
+            if ( nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                              "Input file too large to be opened" );
+                VSIFree( *ppabyRet );
+                *ppabyRet = NULL;
+                if( pnSize != NULL )
+                    *pnSize = 0;
+                if( bFreeFP )
+                    VSIFCloseL( fp );
+                return FALSE;
+            }
+
+            if( pnSize != NULL )
+                *pnSize += nRead;
+            (*ppabyRet)[nDataLen] = '\0';
+            if( nRead == 0 )
+                break;
+        }
+    }
+    else
+    {
+        VSIFSeekL( fp, 0, SEEK_END );
+        nDataLen = VSIFTellL( fp );
+
+        // With "large" VSI I/O API we can read data chunks larger than VSIMalloc
+        // could allocate. Catch it here.
+        if ( nDataLen > (vsi_l_offset)(size_t)nDataLen ||
+             (nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Input file too large to be opened" );
+            if( bFreeFP )
+                VSIFCloseL( fp );
+            return FALSE;
+        }
+
+        VSIFSeekL( fp, 0, SEEK_SET );
+
+        *ppabyRet = (GByte*)VSIMalloc((size_t)(nDataLen + 1));
+        if( NULL == *ppabyRet )
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                      "Cannot allocated " CPL_FRMT_GIB " bytes",
+                      nDataLen + 1 );
+            if( bFreeFP )
+                VSIFCloseL( fp );
+            return FALSE;
+        }
+
+        (*ppabyRet)[nDataLen] = '\0';
+        if( ( nDataLen != VSIFReadL( *ppabyRet, 1, (size_t)nDataLen, fp ) ) )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Cannot read " CPL_FRMT_GIB " bytes",
+                      nDataLen );
+            VSIFree( *ppabyRet );
+            *ppabyRet = NULL;
+            if( bFreeFP )
+                VSIFCloseL( fp );
+            return FALSE;
+        }
+        if( pnSize != NULL )
+            *pnSize = nDataLen;
+    }
+    if( bFreeFP )
+        VSIFCloseL( fp );
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        VSIFGetNativeFileDescriptorL()                */
+/************************************************************************/
+
+/**
+ * \brief Returns the "native" file descriptor for the virtual handle.
+ *
+ * This will only return a non-NULL value for "real" files handled by the
+ * operating system (to be opposed to GDAL virtual file systems).
+ *
+ * On POSIX systems, this will be a integer value ("fd") cast as a void*.
+ * On Windows systems, this will be the HANDLE.
+ *
+ * @param fp file handle opened with VSIFOpenL(). 
+ * 
+ * @return the native file descriptor, or NULL.
+ */
+
+void *VSIFGetNativeFileDescriptorL( VSILFILE* fp )
+{
+    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+    
+    return poFileHandle->GetNativeFileDescriptor();
+}
+
+
+/************************************************************************/
 /* ==================================================================== */
 /*                           VSIFileManager()                           */
 /* ==================================================================== */
diff --git a/port/cpl_vsil_abstract_archive.cpp b/port/cpl_vsil_abstract_archive.cpp
index 4037d13..1a813f6 100644
--- a/port/cpl_vsil_abstract_archive.cpp
+++ b/port/cpl_vsil_abstract_archive.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_abstract_archive.cpp 23817 2012-01-28 17:39:00Z rouault $
+ * $Id: cpl_vsil_abstract_archive.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for archive files.
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -35,7 +35,7 @@
 
 #define ENABLE_DEBUG 0
 
-CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 23817 2012-01-28 17:39:00Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                    ~VSIArchiveEntryFileOffset()                      */
@@ -464,7 +464,7 @@ int VSIArchiveFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pSt
         if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry))
         {
             /* Patching st_size with uncompressed file size */
-            pStatBuf->st_size = (long)archiveEntry->uncompressed_size;
+            pStatBuf->st_size = archiveEntry->uncompressed_size;
             pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime;
             if (archiveEntry->bIsDir)
                 pStatBuf->st_mode = S_IFDIR;
@@ -502,7 +502,7 @@ int VSIArchiveFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pSt
             else
             {
                 /* Patching st_size with uncompressed file size */
-                pStatBuf->st_size = (long)poReader->GetFileSize();
+                pStatBuf->st_size = poReader->GetFileSize();
                 pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime();
                 pStatBuf->st_mode = S_IFREG;
             }
diff --git a/port/cpl_vsil_buffered_reader.cpp b/port/cpl_vsil_buffered_reader.cpp
index 506813a..527a121 100644
--- a/port/cpl_vsil_buffered_reader.cpp
+++ b/port/cpl_vsil_buffered_reader.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_buffered_reader.cpp 22109 2011-04-03 18:39:59Z rouault $
+ * $Id: cpl_vsil_buffered_reader.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of buffered reader IO functions.
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 
 #define MAX_BUFFER_SIZE 65536
 
-CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 22109 2011-04-03 18:39:59Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 class VSIBufferedReaderHandle : public VSIVirtualHandle
 {
diff --git a/port/cpl_vsil_cache.cpp b/port/cpl_vsil_cache.cpp
index c540f3b..8b92bcf 100644
--- a/port/cpl_vsil_cache.cpp
+++ b/port/cpl_vsil_cache.cpp
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,15 +38,27 @@ CPL_CVSID("$Id$");
 /* ==================================================================== */
 /************************************************************************/
 
-#define CHUNK_SIZE  32768
-
 class VSICacheChunk
 {
 public:
-    VSICacheChunk() { 
+    VSICacheChunk() 
+    { 
         poLRUPrev = poLRUNext = NULL;
         nDataFilled = 0;
         bDirty = FALSE;
+        pabyData = NULL;
+    }
+
+    virtual ~VSICacheChunk()
+    {
+        VSIFree( pabyData );
+    }
+
+    bool Allocate( size_t nChunkSize )
+    {
+        CPLAssert( pabyData == NULL );
+        pabyData = (GByte *)VSIMalloc( nChunkSize );
+        return (pabyData != NULL);
     }
 
     int            bDirty;
@@ -55,7 +68,7 @@ public:
     VSICacheChunk *poLRUNext;
 
     vsi_l_offset   nDataFilled;
-    GByte          abyData[CHUNK_SIZE];
+    GByte          *pabyData;
 };
 
 /************************************************************************/
@@ -67,7 +80,9 @@ public:
 class VSICachedFile : public VSIVirtualHandle
 { 
   public:
-    VSICachedFile( VSIVirtualHandle * );
+    VSICachedFile( VSIVirtualHandle *poBaseHandle, 
+                   size_t nChunkSize,
+                   size_t nCacheSize );
     ~VSICachedFile() { Close(); }
 
     void          FlushLRU();
@@ -83,6 +98,8 @@ class VSICachedFile : public VSIVirtualHandle
     GUIntBig      nCacheUsed;
     GUIntBig      nCacheMax;
 
+    size_t        nChunkSize;
+
     VSICacheChunk *poLRUStart;
     VSICacheChunk *poLRUEnd;
 
@@ -97,20 +114,25 @@ class VSICachedFile : public VSIVirtualHandle
     virtual int       Eof();
     virtual int       Flush();
     virtual int       Close();
+    virtual void     *GetNativeFileDescriptor() { return poBase->GetNativeFileDescriptor(); }
 };
 
 /************************************************************************/
 /*                           VSICachedFile()                            */
 /************************************************************************/
 
-VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle )
+VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize, size_t nCacheSize )
 
 {
     poBase = poBaseHandle;
+    this->nChunkSize = nChunkSize;
 
     nCacheUsed = 0;
-    nCacheMax = CPLScanUIntBig( 
-        CPLGetConfigOption( "VSI_CACHE_SIZE", "25000000" ), 40 );
+    if ( nCacheSize == 0 )
+        nCacheMax = CPLScanUIntBig( 
+             CPLGetConfigOption( "VSI_CACHE_SIZE", "25000000" ), 40 );
+    else
+        nCacheMax = nCacheSize;
 
     poLRUStart = NULL;
     poLRUEnd = NULL;
@@ -276,14 +298,19 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 /* -------------------------------------------------------------------- */
     if( nBlockCount == 1 )
     {
-        poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET );
+        poBase->Seek( (vsi_l_offset)nStartBlock * nChunkSize, SEEK_SET );
 
-        apoCache[nStartBlock] = new VSICacheChunk();
+        VSICacheChunk *poBlock = new VSICacheChunk();
+        if ( !poBlock || !poBlock->Allocate( nChunkSize ) )
+        {
+            delete poBlock;
+            return 0;
+        }
 
-        VSICacheChunk *poBlock = apoCache[nStartBlock];
+        apoCache[nStartBlock] = poBlock;
 
         poBlock->iBlock = nStartBlock;
-        poBlock->nDataFilled = poBase->Read( poBlock->abyData, 1, CHUNK_SIZE );
+        poBlock->nDataFilled = poBase->Read( poBlock->pabyData, 1, nChunkSize );
         nCacheUsed += poBlock->nDataFilled;
 
         // Merges into the LRU list. 
@@ -298,8 +325,8 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 /*      io request in two in order to avoid allocating a large          */
 /*      temporary buffer.                                               */
 /* -------------------------------------------------------------------- */
-    if( nBufferSize > CHUNK_SIZE * 20 
-        && nBufferSize < nBlockCount * CHUNK_SIZE )
+    if( nBufferSize > nChunkSize * 20 
+        && nBufferSize < nBlockCount * nChunkSize )
     {
         if( !LoadBlocks( nStartBlock, 2, pBuffer, nBufferSize ) )
             return 0;
@@ -312,23 +339,28 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 /* -------------------------------------------------------------------- */
     GByte *pabyWorkBuffer = (GByte *) pBuffer;
 
-    if( nBufferSize < CHUNK_SIZE * nBlockCount )
-        pabyWorkBuffer = (GByte *) CPLMalloc(CHUNK_SIZE * nBlockCount);
+    if( nBufferSize < nChunkSize * nBlockCount )
+        pabyWorkBuffer = (GByte *) CPLMalloc(nChunkSize * nBlockCount);
 
 /* -------------------------------------------------------------------- */
 /*      Read the whole request into the working buffer.                 */
 /* -------------------------------------------------------------------- */
-    if( poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET ) != 0 )
+    if( poBase->Seek( (vsi_l_offset)nStartBlock * nChunkSize, SEEK_SET ) != 0 )
         return 0;
 
-    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*CHUNK_SIZE);
+    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*nChunkSize);
 
-    if( nBlockCount * CHUNK_SIZE > nDataRead + CHUNK_SIZE - 1 )
-        nBlockCount = (nDataRead + CHUNK_SIZE - 1) / CHUNK_SIZE;
+    if( nBlockCount * nChunkSize > nDataRead + nChunkSize - 1 )
+        nBlockCount = (nDataRead + nChunkSize - 1) / nChunkSize;
 
     for( size_t i = 0; i < nBlockCount; i++ )
     {
         VSICacheChunk *poBlock = new VSICacheChunk();
+        if ( !poBlock || !poBlock->Allocate( nChunkSize ) )
+        {
+            delete poBlock;
+            return 0;
+        }
 
         poBlock->iBlock = nStartBlock + i;
 
@@ -336,12 +368,12 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 
         apoCache[i + nStartBlock] = poBlock;
 
-        if( nDataRead >= (i+1) * CHUNK_SIZE )
-            poBlock->nDataFilled = CHUNK_SIZE;
+        if( nDataRead >= (i+1) * nChunkSize )
+            poBlock->nDataFilled = nChunkSize;
         else
-            poBlock->nDataFilled = nDataRead - i*CHUNK_SIZE;
+            poBlock->nDataFilled = nDataRead - i*nChunkSize;
 
-        memcpy( poBlock->abyData, pabyWorkBuffer + i*CHUNK_SIZE,
+        memcpy( poBlock->pabyData, pabyWorkBuffer + i*nChunkSize,
                 (size_t) poBlock->nDataFilled );
 
         nCacheUsed += poBlock->nDataFilled;
@@ -372,8 +404,8 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* ==================================================================== */
 /*      Make sure the cache is loaded for the whole request region.     */
 /* ==================================================================== */
-    vsi_l_offset nStartBlock = nOffset / CHUNK_SIZE;
-    vsi_l_offset nEndBlock = (nOffset + nSize * nCount - 1) / CHUNK_SIZE;
+    vsi_l_offset nStartBlock = nOffset / nChunkSize;
+    vsi_l_offset nEndBlock = (nOffset + nSize * nCount - 1) / nChunkSize;
 
     for( vsi_l_offset iBlock = nStartBlock; iBlock <= nEndBlock; iBlock++ )
     {
@@ -396,7 +428,7 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 
     while( nAmountCopied < nSize * nCount )
     {
-        vsi_l_offset iBlock = (nOffset + nAmountCopied) / CHUNK_SIZE;
+        vsi_l_offset iBlock = (nOffset + nAmountCopied) / nChunkSize;
         size_t nThisCopy;
         VSICacheChunk *poBlock = apoCache[iBlock];
         if( poBlock == NULL )
@@ -404,13 +436,14 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
             /* We can reach that point when the amount to read exceeds */
             /* the cache size */
             LoadBlocks( iBlock, 1, ((GByte *) pBuffer) + nAmountCopied,
-                        MIN(nSize * nCount - nAmountCopied, CHUNK_SIZE) );
+                        MIN(nSize * nCount - nAmountCopied, nChunkSize) );
             poBlock = apoCache[iBlock];
             CPLAssert(poBlock != NULL);
         }
 
+        vsi_l_offset nStartOffset = (vsi_l_offset)iBlock * nChunkSize;
         nThisCopy = (size_t)
-            ((iBlock * CHUNK_SIZE + poBlock->nDataFilled) 
+            ((nStartOffset + poBlock->nDataFilled) 
              - nAmountCopied - nOffset);
         
         if( nThisCopy > nSize * nCount - nAmountCopied )
@@ -420,8 +453,8 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
             break;
 
         memcpy( ((GByte *) pBuffer) + nAmountCopied,
-                poBlock->abyData 
-                + (nOffset + nAmountCopied) - iBlock * CHUNK_SIZE, 
+                poBlock->pabyData 
+                + (nOffset + nAmountCopied) - nStartOffset, 
                 nThisCopy );
 
         nAmountCopied += nThisCopy;
@@ -476,8 +509,8 @@ int VSICachedFile::Flush()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSICreateCachedFile( VSIVirtualHandle *poBaseHandle )
+VSICreateCachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize, size_t nCacheSize )
 
 {
-    return new VSICachedFile( poBaseHandle );
+    return new VSICachedFile( poBaseHandle, nChunkSize, nCacheSize );
 }
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index b34be4d..a88cf25 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl.cpp 25696 2013-03-02 17:55:51Z rouault $
+ * $Id: cpl_vsil_curl.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2008, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@
 #include "cpl_time.h"
 #include "cpl_vsil_curl_priv.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 25696 2013-03-02 17:55:51Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifndef HAVE_CURL
 
@@ -638,7 +638,8 @@ vsi_l_offset VSICurlHandle::GetFileSize()
     /* HACK for mbtiles driver: proper fix would be to auto-detect servers that don't accept HEAD */
     /* http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, so let's start a GET */
     /* and interrupt is as soon as the header is found */
-    if (strstr(pszURL, ".tiles.mapbox.com/") != NULL)
+    if (strstr(pszURL, ".tiles.mapbox.com/") != NULL
+	|| !CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", "YES")))
     {
         curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
         curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
diff --git a/port/cpl_vsil_curl_priv.h b/port/cpl_vsil_curl_priv.h
index f4d6c64..86a7107 100644
--- a/port/cpl_vsil_curl_priv.h
+++ b/port/cpl_vsil_curl_priv.h
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_priv.h 23735 2012-01-09 19:01:02Z rouault $
+ * $Id: cpl_vsil_curl_priv.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Private API for VSICurl
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cpl_vsil_curl_streaming.cpp b/port/cpl_vsil_curl_streaming.cpp
index 3463737..e2a9f47 100644
--- a/port/cpl_vsil_curl_streaming.cpp
+++ b/port/cpl_vsil_curl_streaming.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_streaming.cpp 25787 2013-03-23 13:59:41Z rouault $
+ * $Id: cpl_vsil_curl_streaming.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files in streaming mode
  * Author:   Even Rouault <even dot rouault at mines dash paris.org>
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris.org>
+ * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,7 +33,7 @@
 #include "cpl_hash_set.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 25787 2013-03-23 13:59:41Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #if !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB)
 
diff --git a/port/cpl_vsil_gzip.cpp b/port/cpl_vsil_gzip.cpp
index d26195a..97b4009 100644
--- a/port/cpl_vsil_gzip.cpp
+++ b/port/cpl_vsil_gzip.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_gzip.cpp 25871 2013-04-06 21:21:33Z rouault $
+ * $Id: cpl_vsil_gzip.cpp 27048 2014-03-17 23:07:47Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for gz/zip files (.gz and .zip).
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2007, Even Rouault
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -84,7 +84,7 @@
 #include "cpl_minizip_unzip.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_gzip.cpp 25871 2013-04-06 21:21:33Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_gzip.cpp 27048 2014-03-17 23:07:47Z rouault $");
 
 #define Z_BUFSIZE 65536  /* original size is 16384 */
 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
@@ -523,6 +523,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
     vsi_l_offset original_offset = offset;
     int original_nWhence = whence;
 
+    z_eof = 0;
     if (ENABLE_DEBUG) CPLDebug("GZIP", "Seek(" CPL_FRMT_GUIB ",%d)", offset, whence);
 
     if (transparent)
@@ -1448,7 +1449,7 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
             if (nCompressedSize == (GUIntBig) pStatBuf->st_size)
             {
                 /* Patch with the uncompressed size */
-                pStatBuf->st_size = (long)nUncompressedSize;
+                pStatBuf->st_size = nUncompressedSize;
 
                 VSIGZipHandle* poHandle =
                     VSIGZipFilesystemHandler::OpenGZipReadOnly(pszFilename, "rb");
@@ -1474,7 +1475,7 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
             poHandle->Seek(0, SEEK_SET);
 
             /* Patch with the uncompressed size */
-            pStatBuf->st_size = (long)uncompressed_size;
+            pStatBuf->st_size = uncompressed_size;
 
             delete poHandle;
         }
@@ -1689,7 +1690,11 @@ int VSIZipReader::GotoFirstFile()
 int VSIZipReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 {
     VSIZipEntryFileOffset* pZipEntryOffset = (VSIZipEntryFileOffset*)pOffset;
-    cpl_unzGoToFilePos(unzF, &(pZipEntryOffset->file_pos));
+    if( cpl_unzGoToFilePos(unzF, &(pZipEntryOffset->file_pos)) != UNZ_OK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GotoFileOffset failed");
+        return FALSE;
+    }
 
     SetInfo();
 
@@ -1793,6 +1798,22 @@ std::vector<CPLString> VSIZipFilesystemHandler::GetExtensions()
     oList.push_back(".dwf");
     oList.push_back(".ods");
     oList.push_back(".xlsx");
+
+    /* Add to zip FS handler extensions array additional extensions */
+    /* listed in CPL_VSIL_ZIP_ALLOWED_EXTENSIONS config option. */
+    /* The extensions divided by comma */
+    const char* pszAllowedExtensions =
+        CPLGetConfigOption("CPL_VSIL_ZIP_ALLOWED_EXTENSIONS", NULL);
+    if (pszAllowedExtensions)
+    {
+        char** papszExtensions = CSLTokenizeString2(pszAllowedExtensions, ", ", 0);
+        for (int i = 0; papszExtensions[i] != NULL; i++)
+        {
+            oList.push_back(papszExtensions[i]);
+        }
+        CSLDestroy(papszExtensions);
+    }
+
     return oList;
 }
 
@@ -1880,12 +1901,23 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
 
     unzFile unzF = ((VSIZipReader*)poReader)->GetUnzFileHandle();
 
-    cpl_unzOpenCurrentFile(unzF);
+    if( cpl_unzOpenCurrentFile(unzF) != UNZ_OK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "cpl_unzOpenCurrentFile() failed");
+        delete poReader;
+        return NULL;
+    }
 
     uLong64 pos = cpl_unzGetCurrentFileZStreamPos(unzF);
 
     unz_file_info file_info;
-    cpl_unzGetCurrentFileInfo (unzF, &file_info, NULL, 0, NULL, 0, NULL, 0);
+    if( cpl_unzGetCurrentFileInfo (unzF, &file_info, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "cpl_unzGetCurrentFileInfo() failed");
+        cpl_unzCloseCurrentFile(unzF);
+        delete poReader;
+        return NULL;
+    }
 
     cpl_unzCloseCurrentFile(unzF);
 
@@ -2213,8 +2245,8 @@ int VSIZipWriteHandle::Eof()
 
 int VSIZipWriteHandle::Flush()
 {
-    CPLError(CE_Failure, CPLE_NotSupported,
-             "VSIFFlushL() is not supported on writable Zip files");
+    /*CPLError(CE_Failure, CPLE_NotSupported,
+             "VSIFFlushL() is not supported on writable Zip files");*/
     return 0;
 }
 
diff --git a/port/cpl_vsil_sparsefile.cpp b/port/cpl_vsil_sparsefile.cpp
index b0edf58..db855b1 100644
--- a/port/cpl_vsil_sparsefile.cpp
+++ b/port/cpl_vsil_sparsefile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_sparsefile.cpp 25883 2013-04-08 21:33:16Z rouault $
+ * $Id: cpl_vsil_sparsefile.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of sparse file virtual io driver.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2010, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +38,7 @@
 #  include <wce_errno.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 25883 2013-04-08 21:33:16Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 class SFRegion { 
 public:
diff --git a/port/cpl_vsil_stdin.cpp b/port/cpl_vsil_stdin.cpp
index 03826a4..5390a97 100644
--- a/port/cpl_vsil_stdin.cpp
+++ b/port/cpl_vsil_stdin.cpp
@@ -1,12 +1,12 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdin.cpp 24432 2012-05-17 16:20:57Z rouault $
+ * $Id: cpl_vsil_stdin.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdin
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdin.cpp 24432 2012-05-17 16:20:57Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdin.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* We buffer the first 1MB of standard input to enable drivers */
 /* to autodetect data. In the first MB, backward and forward seeking */
diff --git a/port/cpl_vsil_stdout.cpp b/port/cpl_vsil_stdout.cpp
index f941f59..8ab16d3 100644
--- a/port/cpl_vsil_stdout.cpp
+++ b/port/cpl_vsil_stdout.cpp
@@ -1,12 +1,12 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdout.cpp 25871 2013-04-06 21:21:33Z rouault $
+ * $Id: cpl_vsil_stdout.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdout
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  **********************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdout.cpp 25871 2013-04-06 21:21:33Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdout.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/port/cpl_vsil_subfile.cpp b/port/cpl_vsil_subfile.cpp
index eb8eeb9..db488de 100644
--- a/port/cpl_vsil_subfile.cpp
+++ b/port/cpl_vsil_subfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_subfile.cpp 26026 2013-05-25 08:10:00Z rouault $
+ * $Id: cpl_vsil_subfile.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of subfile virtual IO functions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,7 +37,7 @@
 #  include <wce_errno.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_subfile.cpp 26026 2013-05-25 08:10:00Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_subfile.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -372,9 +373,9 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
     if( nResult == 0 )
     {
         if( nSize != 0 )
-            psStatBuf->st_size = (long)nSize;
+            psStatBuf->st_size = nSize;
         else
-            psStatBuf->st_size -= (long)nOff;
+            psStatBuf->st_size -= nOff;
     }
 
     return nResult;
diff --git a/port/cpl_vsil_tar.cpp b/port/cpl_vsil_tar.cpp
index a978d8b..a0bb0b5 100644
--- a/port/cpl_vsil_tar.cpp
+++ b/port/cpl_vsil_tar.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_tar.cpp 21781 2011-02-21 21:57:41Z rouault $
+ * $Id: cpl_vsil_tar.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for tar files (.tar).
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2010, Even Rouault
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_tar.cpp 21781 2011-02-21 21:57:41Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_tar.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /************************************************************************/
@@ -133,7 +133,9 @@ int VSITarReader::GotoNextFile()
         (abyHeader[147] != '\0' && abyHeader[147] != ' ') ||
         abyHeader[154] != '\0' ||
         abyHeader[155] != ' ')
+    {
         return FALSE;
+    }
 
     osNextFileName = abyHeader;
     nNextFileSize = 0;
@@ -148,6 +150,12 @@ int VSITarReader::GotoNextFile()
     nCurOffset = VSIFTellL(fp);
 
     GUIntBig nBytesToSkip = ((nNextFileSize + 511) / 512) * 512;
+    if( nBytesToSkip > (~((GUIntBig)0)) - nCurOffset )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Bad .tar structure");
+        return FALSE;
+    }
+
     VSIFSeekL(fp, nBytesToSkip, SEEK_CUR);
 
     return TRUE;
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index f138d5f..365497a 100644
--- a/port/cpl_vsil_unix_stdio_64.cpp
+++ b/port/cpl_vsil_unix_stdio_64.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_unix_stdio_64.cpp 25713 2013-03-09 11:41:30Z rouault $
+ * $Id: cpl_vsil_unix_stdio_64.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
@@ -8,6 +8,7 @@
  *
  **********************************************************************
  * Copyright (c) 2001, Frank Warmerdam
+ * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -51,7 +52,7 @@
 #include <dirent.h>
 #include <errno.h>
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 25713 2013-03-09 11:41:30Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -140,6 +141,7 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
 {
     FILE          *fp;
     vsi_l_offset  nOffset;
+    int           bReadOnly;
     int           bLastOpWrite;
     int           bLastOpRead;
     int           bAtEOF;
@@ -149,7 +151,7 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
 #endif
   public:
                       VSIUnixStdioHandle(VSIUnixStdioFilesystemHandler *poFSIn,
-                                         FILE* fpIn);
+                                         FILE* fpIn, int bReadOnlyIn);
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
@@ -159,6 +161,7 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
     virtual int       Flush();
     virtual int       Close();
     virtual int       Truncate( vsi_l_offset nNewSize );
+    virtual void     *GetNativeFileDescriptor() { return (void*) (size_t) fileno(fp); }
 };
 
 
@@ -167,8 +170,8 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
 /************************************************************************/
 
 VSIUnixStdioHandle::VSIUnixStdioHandle(VSIUnixStdioFilesystemHandler *poFSIn,
-                                       FILE* fpIn) :
-    fp(fpIn), nOffset(0), bLastOpWrite(FALSE), bLastOpRead(FALSE), bAtEOF(FALSE)
+                                       FILE* fpIn, int bReadOnlyIn) :
+    fp(fpIn), nOffset(0), bReadOnly(bReadOnlyIn), bLastOpWrite(FALSE), bLastOpRead(FALSE), bAtEOF(FALSE)
 #ifdef VSI_COUNT_BYTES_READ
     , nTotalBytesRead(0), poFS(poFSIn)
 #endif
@@ -198,11 +201,32 @@ int VSIUnixStdioHandle::Close()
 int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 {
+    GByte abyTemp[4096];
+
     // seeks that do nothing are still surprisingly expensive with MSVCRT.
     // try and short circuit if possible.
     if( nWhence == SEEK_SET && nOffset == this->nOffset )
         return 0;
 
+    // on a read-only file, we can avoid a lseek() system call to be issued
+    // if the next position to seek to is within the buffered page
+    if( bReadOnly && nWhence == SEEK_SET )
+    {
+        GIntBig nDiff = (GIntBig)nOffset - (GIntBig)this->nOffset;
+        if( nDiff > 0 && nDiff < 4096 )
+        {
+            int nRead = (int)fread(abyTemp, 1, (int)nDiff, fp);
+            if( nRead == (int)nDiff )
+            {
+                this->nOffset = nOffset;
+                bLastOpWrite = FALSE;
+                bLastOpRead = FALSE;
+                bAtEOF = FALSE;
+                return 0;
+            }
+        }
+    }
+
     int     nResult = VSI_FSEEK64( fp, nOffset, nWhence );
     int     nError = errno;
 
@@ -454,7 +478,8 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
-    VSIUnixStdioHandle *poHandle = new VSIUnixStdioHandle(this, fp);
+    int bReadOnly = strcmp(pszAccess, "rb") == 0 || strcmp(pszAccess, "r") == 0;
+    VSIUnixStdioHandle *poHandle = new VSIUnixStdioHandle(this, fp, bReadOnly );
 
     errno = nError;
 
@@ -462,7 +487,7 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
 /*      If VSI_CACHE is set we want to use a cached reader instead      */
 /*      of more direct io on the underlying file.                       */
 /* -------------------------------------------------------------------- */
-    if( (EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb"))
+    if( bReadOnly
         && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
     {
         return VSICreateCachedFile( poHandle );
diff --git a/port/cpl_vsil_win32.cpp b/port/cpl_vsil_win32.cpp
index ad3fbf9..6444ee4 100644
--- a/port/cpl_vsil_win32.cpp
+++ b/port/cpl_vsil_win32.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_win32.cpp 23882 2012-02-02 19:50:45Z rouault $
+ * $Id: cpl_vsil_win32.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Win32.
@@ -7,6 +7,7 @@
  *
  **********************************************************************
  * Copyright (c) 2000, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_win32.cpp 23882 2012-02-02 19:50:45Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_win32.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #if defined(WIN32)
 
@@ -93,6 +94,7 @@ class VSIWin32Handle : public VSIVirtualHandle
     virtual int       Flush();
     virtual int       Close();
     virtual int       Truncate( vsi_l_offset nNewSize );
+    virtual void     *GetNativeFileDescriptor() { return (void*) hFile; }
 };
 
 /************************************************************************/
diff --git a/port/cpl_vsisimple.cpp b/port/cpl_vsisimple.cpp
index b2751a1..790073e 100644
--- a/port/cpl_vsisimple.cpp
+++ b/port/cpl_vsisimple.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsisimple.cpp 25359 2012-12-27 15:19:28Z rouault $
+ * $Id: cpl_vsisimple.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library 
  * Purpose:  Simple implementation of POSIX VSI functions.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -60,7 +61,7 @@
 /* DEBUG_VSIMALLOC must also be defined */
 //#define DEBUG_VSIMALLOC_VERBOSE
 
-CPL_CVSID("$Id: cpl_vsisimple.cpp 25359 2012-12-27 15:19:28Z rouault $");
+CPL_CVSID("$Id: cpl_vsisimple.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /* for stat() */
 
diff --git a/port/cpl_xml_validate.cpp b/port/cpl_xml_validate.cpp
index 6dfa408..4df7fcb 100644
--- a/port/cpl_xml_validate.cpp
+++ b/port/cpl_xml_validate.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_xml_validate.cpp 25229 2012-11-16 19:06:58Z rouault $
+ * $Id: cpl_xml_validate.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement XML validation against XSD schema
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2012, Even Rouault
+ * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_xml_validate.cpp 25229 2012-11-16 19:06:58Z rouault $");
+CPL_CVSID("$Id: cpl_xml_validate.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #ifdef HAVE_LIBXML2
 #include <libxml/xmlversion.h>
@@ -853,8 +853,16 @@ static void CPLLibXMLWarningErrorCallback (void * ctx, const char * msg, ...)
         int nLen = (int)strlen(pszStrDup);
         if (nLen > 0 && pszStrDup[nLen-1] == '\n')
             pszStrDup[nLen-1] = '\0';
-        CPLError(CE_Failure, CPLE_AppDefined, "libXML: %s:%d: %s",
-                 pszFilename, pErrorPtr ? pErrorPtr->line : 0, pszStrDup);
+        if( pszFilename != NULL && pszFilename[0] != '<' )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "libXML: %s:%d: %s",
+                     pszFilename, pErrorPtr ? pErrorPtr->line : 0, pszStrDup);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "libXML: %d: %s",
+                     pErrorPtr ? pErrorPtr->line : 0, pszStrDup);
+        }
         CPLFree(pszStrDup);
     }
 
@@ -978,18 +986,27 @@ int CPLValidateXML(const char* pszXMLFilename,
                    const char* pszXSDFilename,
                    char** papszOptions)
 {
-    VSILFILE* fpXML = VSIFOpenL(pszXMLFilename, "rb");
-    if (fpXML == NULL)
+    char szHeader[2048];
+    CPLString osTmpXSDFilename;
+
+    if( pszXMLFilename[0] == '<' )
     {
-        CPLError(CE_Failure, CPLE_OpenFailed,
-                 "Cannot open %s", pszXMLFilename);
-        return FALSE;
+        strncpy(szHeader, pszXMLFilename, sizeof(szHeader));
+        szHeader[sizeof(szHeader)-1] = '\0';
+    }
+    else
+    {
+        VSILFILE* fpXML = VSIFOpenL(pszXMLFilename, "rb");
+        if (fpXML == NULL)
+        {
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                    "Cannot open %s", pszXMLFilename);
+            return FALSE;
+        }
+        int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXML);
+        szHeader[nRead] = '\0';
+        VSIFCloseL(fpXML);
     }
-    CPLString osTmpXSDFilename;
-    char szHeader[2048];
-    int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXML);
-    szHeader[nRead] = '\0';
-    VSIFCloseL(fpXML);
 
     /* Workaround following bug : "element FeatureCollection: Schemas validity error : Element '{http://www.opengis.net/wfs}FeatureCollection': No matching global declaration available for the validation root" */
     /* We create a wrapping XSD that imports the WFS .xsd (and possibly the GML .xsd too) and the application schema */
@@ -1069,7 +1086,16 @@ int CPLValidateXML(const char* pszXMLFilename,
                             (void*) pszXMLFilename);
 
     int bValid = FALSE;
-    if (strncmp(pszXMLFilename, "/vsi", 4) != 0)
+    if( pszXMLFilename[0] == '<' )
+    {
+        xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)pszXMLFilename);
+        if (pDoc != NULL)
+        {
+            bValid = xmlSchemaValidateDoc(pSchemaValidCtxt, pDoc) == 0;
+        }
+        xmlFreeDoc(pDoc);
+    }
+    else if (strncmp(pszXMLFilename, "/vsi", 4) != 0)
     {
         bValid =
             xmlSchemaValidateFile(pSchemaValidCtxt, pszXMLFilename, 0) == 0;
diff --git a/port/cplgetsymbol.cpp b/port/cplgetsymbol.cpp
index 0af104c..843c709 100644
--- a/port/cplgetsymbol.cpp
+++ b/port/cplgetsymbol.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplgetsymbol.cpp 16702 2009-04-01 20:42:49Z rouault $
+ * $Id: cplgetsymbol.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Fetch a function pointer from a shared library / DLL.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cplgetsymbol.cpp 16702 2009-04-01 20:42:49Z rouault $");
+CPL_CVSID("$Id: cplgetsymbol.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 
 /* ==================================================================== */
@@ -140,13 +141,21 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 {
     void        *pLibrary;
     void        *pSymbol;
+    UINT        uOldErrorMode;
+
+    /* Avoid error boxes to pop up (#5122) */
+    uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
 
     pLibrary = LoadLibrary(pszLibrary);
-    if( pLibrary == NULL )
+
+    if( pLibrary <= (void*)HINSTANCE_ERROR )
     {
         LPVOID      lpMsgBuf = NULL;
         int         nLastError = GetLastError();
-        
+
+        /* Restore old error mode */
+        SetErrorMode(uOldErrorMode);
+
         FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
                        | FORMAT_MESSAGE_FROM_SYSTEM
                        | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -160,6 +169,9 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
         return NULL;
     }
 
+    /* Restore old error mode */
+    SetErrorMode(uOldErrorMode);
+
     pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName );
 
     if( pSymbol == NULL )
diff --git a/port/cplkeywordparser.cpp b/port/cplkeywordparser.cpp
index 53a8a21..2a9a8d0 100644
--- a/port/cplkeywordparser.cpp
+++ b/port/cplkeywordparser.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplkeywordparser.cpp 26085 2013-06-14 20:25:21Z warmerdam $
+ * $Id: cplkeywordparser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Implementation of CPLKeywordParser - a class for parsing
@@ -10,6 +10,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/cplstring.cpp b/port/cplstring.cpp
index 8043183..de3d542 100644
--- a/port/cplstring.cpp
+++ b/port/cplstring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplstring.cpp 23406 2011-11-21 19:29:41Z rouault $
+ * $Id: cplstring.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  CPLString implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cplstring.cpp 23406 2011-11-21 19:29:41Z rouault $");
+CPL_CVSID("$Id: cplstring.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /*
  * The CPLString class is derived from std::string, so the vast majority 
@@ -415,3 +416,32 @@ CPLString CPLURLAddKVP(const char* pszURL, const char* pszKey,
         return osURL;
     }
 }
+
+/************************************************************************/
+/*                            CPLOPrintf()                              */
+/************************************************************************/
+
+CPLString CPLOPrintf( const char *pszFormat, ... )
+
+{
+    va_list args;
+    CPLString osTarget;
+
+    va_start( args, pszFormat );
+    osTarget.vPrintf( pszFormat, args );
+    va_end( args );
+
+    return osTarget;
+}
+
+/************************************************************************/
+/*                            CPLOvPrintf()                             */
+/************************************************************************/
+
+CPLString CPLOvPrintf( const char *pszFormat, va_list args )
+
+{
+    CPLString osTarget;
+    osTarget.vPrintf( pszFormat, args);
+    return osTarget;
+}
diff --git a/port/cplstringlist.cpp b/port/cplstringlist.cpp
index 8d1281a..08516dd 100644
--- a/port/cplstringlist.cpp
+++ b/port/cplstringlist.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplstringlist.cpp 24950 2012-09-22 13:54:36Z rouault $
+ * $Id: cplstringlist.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  CPLStringList implementation.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +31,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cplstringlist.cpp 24950 2012-09-22 13:54:36Z rouault $");
+CPL_CVSID("$Id: cplstringlist.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 /************************************************************************/
 /*                           CPLStringList()                            */
diff --git a/port/gdal_csv.h b/port/gdal_csv.h
index 625c9a2..e4f430c 100644
--- a/port/gdal_csv.h
+++ b/port/gdal_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csv.h 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: gdal_csv.h 27044 2014-03-16 23:41:27Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Functions for reading and scaning CSV (comma separated,
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/port/makefile.vc b/port/makefile.vc
index 7f1a8b0..1de6563 100644
--- a/port/makefile.vc
+++ b/port/makefile.vc
@@ -48,6 +48,7 @@ OBJ	=	cpl_conv.obj \
 		cpl_spawn.obj \
 		cpl_google_oauth2.obj \
 		cpl_progress.obj \
+		cpl_virtualmem.obj \
 		$(ODBC_OBJ)
 
 LIB	=	cpl.lib
diff --git a/port/vsipreload.cpp b/port/vsipreload.cpp
new file mode 100644
index 0000000..d153a37
--- /dev/null
+++ b/port/vsipreload.cpp
@@ -0,0 +1,1618 @@
+/******************************************************************************
+ * $Id: vsipreload.cpp 27044 2014-03-16 23:41:27Z rouault $
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Standalone shared library that can be LD_PRELOAD'ed as an overload of
+ *           libc to enable VSI Virtual FILE API to be used with binaries using
+ *           regular libc for I/O.
+ * Author:   Even Rouault <even dot rouault at mines dash paris.org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// WARNING: Linux glibc ONLY
+// Might work with some adaptations (mainly around 64bit symbols) on other Unix systems
+
+// Compile:
+// g++ -Wall -fPIC port/vsipreload.cpp -shared -o vsipreload.so -Iport -L. -L.libs -lgdal
+
+// Run:
+// LD_PRELOAD=./vsipreload.so ....
+// e.g: 
+// LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+// LD_PRELOAD=./vsipreload.so gdalinfo 'HDF4_EOS:EOS_GRID:"/vsicurl/http://download.osgeo.org/gdal/data/hdf4/MOD09Q1G_EVI.A2006233.h07v03.005.2008338190308.hdf":MODIS_NACP_EVI:MODIS_EVI'
+// LD_PRELOAD=./vsipreload.so ogrinfo /vsicurl/http://svn.osgeo.org/gdal/trunk/autotest/ogr/data/testavc -ro
+// even non GDAL binaries :
+// LD_PRELOAD=./vsipreload.so h5dump -d /x /vsicurl/http://download.osgeo.org/gdal/data/netcdf/utm-big-chunks.nc
+// LD_PRELOAD=./vsipreload.so sqlite3 /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+// LD_PRELOAD=./vsipreload.so ls -al /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
+// LD_PRELOAD=./vsipreload.so find /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
+
+#define _GNU_SOURCE 1
+#define _LARGEFILE64_SOURCE 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <set>
+#include <map>
+#include <string>
+#include "cpl_vsi.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_hash_set.h"
+
+CPL_CVSID("$Id: vsipreload.cpp 27044 2014-03-16 23:41:27Z rouault $");
+
+static int DEBUG_VSIPRELOAD = 0;
+static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
+#define DEBUG_OUTPUT_READ 0
+
+#ifndef NO_FSTATAT
+#define HAVE_FSTATAT
+#endif
+
+#define DECLARE_SYMBOL(x, retType, args) \
+    typedef retType (*fn ## x ## Type)args;\
+    static fn ## x ## Type pfn ## x = NULL
+
+DECLARE_SYMBOL(fopen, FILE*, (const char *path, const char *mode));
+DECLARE_SYMBOL(fopen64, FILE*, (const char *path, const char *mode));
+DECLARE_SYMBOL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
+DECLARE_SYMBOL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
+DECLARE_SYMBOL(fclose, int, (FILE *stream));
+DECLARE_SYMBOL(__xstat, int, (int ver, const char *path, struct stat *buf));
+DECLARE_SYMBOL(__lxstat, int, (int ver, const char *path, struct stat *buf));
+DECLARE_SYMBOL(__xstat64, int, (int ver, const char *path, struct stat64 *buf));
+DECLARE_SYMBOL(fseeko64, int, (FILE *stream, off64_t off, int whence));
+DECLARE_SYMBOL(fseek, int, (FILE *stream, off_t off, int whence));
+DECLARE_SYMBOL(ftello64, off64_t, (FILE *stream));
+DECLARE_SYMBOL(ftell, off_t, (FILE *stream));
+DECLARE_SYMBOL(feof, int, (FILE *stream));
+DECLARE_SYMBOL(fflush, int, (FILE *stream));
+DECLARE_SYMBOL(fgetpos, int, (FILE *stream, fpos_t *pos));
+DECLARE_SYMBOL(fsetpos, int, (FILE *stream, fpos_t *pos));
+DECLARE_SYMBOL(fileno, int, (FILE *stream));
+DECLARE_SYMBOL(ferror, int, (FILE *stream));
+
+DECLARE_SYMBOL(fdopen, FILE*, (int fd, const char *mode));
+DECLARE_SYMBOL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
+
+DECLARE_SYMBOL(open, int, (const char *path, int flags, mode_t mode));
+DECLARE_SYMBOL(open64, int, (const char *path, int flags, mode_t mode));
+//DECLARE_SYMBOL(creat, int, (const char *path, mode_t mode));
+DECLARE_SYMBOL(close, int, (int fd));
+DECLARE_SYMBOL(read, ssize_t, (int fd, void *buf, size_t count));
+DECLARE_SYMBOL(write, ssize_t, (int fd, const void *buf, size_t count));
+DECLARE_SYMBOL(fsync, int, (int fd));
+DECLARE_SYMBOL(fdatasync, int, (int fd));
+DECLARE_SYMBOL(__fxstat, int, (int ver, int fd, struct stat *__stat_buf));
+DECLARE_SYMBOL(__fxstat64, int, (int ver, int fd, struct stat64 *__stat_buf));
+#ifdef HAVE_FSTATAT
+DECLARE_SYMBOL(__fxstatat, int, (int ver, int dirfd, const char *pathname, struct stat *buf, int flags));
+#endif
+
+DECLARE_SYMBOL(lseek, off_t, (int fd, off_t off, int whence));
+DECLARE_SYMBOL(lseek64, off64_t , (int fd, off64_t off, int whence));
+
+DECLARE_SYMBOL(truncate, int, (const char *path, off_t length));
+DECLARE_SYMBOL(ftruncate, int, (int fd, off_t length));
+
+DECLARE_SYMBOL(opendir, DIR* , (const char *name));
+DECLARE_SYMBOL(readdir, struct dirent*, (DIR *dirp));
+DECLARE_SYMBOL(closedir, int, (DIR *dirp));
+DECLARE_SYMBOL(dirfd, int, (DIR *dirp));
+DECLARE_SYMBOL(fchdir, int, (int fd));
+
+static void* hMutex = NULL;
+
+typedef struct
+{
+    char*  pszDirname;
+    char** papszDir;
+    int    nIter;
+    struct dirent ent;
+    int    fd;
+} VSIDIR;
+
+std::set<VSILFILE*> oSetFiles;
+std::map<int, VSILFILE*> oMapfdToVSI;
+std::map<VSILFILE*, int> oMapVSITofd;
+std::map<VSILFILE*, std::string> oMapVSIToString;
+std::set<VSIDIR*> oSetVSIDIR;
+std::map<int, VSIDIR*> oMapfdToVSIDIR;
+std::map<int, std::string> oMapDirFdToName;
+std::string osCurDir;
+
+/************************************************************************/
+/*                             myinit()                                 */
+/************************************************************************/
+
+#define LOAD_SYMBOL(x) \
+    pfn ## x = (fn ## x ## Type) dlsym(RTLD_NEXT, #x); \
+    assert(pfn ## x)
+
+static void myinit(void)
+{
+    CPLMutexHolderD(&hMutex);
+
+    if( pfnfopen64 != NULL ) return;
+    DEBUG_VSIPRELOAD = getenv("DEBUG_VSIPRELOAD") != NULL;
+    LOAD_SYMBOL(fopen);
+    LOAD_SYMBOL(fopen64);
+    LOAD_SYMBOL(fread);
+    LOAD_SYMBOL(fwrite);
+    LOAD_SYMBOL(fclose);
+    LOAD_SYMBOL(fseeko64);
+    LOAD_SYMBOL(fseek);
+    LOAD_SYMBOL(__xstat);
+    LOAD_SYMBOL(__lxstat);
+    LOAD_SYMBOL(__xstat64);
+    LOAD_SYMBOL(ftello64);
+    LOAD_SYMBOL(ftell);
+    LOAD_SYMBOL(feof);
+    LOAD_SYMBOL(fflush);
+    LOAD_SYMBOL(fgetpos);
+    LOAD_SYMBOL(fsetpos);
+    LOAD_SYMBOL(fileno);
+    LOAD_SYMBOL(ferror);
+
+    LOAD_SYMBOL(fdopen);
+    LOAD_SYMBOL(freopen);
+
+    LOAD_SYMBOL(open);
+    LOAD_SYMBOL(open64);
+    //LOAD_SYMBOL(creat);
+    LOAD_SYMBOL(close);
+    LOAD_SYMBOL(read);
+    LOAD_SYMBOL(write);
+    LOAD_SYMBOL(fsync);
+    LOAD_SYMBOL(fdatasync);
+    LOAD_SYMBOL(__fxstat);
+    LOAD_SYMBOL(__fxstat64);
+#ifdef HAVE_FSTATAT
+    LOAD_SYMBOL(__fxstatat);
+#endif
+    LOAD_SYMBOL(lseek);
+    LOAD_SYMBOL(lseek64);
+
+    LOAD_SYMBOL(truncate);
+    LOAD_SYMBOL(ftruncate);
+
+    LOAD_SYMBOL(opendir);
+    LOAD_SYMBOL(readdir);
+    LOAD_SYMBOL(closedir);
+    LOAD_SYMBOL(dirfd);
+    LOAD_SYMBOL(fchdir);
+}
+
+/************************************************************************/
+/*                          getVSILFILE()                               */
+/************************************************************************/
+
+static VSILFILE* getVSILFILE(FILE* stream)
+{
+    VSILFILE* ret;
+    CPLMutexHolderD(&hMutex);
+    std::set<VSILFILE*>::iterator oIter = oSetFiles.find((VSILFILE*)stream);
+    if( oIter != oSetFiles.end() )
+        ret = *oIter;
+    else
+        ret = NULL;
+    return ret;
+}
+
+/************************************************************************/
+/*                          getVSILFILE()                               */
+/************************************************************************/
+
+static VSILFILE* getVSILFILE(int fd)
+{
+    VSILFILE* ret;
+    CPLMutexHolderD(&hMutex);
+    std::map<int, VSILFILE*>::iterator oIter = oMapfdToVSI.find(fd);
+    if( oIter != oMapfdToVSI.end() )
+        ret = oIter->second;
+    else
+        ret = NULL;
+    return ret;
+}
+
+/************************************************************************/
+/*                        VSIFSeekLHelper()                             */
+/************************************************************************/
+
+static int VSIFSeekLHelper(VSILFILE* fpVSIL, off64_t off, int whence)
+{
+    if( off < 0 && whence == SEEK_CUR )
+    {
+        return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
+    }
+    else if( off < 0 && whence == SEEK_END )
+    {
+        VSIFSeekL(fpVSIL, 0, SEEK_END);
+        return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
+    }
+    else
+        return VSIFSeekL(fpVSIL, off, whence);
+}
+
+/************************************************************************/
+/*                          VSIFopenHelper()                            */
+/************************************************************************/
+
+static VSILFILE* VSIFfopenHelper(const char *path, const char *mode)
+{
+    VSILFILE* fpVSIL = VSIFOpenL(path, mode);
+    if( fpVSIL != NULL )
+    {
+        CPLMutexHolderD(&hMutex);
+        oSetFiles.insert(fpVSIL);
+        oMapVSIToString[fpVSIL] = path;
+    }
+    return fpVSIL;
+}
+
+/************************************************************************/
+/*                         getfdFromVSILFILE()                          */
+/************************************************************************/
+
+static int getfdFromVSILFILE(VSILFILE* fpVSIL)
+{
+    CPLMutexHolderD(&hMutex);
+
+    int fd;
+    std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
+    if( oIter != oMapVSITofd.end() )
+        fd = oIter->second;
+    else
+    {
+        fd = open("/dev/zero", O_RDONLY);
+        assert(fd >= 0);
+        oMapVSITofd[fpVSIL] = fd;
+        oMapfdToVSI[fd] = fpVSIL;
+    }
+    return fd;
+}
+
+/************************************************************************/
+/*                          VSIFopenHelper()                            */
+/************************************************************************/
+
+static int VSIFopenHelper(const char *path, int flags)
+{
+    const char* pszMode = "rb";
+    if ((flags & 3) == O_RDONLY) 
+        pszMode = "rb";
+    else if ((flags & 3) == O_WRONLY) 
+    {
+        if( flags & O_APPEND )
+            pszMode = "ab";
+        else
+            pszMode = "wb";
+    }
+    else
+    {
+        if( flags & O_APPEND )
+            pszMode = "ab+";
+        else
+            pszMode = "rb+";
+    }
+    VSILFILE* fpVSIL = VSIFfopenHelper(path, pszMode );
+    int fd;
+    if( fpVSIL != NULL )
+    {
+        if( flags & O_TRUNC )
+        {
+            VSIFTruncateL(fpVSIL, 0);
+            VSIFSeekL(fpVSIL, 0, SEEK_SET);
+        }
+        fd = getfdFromVSILFILE(fpVSIL);
+    }
+    else
+        fd = -1;
+    return fd;
+}
+
+/************************************************************************/
+/*                    GET_DEBUG_VSIPRELOAD_COND()                             */
+/************************************************************************/
+
+static int GET_DEBUG_VSIPRELOAD_COND(const char* path)
+{
+    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || strncmp(path, "/vsi", 4) == 0) );
+}
+
+static int GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
+{
+    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != NULL));
+}
+
+static int GET_DEBUG_VSIPRELOAD_COND(VSIDIR* dirP)
+{
+    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || oSetVSIDIR.find(dirP) != oSetVSIDIR.end()));
+}
+
+/************************************************************************/
+/*                     copyVSIStatBufLToBuf()                           */
+/************************************************************************/
+
+static void copyVSIStatBufLToBuf(VSIStatBufL* bufSrc, struct stat *buf)
+{
+    buf->st_dev = bufSrc->st_dev;
+    buf->st_ino = bufSrc->st_ino;
+    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
+    buf->st_nlink = 1; //bufSrc->st_nlink;
+    buf->st_uid = bufSrc->st_uid;
+    buf->st_gid = bufSrc->st_gid;
+    buf->st_rdev = bufSrc->st_rdev;
+    buf->st_size = bufSrc->st_size;
+    buf->st_blksize = bufSrc->st_blksize;
+    buf->st_blocks = bufSrc->st_blocks;
+    buf->st_atime = bufSrc->st_atime;
+    buf->st_mtime = bufSrc->st_mtime;
+    buf->st_ctime = bufSrc->st_ctime;
+}
+
+/************************************************************************/
+/*                     copyVSIStatBufLToBuf64()                         */
+/************************************************************************/
+
+static void copyVSIStatBufLToBuf64(VSIStatBufL *bufSrc, struct stat64 *buf)
+{
+    buf->st_dev = bufSrc->st_dev;
+    buf->st_ino = bufSrc->st_ino;
+    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
+    buf->st_nlink = 1; //bufSrc->st_nlink;
+    buf->st_uid = bufSrc->st_uid;
+    buf->st_gid = bufSrc->st_gid;
+    buf->st_rdev = bufSrc->st_rdev;
+    buf->st_size = bufSrc->st_size;
+    buf->st_blksize = bufSrc->st_blksize;
+    buf->st_blocks = bufSrc->st_blocks;
+    buf->st_atime = bufSrc->st_atime;
+    buf->st_mtime = bufSrc->st_mtime;
+    buf->st_ctime = bufSrc->st_ctime;
+}
+
+/************************************************************************/
+/*                             fopen()                                  */
+/************************************************************************/
+
+FILE *fopen(const char *path, const char *mode)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
+    FILE* ret;
+    if( strncmp(path, "/vsi", 4) == 0 )
+        ret = (FILE*) VSIFfopenHelper(path, mode);
+    else
+        ret = pfnfopen(path, mode);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen() = %p\n", ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                            fopen64()                                 */
+/************************************************************************/
+
+FILE *fopen64(const char *path, const char *mode)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
+    FILE* ret;
+    if( strncmp(path, "/vsi", 4) == 0 )
+        ret = (FILE*) VSIFfopenHelper(path, mode);
+    else
+        ret = pfnfopen64(path, mode);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64() = %p\n", ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                            fread()                                   */
+/************************************************************************/
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
+        stream, (int)size, (int)nmemb);
+    size_t ret;
+    if( fpVSIL )
+        ret = VSIFReadL(ptr, size, nmemb, fpVSIL);
+    else
+        ret = pfnfread(ptr, size, nmemb, stream);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d) -> %d\n",
+        stream, (int)size, (int)nmemb, (int)ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                            fwrite()                                  */
+/************************************************************************/
+
+size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
+        stream, (int)size, (int)nmemb);
+    size_t ret;
+    if( fpVSIL != NULL )
+        ret = VSIFWriteL(ptr, size, nmemb, fpVSIL);
+    else
+        ret = pfnfwrite(ptr, size, nmemb, stream);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d) -> %d\n",
+        stream, (int)size, (int)nmemb, (int)ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                            fclose()                                  */
+/************************************************************************/
+
+int fclose(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fclose(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+    {
+        CPLMutexHolderD(&hMutex);
+
+        int ret = VSIFCloseL(fpVSIL);
+        oMapVSIToString.erase(fpVSIL);
+        oSetFiles.erase(fpVSIL);
+
+        std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
+        if( oIter != oMapVSITofd.end() )
+        {
+            int fd = oIter->second;
+            pfnclose(fd);
+            oMapVSITofd.erase(oIter);
+            oMapfdToVSI.erase(fd);
+        }
+
+        return ret;
+    }
+    else
+        return pfnfclose(stream);
+}
+
+/************************************************************************/
+/*                            __xstat()                                 */
+/************************************************************************/
+
+int __xstat(int ver, const char *path, struct stat *buf)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat(%s)\n", path);
+    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    {
+        VSIStatBufL sStatBufL;
+        int ret;
+        std::string newpath;
+        if( (osCurDir.size() != 0 && path[0] != '/') )
+        {
+            newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
+            path = newpath.c_str();
+        }
+        ret = VSIStatL(path, &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__xstat(%s) ret = 0, mode = %d, size=%d\n",
+                path, sStatBufL.st_mode, (int)sStatBufL.st_size);
+        }
+        return ret;
+    }
+    else
+    {
+        int ret = pfn__xstat(ver, path, buf);
+        if( ret == 0 )
+        {
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__xstat ret = 0, mode = %d\n", buf->st_mode);
+        }
+        return ret;
+    }
+}
+
+/************************************************************************/
+/*                           __lxstat()                                 */
+/************************************************************************/
+
+int __lxstat(int ver, const char *path, struct stat *buf)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__lxstat(%s)\n", path);
+    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    {
+        VSIStatBufL sStatBufL;
+        int ret;
+        std::string newpath;
+        if( (osCurDir.size() != 0 && path[0] != '/') )
+        {
+            newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
+            path = newpath.c_str();
+        }
+        ret = VSIStatL(path, &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__lxstat(%s) ret = 0, mode = %d, size=%d\n",
+                path, sStatBufL.st_mode, (int)sStatBufL.st_size);
+        }
+        return ret;
+    }
+    else
+    {
+        int ret = pfn__lxstat(ver, path, buf);
+        if( ret == 0 )
+        {
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__lxstat ret = 0, mode = %d\n", buf->st_mode);
+        }
+        return ret;
+    }
+}
+
+/************************************************************************/
+/*                           __xstat64()                                */
+/************************************************************************/
+
+int __xstat64(int ver, const char *path, struct stat64 *buf)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat64(%s)\n", path);
+    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    {
+        VSIStatBufL sStatBufL;
+        int ret;
+        std::string newpath;
+        if( (osCurDir.size() != 0 && path[0] != '/') )
+        {
+            newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
+            path = newpath.c_str();
+        }
+        ret = VSIStatL(path, &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf64(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__xstat64(%s) ret = 0, mode = %d, size = %d\n",
+                path, buf->st_mode, (int)buf->st_size);
+        }
+        return ret;
+    }
+    else
+        return pfn__xstat64(ver, path, buf);
+}
+
+/************************************************************************/
+/*                           fseeko64()                                 */
+/************************************************************************/
+
+int fseeko64 (FILE *stream, off64_t off, int whence)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko64(stream=%p, off=%d, whence=%d)\n",
+        stream, (int)off, whence);
+    if( fpVSIL != NULL )
+        return VSIFSeekLHelper(fpVSIL, off, whence);
+    else
+        return pfnfseeko64(stream, off, whence);
+}
+
+/************************************************************************/
+/*                           fseeko()                                 */
+/************************************************************************/
+
+int fseeko (FILE *stream, off_t off, int whence)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko(stream=%p, off=%d, whence=%d)\n",
+        stream, (int)off, whence);
+    if( fpVSIL != NULL )
+        return VSIFSeekLHelper(fpVSIL, off, whence);
+    else
+        return pfnfseeko64(stream, off, whence);
+}
+
+/************************************************************************/
+/*                            fseek()                                   */
+/************************************************************************/
+
+int fseek (FILE *stream, off_t off, int whence)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseek(stream=%p, off=%d, whence=%d)\n",
+        stream, (int)off, whence);
+    if( fpVSIL != NULL )
+        return VSIFSeekLHelper(fpVSIL, off, whence);
+    else
+        return pfnfseek(stream, off, whence);
+}
+
+/************************************************************************/
+/*                           ftello64()                                 */
+/************************************************************************/
+
+off64_t ftello64(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello64(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+        return VSIFTellL(fpVSIL);
+    else
+        return pfnftello64(stream);
+}
+
+/************************************************************************/
+/*                            ftello()                                  */
+/************************************************************************/
+
+off_t ftello(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+        return VSIFTellL(fpVSIL);
+    else
+        return pfnftello64(stream);
+}
+
+/************************************************************************/
+/*                            ftell()                                   */
+/************************************************************************/
+
+off_t ftell(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftell(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+        return VSIFTellL(fpVSIL);
+    else
+        return pfnftell(stream);
+}
+
+/************************************************************************/
+/*                             feof()                                   */
+/************************************************************************/
+
+int feof(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "feof(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+        return VSIFEofL(fpVSIL);
+    else
+        return pfnfeof(stream);
+}
+
+/************************************************************************/
+/*                            rewind()                                  */
+/************************************************************************/
+
+void rewind(FILE *stream)
+{
+    fseek(stream, 0, SEEK_SET);
+}
+
+/************************************************************************/
+/*                            fflush()                                  */
+/************************************************************************/
+
+int fflush(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fflush(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+        return 0;
+    else
+        return pfnfflush(stream);
+}
+
+/************************************************************************/
+/*                            fgetpos()                                 */
+/************************************************************************/
+
+int fgetpos(FILE *stream, fpos_t *pos)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fgetpos(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+    {
+        fprintf(stderr, "fgetpos() unimplemented for VSILFILE\n");
+        return -1; // FIXME
+    }
+    else
+        return pfnfgetpos(stream, pos);
+}
+
+/************************************************************************/
+/*                            fsetpos()                                 */
+/************************************************************************/
+
+int fsetpos(FILE *stream, fpos_t *pos)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsetpos(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+    {
+        fprintf(stderr, "fsetpos() unimplemented for VSILFILE\n");
+        return -1; // FIXME
+    }
+    else
+        return pfnfsetpos(stream, pos);
+}
+
+/************************************************************************/
+/*                             fileno()                                 */
+/************************************************************************/
+
+int fileno(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p)\n", stream);
+    int fd;
+    if( fpVSIL != NULL )
+        fd = getfdFromVSILFILE(fpVSIL);
+    else
+        fd = pfnfileno(stream);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p) = %d\n", stream, fd);
+    return fd;
+}
+
+/************************************************************************/
+/*                             ferror()                                 */
+/************************************************************************/
+
+int ferror(FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ferror(stream=%p)\n", stream);
+    if( fpVSIL != NULL )
+    {
+        fprintf(stderr, "ferror() unimplemented for VSILFILE\n");
+        return 0; // FIXME ?
+    }
+    else
+        return pfnferror(stream);
+}
+
+/************************************************************************/
+/*                             fdopen()                                 */
+/************************************************************************/
+
+FILE * fdopen(int fd, const char *mode)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdopen(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+    {
+        fprintf(stderr, "fdopen() unimplemented for VSILFILE\n");
+        return NULL; // FIXME ?
+    }
+    else
+        return pfnfdopen(fd, mode);
+}
+
+/************************************************************************/
+/*                             freopen()                                */
+/************************************************************************/
+
+FILE *freopen(const char *path, const char *mode, FILE *stream)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(stream);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "freopen(path=%s,mode=%s,stream=%p)\n", path, mode, stream);
+    if( fpVSIL != NULL )
+    {
+        fprintf(stderr, "freopen() unimplemented for VSILFILE\n");
+        return NULL; // FIXME ?
+    }
+    else
+        return pfnfreopen(path, mode, stream);
+}
+
+/************************************************************************/
+/*                              open()                                  */
+/************************************************************************/
+
+int open(const char *path, int flags, ...)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND)
+    {
+        if( osCurDir.size() != 0 && path[0] != '/' )
+            fprintf(stderr, "open(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
+        else
+            fprintf(stderr, "open(%s)\n", path);
+    }
+
+    va_list args;
+    va_start(args, flags);
+    mode_t mode = va_arg(args, mode_t);
+    int fd;
+    if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
+    {
+        VSIStatBufL sStatBufL;
+        char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
+        if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
+        {
+            char* lastslash = strrchr(newname, '/');
+            if( lastslash != NULL )
+            {
+                *lastslash = 0;
+                lastslash = strrchr(newname, '/');
+                if( lastslash != NULL )
+                    *lastslash = 0;
+            }
+        }
+        if( VSIStatL(newname, &sStatBufL) == 0 &&
+            S_ISDIR(sStatBufL.st_mode) )
+        {
+            fd = open("/dev/zero", O_RDONLY);
+            CPLMutexHolderD(&hMutex)
+            oMapDirFdToName[fd] = newname;
+        }
+        else
+            fd = -1;
+    }
+    else if( strncmp(path, "/vsi", 4) == 0 )
+        fd = VSIFopenHelper(path, flags);
+    else
+        fd = pfnopen(path, flags, mode);
+    va_end(args);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open(%s) = %d\n", path, fd);
+    return fd;
+}
+
+/************************************************************************/
+/*                             open64()                                 */
+/************************************************************************/
+
+int open64(const char *path, int flags, ...)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND)
+    {
+        if( osCurDir.size() != 0 && path[0] != '/' )
+            fprintf(stderr, "open64(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
+        else
+            fprintf(stderr, "open64(%s)\n", path);
+    }
+
+    va_list args;
+    va_start(args, flags);
+    mode_t mode = va_arg(args, mode_t);
+    int fd;
+    if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
+    {
+        VSIStatBufL sStatBufL;
+        char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
+        if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
+        {
+            char* lastslash = strrchr(newname, '/');
+            if( lastslash != NULL )
+            {
+                *lastslash = 0;
+                lastslash = strrchr(newname, '/');
+                if( lastslash != NULL )
+                    *lastslash = 0;
+            }
+        }
+        if( VSIStatL(newname, &sStatBufL) == 0 &&
+            S_ISDIR(sStatBufL.st_mode) )
+        {
+            fd = open("/dev/zero", O_RDONLY);
+            CPLMutexHolderD(&hMutex)
+            oMapDirFdToName[fd] = newname;
+        }
+        else
+            fd = -1;
+    }
+    else if( strncmp(path, "/vsi", 4) == 0 )
+        fd = VSIFopenHelper(path, flags);
+    else
+        fd = pfnopen64(path, flags, mode);
+    va_end(args);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open64(%s) = %d\n", path, fd);
+    return fd;
+}
+
+/************************************************************************/
+/*                             creat()                                  */
+/************************************************************************/
+
+int creat(const char *path, mode_t mode)
+{
+    return open64(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
+}
+
+/************************************************************************/
+/*                             close()                                  */
+/************************************************************************/
+
+int close(int fd)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    {
+        CPLMutexHolderD(&hMutex);
+        assert( oMapfdToVSIDIR.find(fd) == oMapfdToVSIDIR.end() );
+
+        if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
+        {
+            oMapDirFdToName.erase(fd);
+            if( DEBUG_VSIPRELOAD )
+                DEBUG_VSIPRELOAD_COND = 1;
+        }
+    }
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "close(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+    {
+        VSIFCloseL(fpVSIL);
+        CPLMutexHolderD(&hMutex);
+        oSetFiles.erase(fpVSIL);
+        pfnclose(oMapVSITofd[fpVSIL]);
+        oMapVSITofd.erase(fpVSIL);
+        oMapfdToVSI.erase(fd);
+        oMapVSIToString.erase(fpVSIL);
+        return 0;
+    }
+    else
+        return pfnclose(fd);
+}
+
+/************************************************************************/
+/*                              read()                                  */
+/************************************************************************/
+
+ssize_t read(int fd, void *buf, size_t count)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read(fd=%d, count=%d)\n", fd, (int)count);
+    ssize_t ret;
+    if( fpVSIL != NULL )
+        ret = VSIFReadL(buf, 1, count, fpVSIL);
+    else
+        ret = pfnread(fd, buf, count);
+    if (DEBUG_VSIPRELOAD_COND && DEBUG_OUTPUT_READ && ret < 40)
+    {
+        fprintf(stderr, "read() : ");
+        for(int i=0;i<ret;i++)
+        {
+            if( ((unsigned char*)buf)[i] >= 'A' && ((unsigned char*)buf)[i] <= 'Z' )
+                fprintf(stderr, "%c ", ((unsigned char*)buf)[i]);
+            else
+                fprintf(stderr, "\\%02X ", ((unsigned char*)buf)[i]);
+        }
+        fprintf(stderr, "\n");
+    }
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read() -> %d\n", (int)ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                              write()                                 */
+/************************************************************************/
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "write(fd=%d, count=%d)\n", fd, (int)count);
+    if( fpVSIL != NULL )
+        return VSIFWriteL(buf, 1, count, fpVSIL);
+    else
+        return pfnwrite(fd, buf, count);
+}
+
+/************************************************************************/
+/*                              fsync()                                 */
+/************************************************************************/
+
+int fsync(int fd)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsync(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+        return 0;
+    else
+        return pfnfsync(fd);
+}
+
+/************************************************************************/
+/*                           fdatasync()                                */
+/************************************************************************/
+
+int fdatasync(int fd)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdatasync(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+        return 0;
+    else
+        return pfnfdatasync(fd);
+}
+
+/************************************************************************/
+/*                            __fxstat()                                */
+/************************************************************************/
+
+int __fxstat (int ver, int fd, struct stat *buf)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    std::string name;
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    {
+        CPLMutexHolderD(&hMutex)
+        if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
+        {
+            name = oMapDirFdToName[fd];
+            if( DEBUG_VSIPRELOAD )
+                DEBUG_VSIPRELOAD_COND = 1;
+        }
+    }
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(fd=%d)\n", fd);
+    if( name.size() )
+    {
+        VSIStatBufL sStatBufL;
+        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(%s)\n", name.c_str());
+        int ret = VSIStatL(name.c_str(), &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__fxstat ret = 0, mode = %d, size = %d\n",
+                sStatBufL.st_mode, (int)sStatBufL.st_size);
+        }
+        return ret;
+    }
+    else if( fpVSIL != NULL )
+    {
+        VSIStatBufL sStatBufL;
+        {
+            CPLMutexHolderD(&hMutex);
+            name = oMapVSIToString[fpVSIL];
+        }
+        int ret = VSIStatL(name.c_str(), &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__fxstat ret = 0, mode = %d, size = %d\n",
+                sStatBufL.st_mode, (int)sStatBufL.st_size);
+        }
+        return ret;
+    }
+    else
+        return pfn__fxstat(ver, fd, buf);
+}
+
+/************************************************************************/
+/*                           __fxstat64()                               */
+/************************************************************************/
+
+int __fxstat64 (int ver, int fd, struct stat64 *buf)
+{
+    myinit();
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat64(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+    {
+        VSIStatBufL sStatBufL;
+        std::string name;
+        {
+            CPLMutexHolderD(&hMutex);
+            name = oMapVSIToString[fpVSIL];
+        }
+        int ret = VSIStatL(name.c_str(), &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf64(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__fxstat64 ret = 0, mode = %d, size = %d\n",
+                buf->st_mode, (int)buf->st_size);
+        }
+        return ret;
+    }
+    else
+        return pfn__fxstat64(ver, fd, buf);
+}
+
+/************************************************************************/
+/*                           __fxstatat()                               */
+/************************************************************************/
+
+#ifdef HAVE_FSTATAT
+int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf,
+                int flags)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(pathname);
+    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n", dirfd, pathname, flags);
+
+    if( osCurDir.size() != 0 || strncmp(pathname, "/vsi", 4) == 0 )
+    {
+        VSIStatBufL sStatBufL;
+        int ret;
+        if( osCurDir.size() && dirfd == AT_FDCWD && pathname[0] != '/' )
+            pathname = CPLFormFilename(osCurDir.c_str(), pathname, NULL);
+        ret = VSIStatL(pathname, &sStatBufL);
+        sStatBufL.st_ino = (int)CPLHashSetHashStr(pathname);
+        if( ret == 0 )
+        {
+            copyVSIStatBufLToBuf(&sStatBufL, buf);
+            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+                "__fxstatat(%s) ret = 0, mode = %d, size = %d\n",
+                pathname, buf->st_mode, (int)buf->st_size);
+        }
+        return ret;
+    }
+    else
+        return pfn__fxstatat(ver, dirfd, pathname, buf, flags);
+}
+#endif
+
+/************************************************************************/
+/*                              lseek()                                 */
+/************************************************************************/
+
+off_t lseek(int fd, off_t off, int whence)
+{
+    myinit();
+    off_t ret;
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+        "lseek(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
+    if( fpVSIL != NULL )
+    {
+        VSIFSeekLHelper(fpVSIL, off, whence);
+        ret = VSIFTellL(fpVSIL);
+    }
+    else
+        ret = pfnlseek(fd, off, whence);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lseek() -> ret = %d\n", (int)ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                             lseek64()                                */
+/************************************************************************/
+
+off64_t lseek64(int fd, off64_t off, int whence)
+{
+    myinit();
+    off_t ret;
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+        "lseek64(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
+    if( fpVSIL != NULL )
+    {
+        VSIFSeekLHelper(fpVSIL, off, whence);
+        ret = VSIFTellL(fpVSIL);
+    }
+    else
+        ret = pfnlseek64(fd, off, whence);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+        "lseek64() -> ret = %d\n", (int)ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                            truncate()                                */
+/************************************************************************/
+
+int truncate(const char *path, off_t length)
+{
+    myinit();
+    int ret;
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "truncate(%s)\n", path);
+
+    if( strncmp(path, "/vsi", 4) == 0 )
+    {
+        VSILFILE* fpVSIL = VSIFOpenL(path, "wb+");
+        if( fpVSIL )
+        {
+            ret = VSIFTruncateL(fpVSIL, length);
+            VSIFCloseL(fpVSIL);
+        }
+        else
+            ret = -1;
+    }
+    else
+        ret = pfntruncate(path, length);
+    return ret;
+}
+
+/************************************************************************/
+/*                           ftruncate()                                */
+/************************************************************************/
+
+int ftruncate(int fd, off_t length)
+{
+    myinit();
+    int ret;
+    VSILFILE* fpVSIL = getVSILFILE(fd);
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
+    if( fpVSIL != NULL )
+    {
+        ret = VSIFTruncateL(fpVSIL, length);
+    }
+    else
+        ret = pfnftruncate(fd, length);
+    return ret;
+}
+
+/************************************************************************/
+/*                             opendir()                                */
+/************************************************************************/
+
+DIR *opendir(const char *name)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(name);
+    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
+        DEBUG_VSIPRELOAD_COND = 1;
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s)\n", name);
+
+    DIR * ret;
+    if( osCurDir.size() != 0 || strncmp(name, "/vsi", 4) == 0 )
+    {
+        char** papszDir;
+        if( osCurDir.size() != 0 && name[0] != '/' )
+            name = CPLFormFilename(osCurDir.c_str(), name, NULL);
+        papszDir = VSIReadDir(name);
+        if( papszDir == NULL )
+        {
+            VSIStatBufL sStatBufL;
+            if( VSIStatL(name, &sStatBufL) == 0 && S_ISDIR(sStatBufL.st_mode) )
+            {
+                papszDir = (char**) CPLMalloc(sizeof(char*));
+                papszDir[0] = NULL;
+            }
+        }
+        if( papszDir == NULL )
+            ret = NULL;
+        else
+        {
+            VSIDIR* mydir = (VSIDIR*)malloc(sizeof(VSIDIR));
+            mydir->pszDirname = CPLStrdup(name);
+            mydir->papszDir = papszDir;
+            mydir->nIter = 0;
+            mydir->fd = -1;
+            ret = (DIR*)mydir;
+            CPLMutexHolderD(&hMutex);
+            oSetVSIDIR.insert(mydir);
+        }
+    }
+    else
+        ret = pfnopendir(name);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s) -> %p\n", name, ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                             readdir()                                */
+/************************************************************************/
+
+struct dirent *readdir(DIR *dirp)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "readdir(%p)\n", dirp);
+    if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
+    {
+        VSIDIR* mydir = (VSIDIR*)dirp;
+        char* pszName = mydir->papszDir[mydir->nIter++];
+        if( pszName == NULL )
+            return NULL;
+        mydir->ent.d_ino = 0;
+        mydir->ent.d_off = 0;
+        mydir->ent.d_reclen = sizeof(mydir->ent);
+        VSIStatBufL sStatBufL;
+        VSIStatL(CPLFormFilename(mydir->pszDirname, pszName, NULL), &sStatBufL);
+        if( DEBUG_VSIPRELOAD_COND && S_ISDIR(sStatBufL.st_mode) )
+            fprintf(stderr, "%s is dir\n", pszName);
+        mydir->ent.d_type = S_ISDIR(sStatBufL.st_mode) ? DT_DIR :
+                            S_ISREG(sStatBufL.st_mode) ? DT_REG :
+                            S_ISLNK(sStatBufL.st_mode) ? DT_LNK :
+                            DT_UNKNOWN;
+        strncpy(mydir->ent.d_name, pszName, 256);
+        mydir->ent.d_name[255] = '\0';
+        return &(mydir->ent);
+    }
+    else
+        return pfnreaddir(dirp);
+}
+
+/************************************************************************/
+/*                             closedir()                               */
+/************************************************************************/
+
+int closedir(DIR *dirp)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "closedir(%p)\n", dirp);
+    if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
+    {
+        VSIDIR* mydir = (VSIDIR*)dirp;
+        CPLFree(mydir->pszDirname);
+        CSLDestroy(mydir->papszDir);
+        CPLMutexHolderD(&hMutex);
+        if( mydir->fd >= 0 )
+        {
+            oMapfdToVSIDIR.erase(mydir->fd);
+            close(mydir->fd);
+        }
+        oSetVSIDIR.erase(mydir);
+        free(mydir);
+        return 0;
+    }
+    else
+        return pfnclosedir(dirp);
+}
+
+/************************************************************************/
+/*                               dirfd()                                */
+/************************************************************************/
+
+int dirfd(DIR *dirp)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p)\n", dirp);
+    int ret;
+    if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
+    {
+        VSIDIR* mydir = (VSIDIR*)dirp;
+        if( mydir->fd < 0 )
+        {
+            mydir->fd = open("/dev/zero", O_RDONLY);
+            CPLMutexHolderD(&hMutex);
+            oMapfdToVSIDIR[mydir->fd] = mydir;
+        }
+        ret = mydir->fd;
+    }
+    else
+        ret = pfndirfd(dirp);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p) -> %d\n", dirp, ret);
+    return ret;
+}
+
+/************************************************************************/
+/*                              fchdir()                                */
+/************************************************************************/
+
+int fchdir(int fd)
+{
+    VSIDIR* mydir = NULL;
+    {
+        CPLMutexHolderD(&hMutex);
+        if( oMapfdToVSIDIR.find(fd) != oMapfdToVSIDIR.end() )
+            mydir = oMapfdToVSIDIR[fd];
+    }
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
+    std::string name;
+    {
+        CPLMutexHolderD(&hMutex)
+        if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
+        {
+            name = oMapDirFdToName[fd];
+            if( DEBUG_VSIPRELOAD )
+                DEBUG_VSIPRELOAD_COND = 1;
+        }
+    }
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d)\n", fd);
+    if( name.size() )
+    {
+        osCurDir = name;
+        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        return 0;
+    }
+    else if( mydir != NULL )
+    {
+        osCurDir = mydir->pszDirname;
+        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        return 0;
+    }
+    else
+    {
+        osCurDir = "";
+        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        return pfnfchdir(fd);
+    }
+}
+
+/************************************************************************/
+/*                        acl_extended_file()                           */
+/************************************************************************/
+
+// #include <acl/acl.h>
+extern "C" int acl_extended_file(const char *name);
+DECLARE_SYMBOL(acl_extended_file, int, (const char *name));
+
+int acl_extended_file(const char *path)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "acl_extended_file(%s)\n", path);
+    int ret;
+    if( strncmp(path, "/vsi", 4) == 0 )
+        ret = -1;
+    else
+    {
+        if( pfnacl_extended_file == NULL )
+            pfnacl_extended_file = (fnacl_extended_fileType) dlsym(RTLD_NEXT, "acl_extended_file");
+        if( pfnacl_extended_file == NULL )
+            ret = -1;
+        else
+            ret = pfnacl_extended_file(path);
+    }
+    return ret;
+}
+
+/************************************************************************/
+/*                          getfilecon()                                */
+/************************************************************************/
+
+// #include <selinux/selinux.h>
+extern "C" int getfilecon(const char *name, void* con);
+DECLARE_SYMBOL(getfilecon, int, (const char *name, void* con));
+
+int getfilecon(const char *path, /*security_context_t **/ void* con)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "getfilecon(%s)\n", path);
+    int ret;
+    if( strncmp(path, "/vsi", 4) == 0 )
+    {
+        errno = ENOTSUP;
+        ret = -1;
+    }
+    else
+    {
+        if( pfngetfilecon == NULL )
+            pfngetfilecon = (fngetfileconType) dlsym(RTLD_NEXT, "getfilecon");
+        if( pfngetfilecon == NULL )
+            ret = -1;
+        else
+            ret = pfngetfilecon(path, con);
+    }
+    return ret;
+}
+
+/************************************************************************/
+/*                          lgetfilecon()                                */
+/************************************************************************/
+
+// #include <selinux/selinux.h>
+extern "C" int lgetfilecon(const char *name, void* con);
+DECLARE_SYMBOL(lgetfilecon, int, (const char *name, void* con));
+
+int lgetfilecon(const char *path, /*security_context_t **/ void* con)
+{
+    myinit();
+    int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
+    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lgetfilecon(%s)\n", path);
+    int ret;
+    if( strncmp(path, "/vsi", 4) == 0 )
+    {
+        errno = ENOTSUP;
+        ret = -1;
+    }
+    else
+    {
+        if( pfnlgetfilecon == NULL )
+            pfnlgetfilecon = (fnlgetfileconType) dlsym(RTLD_NEXT, "lgetfilecon");
+        if( pfnlgetfilecon == NULL )
+            ret = -1;
+        else
+            ret = pfnlgetfilecon(path, con);
+    }
+    return ret;
+}
diff --git a/scripts/vagrant/gdal.sh b/scripts/vagrant/gdal.sh
new file mode 100755
index 0000000..406c6d3
--- /dev/null
+++ b/scripts/vagrant/gdal.sh
@@ -0,0 +1,31 @@
+NUMTHREADS=2
+if [[ -f /sys/devices/system/cpu/online ]]; then
+	# Calculates 1.5 times physical threads
+	NUMTHREADS=$(( ( $(cut -f 2 -d '-' /sys/devices/system/cpu/online) + 1 ) * 15 / 10  ))
+fi
+#NUMTHREADS=1 # disable MP
+export NUMTHREADS
+
+svn checkout https://svn.osgeo.org/gdal/trunk gdal
+cd gdal/gdal
+#  --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local
+./configure  --prefix=/usr --without-libtool --enable-debug --with-jpeg12 \
+            --with-perl --with-python --with-poppler \
+            --with-podofo --with-spatialite --with-java --with-mdb \
+            --with-jvm-lib-add-rpath --with-epsilon --with-gta \
+            --with-mysql --with-liblzma --with-webp --with-libkml \
+            --with-openjpeg=/usr/local --with-armadillo
+
+make -j $NUMTHREADS
+cd apps
+make test_ogrsf
+cd ..
+
+# A previous version of GDAL has been installed by PostGIS
+sudo rm -f /usr/lib/libgdal.so*
+sudo make install
+sudo ldconfig
+# not sure why we need to do that
+sudo cp -r /usr/lib/python2.7/site-packages/*  /usr/lib/python2.7/dist-packages/
+
+cd ../..
diff --git a/scripts/vagrant/libkml.sh b/scripts/vagrant/libkml.sh
new file mode 100755
index 0000000..a0c345f
--- /dev/null
+++ b/scripts/vagrant/libkml.sh
@@ -0,0 +1,20 @@
+NUMTHREADS=2
+if [[ -f /sys/devices/system/cpu/online ]]; then
+	# Calculates 1.5 times physical threads
+	NUMTHREADS=$(( ( $(cut -f 2 -d '-' /sys/devices/system/cpu/online) + 1 ) * 15 / 10  ))
+fi
+#NUMTHREADS=1 # disable MP
+export NUMTHREADS
+
+#svn checkout http://libkml.googlecode.com/svn/trunk/ libkml-read-only
+#cd libkml-read-only
+#git clone https://github.com/google/libkml.git
+svn co https://github.com/google/libkml/trunk libkml
+cd libkml
+./autogen.sh
+./configure
+
+make -j $NUMTHREADS
+sudo make install
+
+cd ..
diff --git a/scripts/vagrant/openjpeg.sh b/scripts/vagrant/openjpeg.sh
new file mode 100755
index 0000000..7660ca1
--- /dev/null
+++ b/scripts/vagrant/openjpeg.sh
@@ -0,0 +1,19 @@
+NUMTHREADS=2
+if [[ -f /sys/devices/system/cpu/online ]]; then
+	# Calculates 1.5 times physical threads
+	NUMTHREADS=$(( ( $(cut -f 2 -d '-' /sys/devices/system/cpu/online) + 1 ) * 15 / 10  ))
+fi
+#NUMTHREADS=1 # disable MP
+export NUMTHREADS
+
+wget http://sourceforge.net/projects/openjpeg.mirror/files/openjpeg-2.0.0.tar.gz/download -O openjpeg-2.0.0.tar.gz
+tar xvzf openjpeg-2.0.0.tar.gz
+cd openjpeg-2.0.0
+mkdir build
+cd build
+cmake ..
+
+make -j $NUMTHREADS
+sudo make install
+
+cd ../..
diff --git a/scripts/vagrant/postgis.sh b/scripts/vagrant/postgis.sh
new file mode 100755
index 0000000..94fca70
--- /dev/null
+++ b/scripts/vagrant/postgis.sh
@@ -0,0 +1,6 @@
+sudo sed -i  's/md5/trust/' /etc/postgresql/9.1/main/pg_hba.conf
+sudo sed -i  's/peer/trust/' /etc/postgresql/9.1/main/pg_hba.conf
+
+sudo service postgresql restart
+psql -c "create database autotest" -U postgres
+psql -c "create extension postgis" -d autotest -U postgres
diff --git a/scripts/vce2008_wine/build_vce2008.bat b/scripts/vce2008_wine/build_vce2008.bat
new file mode 100644
index 0000000..64b33ec
--- /dev/null
+++ b/scripts/vce2008_wine/build_vce2008.bat
@@ -0,0 +1,14 @@
+c:
+
+set PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools;C:\windows\Microsoft.NET\Framework\v3.5;C:\windows\Microsoft.NET\Framework\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCPackages;%PATH%
+set INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE;%INCLUDE%
+set LIB=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB;%LIB%
+set LIBPATH=C:\windows\Microsoft.NET\Framework\v3.5;C:\windows\Microsoft.NET\Framework\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB;%LIBPATH%
+
+cd c:\gdal\gdal
+set INCLUDE=%INCLUDE%c:\psdk
+set LIB=%LIB%c:\psdk
+set PATH=c:\psdk;%PATH%
+
+del /q port\cpl_config.h
+nmake /f makefile.vc
diff --git a/scripts/vce2008_wine/build_vce2008.patch b/scripts/vce2008_wine/build_vce2008.patch
new file mode 100644
index 0000000..819c986
--- /dev/null
+++ b/scripts/vce2008_wine/build_vce2008.patch
@@ -0,0 +1,61 @@
+Index: frmts/jpeg/libjpeg12/makefile.vc
+===================================================================
+--- frmts/jpeg/libjpeg12/makefile.vc	(révision 27183)
++++ frmts/jpeg/libjpeg12/makefile.vc	(copie de travail)
+@@ -20,6 +20,8 @@
+ 	xcopy /D  /Y *.obj ..\..\o
+ 
+ jcapimin12.c:	../libjpeg/jcapimin.c
++
++_jcapimin12.c:	../libjpeg/jcapimin.c
+ 	xcopy /Y ..\libjpeg\*.h
+ 	xcopy /Y jmorecfg.h.12 jmorecfg.h
+ 	xcopy /Y ..\libjpeg\*.c
+Index: frmts/makefile.vc
+===================================================================
+--- frmts/makefile.vc	(révision 27183)
++++ frmts/makefile.vc	(copie de travail)
+@@ -174,10 +174,11 @@
+ 	for %d in ( $(DIRLIST) ) do \
+ 		cd %d \
+ 		&& $(MAKE) /f makefile.vc \
+-		&& cd .. \
+-		|| exit 1
++		&& cd ..
+ 
+ plugindirs:
++	@echo plugins: $(PLUGINDIRLIST)
++aplugindirs:
+ 	-for %d in ( $(PLUGINDIRLIST) ) do \
+ 		cd %d \
+ 		&& $(MAKE) /f makefile.vc plugin \
+Index: ogr/ogrsf_frmts/makefile.vc
+===================================================================
+--- ogr/ogrsf_frmts/makefile.vc	(révision 27183)
++++ ogr/ogrsf_frmts/makefile.vc	(copie de travail)
+@@ -219,8 +219,7 @@
+ 	for %d in ( $(DIRLIST) ) do \
+ 		cd %d \
+ 		&& $(MAKE) /f makefile.vc \
+-		&& cd .. \
+-		|| exit 1
++		&& cd ..
+ 
+ 	lib /out:ogrsf_frmts.lib generic\*.obj shape\*.obj ntf\*.obj \
+ 				 sdts\*.obj s57\*.obj tiger\*.obj gml\*.obj \
+@@ -256,11 +255,13 @@
+ 
+ plugindirs:
+ 	@echo plugins: $(PLUGINDIRLIST)
++
++aplugindirs:
++	@echo plugins: $(PLUGINDIRLIST)
+         -for %d in ( $(PLUGINDIRLIST) ) do \
+                 cd %d \
+                 && $(MAKE) /f makefile.vc plugin \
+-                && cd .. \
+-                || exit 1
++                && cd .. 
+ 
+ clean:
+ 	-del ogrsf_frmts.lib
diff --git a/scripts/vce2008_wine/build_vce2008.sh b/scripts/vce2008_wine/build_vce2008.sh
new file mode 100755
index 0000000..0d99b16
--- /dev/null
+++ b/scripts/vce2008_wine/build_vce2008.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+if ! test -d $HOME/gdal_vce2008; then
+    echo "$HOME/gdal_vce2008 does not exist. Run ./prepare-gdal-vce2008.sh first"
+    exit 1
+fi
+
+cd $HOME/gdal_vce2008/gdal
+
+# Hack for libjpeg12
+if ! test -f frmts/jpeg/libjpeg12/jmorecfg.h; then
+    cd frmts/jpeg/libjpeg12
+    cp ../libjpeg/*.h .
+    cp jmorecfg.h.12 jmorecfg.h
+    cp ../libjpeg/*.c .
+    mv jcapimin.c jcapimin12.c
+    mv jcapistd.c jcapistd12.c
+    mv jccoefct.c jccoefct12.c
+    mv jccolor.c jccolor12.c
+    mv jcdctmgr.c jcdctmgr12.c
+    mv jchuff.c jchuff12.c
+    mv jcinit.c jcinit12.c
+    mv jcmainct.c jcmainct12.c
+    mv jcmarker.c jcmarker12.c
+    mv jcmaster.c jcmaster12.c
+    mv jcomapi.c jcomapi12.c
+    mv jcparam.c jcparam12.c
+    mv jcphuff.c jcphuff12.c
+    mv jcprepct.c jcprepct12.c
+    mv jcsample.c jcsample12.c
+    mv jctrans.c jctrans12.c
+    mv jdapimin.c jdapimin12.c
+    mv jdapistd.c jdapistd12.c
+    mv jdatadst.c jdatadst12.c
+    mv jdatasrc.c jdatasrc12.c
+    mv jdcoefct.c jdcoefct12.c
+    mv jdcolor.c jdcolor12.c
+    mv jddctmgr.c jddctmgr12.c
+    mv jdhuff.c jdhuff12.c
+    mv jdinput.c jdinput12.c
+    mv jdmainct.c jdmainct12.c
+    mv jdmarker.c jdmarker12.c
+    mv jdmaster.c jdmaster12.c
+    mv jdmerge.c jdmerge12.c
+    mv jdphuff.c jdphuff12.c
+    mv jdpostct.c jdpostct12.c
+    mv jdsample.c jdsample12.c
+    mv jdtrans.c jdtrans12.c
+    mv jerror.c jerror12.c
+    mv jfdctflt.c jfdctflt12.c
+    mv jfdctfst.c jfdctfst12.c
+    mv jfdctint.c jfdctint12.c
+    mv jidctflt.c jidctflt12.c
+    mv jidctfst.c jidctfst12.c
+    mv jidctint.c jidctint12.c
+    mv jidctred.c jidctred12.c
+    mv jmemansi.c jmemansi12.c
+    mv jmemmgr.c jmemmgr12.c
+    mv jquant1.c jquant112.c
+    mv jquant2.c jquant212.c
+    mv jutils.c jutils12.c
+    cd $OLDPWD
+fi
+
+wine cmd /c build_vce2008.bat
diff --git a/scripts/vce2008_wine/clean_vce2008.bat b/scripts/vce2008_wine/clean_vce2008.bat
new file mode 100644
index 0000000..67c04fe
--- /dev/null
+++ b/scripts/vce2008_wine/clean_vce2008.bat
@@ -0,0 +1,13 @@
+c:
+
+set PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools;C:\windows\Microsoft.NET\Framework\v3.5;C:\windows\Microsoft.NET\Framework\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCPackages;%PATH%
+set INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE;%INCLUDE%
+set LIB=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB;%LIB%
+set LIBPATH=C:\windows\Microsoft.NET\Framework\v3.5;C:\windows\Microsoft.NET\Framework\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB;%LIBPATH%
+
+cd c:\gdal\gdal
+set INCLUDE=%INCLUDE%c:\psdk
+set LIB=%LIB%c:\psdk
+set PATH=c:\psdk;%PATH%
+
+nmake /f makefile.vc clean
diff --git a/scripts/vce2008_wine/clean_vce2008.sh b/scripts/vce2008_wine/clean_vce2008.sh
new file mode 100755
index 0000000..3af55e3
--- /dev/null
+++ b/scripts/vce2008_wine/clean_vce2008.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if ! test -d $HOME/gdal_vce2008; then
+    echo "$HOME/gdal_vce2008 does not exist. Run ./prepare-gdal-vce2008.sh first"
+    exit 1
+fi
+
+cd $HOME/gdal_vce2008/gdal
+
+wine cmd /c clean_vce2008.bat
diff --git a/scripts/vce2008_wine/nmake_vce2008.local b/scripts/vce2008_wine/nmake_vce2008.local
new file mode 100644
index 0000000..7eecf19
--- /dev/null
+++ b/scripts/vce2008_wine/nmake_vce2008.local
@@ -0,0 +1,73 @@
+# SQLite Libraries
+SQLITE_INC=-Ic:\release-1500\include -DHAVE_SPATIALITE -DSPATIALITE_AMALGAMATION
+SQLITE_LIB=c:\release-1500\lib\spatialite_i.lib
+
+#PCRE_INC=-I"C:\Program Files\GNUWin32\include" -DHAVE_PCRE
+#PCRE_LIB="C:\Program Files\GNUWin32\lib\pcre.lib"
+
+GEOS_DIR = c:\release-1500
+GEOS_CFLAGS = -Ic:\release-1500\include -DHAVE_GEOS
+GEOS_LIB     = c:\release-1500\lib\geos_c.lib
+
+# Uncomment to use libcurl (DLL by default)
+# The cURL library is used for WCS, WMS, GeoJSON, SRS call importFromUrl(), WFS, GFT, CouchDB, /vsicurl/ etc.
+CURL_DIR=c:\release-1500
+CURL_INC = -I$(CURL_DIR)/include
+# Uncoment following line to use libcurl as dynamic library
+CURL_LIB = $(CURL_DIR)/lib/libcurl_imp.lib wsock32.lib wldap32.lib winmm.lib
+
+# Uncomment for Expat support (required for KML, GPX and GeoRSS read support).
+EXPAT_DIR = c:\release-1500
+EXPAT_INCLUDE = -I$(EXPAT_DIR)\include
+EXPAT_LIB = $(EXPAT_DIR)\lib\libexpat.lib
+
+# Uncomment for Xerces based GML and ILI support.
+XERCES_DIR =   c:\release-1500
+XERCES_INCLUDE = -I$(XERCES_DIR)/include -I$(XERCES_DIR)/include/xercesc
+XERCES_LIB = $(XERCES_DIR)/lib/xerces-c_2.lib
+
+# Uncomment the following for Interlis support.  Note that a Xercex 2.x
+# is also required (see above).  Also, Interlis support only works with
+# Visual Studio.NET or newer, not VC6.
+ILI_ENABLED = YES
+
+
+# Uncomment the following and update to enable ECW support with the 3.3 SDK.
+# Significant adaption may be needed.
+ECWDIR  =  c:\release-1500
+ECWLIB  =  $(ECWDIR)\lib\libecwj2.lib
+ECWFLAGS =     -DECWSDK_VERSION=33 \
+       -I$(ECWDIR)\include \
+       /D_MBCS /D_UNICODE /DUNICODE /D_WINDOWS \
+       /DLIBECWJ2 /DWIN32 /D_WINDLL -DNO_X86_MMI
+
+# Uncomment for PDF support
+POPPLER_ENABLED = YES
+POPPLER_CFLAGS = -Ic:\release-1500\include -Ic:\release-1500\include\poppler
+POPPLER_HAS_OPTCONTENT = YES
+POPPLER_BASE_STREAM_HAS_TWO_ARGS = YES
+POPPLER_0_20_OR_LATER = YES
+POPPLER_0_23_OR_LATER = YES
+POPPLER_LIBS = c:\release-1500\lib\poppler.lib c:\release-1500\lib\freetype239.lib advapi32.lib gdi32.lib /FORCE:MULTIPLE
+
+# Uncomment for OpenJpeg support
+OPENJPEG_ENABLED = YES
+OPENJPEG_CFLAGS = -Ic:\release-1500\include
+OPENJPEG_LIB = c:\release-1500\lib\openjp2.lib
+
+# Uncomment for libxml2 support (for cpl_xml_validate.cpp routines, used optionaly by the GML driver)
+LIBXML2_INC = -Ic:\release-1500\include
+LIBXML2_LIB = c:\release-1500\lib\libxml2.lib
+
+FREEXL_CFLAGS = -Ic:\release-1500\include
+FREEXL_LIBS = c:\release-1500\lib\freexl_i.lib
+
+LIBKML_DIR=c:\release-1500
+LIBKML_INCLUDE=-Ic:\release-1500\include
+LIBKML_LIBS=c:\release-1500\lib\libkmlbase.lib c:\release-1500\lib\libkmlconvenience.lib c:\release-1500\lib\libkmldom.lib c:\release-1500\lib\libkmlengine.lib c:\release-1500\lib\libkmlregionator.lib c:\release-1500\lib\libkmlxsd.lib c:\release-1500\lib\libexpat.lib c:\release-1500\lib\zdll.lib
+
+PG_INC_DIR = c:\release-1500\include
+PG_LIB = c:\release-1500\lib\libpqdll.lib wsock32.lib
+
+MYSQL_INC_DIR=c:\release-1500\include
+MYSQL_LIB=c:\release-1500\lib\libmysql.lib advapi32.lib
diff --git a/scripts/vce2008_wine/prepare-gdal-vce2008.sh b/scripts/vce2008_wine/prepare-gdal-vce2008.sh
new file mode 100755
index 0000000..cff6ebd
--- /dev/null
+++ b/scripts/vce2008_wine/prepare-gdal-vce2008.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+if test "$(lsb_release -c -s)" != "precise"; then
+    echo "Only works with Ubuntu 12.04 Precise"
+    exit 1
+fi
+
+# Install various packages
+sudo add-apt-repository -y ppa:ubuntu-wine/ppa
+sudo apt-get update -qq
+# We need wine1.4 to be able to run nmake.exe. wine1.6 or 1.7 does not work
+sudo apt-get install -y wine1.4 wget p7zip-full cabextract unzip
+
+# Download and install Visual Studio Express 2008
+if test "$(test -f /tmp/VC.iso && stat -c '%s' /tmp/VC.iso)" != "938108928"; then
+    wget "http://go.microsoft.com/fwlink/?LinkId=104679" -O /tmp/VC.iso
+fi
+rm -rf /tmp/vc
+mkdir /tmp/vc
+7z x /tmp/VC.iso VCExpress/* -o/tmp/vc
+cabextract /tmp/vc/VCExpress/Ixpvc.exe -d /tmp/vc/VCExpress
+wine msiexec /i /tmp/vc/VCExpress/vs_setup.msi  VSEXTUI=1 ADDLOCAL=ALL REBOOT=ReallySuppress /qn
+
+# Download and install Platform SDK
+for i in PSDK-SDK_Core_BLD-common.0.cab PSDK-SDK_Core_BLD-common.1.cab PSDK-SDK_Core_BLD-common.2.cab PSDK-SDK_Core_BLD_X86-common.0.cab PSDK-SDK_Core_BIN-x86.0.cab PSDK-SDK_MDAC_BLD_X86-common.0.cab PSDK-SDK_MDAC_BLD-common.0.cab; do
+    wget http://download.microsoft.com/download/a/5/f/a5f0d781-e201-4ab6-8c6a-9bb4efed1e1a/$i -O /tmp/$i
+done
+mkdir /tmp/psdk
+cabextract -d/tmp/psdk /tmp/*.cab
+for i in /tmp/psdk/*; do mv $i `echo $i | sed "s/\(.*\)\..*/\1/" | sed "s/\(.*\)_\(.*\)/\1\.\2/"`; done
+mkdir ~/.wine/drive_c/psdk
+mv /tmp/psdk ~/.wine/drive_c
+
+# Download third-party libraries
+wget "http://www.gisinternals.com/sdk/Download.aspx?file=release-1500-dev.zip" -O /tmp/release-1500-dev.zip
+unzip /tmp/release-1500-dev.zip release-1500/* -d ~/.wine/drive_c
+
+# Download and install Python
+# wget http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi -O /tmp/python-2.7.3.msi
+# wine msiexec /i  /tmp/python-2.7.3.msi
+
+# Checkout GDAL
+svn checkout https://svn.osgeo.org/gdal/trunk $HOME/gdal_vce2008
+ln -s $HOME/gdal_vce2008 ~/.wine/drive_c/gdal
+
+# Install usefull scripts
+cp build_vce2008.patch /tmp
+cp build_vce2008.bat $HOME/gdal_vce2008/gdal
+cp build_vce2008.sh $HOME/gdal_vce2008/gdal
+cp clean_vce2008.bat $HOME/gdal_vce2008/gdal
+cp clean_vce2008.sh $HOME/gdal_vce2008/gdal
+cp nmake_vce2008.local $HOME/gdal_vce2008/gdal/nmake.local
+
+cd ~/.wine/drive_c/gdal/gdal
+
+# Makefile patches to workaround Wine issues
+patch -p0 < /tmp/build_vce2008.patch
+
+echo ""
+echo "Installation finished !"
+echo ""
+echo "You can now run :"
+echo "cd $HOME/gdal_vce2008/gdal"
+echo "./build_vce2008.sh"
diff --git a/swig/csharp/apps/OGRLayerAlg.cs b/swig/csharp/apps/OGRLayerAlg.cs
new file mode 100644
index 0000000..6b06d02
--- /dev/null
+++ b/swig/csharp/apps/OGRLayerAlg.cs
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * $Id: OGRLayerAlg.cs 27014 2014-03-06 20:06:32Z tamas $
+ *
+ * Name:     OGRLayerAlg.cs
+ * Project:  GDAL CSharp Interface
+ * Purpose:  A sample app to demonstrate the usage of the RFC-39 functions.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+using System;
+
+using OSGeo.OGR;
+
+
+/**
+
+ * <p>Title: OGR C# OGRLayerAlg example.</p>
+ * <p>Description: A sample app to demonstrate the usage of the RFC-39 functions.</p>
+ * @author Tamas Szekeres (szekerest at gmail.com)
+ * @version 1.0
+ */
+
+
+
+/// <summary>
+/// A sample app to demonstrate the usage of the RFC-39 functions.
+/// </summary> 
+
+class OGRLayerAlg {
+	
+	public static void usage() 
+
+	{
+        Console.WriteLine("usage: ogrlayeralg {function} {Data Source 1} {layer1} {Data Source 2} {layer2} {Result Data Source Name} {Result Layer Name} [{Options}]");
+        Console.WriteLine("example: ogrlayeralg Union data1.shp layer1 data.shp layer2 result.shp resultlayer SKIP_FAILURES=YES");
+		System.Environment.Exit(-1);
+	}
+ 
+    public static void Main(string[] args) 
+    {
+        if (args.Length <= 6) usage();
+        
+        Console.WriteLine("");
+
+        try 
+        {
+            /* -------------------------------------------------------------------- */
+            /*      Register driver(s).                                             */
+            /* -------------------------------------------------------------------- */
+            Ogr.RegisterAll();
+
+            /* -------------------------------------------------------------------- */
+            /*      Open data source.                                              */
+            /* -------------------------------------------------------------------- */
+            DataSource ds1 = Ogr.Open(args[1], 0);
+
+            if (ds1 == null)
+            {
+                Console.WriteLine("Can't open " + args[1]);
+                System.Environment.Exit(-1);
+            }
+
+            Layer layer1 = ds1.GetLayerByName(args[2]);
+
+            if (layer1 == null)
+            {
+                Console.WriteLine("FAILURE: Couldn't fetch layer " + args[2]);
+                System.Environment.Exit(-1);
+            }
+
+            DataSource ds2 = Ogr.Open(args[3], 0);
+
+            if (ds2 == null)
+            {
+                Console.WriteLine("Can't open " + args[3]);
+                System.Environment.Exit(-1);
+            }
+
+            Layer layer2 = ds2.GetLayerByName(args[4]);
+
+            if (layer2 == null)
+            {
+                Console.WriteLine("FAILURE: Couldn't fetch layer " + args[4]);
+                System.Environment.Exit(-1);
+            }
+
+            /* -------------------------------------------------------------------- */
+		    /*      Get driver for creating the result ds                          */
+		    /* -------------------------------------------------------------------- */	
+            Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
+
+		    if (drv == null) 
+		    {
+			    Console.WriteLine("Can't get driver.");
+                System.Environment.Exit(-1);
+		    }
+
+            /* -------------------------------------------------------------------- */
+		    /*      Creating the datasource                                         */
+		    /* -------------------------------------------------------------------- */	
+
+            DataSource ds = drv.CreateDataSource( args[5], new string[] {} );
+            if (drv == null) 
+            {
+                Console.WriteLine("Can't create the datasource.");
+                System.Environment.Exit(-1);
+            }
+
+            /* -------------------------------------------------------------------- */
+            /*      Process options                                                 */
+            /* -------------------------------------------------------------------- */
+
+            string[] options = null;
+            if (args.Length > 7)
+            {
+                options = new string[args.Length - 7];
+                Array.Copy(args, 7, options, 0, args.Length - 7);
+            }
+
+            /* -------------------------------------------------------------------- */
+            /*      Creating the layer                                              */
+            /* -------------------------------------------------------------------- */
+
+            Layer layer;
+        
+            int i;
+            for(i=0;i<ds.GetLayerCount();i++)
+            {
+                layer = ds.GetLayerByIndex( i );
+                if( layer != null && layer.GetLayerDefn().GetName() == args[6])
+                {
+                    Console.WriteLine("Layer already existed. Recreating it.\n");
+                    ds.DeleteLayer(i);
+                    break;
+                }
+            }
+
+            layer = ds.CreateLayer(args[6], null, layer1.GetLayerDefn().GetGeomType(), new string[] { });
+            if( layer == null )
+            {
+                Console.WriteLine("Layer creation failed.");
+                System.Environment.Exit(-1);
+            }
+
+            switch(args[0])
+            {
+                case "Intersection":
+                    layer1.Intersection(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Intersection");
+                    break;
+                case "Union":
+                    layer1.Union(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Union");
+                    break;
+                case "SymDifference":
+                    layer1.SymDifference(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "SymDifference");
+                    break;
+                case "Identity":
+                    layer1.Identity(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Identity");
+                    break;
+                case "Update":
+                    layer1.Update(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Update");
+                    break;
+                case "Clip":
+                    layer1.Clip(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Clip");
+                    break;
+                case "Erase":
+                    layer1.Erase(layer2, layer, options, new Ogr.GDALProgressFuncDelegate(ProgressFunc), "Erase");
+                    break;
+            }
+        }
+        catch (Exception e) 
+        {
+            Console.WriteLine("Application error: " + e.Message);
+        }
+    }
+
+	public static int ProgressFunc(double Complete, IntPtr Message, IntPtr Data)
+	{
+		Console.Write("Processing ... " + Complete * 100 + "% Completed.");
+		if (Message != IntPtr.Zero)
+			Console.Write(" Message:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Message));
+		if (Data != IntPtr.Zero)
+			Console.Write(" Data:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Data));
+	
+		Console.WriteLine("");
+		return 1;
+	}
+}
\ No newline at end of file
diff --git a/swig/csharp/apps/createdata.cs b/swig/csharp/apps/createdata.cs
index 0792d37..ca1aea7 100644
--- a/swig/csharp/apps/createdata.cs
+++ b/swig/csharp/apps/createdata.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: createdata.cs 19757 2010-05-22 18:37:08Z rouault $
+ * $Id: createdata.cs 27044 2014-03-16 23:41:27Z rouault $
  *
  * Name:     createdata.cs
  * Project:  GDAL CSharp Interface
@@ -8,6 +8,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2007, Tamas Szekeres
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
diff --git a/swig/csharp/const/GdalConst.cs b/swig/csharp/const/GdalConst.cs
index 3cee295..b64b7e4 100644
--- a/swig/csharp/const/GdalConst.cs
+++ b/swig/csharp/const/GdalConst.cs
@@ -122,6 +122,9 @@ public class GdalConst {
   public static readonly int GARIO_UPDATE = GdalConstPINVOKE.GARIO_UPDATE_get();
   public static readonly int GARIO_ERROR = GdalConstPINVOKE.GARIO_ERROR_get();
   public static readonly int GARIO_COMPLETE = GdalConstPINVOKE.GARIO_COMPLETE_get();
+  public static readonly int GTO_TIP = GdalConstPINVOKE.GTO_TIP_get();
+  public static readonly int GTO_BIT = GdalConstPINVOKE.GTO_BIT_get();
+  public static readonly int GTO_BSQ = GdalConstPINVOKE.GTO_BSQ_get();
 }
 
 }
diff --git a/swig/csharp/const/GdalConstPINVOKE.cs b/swig/csharp/const/GdalConstPINVOKE.cs
index 246b07d..58562b5 100644
--- a/swig/csharp/const/GdalConstPINVOKE.cs
+++ b/swig/csharp/const/GdalConstPINVOKE.cs
@@ -518,6 +518,15 @@ class GdalConstPINVOKE {
 
   [DllImport("gdalconst_wrap", EntryPoint="CSharp_GARIO_COMPLETE_get")]
   public static extern int GARIO_COMPLETE_get();
+
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GTO_TIP_get")]
+  public static extern int GTO_TIP_get();
+
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GTO_BIT_get")]
+  public static extern int GTO_BIT_get();
+
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GTO_BSQ_get")]
+  public static extern int GTO_BSQ_get();
 }
 
 }
diff --git a/swig/csharp/const/gdalconst_wrap.c b/swig/csharp/const/gdalconst_wrap.c
index 2095750..5b87bab 100644
--- a/swig/csharp/const/gdalconst_wrap.c
+++ b/swig/csharp/const/gdalconst_wrap.c
@@ -1366,6 +1366,36 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GARIO_COMPLETE_get() {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_GTO_TIP_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(GTO_TIP);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_GTO_BIT_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(GTO_BIT);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_GTO_BSQ_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(GTO_BSQ);
+  jresult = result; 
+  return jresult;
+}
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/swig/csharp/gdal/Band.cs b/swig/csharp/gdal/Band.cs
index 051f67d..1a9f508 100644
--- a/swig/csharp/gdal/Band.cs
+++ b/swig/csharp/gdal/Band.cs
@@ -58,7 +58,7 @@ public class Band : MajorObject {
       base.Dispose();
     }
   }
-/*! Eight bit unsigned integer */ /*@SWIG:../include/csharp/gdal_csharp.i,55,%rasterio_functions@*/
+/*! Eight bit unsigned integer */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
@@ -83,7 +83,7 @@ public class Band : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,55,%rasterio_functions@*/
+/*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
@@ -108,7 +108,7 @@ public class Band : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,55,%rasterio_functions@*/
+/*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
@@ -133,7 +133,7 @@ public class Band : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,55,%rasterio_functions@*/
+/*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
@@ -158,7 +158,7 @@ public class Band : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,55,%rasterio_functions@*/
+/*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
@@ -446,14 +446,14 @@ public class Band : MajorObject {
     return ret;
   }
 
-  public CPLErr GetDefaultHistogram(SWIGTYPE_p_double min_ret, SWIGTYPE_p_double max_ret, SWIGTYPE_p_int buckets_ret, SWIGTYPE_p_p_int ppanHistogram, int force, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
-    CPLErr ret = (CPLErr)GdalPINVOKE.Band_GetDefaultHistogram(swigCPtr, SWIGTYPE_p_double.getCPtr(min_ret), SWIGTYPE_p_double.getCPtr(max_ret), SWIGTYPE_p_int.getCPtr(buckets_ret), SWIGTYPE_p_p_int.getCPtr(ppanHistogram), force, callback, callback_data);
+  public CPLErr GetDefaultHistogram(out double min_ret, out double max_ret, out int buckets_ret, out int[] ppanHistogram, int force, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    CPLErr ret = (CPLErr)GdalPINVOKE.Band_GetDefaultHistogram(swigCPtr, out min_ret, out max_ret, out buckets_ret, out ppanHistogram, force, callback, callback_data);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public CPLErr SetDefaultHistogram(double min, double max, int buckets_in, SWIGTYPE_p_int panHistogram_in) {
-    CPLErr ret = (CPLErr)GdalPINVOKE.Band_SetDefaultHistogram(swigCPtr, min, max, buckets_in, SWIGTYPE_p_int.getCPtr(panHistogram_in));
+  public CPLErr SetDefaultHistogram(double min, double max, int buckets_in, int[] panHistogram_in) {
+    CPLErr ret = (CPLErr)GdalPINVOKE.Band_SetDefaultHistogram(swigCPtr, min, max, buckets_in, panHistogram_in);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
diff --git a/swig/csharp/gdal/Dataset.cs b/swig/csharp/gdal/Dataset.cs
index 79fecfc..9ef3849 100644
--- a/swig/csharp/gdal/Dataset.cs
+++ b/swig/csharp/gdal/Dataset.cs
@@ -62,7 +62,7 @@ public class Dataset : MajorObject {
       base.Dispose();
     }
   }
-/*! Eight bit unsigned integer */ /*@SWIG:../include/csharp/gdal_csharp.i,96,%ds_rasterio_functions@*/
+/*! Eight bit unsigned integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, int buf_xSize, int buf_ySize, 
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
@@ -91,7 +91,7 @@ public class Dataset : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,96,%ds_rasterio_functions@*/
+/*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, int buf_xSize, int buf_ySize, 
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
@@ -120,7 +120,7 @@ public class Dataset : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,96,%ds_rasterio_functions@*/
+/*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, int buf_xSize, int buf_ySize, 
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
@@ -149,7 +149,7 @@ public class Dataset : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,96,%ds_rasterio_functions@*/
+/*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, int buf_xSize, int buf_ySize, 
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
@@ -178,7 +178,7 @@ public class Dataset : MajorObject {
   }
   
 /*@SWIG@*/
-/*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,96,%ds_rasterio_functions@*/
+/*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, int buf_xSize, int buf_ySize, 
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
diff --git a/swig/csharp/gdal/Driver.cs b/swig/csharp/gdal/Driver.cs
index 8785d34..900db9c 100644
--- a/swig/csharp/gdal/Driver.cs
+++ b/swig/csharp/gdal/Driver.cs
@@ -84,21 +84,21 @@ public class Driver : MajorObject {
   }
 
   public Dataset Create(string utf8_path, int xsize, int ysize, int bands, DataType eType, string[] options) {
-    IntPtr cPtr = GdalPINVOKE.Driver_Create(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), xsize, ysize, bands, (int)eType, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null);
+    IntPtr cPtr = GdalPINVOKE.Driver_Create(swigCPtr, Gdal.StringToUtf8Bytes(utf8_path), xsize, ysize, bands, (int)eType, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null);
     Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public Dataset CreateCopy(string utf8_path, Dataset src, int strict, string[] options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
-    IntPtr cPtr = GdalPINVOKE.Driver_CreateCopy(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), Dataset.getCPtr(src), strict, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
+    IntPtr cPtr = GdalPINVOKE.Driver_CreateCopy(swigCPtr, Gdal.StringToUtf8Bytes(utf8_path), Dataset.getCPtr(src), strict, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public int Delete(string utf8_path) {
-    int ret = GdalPINVOKE.Driver_Delete(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    int ret = GdalPINVOKE.Driver_Delete(swigCPtr, Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 2fb96a0..d72b11d 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -30,6 +30,29 @@ public class Gdal {
     GdalPINVOKE.DontUseExceptions();
   }
 
+
+  internal static byte[] StringToUtf8Bytes(string str)
+  {
+    if (str == null)
+      return null;
+    
+    int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
+    byte[] bytes = new byte[bytecount + 1];
+    System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
+    return bytes;
+  }
+  
+  internal static string Utf8BytesToString(IntPtr pNativeData)
+  {
+    if (pNativeData == IntPtr.Zero)
+        return null;
+        
+    int length = Marshal.PtrToStringAnsi(pNativeData).Length;
+    byte[] strbuf = new byte[length];  
+    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    return System.Text.Encoding.UTF8.GetString(strbuf);
+  }
+
   internal static void StringListDestroy(IntPtr buffer_ptr) {
     GdalPINVOKE.StringListDestroy(buffer_ptr);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -149,7 +172,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   }
 
   public static void PushFinderLocation(string utf8_path) {
-    GdalPINVOKE.PushFinderLocation(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    GdalPINVOKE.PushFinderLocation(Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
@@ -164,14 +187,14 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   }
 
   public static string FindFile(string pszClass, string utf8_path) {
-    string ret = GdalPINVOKE.FindFile(pszClass, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    string ret = GdalPINVOKE.FindFile(pszClass, Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public static string[] ReadDir(string utf8_path) {
         /* %typemap(csout) char** CSL */
-        IntPtr cPtr = GdalPINVOKE.ReadDir(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+        IntPtr cPtr = GdalPINVOKE.ReadDir(Gdal.StringToUtf8Bytes(utf8_path));
         IntPtr objPtr;
         int count = 0;
         if (cPtr != IntPtr.Zero) {
@@ -194,7 +217,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
 
   public static string[] ReadDirRecursive(string utf8_path) {
         /* %typemap(csout) char** CSL */
-        IntPtr cPtr = GdalPINVOKE.ReadDirRecursive(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+        IntPtr cPtr = GdalPINVOKE.ReadDirRecursive(Gdal.StringToUtf8Bytes(utf8_path));
         IntPtr objPtr;
         int count = 0;
         if (cPtr != IntPtr.Zero) {
@@ -239,12 +262,12 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
 }
 
   public static void FileFromMemBuffer(string utf8_path, int nBytes, IntPtr pabyData) {
-    GdalPINVOKE.FileFromMemBuffer(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), nBytes, pabyData);
+    GdalPINVOKE.FileFromMemBuffer(Gdal.StringToUtf8Bytes(utf8_path), nBytes, pabyData);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
   public static int Unlink(string utf8_path) {
-    int ret = GdalPINVOKE.Unlink(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    int ret = GdalPINVOKE.Unlink(Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -256,13 +279,13 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   }
 
   public static int Mkdir(string utf8_path, int mode) {
-    int ret = GdalPINVOKE.Mkdir(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), mode);
+    int ret = GdalPINVOKE.Mkdir(Gdal.StringToUtf8Bytes(utf8_path), mode);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public static int Rmdir(string utf8_path) {
-    int ret = GdalPINVOKE.Rmdir(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    int ret = GdalPINVOKE.Rmdir(Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -273,38 +296,37 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static SWIGTYPE_p_void VSIFOpenL(string utf8_path, string pszMode) {
-    IntPtr cPtr = GdalPINVOKE.VSIFOpenL(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), pszMode);
-    SWIGTYPE_p_void ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_void(cPtr, false, ThisOwn_false());
+  public static IntPtr VSIFOpenL(string utf8_path, string pszMode) {
+      IntPtr ret = GdalPINVOKE.VSIFOpenL(Gdal.StringToUtf8Bytes(utf8_path), pszMode);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
-    return ret;
-  }
+      return ret;
+}
 
-  public static void VSIFCloseL(SWIGTYPE_p_void arg0) {
-    GdalPINVOKE.VSIFCloseL(SWIGTYPE_p_void.getCPtr(arg0));
+  public static void VSIFCloseL(IntPtr arg0) {
+    GdalPINVOKE.VSIFCloseL(arg0);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
-  public static int VSIFSeekL(SWIGTYPE_p_void arg0, int arg1, int arg2) {
-    int ret = GdalPINVOKE.VSIFSeekL(SWIGTYPE_p_void.getCPtr(arg0), arg1, arg2);
+  public static int VSIFSeekL(IntPtr arg0, int arg1, int arg2) {
+    int ret = GdalPINVOKE.VSIFSeekL(arg0, arg1, arg2);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFTellL(SWIGTYPE_p_void arg0) {
-    int ret = GdalPINVOKE.VSIFTellL(SWIGTYPE_p_void.getCPtr(arg0));
+  public static int VSIFTellL(IntPtr arg0) {
+    int ret = GdalPINVOKE.VSIFTellL(arg0);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFTruncateL(SWIGTYPE_p_void arg0, int arg1) {
-    int ret = GdalPINVOKE.VSIFTruncateL(SWIGTYPE_p_void.getCPtr(arg0), arg1);
+  public static int VSIFTruncateL(IntPtr arg0, int arg1) {
+    int ret = GdalPINVOKE.VSIFTruncateL(arg0, arg1);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFWriteL(string arg0, int arg1, int arg2, SWIGTYPE_p_void arg3) {
-    int ret = GdalPINVOKE.VSIFWriteL(arg0, arg1, arg2, SWIGTYPE_p_void.getCPtr(arg3));
+  public static int VSIFWriteL(string arg0, int arg1, int arg2, IntPtr arg3) {
+    int ret = GdalPINVOKE.VSIFWriteL(arg0, arg1, arg2, arg3);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -493,8 +515,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static int RasterizeLayer(Dataset dataset, int bands, SWIGTYPE_p_int band_list, OSGeo.OGR.Layer layer, SWIGTYPE_p_void pfnTransformer, SWIGTYPE_p_void pTransformArg, int burn_values, SWIGTYPE_p_double burn_values_list, string[] options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
-    int ret = GdalPINVOKE.RasterizeLayer(Dataset.getCPtr(dataset), bands, SWIGTYPE_p_int.getCPtr(band_list), OSGeo.OGR.Layer.getCPtr(layer), SWIGTYPE_p_void.getCPtr(pfnTransformer), SWIGTYPE_p_void.getCPtr(pTransformArg), burn_values, SWIGTYPE_p_double.getCPtr(burn_values_list), (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
+  public static int RasterizeLayer(Dataset dataset, int bands, int[] band_list, OSGeo.OGR.Layer layer, IntPtr pfnTransformer, IntPtr pTransformArg, int burn_values, double[] burn_values_list, string[] options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.RasterizeLayer(Dataset.getCPtr(dataset), bands, band_list, OSGeo.OGR.Layer.getCPtr(layer), pfnTransformer, pTransformArg, burn_values, burn_values_list, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -529,8 +551,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static int ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, SWIGTYPE_p_double fixedLevels, int useNoData, double noDataValue, OSGeo.OGR.Layer dstLayer, int idField, int elevField, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
-    int ret = GdalPINVOKE.ContourGenerate(Band.getCPtr(srcBand), contourInterval, contourBase, fixedLevelCount, SWIGTYPE_p_double.getCPtr(fixedLevels), useNoData, noDataValue, OSGeo.OGR.Layer.getCPtr(dstLayer), idField, elevField, callback, callback_data);
+  public static int ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, double[] fixedLevels, int useNoData, double noDataValue, OSGeo.OGR.Layer dstLayer, int idField, int elevField, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.ContourGenerate(Band.getCPtr(srcBand), contourInterval, contourBase, fixedLevelCount, fixedLevels, useNoData, noDataValue, OSGeo.OGR.Layer.getCPtr(dstLayer), idField, elevField, callback, callback_data);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -674,21 +696,21 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   }
 
   public static Dataset Open(string utf8_path, Access eAccess) {
-    IntPtr cPtr = GdalPINVOKE.Open(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), (int)eAccess);
+    IntPtr cPtr = GdalPINVOKE.Open(Gdal.StringToUtf8Bytes(utf8_path), (int)eAccess);
     Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public static Dataset OpenShared(string utf8_path, Access eAccess) {
-    IntPtr cPtr = GdalPINVOKE.OpenShared(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), (int)eAccess);
+    IntPtr cPtr = GdalPINVOKE.OpenShared(Gdal.StringToUtf8Bytes(utf8_path), (int)eAccess);
     Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public static Driver IdentifyDriver(string utf8_path, string[] papszSiblings) {
-    IntPtr cPtr = GdalPINVOKE.IdentifyDriver(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), (papszSiblings != null)? new GdalPINVOKE.StringListMarshal(papszSiblings)._ar : null);
+    IntPtr cPtr = GdalPINVOKE.IdentifyDriver(Gdal.StringToUtf8Bytes(utf8_path), (papszSiblings != null)? new GdalPINVOKE.StringListMarshal(papszSiblings)._ar : null);
     Driver ret = (cPtr == IntPtr.Zero) ? null : new Driver(cPtr, false, ThisOwn_false());
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 2b6faa5..362b210 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -263,7 +263,7 @@ class GdalPINVOKE {
   public static extern string GetLastErrorMsg();
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_PushFinderLocation")]
-  public static extern void PushFinderLocation(string jarg1);
+  public static extern void PushFinderLocation(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_PopFinderLocation")]
   public static extern void PopFinderLocation();
@@ -272,13 +272,13 @@ class GdalPINVOKE {
   public static extern void FinderClean();
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_FindFile")]
-  public static extern string FindFile(string jarg1, string jarg2);
+  public static extern string FindFile(string jarg1, byte[] jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ReadDir")]
-  public static extern IntPtr ReadDir(string jarg1);
+  public static extern IntPtr ReadDir(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ReadDirRecursive")]
-  public static extern IntPtr ReadDirRecursive(string jarg1);
+  public static extern IntPtr ReadDirRecursive(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_SetConfigOption")]
   public static extern void SetConfigOption(string jarg1, string jarg2);
@@ -293,40 +293,40 @@ class GdalPINVOKE {
   public static extern IntPtr CPLHexToBinary(string jarg1, out int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_FileFromMemBuffer")]
-  public static extern void FileFromMemBuffer(string jarg1, int jarg2, IntPtr jarg3);
+  public static extern void FileFromMemBuffer(byte[] jarg1, int jarg2, IntPtr jarg3);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Unlink")]
-  public static extern int Unlink(string jarg1);
+  public static extern int Unlink(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_HasThreadSupport")]
   public static extern int HasThreadSupport();
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Mkdir")]
-  public static extern int Mkdir(string jarg1, int jarg2);
+  public static extern int Mkdir(byte[] jarg1, int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Rmdir")]
-  public static extern int Rmdir(string jarg1);
+  public static extern int Rmdir(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Rename")]
   public static extern int Rename(string jarg1, string jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFOpenL")]
-  public static extern IntPtr VSIFOpenL(string jarg1, string jarg2);
+  public static extern IntPtr VSIFOpenL(byte[] jarg1, string jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFCloseL")]
-  public static extern void VSIFCloseL(HandleRef jarg1);
+  public static extern void VSIFCloseL(IntPtr jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFSeekL")]
-  public static extern int VSIFSeekL(HandleRef jarg1, int jarg2, int jarg3);
+  public static extern int VSIFSeekL(IntPtr jarg1, int jarg2, int jarg3);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFTellL")]
-  public static extern int VSIFTellL(HandleRef jarg1);
+  public static extern int VSIFTellL(IntPtr jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFTruncateL")]
-  public static extern int VSIFTruncateL(HandleRef jarg1, int jarg2);
+  public static extern int VSIFTruncateL(IntPtr jarg1, int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFWriteL")]
-  public static extern int VSIFWriteL(string jarg1, int jarg2, int jarg3, HandleRef jarg4);
+  public static extern int VSIFWriteL(string jarg1, int jarg2, int jarg3, IntPtr jarg4);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_XMLNode_Type_get")]
   public static extern int XMLNode_Type_get(HandleRef jarg1);
@@ -394,6 +394,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_MajorObject_SetDescription")]
   public static extern void MajorObject_SetDescription(HandleRef jarg1, string jarg2);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_MajorObject_GetMetadataDomainList")]
+  public static extern IntPtr MajorObject_GetMetadataDomainList(HandleRef jarg1);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_MajorObject_GetMetadata")]
   public static extern IntPtr MajorObject_GetMetadata(HandleRef jarg1, string jarg2);
 
@@ -419,13 +422,13 @@ class GdalPINVOKE {
   public static extern string Driver_HelpTopic_get(HandleRef jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Driver_Create")]
-  public static extern IntPtr Driver_Create(HandleRef jarg1, string jarg2, int jarg3, int jarg4, int jarg5, int jarg6, IntPtr[] jarg7);
+  public static extern IntPtr Driver_Create(HandleRef jarg1, byte[] jarg2, int jarg3, int jarg4, int jarg5, int jarg6, IntPtr[] jarg7);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Driver_CreateCopy")]
-  public static extern IntPtr Driver_CreateCopy(HandleRef jarg1, string jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
+  public static extern IntPtr Driver_CreateCopy(HandleRef jarg1, byte[] jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Driver_Delete")]
-  public static extern int Driver_Delete(HandleRef jarg1, string jarg2);
+  public static extern int Driver_Delete(HandleRef jarg1, byte[] jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Driver_Rename")]
   public static extern int Driver_Rename(HandleRef jarg1, string jarg2, string jarg3);
@@ -818,10 +821,10 @@ class GdalPINVOKE {
   public static extern int Band_GetHistogram(HandleRef jarg1, double jarg2, double jarg3, int jarg4, int[] jarg5, int jarg6, int jarg7, Gdal.GDALProgressFuncDelegate jarg8, string jarg9);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_GetDefaultHistogram")]
-  public static extern int Band_GetDefaultHistogram(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, HandleRef jarg5, int jarg6, Gdal.GDALProgressFuncDelegate jarg7, string jarg8);
+  public static extern int Band_GetDefaultHistogram(HandleRef jarg1, out double jarg2, out double jarg3, out int jarg4, out int[] jarg5, int jarg6, Gdal.GDALProgressFuncDelegate jarg7, string jarg8);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_SetDefaultHistogram")]
-  public static extern int Band_SetDefaultHistogram(HandleRef jarg1, double jarg2, double jarg3, int jarg4, HandleRef jarg5);
+  public static extern int Band_SetDefaultHistogram(HandleRef jarg1, double jarg2, double jarg3, int jarg4, int[] jarg5);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_HasArbitraryOverviews")]
   public static extern bool Band_HasArbitraryOverviews(HandleRef jarg1);
@@ -925,6 +928,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_RasterAttributeTable_GetRowOfValue")]
   public static extern int RasterAttributeTable_GetRowOfValue(HandleRef jarg1, double jarg2);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_RasterAttributeTable_ChangesAreWrittenToFile")]
+  public static extern int RasterAttributeTable_ChangesAreWrittenToFile(HandleRef jarg1);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_ComputeMedianCutPCT")]
   public static extern int ComputeMedianCutPCT(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, int jarg4, HandleRef jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
 
@@ -938,7 +944,7 @@ class GdalPINVOKE {
   public static extern int ComputeProximity(HandleRef jarg1, HandleRef jarg2, IntPtr[] jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_RasterizeLayer")]
-  public static extern int RasterizeLayer(HandleRef jarg1, int jarg2, HandleRef jarg3, HandleRef jarg4, HandleRef jarg5, HandleRef jarg6, int jarg7, HandleRef jarg8, IntPtr[] jarg9, Gdal.GDALProgressFuncDelegate jarg10, string jarg11);
+  public static extern int RasterizeLayer(HandleRef jarg1, int jarg2, int[] jarg3, HandleRef jarg4, IntPtr jarg5, IntPtr jarg6, int jarg7, double[] jarg8, IntPtr[] jarg9, Gdal.GDALProgressFuncDelegate jarg10, string jarg11);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Polygonize")]
   public static extern int Polygonize(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
@@ -956,7 +962,7 @@ class GdalPINVOKE {
   public static extern int RegenerateOverview(HandleRef jarg1, HandleRef jarg2, string jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ContourGenerate")]
-  public static extern int ContourGenerate(HandleRef jarg1, double jarg2, double jarg3, int jarg4, HandleRef jarg5, int jarg6, double jarg7, HandleRef jarg8, int jarg9, int jarg10, Gdal.GDALProgressFuncDelegate jarg11, string jarg12);
+  public static extern int ContourGenerate(HandleRef jarg1, double jarg2, double jarg3, int jarg4, double[] jarg5, int jarg6, double jarg7, HandleRef jarg8, int jarg9, int jarg10, Gdal.GDALProgressFuncDelegate jarg11, string jarg12);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_AutoCreateWarpedVRT")]
   public static extern IntPtr AutoCreateWarpedVRT(HandleRef jarg1, string jarg2, string jarg3, int jarg4, double jarg5);
@@ -1046,13 +1052,13 @@ class GdalPINVOKE {
   public static extern IntPtr GetDriver(int jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Open")]
-  public static extern IntPtr Open(string jarg1, int jarg2);
+  public static extern IntPtr Open(byte[] jarg1, int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_OpenShared")]
-  public static extern IntPtr OpenShared(string jarg1, int jarg2);
+  public static extern IntPtr OpenShared(byte[] jarg1, int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_IdentifyDriver")]
-  public static extern IntPtr IdentifyDriver(string jarg1, IntPtr[] jarg2);
+  public static extern IntPtr IdentifyDriver(byte[] jarg1, IntPtr[] jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_GeneralCmdLineProcessor")]
   public static extern IntPtr GeneralCmdLineProcessor(IntPtr[] jarg1, int jarg2);
diff --git a/swig/csharp/gdal/MajorObject.cs b/swig/csharp/gdal/MajorObject.cs
index d4266e3..c9ae66a 100644
--- a/swig/csharp/gdal/MajorObject.cs
+++ b/swig/csharp/gdal/MajorObject.cs
@@ -75,6 +75,29 @@ public class MajorObject : IDisposable {
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public string[] GetMetadataDomainList() {
+        /* %typemap(csout) char** CSL */
+        IntPtr cPtr = GdalPINVOKE.MajorObject_GetMetadataDomainList(swigCPtr);
+        IntPtr objPtr;
+        int count = 0;
+        if (cPtr != IntPtr.Zero) {
+            while (Marshal.ReadIntPtr(cPtr, count*IntPtr.Size) != IntPtr.Zero)
+                ++count;
+        }
+        string[] ret = new string[count];
+        if (count > 0) {       
+	        for(int cx = 0; cx < count; cx++) {
+                objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
+                ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
+            }
+        }
+        if (cPtr != IntPtr.Zero)
+            GdalPINVOKE.StringListDestroy(cPtr);
+        
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+        return ret;
+}
+
   public string[] GetMetadata(string pszDomain) {
         /* %typemap(csout) char**options */
         IntPtr cPtr = GdalPINVOKE.MajorObject_GetMetadata(swigCPtr, pszDomain);
diff --git a/swig/csharp/gdal/RasterAttributeTable.cs b/swig/csharp/gdal/RasterAttributeTable.cs
index 1cf1602..42986f6 100644
--- a/swig/csharp/gdal/RasterAttributeTable.cs
+++ b/swig/csharp/gdal/RasterAttributeTable.cs
@@ -177,6 +177,12 @@ public class RasterAttributeTable : IDisposable {
     return ret;
   }
 
+  public int ChangesAreWrittenToFile() {
+    int ret = GdalPINVOKE.RasterAttributeTable_ChangesAreWrittenToFile(swigCPtr);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
 }
 
 }
diff --git a/swig/csharp/gdal/SWIGTYPE_p_double.cs b/swig/csharp/gdal/SWIGTYPE_p_double.cs
deleted file mode 100644
index a45eab1..0000000
--- a/swig/csharp/gdal/SWIGTYPE_p_double.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.GDAL {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_double {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_double(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_double() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_double obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/gdal/SWIGTYPE_p_int.cs b/swig/csharp/gdal/SWIGTYPE_p_int.cs
deleted file mode 100644
index 49bd600..0000000
--- a/swig/csharp/gdal/SWIGTYPE_p_int.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.GDAL {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_int {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_int(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_int() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_int obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/gdal/SWIGTYPE_p_p_int.cs b/swig/csharp/gdal/SWIGTYPE_p_p_int.cs
deleted file mode 100644
index c72a938..0000000
--- a/swig/csharp/gdal/SWIGTYPE_p_p_int.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.GDAL {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_p_int {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_p_int(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_p_int() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_p_int obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/gdal/SWIGTYPE_p_void.cs b/swig/csharp/gdal/SWIGTYPE_p_void.cs
deleted file mode 100644
index 6277f1e..0000000
--- a/swig/csharp/gdal/SWIGTYPE_p_void.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.GDAL {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_void {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_void(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_void() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_void obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index 9525d02..10d24cc 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -297,6 +297,45 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterStringCallback_Gdal(SWIG_CSharpStringHel
 
 
 
+SWIGINTERN void SWIG_CSharpException(int code, const char *msg) {
+  if (code == SWIG_ValueError) {
+    SWIG_CSharpExceptionArgumentCodes exception_code = SWIG_CSharpArgumentOutOfRangeException;
+    SWIG_CSharpSetPendingExceptionArgument(exception_code, msg, 0);
+  } else {
+    SWIG_CSharpExceptionCodes exception_code = SWIG_CSharpApplicationException;
+    switch(code) {
+    case SWIG_MemoryError:
+      exception_code = SWIG_CSharpOutOfMemoryException;
+      break;
+    case SWIG_IndexError:
+      exception_code = SWIG_CSharpIndexOutOfRangeException;
+      break;
+    case SWIG_DivisionByZero:
+      exception_code = SWIG_CSharpDivideByZeroException;
+      break;
+    case SWIG_IOError:
+      exception_code = SWIG_CSharpIOException;
+      break;
+    case SWIG_OverflowError:
+      exception_code = SWIG_CSharpOverflowException;
+      break;
+    case SWIG_RuntimeError:
+    case SWIG_TypeError:
+    case SWIG_SyntaxError:
+    case SWIG_SystemError:
+    case SWIG_UnknownError:
+    default:
+      exception_code = SWIG_CSharpApplicationException;
+      break;
+    }
+    SWIG_CSharpSetPendingException(exception_code, msg);
+  }
+}
+
+
+#include <stdexcept>
+
+
 #include <iostream>
 using namespace std;
 
@@ -343,45 +382,6 @@ void DontUseExceptions() {
 }
 
 
-SWIGINTERN void SWIG_CSharpException(int code, const char *msg) {
-  if (code == SWIG_ValueError) {
-    SWIG_CSharpExceptionArgumentCodes exception_code = SWIG_CSharpArgumentOutOfRangeException;
-    SWIG_CSharpSetPendingExceptionArgument(exception_code, msg, 0);
-  } else {
-    SWIG_CSharpExceptionCodes exception_code = SWIG_CSharpApplicationException;
-    switch(code) {
-    case SWIG_MemoryError:
-      exception_code = SWIG_CSharpOutOfMemoryException;
-      break;
-    case SWIG_IndexError:
-      exception_code = SWIG_CSharpIndexOutOfRangeException;
-      break;
-    case SWIG_DivisionByZero:
-      exception_code = SWIG_CSharpDivideByZeroException;
-      break;
-    case SWIG_IOError:
-      exception_code = SWIG_CSharpIOException;
-      break;
-    case SWIG_OverflowError:
-      exception_code = SWIG_CSharpOverflowException;
-      break;
-    case SWIG_RuntimeError:
-    case SWIG_TypeError:
-    case SWIG_SyntaxError:
-    case SWIG_SystemError:
-    case SWIG_UnknownError:
-    default:
-      exception_code = SWIG_CSharpApplicationException;
-      break;
-    }
-    SWIG_CSharpSetPendingException(exception_code, msg);
-  }
-}
-
-
-#include <stdexcept>
-
-
     void StringListDestroy(void *buffer_ptr) {
        CSLDestroy((char**)buffer_ptr);
     }
@@ -517,6 +517,9 @@ SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShado
 SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
     GDALSetDescription( self, pszNewDesc );
   }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
+    return GDALGetMetadataDomainList( self );
+  }
 SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_List(GDALMajorObjectShadow *self,char const *pszDomain=""){
     return GDALGetMetadata( self, pszDomain );
   }
@@ -809,11 +812,13 @@ static GDALAsyncReaderH AsyncReaderWrapperGetReader(GDALAsyncReaderWrapperH hWra
     return psWrapper->hAsyncReader;
 }
 
+#if defined(SWIGPYTHON)
 static void* AsyncReaderWrapperGetPyObject(GDALAsyncReaderWrapperH hWrapper)
 {
     GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
     return psWrapper->pyObject;
 }
+#endif
 
 static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 {
@@ -1275,6 +1280,9 @@ SWIGINTERN int GDALRasterAttributeTableShadow_SetLinearBinning(GDALRasterAttribu
 SWIGINTERN int GDALRasterAttributeTableShadow_GetRowOfValue(GDALRasterAttributeTableShadow *self,double dfValue){
         return GDALRATGetRowOfValue( self, dfValue );
     }
+SWIGINTERN int GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(GDALRasterAttributeTableShadow *self){
+        return GDALRATChangesAreWrittenToFile( self );
+    }
 
 #include "gdalgrid.h"
 
@@ -2163,6 +2171,13 @@ SWIGEXPORT void SWIGSTDCALL CSharp_PushFinderLocation(char * jarg1) {
   
   arg1 = (char *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     CPLPushFinderLocation((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2248,6 +2263,13 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FindFile(char * jarg1, char * jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (char *)CPLFindFile((char const *)arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2281,6 +2303,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_ReadDir(char * jarg1) {
   
   arg1 = (char *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (char **)VSIReadDir((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2314,6 +2343,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_ReadDirRecursive(char * jarg1) {
   
   arg1 = (char *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (char **)VSIReadDirRecursive((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2513,6 +2549,13 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FileFromMemBuffer(char * jarg1, int jarg2, vo
   arg2 = (int)jarg2; 
   arg3 = (GByte *)jarg3; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     wrapper_VSIFileFromMemBuffer((char const *)arg1,arg2,(GByte const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2544,6 +2587,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Unlink(char * jarg1) {
   
   arg1 = (char *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (int)VSIUnlink((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2610,6 +2660,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Mkdir(char * jarg1, int jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (int)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (int)VSIMkdir((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2643,6 +2700,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Rmdir(char * jarg1) {
   
   arg1 = (char *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (int)VSIRmdir((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2713,6 +2777,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_VSIFOpenL(char * jarg1, char * jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (VSILFILE *)VSIFOpenL((char const *)arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2734,7 +2805,7 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_VSIFOpenL(char * jarg1, char * jarg2) {
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
@@ -3595,6 +3666,39 @@ SWIGEXPORT void SWIGSTDCALL CSharp_MajorObject_SetDescription(void * jarg1, char
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_MajorObject_GetMetadataDomainList(void * jarg1) {
+  void * jresult ;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char **result = 0 ;
+  
+  arg1 = (GDALMajorObjectShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_MajorObject_GetMetadata(void * jarg1, char * jarg2) {
   void * jresult ;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
@@ -3912,6 +4016,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_Create(void * jarg1, char * jarg2, i
   arg6 = (GDALDataType)jarg6; 
   arg7 = (char **)jarg7; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (GDALDatasetShadow *)GDALDriverShadow_Create(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
     CPLErr eclass = CPLGetLastErrorType();
@@ -3957,6 +4068,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CreateCopy(void * jarg1, char * jarg
   arg6 = (GDALProgressFunc)jarg6; 
   arg7 = (void *)jarg7; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     if (!arg3) {
       {
         SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
@@ -3999,6 +4117,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Driver_Delete(void * jarg1, char * jarg2) {
   arg1 = (GDALDriverShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (int)GDALDriverShadow_Delete(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -8586,7 +8711,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Band_GetHistogram(void * jarg1, double jarg2,
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Band_GetDefaultHistogram(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, int jarg6, void * jarg7, void * jarg8) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Band_GetDefaultHistogram(void * jarg1, double * jarg2, double * jarg3, void * jarg4, void * jarg5, int jarg6, void * jarg7, void * jarg8) {
   int jresult ;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) NULL ;
@@ -8599,10 +8724,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Band_GetDefaultHistogram(void * jarg1, void *
   CPLErr result;
   
   arg1 = (GDALRasterBandShadow *)jarg1; 
-  arg2 = (double *)jarg2; 
-  arg3 = (double *)jarg3; 
-  arg4 = (int *)jarg4; 
-  arg5 = (int **)jarg5; 
+  {
+    /* %typemap(in) (double *val) */
+    arg2 = (double *)jarg2;
+  }
+  {
+    /* %typemap(in) (double *val) */
+    arg3 = (double *)jarg3;
+  }
+  {
+    /* %typemap(in) (int *hasval) */
+    arg4 = (int *)jarg4;
+  }
+  {
+    /* %typemap(in) (int **array_argout) */
+    arg5 = (int **)jarg5;
+  }
   arg6 = (int)jarg6; 
   arg7 = (GDALProgressFunc)jarg7; 
   arg8 = (void *)jarg8; 
@@ -8646,7 +8783,10 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Band_SetDefaultHistogram(void * jarg1, double
   arg2 = (double)jarg2; 
   arg3 = (double)jarg3; 
   arg4 = (int)jarg4; 
-  arg5 = (int *)jarg5; 
+  {
+    /* %typemap(in) (int inout[ANY]) */
+    arg5 = (int *)jarg5;
+  }
   {
     CPLErrorReset();
     result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5);
@@ -9888,6 +10028,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_RasterAttributeTable_GetRowOfValue(void * jarg
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_RasterAttributeTable_ChangesAreWrittenToFile(void * jarg1) {
+  int jresult ;
+  GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
+  int result;
+  
+  arg1 = (GDALRasterAttributeTableShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_ComputeMedianCutPCT(void * jarg1, void * jarg2, void * jarg3, int jarg4, void * jarg5, void * jarg6, void * jarg7) {
   int jresult ;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -10176,12 +10349,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_RasterizeLayer(void * jarg1, int jarg2, void *
   
   arg1 = (GDALDatasetShadow *)jarg1; 
   arg2 = (int)jarg2; 
-  arg3 = (int *)jarg3; 
+  {
+    /* %typemap(in) (int inout[ANY]) */
+    arg3 = (int *)jarg3;
+  }
   arg4 = (OGRLayerShadow *)jarg4; 
   arg5 = (void *)jarg5; 
   arg6 = (void *)jarg6; 
   arg7 = (int)jarg7; 
-  arg8 = (double *)jarg8; 
+  {
+    /* %typemap(in) (double inout[ANY]) */
+    arg8 = (double *)jarg8;
+  }
   arg9 = (char **)jarg9; 
   arg10 = (GDALProgressFunc)jarg10; 
   arg11 = (void *)jarg11; 
@@ -10523,7 +10702,10 @@ SWIGEXPORT int SWIGSTDCALL CSharp_ContourGenerate(void * jarg1, double jarg2, do
   arg2 = (double)jarg2; 
   arg3 = (double)jarg3; 
   arg4 = (int)jarg4; 
-  arg5 = (double *)jarg5; 
+  {
+    /* %typemap(in) (double inout[ANY]) */
+    arg5 = (double *)jarg5;
+  }
   arg6 = (int)jarg6; 
   arg7 = (double)jarg7; 
   arg8 = (OGRLayerShadow *)jarg8; 
@@ -11649,6 +11831,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Open(char * jarg1, int jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (GDALAccess)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (GDALDatasetShadow *)Open((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -11684,6 +11873,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_OpenShared(char * jarg1, int jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (GDALAccess)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (GDALDatasetShadow *)OpenShared((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -11719,6 +11915,13 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_IdentifyDriver(char * jarg1, void * jarg2)
   arg1 = (char *)jarg1; 
   arg2 = (char **)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
diff --git a/swig/csharp/makefile.vc b/swig/csharp/makefile.vc
index 529105d..c05c9c8 100644
--- a/swig/csharp/makefile.vc
+++ b/swig/csharp/makefile.vc
@@ -8,7 +8,7 @@
 #  - Run the VCVARS32.BAT script to initialize the VC++ environment variables
 #  - Start the build with:  nmake /f makefile.vc
 #
-# $Id: makefile.vc 25794 2013-03-24 13:15:43Z tamas $
+# $Id: makefile.vc 26521 2013-10-11 09:13:30Z tamas $
 #
 
 GDAL_ROOT	=	..\..
@@ -131,6 +131,7 @@ samples:
     $(CSC) $(CSDEBUG) /r:gdal_csharp.dll /out:GDALGetHistogram.exe apps\GDALGetHistogram.cs
     $(CSC) $(CSDEBUG) /r:gdal_csharp.dll /out:VSIMem.exe apps\VSIMem.cs
     $(CSC) $(CSDEBUG) /r:gdal_csharp.dll /r:System.Drawing.dll /out:GDALMemDataset.exe apps\GDALMemDataset.cs
+	$(CSC) $(CSDEBUG) /r:ogr_csharp.dll /r:osr_csharp.dll /out:OGRLayerAlg.exe apps\OGRLayerAlg.cs
     
 test:
 !IFDEF MONO
@@ -151,6 +152,8 @@ test:
 	GDALCreateCopy.exe Data/sample.tif Data/sample2.tif
 	GDALOverviews.exe Data/sample.tif NEAREST 2 4
 	GDALInfo.exe Data/sample.tif
+	ogrlayeralg.exe Intersection Data/pointlayer.shp pointlayer Data/pointlayer.shp pointlayer Data intersectionresult
+	ogrinfo.exe Data/intersectionresult.shp
 !ENDIF
 	
 clean:	
diff --git a/swig/csharp/ogr/DataSource.cs b/swig/csharp/ogr/DataSource.cs
index 7cd02ea..3d87fde 100644
--- a/swig/csharp/ogr/DataSource.cs
+++ b/swig/csharp/ogr/DataSource.cs
@@ -165,6 +165,18 @@ public class DataSource : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public StyleTable GetStyleTable() {
+    IntPtr cPtr = OgrPINVOKE.DataSource_GetStyleTable(swigCPtr);
+    StyleTable ret = (cPtr == IntPtr.Zero) ? null : new StyleTable(cPtr, false, ThisOwn_false());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetStyleTable(StyleTable table) {
+    OgrPINVOKE.DataSource_SetStyleTable(swigCPtr, StyleTable.getCPtr(table));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
 }
 
 }
diff --git a/swig/csharp/ogr/Driver.cs b/swig/csharp/ogr/Driver.cs
index 5f17efc..4f3522a 100644
--- a/swig/csharp/ogr/Driver.cs
+++ b/swig/csharp/ogr/Driver.cs
@@ -73,28 +73,28 @@ public class Driver : IDisposable {
   }
 
   public DataSource CreateDataSource(string utf8_path, string[] options) {
-    IntPtr cPtr = OgrPINVOKE.Driver_CreateDataSource(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
+    IntPtr cPtr = OgrPINVOKE.Driver_CreateDataSource(swigCPtr, Ogr.StringToUtf8Bytes(utf8_path), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
     DataSource ret = (cPtr == IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public DataSource CopyDataSource(DataSource copy_ds, string utf8_path, string[] options) {
-    IntPtr cPtr = OgrPINVOKE.Driver_CopyDataSource(swigCPtr, DataSource.getCPtr(copy_ds), System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
+    IntPtr cPtr = OgrPINVOKE.Driver_CopyDataSource(swigCPtr, DataSource.getCPtr(copy_ds), Ogr.StringToUtf8Bytes(utf8_path), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
     DataSource ret = (cPtr == IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public DataSource Open(string utf8_path, int update) {
-    IntPtr cPtr = OgrPINVOKE.Driver_Open(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), update);
+    IntPtr cPtr = OgrPINVOKE.Driver_Open(swigCPtr, Ogr.StringToUtf8Bytes(utf8_path), update);
     DataSource ret = (cPtr == IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public int DeleteDataSource(string utf8_path) {
-    int ret = OgrPINVOKE.Driver_DeleteDataSource(swigCPtr, System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
+    int ret = OgrPINVOKE.Driver_DeleteDataSource(swigCPtr, Ogr.StringToUtf8Bytes(utf8_path));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
diff --git a/swig/csharp/ogr/Feature.cs b/swig/csharp/ogr/Feature.cs
index 4b5b549..6b7f265 100644
--- a/swig/csharp/ogr/Feature.cs
+++ b/swig/csharp/ogr/Feature.cs
@@ -98,6 +98,44 @@ public class Feature : IDisposable {
     return ret;
   }
 
+  public int SetGeomField(int iField, Geometry geom) {
+    int ret = OgrPINVOKE.Feature_SetGeomField__SWIG_0(swigCPtr, iField, Geometry.getCPtr(geom));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetGeomField(string name, Geometry geom) {
+    int ret = OgrPINVOKE.Feature_SetGeomField__SWIG_1(swigCPtr, name, Geometry.getCPtr(geom));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetGeomFieldDirectly(int iField, Geometry geom) {
+    int ret = OgrPINVOKE.Feature_SetGeomFieldDirectly__SWIG_0(swigCPtr, iField, Geometry.getCPtrAndDisown(geom, ThisOwn_false()));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetGeomFieldDirectly(string name, Geometry geom) {
+    int ret = OgrPINVOKE.Feature_SetGeomFieldDirectly__SWIG_1(swigCPtr, name, Geometry.getCPtrAndDisown(geom, ThisOwn_false()));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public Geometry GetGeomFieldRef(int iField) {
+    IntPtr cPtr = OgrPINVOKE.Feature_GetGeomFieldRef__SWIG_0(swigCPtr, iField);
+    Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, false, ThisOwn_false());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public Geometry GetGeomFieldRef(string name) {
+    IntPtr cPtr = OgrPINVOKE.Feature_GetGeomFieldRef__SWIG_1(swigCPtr, name);
+    Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, false, ThisOwn_false());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public Feature Clone() {
     IntPtr cPtr = OgrPINVOKE.Feature_Clone(swigCPtr);
     Feature ret = (cPtr == IntPtr.Zero) ? null : new Feature(cPtr, true, ThisOwn_true());
@@ -131,18 +169,44 @@ public class Feature : IDisposable {
     return ret;
   }
 
-  public string GetFieldAsString(int id) {
-    string ret = OgrPINVOKE.Feature_GetFieldAsString__SWIG_0(swigCPtr, id);
+  public int GetGeomFieldCount() {
+    int ret = OgrPINVOKE.Feature_GetGeomFieldCount(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public string GetFieldAsString(string name) {
-    string ret = OgrPINVOKE.Feature_GetFieldAsString__SWIG_1(swigCPtr, name);
+  public GeomFieldDefn GetGeomFieldDefnRef(int id) {
+    IntPtr cPtr = OgrPINVOKE.Feature_GetGeomFieldDefnRef__SWIG_0(swigCPtr, id);
+    GeomFieldDefn ret = (cPtr == IntPtr.Zero) ? null : new GeomFieldDefn(cPtr, false, ThisOwn_false());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
+  public GeomFieldDefn GetGeomFieldDefnRef(string name) {
+    IntPtr cPtr = OgrPINVOKE.Feature_GetGeomFieldDefnRef__SWIG_1(swigCPtr, name);
+    GeomFieldDefn ret = (cPtr == IntPtr.Zero) ? null : new GeomFieldDefn(cPtr, false, ThisOwn_false());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public string GetFieldAsString(int id) {
+        /* %typemap(csout) (const char *utf8_path) */
+        IntPtr cPtr = OgrPINVOKE.Feature_GetFieldAsString__SWIG_0(swigCPtr, id);
+        string ret = Ogr.Utf8BytesToString(cPtr);
+        
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+        return ret;
+}
+
+  public string GetFieldAsString(string name) {
+        /* %typemap(csout) (const char *utf8_path) */
+        IntPtr cPtr = OgrPINVOKE.Feature_GetFieldAsString__SWIG_1(swigCPtr, name);
+        string ret = Ogr.Utf8BytesToString(cPtr);
+        
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+        return ret;
+}
+
   public int GetFieldAsInteger(int id) {
     int ret = OgrPINVOKE.Feature_GetFieldAsInteger__SWIG_0(swigCPtr, id);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -235,6 +299,12 @@ public class Feature : IDisposable {
     return ret;
   }
 
+  public int GetGeomFieldIndex(string name) {
+    int ret = OgrPINVOKE.Feature_GetGeomFieldIndex(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int GetFID() {
     int ret = OgrPINVOKE.Feature_GetFID(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -263,12 +333,12 @@ public class Feature : IDisposable {
   }
 
   public void SetField(int id, string value) {
-    OgrPINVOKE.Feature_SetField__SWIG_0(swigCPtr, id, value);
+    OgrPINVOKE.Feature_SetField__SWIG_0(swigCPtr, id, Ogr.StringToUtf8Bytes(value));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
   public void SetField(string name, string value) {
-    OgrPINVOKE.Feature_SetField__SWIG_1(swigCPtr, name, value);
+    OgrPINVOKE.Feature_SetField__SWIG_1(swigCPtr, name, Ogr.StringToUtf8Bytes(value));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
@@ -317,6 +387,16 @@ public class Feature : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void SetFieldBinaryFromHexString(int id, string pszValue) {
+    OgrPINVOKE.Feature_SetFieldBinaryFromHexString__SWIG_0(swigCPtr, id, pszValue);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetFieldBinaryFromHexString(string name, string pszValue) {
+    OgrPINVOKE.Feature_SetFieldBinaryFromHexString__SWIG_1(swigCPtr, name, pszValue);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public int SetFrom(Feature other, int forgiving) {
     int ret = OgrPINVOKE.Feature_SetFrom(swigCPtr, Feature.getCPtr(other), forgiving);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/FeatureDefn.cs b/swig/csharp/ogr/FeatureDefn.cs
index 065460e..b23fedc 100644
--- a/swig/csharp/ogr/FeatureDefn.cs
+++ b/swig/csharp/ogr/FeatureDefn.cs
@@ -102,6 +102,36 @@ public class FeatureDefn : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public int GetGeomFieldCount() {
+    int ret = OgrPINVOKE.FeatureDefn_GetGeomFieldCount(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public GeomFieldDefn GetGeomFieldDefn(int i) {
+    IntPtr cPtr = OgrPINVOKE.FeatureDefn_GetGeomFieldDefn(swigCPtr, i);
+    GeomFieldDefn ret = (cPtr == IntPtr.Zero) ? null : new GeomFieldDefn(cPtr, false, ThisOwn_false());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int GetGeomFieldIndex(string name) {
+    int ret = OgrPINVOKE.FeatureDefn_GetGeomFieldIndex(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void AddGeomFieldDefn(GeomFieldDefn defn) {
+    OgrPINVOKE.FeatureDefn_AddGeomFieldDefn(swigCPtr, GeomFieldDefn.getCPtr(defn));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public int DeleteGeomFieldDefn(int idx) {
+    int ret = OgrPINVOKE.FeatureDefn_DeleteGeomFieldDefn(swigCPtr, idx);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public wkbGeometryType GetGeomType() {
     wkbGeometryType ret = (wkbGeometryType)OgrPINVOKE.FeatureDefn_GetGeomType(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -141,6 +171,12 @@ public class FeatureDefn : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public int IsSame(FeatureDefn other_defn) {
+    int ret = OgrPINVOKE.FeatureDefn_IsSame(swigCPtr, FeatureDefn.getCPtr(other_defn));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
 }
 
 }
diff --git a/swig/csharp/ogr/GeomFieldDefn.cs b/swig/csharp/ogr/GeomFieldDefn.cs
new file mode 100644
index 0000000..61dcc16
--- /dev/null
+++ b/swig/csharp/ogr/GeomFieldDefn.cs
@@ -0,0 +1,128 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.7
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.OGR {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GeomFieldDefn : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+  
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GeomFieldDefn(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GeomFieldDefn obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GeomFieldDefn obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GeomFieldDefn obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GeomFieldDefn() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        OgrPINVOKE.delete_GeomFieldDefn(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GeomFieldDefn(string name_null_ok, wkbGeometryType field_type) : this(OgrPINVOKE.new_GeomFieldDefn(name_null_ok, (int)field_type), true, null) {
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public string GetName() {
+    string ret = OgrPINVOKE.GeomFieldDefn_GetName(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public string GetNameRef() {
+    string ret = OgrPINVOKE.GeomFieldDefn_GetNameRef(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetName(string name) {
+    OgrPINVOKE.GeomFieldDefn_SetName(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public wkbGeometryType GetFieldType() {
+    wkbGeometryType ret = (wkbGeometryType)OgrPINVOKE.GeomFieldDefn_GetFieldType(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetType(wkbGeometryType type) {
+    OgrPINVOKE.GeomFieldDefn_SetType(swigCPtr, (int)type);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public OSGeo.OSR.SpatialReference GetSpatialRef() {
+    IntPtr cPtr = OgrPINVOKE.GeomFieldDefn_GetSpatialRef(swigCPtr);
+    OSGeo.OSR.SpatialReference ret = (cPtr == IntPtr.Zero) ? null : new OSGeo.OSR.SpatialReference(cPtr, true, ThisOwn_true());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetSpatialRef(OSGeo.OSR.SpatialReference srs) {
+    OgrPINVOKE.GeomFieldDefn_SetSpatialRef(swigCPtr, OSGeo.OSR.SpatialReference.getCPtr(srs));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public int IsIgnored() {
+    int ret = OgrPINVOKE.GeomFieldDefn_IsIgnored(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetIgnored(int bIgnored) {
+    OgrPINVOKE.GeomFieldDefn_SetIgnored(swigCPtr, bIgnored);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/ogr/Layer.cs b/swig/csharp/ogr/Layer.cs
index 3c65c8e..6204a8b 100644
--- a/swig/csharp/ogr/Layer.cs
+++ b/swig/csharp/ogr/Layer.cs
@@ -71,12 +71,22 @@ public class Layer : IDisposable {
   }
 
   public void SetSpatialFilter(Geometry filter) {
-    OgrPINVOKE.Layer_SetSpatialFilter(swigCPtr, Geometry.getCPtr(filter));
+    OgrPINVOKE.Layer_SetSpatialFilter__SWIG_0(swigCPtr, Geometry.getCPtr(filter));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
   public void SetSpatialFilterRect(double minx, double miny, double maxx, double maxy) {
-    OgrPINVOKE.Layer_SetSpatialFilterRect(swigCPtr, minx, miny, maxx, maxy);
+    OgrPINVOKE.Layer_SetSpatialFilterRect__SWIG_0(swigCPtr, minx, miny, maxx, maxy);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetSpatialFilter(int iGeomField, Geometry filter) {
+    OgrPINVOKE.Layer_SetSpatialFilter__SWIG_1(swigCPtr, iGeomField, Geometry.getCPtr(filter));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetSpatialFilterRect(int iGeomField, double minx, double miny, double maxx, double maxy) {
+    OgrPINVOKE.Layer_SetSpatialFilterRect__SWIG_1(swigCPtr, iGeomField, minx, miny, maxx, maxy);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
@@ -88,7 +98,7 @@ public class Layer : IDisposable {
   }
 
   public int SetAttributeFilter(string filter_string) {
-    int ret = OgrPINVOKE.Layer_SetAttributeFilter(swigCPtr, filter_string);
+    int ret = OgrPINVOKE.Layer_SetAttributeFilter(swigCPtr, Ogr.StringToUtf8Bytes(filter_string));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -221,6 +231,12 @@ public class Layer : IDisposable {
     return ret;
   }
 
+  public int CreateGeomField(GeomFieldDefn field_def, int approx_ok) {
+    int ret = OgrPINVOKE.Layer_CreateGeomField(swigCPtr, GeomFieldDefn.getCPtr(field_def), approx_ok);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int StartTransaction() {
     int ret = OgrPINVOKE.Layer_StartTransaction(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -239,6 +255,12 @@ public class Layer : IDisposable {
     return ret;
   }
 
+  public int FindFieldIndex(string pszFieldName, int bExactMatch) {
+    int ret = OgrPINVOKE.Layer_FindFieldIndex(swigCPtr, pszFieldName, bExactMatch);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public OSGeo.OSR.SpatialReference GetSpatialRef() {
     IntPtr cPtr = OgrPINVOKE.Layer_GetSpatialRef(swigCPtr);
     OSGeo.OSR.SpatialReference ret = (cPtr == IntPtr.Zero) ? null : new OSGeo.OSR.SpatialReference(cPtr, true, ThisOwn_true());
@@ -258,48 +280,60 @@ public class Layer : IDisposable {
     return ret;
   }
 
-  public int Intersection(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Intersection(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int Intersection(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Intersection(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int Union(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Union(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int Union(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Union(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int SymDifference(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_SymDifference(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int SymDifference(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_SymDifference(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int Identity(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Identity(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int Identity(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Identity(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int Update(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Update(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int Update(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Update(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int Clip(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Clip(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int Clip(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Clip(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public int Erase(Layer method_layer, Layer result_layer, string[] options, Ogr.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = OgrPINVOKE.Layer_Erase(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public int Erase(Layer method_layer, Layer result_layer, string[] options, SWIGTYPE_p_GDALProgressFunc callback, SWIGTYPE_p_void callback_data) {
-    int ret = OgrPINVOKE.Layer_Erase(swigCPtr, Layer.getCPtr(method_layer), Layer.getCPtr(result_layer), (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null, SWIGTYPE_p_GDALProgressFunc.getCPtr(callback), SWIGTYPE_p_void.getCPtr(callback_data));
+  public StyleTable GetStyleTable() {
+    IntPtr cPtr = OgrPINVOKE.Layer_GetStyleTable(swigCPtr);
+    StyleTable ret = (cPtr == IntPtr.Zero) ? null : new StyleTable(cPtr, false, ThisOwn_false());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
+  public void SetStyleTable(StyleTable table) {
+    OgrPINVOKE.Layer_SetStyleTable(swigCPtr, StyleTable.getCPtr(table));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
 }
 
 }
diff --git a/swig/csharp/ogr/Ogr.cs b/swig/csharp/ogr/Ogr.cs
index 1c9ce98..8815aba 100644
--- a/swig/csharp/ogr/Ogr.cs
+++ b/swig/csharp/ogr/Ogr.cs
@@ -30,12 +30,36 @@ public class Ogr {
     OgrPINVOKE.DontUseExceptions();
   }
 
+
+  internal static byte[] StringToUtf8Bytes(string str)
+  {
+    if (str == null)
+      return null;
+    
+    int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
+    byte[] bytes = new byte[bytecount + 1];
+    System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
+    return bytes;
+  }
+  
+  internal static string Utf8BytesToString(IntPtr pNativeData)
+  {
+    if (pNativeData == IntPtr.Zero)
+        return null;
+        
+    int length = Marshal.PtrToStringAnsi(pNativeData).Length;
+    byte[] strbuf = new byte[length];  
+    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    return System.Text.Encoding.UTF8.GetString(strbuf);
+  }
+
   internal static void StringListDestroy(IntPtr buffer_ptr) {
     OgrPINVOKE.StringListDestroy(buffer_ptr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
 public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
+public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data);
   public static Geometry CreateGeometryFromWkb(int len, IntPtr bin_string, OSGeo.OSR.SpatialReference reference) {
     IntPtr cPtr = OgrPINVOKE.CreateGeometryFromWkb(len, bin_string, OSGeo.OSR.SpatialReference.getCPtr(reference));
     Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
@@ -156,14 +180,14 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   }
 
   public static DataSource Open(string utf8_path, int update) {
-    IntPtr cPtr = OgrPINVOKE.Open(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), update);
+    IntPtr cPtr = OgrPINVOKE.Open(Ogr.StringToUtf8Bytes(utf8_path), update);
     DataSource ret = (cPtr == IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
   public static DataSource OpenShared(string utf8_path, int update) {
-    IntPtr cPtr = OgrPINVOKE.OpenShared(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)), update);
+    IntPtr cPtr = OgrPINVOKE.OpenShared(Ogr.StringToUtf8Bytes(utf8_path), update);
     DataSource ret = (cPtr == IntPtr.Zero) ? null : new DataSource(cPtr, true, ThisOwn_true());
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
@@ -222,8 +246,10 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public static readonly string OLCDeleteFeature = OgrPINVOKE.OLCDeleteFeature_get();
   public static readonly string OLCFastSetNextByIndex = OgrPINVOKE.OLCFastSetNextByIndex_get();
   public static readonly string OLCStringsAsUTF8 = OgrPINVOKE.OLCStringsAsUTF8_get();
+  public static readonly string OLCCreateGeomField = OgrPINVOKE.OLCCreateGeomField_get();
   public static readonly string ODsCCreateLayer = OgrPINVOKE.ODsCCreateLayer_get();
   public static readonly string ODsCDeleteLayer = OgrPINVOKE.ODsCDeleteLayer_get();
+  public static readonly string ODsCCreateGeomFieldAfterCreateLayer = OgrPINVOKE.ODsCCreateGeomFieldAfterCreateLayer_get();
   public static readonly string ODrCCreateDataSource = OgrPINVOKE.ODrCCreateDataSource_get();
   public static readonly string ODrCDeleteDataSource = OgrPINVOKE.ODrCDeleteDataSource_get();
   public static readonly int OGRERR_NONE = OgrPINVOKE.OGRERR_NONE_get();
diff --git a/swig/csharp/ogr/OgrPINVOKE.cs b/swig/csharp/ogr/OgrPINVOKE.cs
index debe493..37adca2 100644
--- a/swig/csharp/ogr/OgrPINVOKE.cs
+++ b/swig/csharp/ogr/OgrPINVOKE.cs
@@ -247,12 +247,18 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_OLCStringsAsUTF8_get")]
   public static extern string OLCStringsAsUTF8_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_OLCCreateGeomField_get")]
+  public static extern string OLCCreateGeomField_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCCreateLayer_get")]
   public static extern string ODsCCreateLayer_get();
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCDeleteLayer_get")]
   public static extern string ODsCDeleteLayer_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCCreateGeomFieldAfterCreateLayer_get")]
+  public static extern string ODsCCreateGeomFieldAfterCreateLayer_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODrCCreateDataSource_get")]
   public static extern string ODrCCreateDataSource_get();
 
@@ -382,20 +388,47 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_delete_Envelope3D")]
   public static extern void delete_Envelope3D(HandleRef jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_new_StyleTable")]
+  public static extern IntPtr new_StyleTable();
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_delete_StyleTable")]
+  public static extern void delete_StyleTable(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_AddStyle")]
+  public static extern int StyleTable_AddStyle(HandleRef jarg1, string jarg2, string jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_LoadStyleTable")]
+  public static extern int StyleTable_LoadStyleTable(HandleRef jarg1, byte[] jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_SaveStyleTable")]
+  public static extern int StyleTable_SaveStyleTable(HandleRef jarg1, byte[] jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_Find")]
+  public static extern string StyleTable_Find(HandleRef jarg1, string jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_ResetStyleStringReading")]
+  public static extern void StyleTable_ResetStyleStringReading(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_GetNextStyle")]
+  public static extern string StyleTable_GetNextStyle(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_StyleTable_GetLastStyleName")]
+  public static extern string StyleTable_GetLastStyleName(HandleRef jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_name_get")]
   public static extern string Driver_name_get(HandleRef jarg1);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_CreateDataSource")]
-  public static extern IntPtr Driver_CreateDataSource(HandleRef jarg1, string jarg2, IntPtr[] jarg3);
+  public static extern IntPtr Driver_CreateDataSource(HandleRef jarg1, byte[] jarg2, IntPtr[] jarg3);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_CopyDataSource")]
-  public static extern IntPtr Driver_CopyDataSource(HandleRef jarg1, HandleRef jarg2, string jarg3, IntPtr[] jarg4);
+  public static extern IntPtr Driver_CopyDataSource(HandleRef jarg1, HandleRef jarg2, byte[] jarg3, IntPtr[] jarg4);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_Open")]
-  public static extern IntPtr Driver_Open(HandleRef jarg1, string jarg2, int jarg3);
+  public static extern IntPtr Driver_Open(HandleRef jarg1, byte[] jarg2, int jarg3);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_DeleteDataSource")]
-  public static extern int Driver_DeleteDataSource(HandleRef jarg1, string jarg2);
+  public static extern int Driver_DeleteDataSource(HandleRef jarg1, byte[] jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_TestCapability")]
   public static extern bool Driver_TestCapability(HandleRef jarg1, string jarg2);
@@ -457,20 +490,32 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_ReleaseResultSet")]
   public static extern void DataSource_ReleaseResultSet(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_GetStyleTable")]
+  public static extern IntPtr DataSource_GetStyleTable(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_SetStyleTable")]
+  public static extern void DataSource_SetStyleTable(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_GetRefCount")]
   public static extern int Layer_GetRefCount(HandleRef jarg1);
 
-  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilter")]
-  public static extern void Layer_SetSpatialFilter(HandleRef jarg1, HandleRef jarg2);
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilter__SWIG_0")]
+  public static extern void Layer_SetSpatialFilter__SWIG_0(HandleRef jarg1, HandleRef jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilterRect__SWIG_0")]
+  public static extern void Layer_SetSpatialFilterRect__SWIG_0(HandleRef jarg1, double jarg2, double jarg3, double jarg4, double jarg5);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilter__SWIG_1")]
+  public static extern void Layer_SetSpatialFilter__SWIG_1(HandleRef jarg1, int jarg2, HandleRef jarg3);
 
-  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilterRect")]
-  public static extern void Layer_SetSpatialFilterRect(HandleRef jarg1, double jarg2, double jarg3, double jarg4, double jarg5);
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetSpatialFilterRect__SWIG_1")]
+  public static extern void Layer_SetSpatialFilterRect__SWIG_1(HandleRef jarg1, int jarg2, double jarg3, double jarg4, double jarg5, double jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_GetSpatialFilter")]
   public static extern IntPtr Layer_GetSpatialFilter(HandleRef jarg1);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetAttributeFilter")]
-  public static extern int Layer_SetAttributeFilter(HandleRef jarg1, string jarg2);
+  public static extern int Layer_SetAttributeFilter(HandleRef jarg1, byte[] jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_ResetReading")]
   public static extern void Layer_ResetReading(HandleRef jarg1);
@@ -535,6 +580,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_AlterFieldDefn")]
   public static extern int Layer_AlterFieldDefn(HandleRef jarg1, int jarg2, HandleRef jarg3, int jarg4);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_CreateGeomField")]
+  public static extern int Layer_CreateGeomField(HandleRef jarg1, HandleRef jarg2, int jarg3);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_StartTransaction")]
   public static extern int Layer_StartTransaction(HandleRef jarg1);
 
@@ -544,6 +592,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_RollbackTransaction")]
   public static extern int Layer_RollbackTransaction(HandleRef jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_FindFieldIndex")]
+  public static extern int Layer_FindFieldIndex(HandleRef jarg1, string jarg2, int jarg3);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_GetSpatialRef")]
   public static extern IntPtr Layer_GetSpatialRef(HandleRef jarg1);
 
@@ -554,25 +605,31 @@ class OgrPINVOKE {
   public static extern int Layer_SetIgnoredFields(HandleRef jarg1, IntPtr[] jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Intersection")]
-  public static extern int Layer_Intersection(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Intersection(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Union")]
-  public static extern int Layer_Union(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Union(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SymDifference")]
-  public static extern int Layer_SymDifference(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_SymDifference(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Identity")]
-  public static extern int Layer_Identity(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Identity(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Update")]
-  public static extern int Layer_Update(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Update(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Clip")]
-  public static extern int Layer_Clip(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Clip(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_Erase")]
-  public static extern int Layer_Erase(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, HandleRef jarg5, HandleRef jarg6);
+  public static extern int Layer_Erase(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, IntPtr[] jarg4, Ogr.GDALProgressFuncDelegate jarg5, string jarg6);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_GetStyleTable")]
+  public static extern IntPtr Layer_GetStyleTable(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_SetStyleTable")]
+  public static extern void Layer_SetStyleTable(HandleRef jarg1, HandleRef jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_delete_Feature")]
   public static extern void delete_Feature(HandleRef jarg1);
@@ -592,6 +649,24 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeometryRef")]
   public static extern IntPtr Feature_GetGeometryRef(HandleRef jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetGeomField__SWIG_0")]
+  public static extern int Feature_SetGeomField__SWIG_0(HandleRef jarg1, int jarg2, HandleRef jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetGeomField__SWIG_1")]
+  public static extern int Feature_SetGeomField__SWIG_1(HandleRef jarg1, string jarg2, HandleRef jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetGeomFieldDirectly__SWIG_0")]
+  public static extern int Feature_SetGeomFieldDirectly__SWIG_0(HandleRef jarg1, int jarg2, HandleRef jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetGeomFieldDirectly__SWIG_1")]
+  public static extern int Feature_SetGeomFieldDirectly__SWIG_1(HandleRef jarg1, string jarg2, HandleRef jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldRef__SWIG_0")]
+  public static extern IntPtr Feature_GetGeomFieldRef__SWIG_0(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldRef__SWIG_1")]
+  public static extern IntPtr Feature_GetGeomFieldRef__SWIG_1(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_Clone")]
   public static extern IntPtr Feature_Clone(HandleRef jarg1);
 
@@ -607,11 +682,20 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldDefnRef__SWIG_1")]
   public static extern IntPtr Feature_GetFieldDefnRef__SWIG_1(HandleRef jarg1, string jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldCount")]
+  public static extern int Feature_GetGeomFieldCount(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldDefnRef__SWIG_0")]
+  public static extern IntPtr Feature_GetGeomFieldDefnRef__SWIG_0(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldDefnRef__SWIG_1")]
+  public static extern IntPtr Feature_GetGeomFieldDefnRef__SWIG_1(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsString__SWIG_0")]
-  public static extern string Feature_GetFieldAsString__SWIG_0(HandleRef jarg1, int jarg2);
+  public static extern IntPtr Feature_GetFieldAsString__SWIG_0(HandleRef jarg1, int jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsString__SWIG_1")]
-  public static extern string Feature_GetFieldAsString__SWIG_1(HandleRef jarg1, string jarg2);
+  public static extern IntPtr Feature_GetFieldAsString__SWIG_1(HandleRef jarg1, string jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsInteger__SWIG_0")]
   public static extern int Feature_GetFieldAsInteger__SWIG_0(HandleRef jarg1, int jarg2);
@@ -646,6 +730,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldIndex")]
   public static extern int Feature_GetFieldIndex(HandleRef jarg1, string jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetGeomFieldIndex")]
+  public static extern int Feature_GetGeomFieldIndex(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFID")]
   public static extern int Feature_GetFID(HandleRef jarg1);
 
@@ -662,10 +749,10 @@ class OgrPINVOKE {
   public static extern void Feature_UnsetField__SWIG_1(HandleRef jarg1, string jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetField__SWIG_0")]
-  public static extern void Feature_SetField__SWIG_0(HandleRef jarg1, int jarg2, string jarg3);
+  public static extern void Feature_SetField__SWIG_0(HandleRef jarg1, int jarg2, byte[] jarg3);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetField__SWIG_1")]
-  public static extern void Feature_SetField__SWIG_1(HandleRef jarg1, string jarg2, string jarg3);
+  public static extern void Feature_SetField__SWIG_1(HandleRef jarg1, string jarg2, byte[] jarg3);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetField__SWIG_2")]
   public static extern void Feature_SetField__SWIG_2(HandleRef jarg1, int jarg2, int jarg3);
@@ -694,6 +781,12 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFieldStringList")]
   public static extern void Feature_SetFieldStringList(HandleRef jarg1, int jarg2, IntPtr[] jarg3);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFieldBinaryFromHexString__SWIG_0")]
+  public static extern void Feature_SetFieldBinaryFromHexString__SWIG_0(HandleRef jarg1, int jarg2, string jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFieldBinaryFromHexString__SWIG_1")]
+  public static extern void Feature_SetFieldBinaryFromHexString__SWIG_1(HandleRef jarg1, string jarg2, string jarg3);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFrom")]
   public static extern int Feature_SetFrom(HandleRef jarg1, HandleRef jarg2, int jarg3);
 
@@ -733,6 +826,21 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_AddFieldDefn")]
   public static extern void FeatureDefn_AddFieldDefn(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_GetGeomFieldCount")]
+  public static extern int FeatureDefn_GetGeomFieldCount(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_GetGeomFieldDefn")]
+  public static extern IntPtr FeatureDefn_GetGeomFieldDefn(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_GetGeomFieldIndex")]
+  public static extern int FeatureDefn_GetGeomFieldIndex(HandleRef jarg1, string jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_AddGeomFieldDefn")]
+  public static extern void FeatureDefn_AddGeomFieldDefn(HandleRef jarg1, HandleRef jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_DeleteGeomFieldDefn")]
+  public static extern int FeatureDefn_DeleteGeomFieldDefn(HandleRef jarg1, int jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_GetGeomType")]
   public static extern int FeatureDefn_GetGeomType(HandleRef jarg1);
 
@@ -754,6 +862,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_SetStyleIgnored")]
   public static extern void FeatureDefn_SetStyleIgnored(HandleRef jarg1, int jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_FeatureDefn_IsSame")]
+  public static extern int FeatureDefn_IsSame(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_delete_FieldDefn")]
   public static extern void delete_FieldDefn(HandleRef jarg1);
 
@@ -805,6 +916,39 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_FieldDefn_SetIgnored")]
   public static extern void FieldDefn_SetIgnored(HandleRef jarg1, int jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_delete_GeomFieldDefn")]
+  public static extern void delete_GeomFieldDefn(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_new_GeomFieldDefn")]
+  public static extern IntPtr new_GeomFieldDefn(string jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_GetName")]
+  public static extern string GeomFieldDefn_GetName(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_GetNameRef")]
+  public static extern string GeomFieldDefn_GetNameRef(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_SetName")]
+  public static extern void GeomFieldDefn_SetName(HandleRef jarg1, string jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_GetFieldType")]
+  public static extern int GeomFieldDefn_GetFieldType(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_SetType")]
+  public static extern void GeomFieldDefn_SetType(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_GetSpatialRef")]
+  public static extern IntPtr GeomFieldDefn_GetSpatialRef(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_SetSpatialRef")]
+  public static extern void GeomFieldDefn_SetSpatialRef(HandleRef jarg1, HandleRef jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_IsIgnored")]
+  public static extern int GeomFieldDefn_IsIgnored(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GeomFieldDefn_SetIgnored")]
+  public static extern void GeomFieldDefn_SetIgnored(HandleRef jarg1, int jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_CreateGeometryFromWkb")]
   public static extern IntPtr CreateGeometryFromWkb(int jarg1, IntPtr jarg2, HandleRef jarg3);
 
@@ -1073,10 +1217,10 @@ class OgrPINVOKE {
   public static extern IntPtr GetOpenDS(int jarg1);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Open")]
-  public static extern IntPtr Open(string jarg1, int jarg2);
+  public static extern IntPtr Open(byte[] jarg1, int jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_OpenShared")]
-  public static extern IntPtr OpenShared(string jarg1, int jarg2);
+  public static extern IntPtr OpenShared(byte[] jarg1, int jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_GetDriverByName")]
   public static extern IntPtr GetDriverByName(string jarg1);
diff --git a/swig/csharp/ogr/Osr.cs b/swig/csharp/ogr/Osr.cs
index b289ea3..02a3f29 100644
--- a/swig/csharp/ogr/Osr.cs
+++ b/swig/csharp/ogr/Osr.cs
@@ -30,12 +30,36 @@ public class Osr {
     OsrPINVOKE.DontUseExceptions();
   }
 
+
+  internal static byte[] StringToUtf8Bytes(string str)
+  {
+    if (str == null)
+      return null;
+    
+    int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
+    byte[] bytes = new byte[bytecount + 1];
+    System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
+    return bytes;
+  }
+  
+  internal static string Utf8BytesToString(IntPtr pNativeData)
+  {
+    if (pNativeData == IntPtr.Zero)
+        return null;
+        
+    int length = Marshal.PtrToStringAnsi(pNativeData).Length;
+    byte[] strbuf = new byte[length];  
+    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    return System.Text.Encoding.UTF8.GetString(strbuf);
+  }
+
   internal static void StringListDestroy(IntPtr buffer_ptr) {
     OsrPINVOKE.StringListDestroy(buffer_ptr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
   }
 
 public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
+public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data);
   public static int GetWellKnownGeogCSAsWKT(string name, out string argout) {
     int ret = OsrPINVOKE.GetWellKnownGeogCSAsWKT(name, out argout);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -210,6 +234,44 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_UL_ROD_CONV = "5.02921005842012";
   public const string SRS_UL_LINK_Clarke = "Link_Clarke";
   public const string SRS_UL_LINK_Clarke_CONV = "0.2011661949";
+  public const string SRS_UL_KILOMETER = "Kilometer";
+  public const string SRS_UL_KILOMETER_CONV = "1000.";
+  public const string SRS_UL_DECIMETER = "Decimeter";
+  public const string SRS_UL_DECIMETER_CONV = "0.1";
+  public const string SRS_UL_CENTIMETER = "Centimeter";
+  public const string SRS_UL_CENTIMETER_CONV = "0.01";
+  public const string SRS_UL_MILLIMETER = "Millimeter";
+  public const string SRS_UL_MILLIMETER_CONV = "0.001";
+  public const string SRS_UL_INTL_NAUT_MILE = "Nautical_Mile_International";
+  public const string SRS_UL_INTL_NAUT_MILE_CONV = "1852.0";
+  public const string SRS_UL_INTL_INCH = "Inch_International";
+  public const string SRS_UL_INTL_INCH_CONV = "0.0254";
+  public const string SRS_UL_INTL_FOOT = "Foot_International";
+  public const string SRS_UL_INTL_FOOT_CONV = "0.3048";
+  public const string SRS_UL_INTL_YARD = "Yard_International";
+  public const string SRS_UL_INTL_YARD_CONV = "0.9144";
+  public const string SRS_UL_INTL_STAT_MILE = "Statute_Mile_International";
+  public const string SRS_UL_INTL_STAT_MILE_CONV = "1609.344";
+  public const string SRS_UL_INTL_FATHOM = "Fathom_International";
+  public const string SRS_UL_INTL_FATHOM_CONV = "1.8288";
+  public const string SRS_UL_INTL_CHAIN = "Chain_International";
+  public const string SRS_UL_INTL_CHAIN_CONV = "20.1168";
+  public const string SRS_UL_INTL_LINK = "Link_International";
+  public const string SRS_UL_INTL_LINK_CONV = "0.201168";
+  public const string SRS_UL_US_INCH = "Inch_US_Surveyor";
+  public const string SRS_UL_US_INCH_CONV = "0.025400050800101603";
+  public const string SRS_UL_US_YARD = "Yard_US_Surveyor";
+  public const string SRS_UL_US_YARD_CONV = "0.914401828803658";
+  public const string SRS_UL_US_CHAIN = "Chain_US_Surveyor";
+  public const string SRS_UL_US_CHAIN_CONV = "20.11684023368047";
+  public const string SRS_UL_US_STAT_MILE = "Statute_Mile_US_Surveyor";
+  public const string SRS_UL_US_STAT_MILE_CONV = "1609.347218694437";
+  public const string SRS_UL_INDIAN_YARD = "Yard_Indian";
+  public const string SRS_UL_INDIAN_YARD_CONV = "0.91439523";
+  public const string SRS_UL_INDIAN_FOOT = "Foot_Indian";
+  public const string SRS_UL_INDIAN_FOOT_CONV = "0.30479841";
+  public const string SRS_UL_INDIAN_CHAIN = "Chain_Indian";
+  public const string SRS_UL_INDIAN_CHAIN_CONV = "20.11669506";
   public const string SRS_UA_DEGREE = "degree";
   public const string SRS_UA_DEGREE_CONV = "0.0174532925199433";
   public const string SRS_UA_RADIAN = "radian";
diff --git a/swig/csharp/ogr/OsrPINVOKE.cs b/swig/csharp/ogr/OsrPINVOKE.cs
index cf2d10e..9e5e2e5 100644
--- a/swig/csharp/ogr/OsrPINVOKE.cs
+++ b/swig/csharp/ogr/OsrPINVOKE.cs
@@ -274,6 +274,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsLatLong")]
   public static extern int SpatialReference_EPSGTreatsAsLatLong(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsNorthingEasting")]
+  public static extern int SpatialReference_EPSGTreatsAsNorthingEasting(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetAuthority")]
   public static extern int SpatialReference_SetAuthority(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
 
diff --git a/swig/csharp/ogr/SWIGTYPE_p_GDALProgressFunc.cs b/swig/csharp/ogr/SWIGTYPE_p_GDALProgressFunc.cs
deleted file mode 100644
index b2a4d6e..0000000
--- a/swig/csharp/ogr/SWIGTYPE_p_GDALProgressFunc.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.OGR {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_GDALProgressFunc {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_GDALProgressFunc(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_GDALProgressFunc() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_GDALProgressFunc obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/ogr/SWIGTYPE_p_void.cs b/swig/csharp/ogr/SWIGTYPE_p_void.cs
deleted file mode 100644
index 3681b36..0000000
--- a/swig/csharp/ogr/SWIGTYPE_p_void.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
- *
- * Do not make changes to this file unless you know what you are doing--modify
- * the SWIG interface file instead.
- * ----------------------------------------------------------------------------- */
-
-namespace OSGeo.OGR {
-
-using System;
-using System.Runtime.InteropServices;
-
-public class SWIGTYPE_p_void {
-  private HandleRef swigCPtr;
-
-  public SWIGTYPE_p_void(IntPtr cPtr, bool futureUse, object parent) {
-    swigCPtr = new HandleRef(this, cPtr);
-  }
-
-  protected SWIGTYPE_p_void() {
-    swigCPtr = new HandleRef(null, IntPtr.Zero);
-  }
-
-  public static HandleRef getCPtr(SWIGTYPE_p_void obj) {
-    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
-  }
-}
-
-}
diff --git a/swig/csharp/ogr/SpatialReference.cs b/swig/csharp/ogr/SpatialReference.cs
index 75b2e79..907c0ad 100644
--- a/swig/csharp/ogr/SpatialReference.cs
+++ b/swig/csharp/ogr/SpatialReference.cs
@@ -138,6 +138,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int EPSGTreatsAsNorthingEasting() {
+    int ret = OsrPINVOKE.SpatialReference_EPSGTreatsAsNorthingEasting(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetAuthority(string pszTargetKey, string pszAuthority, int nCode) {
     int ret = OsrPINVOKE.SpatialReference_SetAuthority(swigCPtr, pszTargetKey, pszAuthority, nCode);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/StyleTable.cs b/swig/csharp/ogr/StyleTable.cs
new file mode 100644
index 0000000..dac966b
--- /dev/null
+++ b/swig/csharp/ogr/StyleTable.cs
@@ -0,0 +1,118 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.7
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.OGR {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class StyleTable : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+  
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public StyleTable(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(StyleTable obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(StyleTable obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(StyleTable obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~StyleTable() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        OgrPINVOKE.delete_StyleTable(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public StyleTable() : this(OgrPINVOKE.new_StyleTable(), true, null) {
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public int AddStyle(string pszName, string pszStyleString) {
+    int ret = OgrPINVOKE.StyleTable_AddStyle(swigCPtr, pszName, pszStyleString);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int LoadStyleTable(string utf8_path) {
+    int ret = OgrPINVOKE.StyleTable_LoadStyleTable(swigCPtr, Ogr.StringToUtf8Bytes(utf8_path));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SaveStyleTable(string utf8_path) {
+    int ret = OgrPINVOKE.StyleTable_SaveStyleTable(swigCPtr, Ogr.StringToUtf8Bytes(utf8_path));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public string Find(string pszName) {
+    string ret = OgrPINVOKE.StyleTable_Find(swigCPtr, pszName);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void ResetStyleStringReading() {
+    OgrPINVOKE.StyleTable_ResetStyleStringReading(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public string GetNextStyle() {
+    string ret = OgrPINVOKE.StyleTable_GetNextStyle(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public string GetLastStyleName() {
+    string ret = OgrPINVOKE.StyleTable_GetLastStyleName(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+}
+
+}
diff --git a/swig/csharp/ogr/ogr_wrap.cpp b/swig/csharp/ogr/ogr_wrap.cpp
index 59bbe3b..bcc6136 100644
--- a/swig/csharp/ogr/ogr_wrap.cpp
+++ b/swig/csharp/ogr/ogr_wrap.cpp
@@ -371,6 +371,8 @@ typedef void OGRGeometryShadow;
 typedef void OSRCoordinateTransformationShadow;
 typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
 void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
@@ -396,6 +398,33 @@ void DontUseExceptions() {
        CSLDestroy((char**)buffer_ptr);
     }
 
+SWIGINTERN OGRStyleTableShadow *new_OGRStyleTableShadow(){
+        return (OGRStyleTableShadow*) OGR_STBL_Create();
+   }
+SWIGINTERN void delete_OGRStyleTableShadow(OGRStyleTableShadow *self){
+        OGR_STBL_Destroy( (OGRStyleTableH) self );
+   }
+SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const *pszName,char const *pszStyleString){
+        return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
+   }
+SWIGINTERN int OGRStyleTableShadow_LoadStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_LoadStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN int OGRStyleTableShadow_SaveStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_SaveStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_Find(OGRStyleTableShadow *self,char const *pszName){
+        return OGR_STBL_Find( (OGRStyleTableH) self, pszName );
+   }
+SWIGINTERN void OGRStyleTableShadow_ResetStyleStringReading(OGRStyleTableShadow *self){
+        OGR_STBL_ResetStyleStringReading( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetNextStyle(OGRStyleTableShadow *self){
+        return OGR_STBL_GetNextStyle( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetLastStyleName(OGRStyleTableShadow *self){
+        return OGR_STBL_GetLastStyleName( (OGRStyleTableH) self );
+   }
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CreateDataSource(OGRDriverShadow *self,char const *utf8_path,char **options=0){
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
     return ds;
@@ -519,14 +548,27 @@ SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_ExecuteSQL(OGRDataSourceShadow *s
 SWIGINTERN void OGRDataSourceShadow_ReleaseResultSet(OGRDataSourceShadow *self,OGRLayerShadow *layer){
     OGR_DS_ReleaseResultSet(self, layer);
   }
+SWIGINTERN OGRStyleTableShadow *OGRDataSourceShadow_GetStyleTable(OGRDataSourceShadow *self){
+    return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
+  }
+SWIGINTERN void OGRDataSourceShadow_SetStyleTable(OGRDataSourceShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_DS_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN int OGRLayerShadow_GetRefCount(OGRLayerShadow *self){
     return OGR_L_GetRefCount(self);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilter(OGRLayerShadow *self,OGRGeometryShadow *filter){
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_0(OGRLayerShadow *self,OGRGeometryShadow *filter){
     OGR_L_SetSpatialFilter (self, filter);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
-    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);                          
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_0(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_1(OGRLayerShadow *self,int iGeomField,OGRGeometryShadow *filter){
+    OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_1(OGRLayerShadow *self,int iGeomField,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
   }
 SWIGINTERN OGRGeometryShadow *OGRLayerShadow_GetSpatialFilter(OGRLayerShadow *self){
     return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
@@ -604,6 +646,9 @@ SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,in
 SWIGINTERN OGRErr OGRLayerShadow_AlterFieldDefn(OGRLayerShadow *self,int iField,OGRFieldDefnShadow *field_def,int nFlags){
     return OGR_L_AlterFieldDefn(self, iField, field_def, nFlags);
   }
+SWIGINTERN OGRErr OGRLayerShadow_CreateGeomField(OGRLayerShadow *self,OGRGeomFieldDefnShadow *field_def,int approx_ok=1){
+    return OGR_L_CreateGeomField(self, field_def, approx_ok);
+  }
 SWIGINTERN OGRErr OGRLayerShadow_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -613,6 +658,9 @@ SWIGINTERN OGRErr OGRLayerShadow_CommitTransaction(OGRLayerShadow *self){
 SWIGINTERN OGRErr OGRLayerShadow_RollbackTransaction(OGRLayerShadow *self){
     return OGR_L_RollbackTransaction(self);
   }
+SWIGINTERN int OGRLayerShadow_FindFieldIndex(OGRLayerShadow *self,char const *pszFieldName,int bExactMatch){
+    return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
+  }
 SWIGINTERN OSRSpatialReferenceShadow *OGRLayerShadow_GetSpatialRef(OGRLayerShadow *self){
     OGRSpatialReferenceH ref =  OGR_L_GetSpatialRef(self);
     if( ref )
@@ -646,6 +694,13 @@ SWIGINTERN OGRErr OGRLayerShadow_Clip(OGRLayerShadow *self,OGRLayerShadow *metho
 SWIGINTERN OGRErr OGRLayerShadow_Erase(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
   }
+SWIGINTERN OGRStyleTableShadow *OGRLayerShadow_GetStyleTable(OGRLayerShadow *self){
+    return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
+  }
+SWIGINTERN void OGRLayerShadow_SetStyleTable(OGRLayerShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_L_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN void delete_OGRFeatureShadow(OGRFeatureShadow *self){
     OGR_F_Destroy(self);
   }
@@ -664,6 +719,45 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeometryDirectly(OGRFeatureShadow *self,OG
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeometryRef(OGRFeatureShadow *self){
     return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
   }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return 6;
+      }
+      else
+        return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return 6;
+      }
+      else
+        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
+    return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+    int i = OGR_F_GetGeomFieldIndex(self, name);
+    if (i == -1)
+    {
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      return NULL;
+    }
+    else
+      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+  }
 SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
     return (OGRFeatureShadow*) OGR_F_Clone(self);
   }
@@ -684,6 +778,20 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatu
 	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
+    return OGR_F_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+      return NULL;
+  }
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShadow *self,int id){
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
@@ -745,6 +853,9 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
       return OGR_F_GetFieldIndex(self, name);
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
+      return OGR_F_GetGeomFieldIndex(self, name);
+  }
 SWIGINTERN int OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
   }
@@ -817,6 +928,24 @@ SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList(OGRFeatureShadow *self,int i
 SWIGINTERN void OGRFeatureShadow_SetFieldStringList(OGRFeatureShadow *self,int id,char **pList){
       OGR_F_SetFieldStringList(self, id, pList);
   }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureShadow *self,int id,char const *pszValue){
+     int nBytes;
+     GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+     OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
+     CPLFree(pabyBuf);
+  }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      {
+        int nBytes;
+        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+        CPLFree(pabyBuf);
+      }
+  }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
     return OGR_F_SetFrom(self, other, forgiving);
   }
@@ -848,6 +977,35 @@ SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *
 	      OGR_F_GetFieldDefnRef( self,  i )
 	      );
   }
+
+    static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
+    {
+        switch(field_type)
+        {
+            case wkbUnknown:
+            case wkbPoint:
+            case wkbLineString:
+            case wkbPolygon:
+            case wkbMultiPoint:
+            case wkbMultiLineString:
+            case wkbMultiPolygon:
+            case wkbGeometryCollection:
+            case wkbNone:
+            /*case wkbLinearRing:*/
+            case wkbPoint25D:
+            case wkbLineString25D:
+            case wkbPolygon25D:
+            case wkbMultiPoint25D:
+            case wkbMultiLineString25D:
+            case wkbMultiPolygon25D:
+            case wkbGeometryCollection25D:
+                return TRUE;
+            default:
+                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
+                return FALSE;
+        }
+    }
+
 SWIGINTERN void delete_OGRFeatureDefnShadow(OGRFeatureDefnShadow *self){
     /*OGR_FD_Destroy(self);*/
     OGR_FD_Release( OGRFeatureDefnH(self) );
@@ -872,11 +1030,27 @@ SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,cha
 SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
     OGR_FD_AddFieldDefn(self, defn);
   }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldCount(OGRFeatureDefnShadow *self){
+    return OGR_FD_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn(OGRFeatureDefnShadow *self,int i){
+    return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
+  }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex(OGRFeatureDefnShadow *self,char const *name){
+      return OGR_FD_GetGeomFieldIndex(self, name);
+  }
+SWIGINTERN void OGRFeatureDefnShadow_AddGeomFieldDefn(OGRFeatureDefnShadow *self,OGRGeomFieldDefnShadow *defn){
+    OGR_FD_AddGeomFieldDefn(self, defn);
+  }
+SWIGINTERN OGRErr OGRFeatureDefnShadow_DeleteGeomFieldDefn(OGRFeatureDefnShadow *self,int idx){
+    return OGR_FD_DeleteGeomFieldDefn(self, idx);
+  }
 SWIGINTERN OGRwkbGeometryType OGRFeatureDefnShadow_GetGeomType(OGRFeatureDefnShadow *self){
     return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
   }
 SWIGINTERN void OGRFeatureDefnShadow_SetGeomType(OGRFeatureDefnShadow *self,OGRwkbGeometryType geom_type){
-    OGR_FD_SetGeomType(self, geom_type);
+    if( ValidateOGRGeometryType(geom_type) )
+        OGR_FD_SetGeomType(self, geom_type);
   }
 SWIGINTERN int OGRFeatureDefnShadow_GetReferenceCount(OGRFeatureDefnShadow *self){
     return OGR_FD_GetReferenceCount(self);
@@ -893,6 +1067,9 @@ SWIGINTERN int OGRFeatureDefnShadow_IsStyleIgnored(OGRFeatureDefnShadow *self){
 SWIGINTERN void OGRFeatureDefnShadow_SetStyleIgnored(OGRFeatureDefnShadow *self,int bIgnored){
     return OGR_FD_SetStyleIgnored(self,bIgnored);
   }
+SWIGINTERN int OGRFeatureDefnShadow_IsSame(OGRFeatureDefnShadow *self,OGRFeatureDefnShadow *other_defn){
+    return OGR_FD_IsSame(self, other_defn);
+  }
 
     static int ValidateOGRFieldType(OGRFieldType field_type)
     {
@@ -970,6 +1147,46 @@ SWIGINTERN int OGRFieldDefnShadow_IsIgnored(OGRFieldDefnShadow *self){
 SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgnored){
     return OGR_Fld_SetIgnored( self, bIgnored );
   }
+SWIGINTERN void delete_OGRGeomFieldDefnShadow(OGRGeomFieldDefnShadow *self){
+    OGR_GFld_Destroy(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *new_OGRGeomFieldDefnShadow(char const *name_null_ok="",OGRwkbGeometryType field_type=wkbUnknown){
+    if( ValidateOGRGeometryType(field_type) )
+        return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
+    else
+        return NULL;
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetName(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetNameRef(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetName(OGRGeomFieldDefnShadow *self,char const *name){
+    OGR_GFld_SetName(self, name);
+  }
+SWIGINTERN OGRwkbGeometryType OGRGeomFieldDefnShadow_GetType(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_GetType(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetType(OGRGeomFieldDefnShadow *self,OGRwkbGeometryType type){
+    if( ValidateOGRGeometryType(type) )
+        OGR_GFld_SetType(self, type);
+  }
+SWIGINTERN OSRSpatialReferenceShadow *OGRGeomFieldDefnShadow_GetSpatialRef(OGRGeomFieldDefnShadow *self){
+    OGRSpatialReferenceH ref =  OGR_GFld_GetSpatialRef(self);
+    if( ref )
+        OSRReference(ref);
+    return (OSRSpatialReferenceShadow*) ref;
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetSpatialRef(OGRGeomFieldDefnShadow *self,OSRSpatialReferenceShadow *srs){
+     OGR_GFld_SetSpatialRef( self, (OGRSpatialReferenceH)srs );
+  }
+SWIGINTERN int OGRGeomFieldDefnShadow_IsIgnored(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_IsIgnored( self );
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetIgnored(OGRGeomFieldDefnShadow *self,int bIgnored){
+    OGR_GFld_SetIgnored( self, bIgnored );
+  }
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
@@ -1581,6 +1798,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_OLCStringsAsUTF8_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_OLCCreateGeomField_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("CreateGeomField");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCCreateLayer_get() {
   char * jresult ;
   char *result = 0 ;
@@ -1601,6 +1828,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCDeleteLayer_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCCreateGeomFieldAfterCreateLayer_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("CreateGeomFieldAfterCreateLayer");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_ODrCCreateDataSource_get() {
   char * jresult ;
   char *result = 0 ;
@@ -2080,15 +2317,13 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_Envelope3D(void * jarg1) {
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_name_get(void * jarg1) {
-  char * jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_StyleTable() {
+  void * jresult ;
+  OGRStyleTableShadow *result = 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRDriverShadow_name_get(arg1);
+    result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2108,24 +2343,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_name_get(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CreateDataSource(void * jarg1, char * jarg2, void * jarg3) {
-  void * jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char **arg3 = (char **) 0 ;
-  OGRDataSourceShadow *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_StyleTable(void * jarg1) {
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  arg3 = (char **)jarg3; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+    delete_OGRStyleTableShadow(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2145,26 +2374,22 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CreateDataSource(void * jarg1, char
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CopyDataSource(void * jarg1, void * jarg2, char * jarg3, void * jarg4) {
-  void * jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_StyleTable_AddStyle(void * jarg1, char * jarg2, char * jarg3) {
+  int jresult ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
-  char **arg4 = (char **) 0 ;
-  OGRDataSourceShadow *result = 0 ;
+  int result;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
-  arg2 = (OGRDataSourceShadow *)jarg2; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
   arg3 = (char *)jarg3; 
-  arg4 = (char **)jarg4; 
   {
     CPLErrorReset();
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
+    result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2184,24 +2409,22 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CopyDataSource(void * jarg1, void *
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_Open(void * jarg1, char * jarg2, int jarg3) {
-  void * jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_StyleTable_LoadStyleTable(void * jarg1, char * jarg2) {
+  int jresult ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  int arg3 = (int) 0 ;
-  OGRDataSourceShadow *result = 0 ;
+  int result;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   arg2 = (char *)jarg2; 
-  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
+    result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2221,22 +2444,22 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_Open(void * jarg1, char * jarg2, int
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Driver_DeleteDataSource(void * jarg1, char * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_StyleTable_SaveStyleTable(void * jarg1, char * jarg2) {
   int jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int result;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
+    result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2261,24 +2484,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Driver_DeleteDataSource(void * jarg1, char * j
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Driver_TestCapability(void * jarg1, char * jarg2) {
-  unsigned int jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_StyleTable_Find(void * jarg1, char * jarg2) {
+  char * jresult ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  bool result;
+  char *result = 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
-  {
     CPLErrorReset();
-    result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
+    result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2298,20 +2514,18 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Driver_TestCapability(void * jarg1, c
     
     
   }
-  jresult = result; 
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_GetName(void * jarg1) {
-  char * jresult ;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_StyleTable_ResetStyleStringReading(void * jarg1) {
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRDriverShadow_GetName(arg1);
+    OGRStyleTableShadow_ResetStyleStringReading(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2331,18 +2545,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_GetName(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Register(void * jarg1) {
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_StyleTable_GetNextStyle(void * jarg1) {
+  char * jresult ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRDriverShadow_Register(arg1);
+    result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2362,16 +2576,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Register(void * jarg1) {
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Deregister(void * jarg1) {
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_StyleTable_GetLastStyleName(void * jarg1) {
+  char * jresult ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRDriverShadow *)jarg1; 
+  arg1 = (OGRStyleTableShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRDriverShadow_Deregister(arg1);
+    result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2391,18 +2609,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Deregister(void * jarg1) {
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_name_get(void * jarg1) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_name_get(void * jarg1) {
   char * jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *result = 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRDataSourceShadow_name_get(arg1);
+    result = (char *)OGRDriverShadow_name_get(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2427,13 +2647,19 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_name_get(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_delete_DataSource(void * jarg1) {
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CreateDataSource(void * jarg1, char * jarg2, void * jarg3) {
+  void * jresult ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char **arg3 = (char **) 0 ;
+  OGRDataSourceShadow *result = 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char **)jarg3; 
   {
     CPLErrorReset();
-    delete_OGRDataSourceShadow(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2453,18 +2679,26 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_DataSource(void * jarg1) {
     
     
   }
+  jresult = (void *)result; 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetRefCount(void * jarg1) {
-  int jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_CopyDataSource(void * jarg1, void * jarg2, char * jarg3, void * jarg4) {
+  void * jresult ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
+  OGRDataSourceShadow *result = 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
+  arg2 = (OGRDataSourceShadow *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (char **)jarg4; 
   {
     CPLErrorReset();
-    result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2484,20 +2718,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetRefCount(void * jarg1) {
     
     
   }
-  jresult = result; 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetSummaryRefCount(void * jarg1) {
-  int jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_Driver_Open(void * jarg1, char * jarg2, int jarg3) {
+  void * jresult ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 = (int) 0 ;
+  OGRDataSourceShadow *result = 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2517,20 +2755,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetSummaryRefCount(void * jarg1) {
     
     
   }
-  jresult = result; 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetLayerCount(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Driver_DeleteDataSource(void * jarg1, char * jarg2) {
   int jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   int result;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
+    result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2555,15 +2795,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetLayerCount(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetDriver(void * jarg1) {
-  void * jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  OGRDriverShadow *result = 0 ;
-  
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Driver_TestCapability(void * jarg1, char * jarg2) {
+  unsigned int jresult ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  bool result;
+  
+  arg1 = (OGRDriverShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+    result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2583,20 +2832,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetDriver(void * jarg1) {
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_GetName(void * jarg1) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_GetName(void * jarg1) {
   char * jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *result = 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRDataSourceShadow_GetName(arg1);
+    result = (char *)OGRDriverShadow_GetName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2621,17 +2870,13 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_GetName(void * jarg1) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_DeleteLayer(void * jarg1, int jarg2) {
-  int jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int arg2 ;
-  OGRErr result;
+SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Register(void * jarg1) {
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRDriverShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+    OGRDriverShadow_Register(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2651,27 +2896,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_DeleteLayer(void * jarg1, int jarg2
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_SyncToDisk(void * jarg1) {
-  int jresult ;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  OGRErr result;
+SWIGEXPORT void SWIGSTDCALL CSharp_Driver_Deregister(void * jarg1) {
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   
-  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg1 = (OGRDriverShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+    OGRDriverShadow_Deregister(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2691,42 +2925,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_SyncToDisk(void * jarg1) {
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CreateLayer(void * jarg1, char * jarg2, void * jarg3, int jarg4, void * jarg5) {
-  void * jresult ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_name_get(void * jarg1) {
+  char * jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
-  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
-  char **arg5 = (char **) 0 ;
-  OGRLayerShadow *result = 0 ;
+  char *result = 0 ;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  arg3 = (OSRSpatialReferenceShadow *)jarg3; 
-  arg4 = (OGRwkbGeometryType)jarg4; 
-  arg5 = (char **)jarg5; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+    result = (char *)OGRDataSourceShadow_name_get(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2746,33 +2956,18 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CreateLayer(void * jarg1, char *
     
     
   }
-  jresult = (void *)result; 
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CopyLayer(void * jarg1, void * jarg2, char * jarg3, void * jarg4) {
-  void * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_DataSource(void * jarg1) {
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  char *arg3 = (char *) 0 ;
-  char **arg4 = (char **) 0 ;
-  OGRLayerShadow *result = 0 ;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (char *)jarg3; 
-  arg4 = (char **)jarg4; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+    delete_OGRDataSourceShadow(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2792,22 +2987,18 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CopyLayer(void * jarg1, void * j
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByIndex(void * jarg1, int jarg2) {
-  void * jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetRefCount(void * jarg1) {
+  int jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int arg2 = (int) 0 ;
-  OGRLayerShadow *result = 0 ;
+  int result;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+    result = (int)OGRDataSourceShadow_GetRefCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2827,22 +3018,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByIndex(void * jarg1, in
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByName(void * jarg1, char * jarg2) {
-  void * jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetSummaryRefCount(void * jarg1) {
+  int jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OGRLayerShadow *result = 0 ;
+  int result;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+    result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2862,29 +3051,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByName(void * jarg1, cha
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_DataSource_TestCapability(void * jarg1, char * jarg2) {
-  unsigned int jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_GetLayerCount(void * jarg1) {
+  int jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  bool result;
+  int result;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+    result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2909,28 +3089,15 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_DataSource_TestCapability(void * jarg
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_ExecuteSQL(void * jarg1, char * jarg2, void * jarg3, char * jarg4) {
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetDriver(void * jarg1) {
   void * jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
-  char *arg4 = (char *) "" ;
-  OGRLayerShadow *result = 0 ;
+  OGRDriverShadow *result = 0 ;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  arg3 = (OGRGeometryShadow *)jarg3; 
-  arg4 = (char *)jarg4; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+    result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2955,15 +3122,15 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_ExecuteSQL(void * jarg1, char *
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_DataSource_ReleaseResultSet(void * jarg1, void * jarg2) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_DataSource_GetName(void * jarg1) {
+  char * jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *result = 0 ;
   
   arg1 = (OGRDataSourceShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
   {
     CPLErrorReset();
-    OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+    result = (char *)OGRDataSourceShadow_GetName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2983,18 +3150,22 @@ SWIGEXPORT void SWIGSTDCALL CSharp_DataSource_ReleaseResultSet(void * jarg1, voi
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetRefCount(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_DeleteLayer(void * jarg1, int jarg2) {
   int jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int result;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  int arg2 ;
+  OGRErr result;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRLayerShadow_GetRefCount(arg1);
+    result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3014,20 +3185,27 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetRefCount(void * jarg1) {
     
     
   }
-  jresult = result; 
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilter(void * jarg1, void * jarg2) {
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_SyncToDisk(void * jarg1) {
+  int jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRErr result;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRGeometryShadow *)jarg2; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRLayerShadow_SetSpatialFilter(arg1,arg2);
+    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3047,24 +3225,42 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilter(void * jarg1, void * j
     
     
   }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilterRect(void * jarg1, double jarg2, double jarg3, double jarg4, double jarg5) {
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  double arg2 ;
-  double arg3 ;
-  double arg4 ;
-  double arg5 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CreateLayer(void * jarg1, char * jarg2, void * jarg3, int jarg4, void * jarg5) {
+  void * jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
+  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
+  char **arg5 = (char **) 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (double)jarg2; 
-  arg3 = (double)jarg3; 
-  arg4 = (double)jarg4; 
-  arg5 = (double)jarg5; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OSRSpatialReferenceShadow *)jarg3; 
+  arg4 = (OGRwkbGeometryType)jarg4; 
+  arg5 = (char **)jarg5; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    OGRLayerShadow_SetSpatialFilterRect(arg1,arg2,arg3,arg4,arg5);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3084,18 +3280,33 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilterRect(void * jarg1, doub
     
     
   }
-}
+  jresult = (void *)result; 
+  return jresult;
+}
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialFilter(void * jarg1) {
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_CopyLayer(void * jarg1, void * jarg2, char * jarg3, void * jarg4) {
   void * jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRGeometryShadow *result = 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (char **)jarg4; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3120,17 +3331,17 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialFilter(void * jarg1) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetAttributeFilter(void * jarg1, char * jarg2) {
-  int jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OGRErr result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByIndex(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3150,25 +3361,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetAttributeFilter(void * jarg1, char *
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Layer_ResetReading(void * jarg1) {
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetLayerByName(void * jarg1, char * jarg2) {
+  void * jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    OGRLayerShadow_ResetReading(arg1);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3188,18 +3396,29 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Layer_ResetReading(void * jarg1) {
     
     
   }
+  jresult = (void *)result; 
+  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetName(void * jarg1) {
-  char * jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_DataSource_TestCapability(void * jarg1, char * jarg2) {
+  unsigned int jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  bool result;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (char *)OGRLayerShadow_GetName(arg1);
+    result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3219,20 +3438,33 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetName(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetGeomType(void * jarg1) {
-  int jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRwkbGeometryType result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_ExecuteSQL(void * jarg1, char * jarg2, void * jarg3, char * jarg4) {
+  void * jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
+  char *arg4 = (char *) "" ;
+  OGRLayerShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
+  arg4 = (char *)jarg4; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3252,20 +3484,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetGeomType(void * jarg1) {
     
     
   }
-  jresult = result; 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetGeometryColumn(void * jarg1) {
-  char * jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_DataSource_ReleaseResultSet(void * jarg1, void * jarg2) {
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
   {
     CPLErrorReset();
-    result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+    OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3285,20 +3517,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetGeometryColumn(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetFIDColumn(void * jarg1) {
-  char * jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_DataSource_GetStyleTable(void * jarg1) {
+  void * jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRStyleTableShadow *result = 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+    result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3318,22 +3548,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetFIDColumn(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetFeature(void * jarg1, long jarg2) {
-  void * jresult ;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
-  OGRFeatureShadow *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_DataSource_SetStyleTable(void * jarg1, void * jarg2) {
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
   
-  arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (long)jarg2; 
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  arg2 = (OGRStyleTableShadow *)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+    OGRDataSourceShadow_SetStyleTable(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3353,20 +3581,18 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetFeature(void * jarg1, long jarg2)
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetNextFeature(void * jarg1) {
-  void * jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetRefCount(void * jarg1) {
+  int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureShadow *result = 0 ;
+  int result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
+    result = (int)OGRLayerShadow_GetRefCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3386,22 +3612,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetNextFeature(void * jarg1) {
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetNextByIndex(void * jarg1, long jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilter__SWIG_0(void * jarg1, void * jarg2) {
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
-  OGRErr result;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (long)jarg2; 
+  arg2 = (OGRGeometryShadow *)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3421,36 +3645,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetNextByIndex(void * jarg1, long jarg2)
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetFeature(void * jarg1, void * jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilterRect__SWIG_0(void * jarg1, double jarg2, double jarg3, double jarg4, double jarg5) {
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  OGRErr result;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRFeatureShadow *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
+  arg2 = (double)jarg2; 
+  arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3470,36 +3682,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetFeature(void * jarg1, void * jarg2) {
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateFeature(void * jarg1, void * jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilter__SWIG_1(void * jarg1, int jarg2, void * jarg3) {
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  OGRErr result;
+  int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRFeatureShadow *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
+  arg2 = (int)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3519,29 +3715,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateFeature(void * jarg1, void * jarg2
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteFeature(void * jarg1, long jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetSpatialFilterRect__SWIG_1(void * jarg1, int jarg2, double jarg3, double jarg4, double jarg5, double jarg6) {
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
-  OGRErr result;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  double arg6 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (long)jarg2; 
+  arg2 = (int)jarg2; 
+  arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
+  arg6 = (double)jarg6; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3561,27 +3754,53 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteFeature(void * jarg1, long jarg2)
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialFilter(void * jarg1) {
+  void * jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
     
   }
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SyncToDisk(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetAttributeFilter(void * jarg1, char * jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
+    result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3613,15 +3832,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SyncToDisk(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetLayerDefn(void * jarg1) {
-  void * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_ResetReading(void * jarg1) {
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureDefnShadow *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
+    OGRLayerShadow_ResetReading(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3641,22 +3858,18 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetLayerDefn(void * jarg1) {
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetFeatureCount(void * jarg1, int jarg2) {
-  int jresult ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetName(void * jarg1) {
+  char * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 = (int) 1 ;
-  int result;
+  char *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
+    result = (char *)OGRLayerShadow_GetName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3676,24 +3889,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetFeatureCount(void * jarg1, int jarg2)
     
     
   }
-  jresult = result; 
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetExtent(void * jarg1, void * jarg2, int jarg3) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetGeomType(void * jarg1) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGREnvelope *arg2 = (OGREnvelope *) 0 ;
-  int arg3 = (int) 1 ;
-  OGRErr result;
+  OGRwkbGeometryType result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGREnvelope *)jarg2; 
-  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
+    result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3713,36 +3922,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetExtent(void * jarg1, void * jarg2, in
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Layer_TestCapability(void * jarg1, char * jarg2) {
-  unsigned int jresult ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetGeometryColumn(void * jarg1) {
+  char * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  bool result;
+  char *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+    result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3762,31 +3955,20 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Layer_TestCapability(void * jarg1, ch
     
     
   }
-  jresult = result; 
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateField(void * jarg1, void * jarg2, int jarg3) {
-  int jresult ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_Layer_GetFIDColumn(void * jarg1) {
+  char * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
-  int arg3 = (int) 1 ;
-  OGRErr result;
+  char *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRFieldDefnShadow *)jarg2; 
-  arg3 = (int)jarg3; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+    result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3806,29 +3988,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateField(void * jarg1, void * jarg2,
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteField(void * jarg1, int jarg2) {
-  int jresult ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetFeature(void * jarg1, long jarg2) {
+  void * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  OGRErr result;
+  long arg2 ;
+  OGRFeatureShadow *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg2 = (long)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+    result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3848,31 +4023,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteField(void * jarg1, int jarg2) {
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderField(void * jarg1, int jarg2, int jarg3) {
-  int jresult ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetNextFeature(void * jarg1) {
+  void * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
-  OGRErr result;
+  OGRFeatureShadow *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+    result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3892,34 +4056,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderField(void * jarg1, int jarg2, in
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderFields(void * jarg1, int jarg2, void * jarg3) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetNextByIndex(void * jarg1, long jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
+  long arg2 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  {
-    /* %typemap(in) (int inout[ANY]) */
-    arg3 = (int *)jarg3;
-  }
+  arg2 = (long)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+    result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -3951,20 +4103,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderFields(void * jarg1, int jarg2, v
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_AlterFieldDefn(void * jarg1, int jarg2, void * jarg3, int jarg4) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetFeature(void * jarg1, void * jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
-  int arg4 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (OGRFieldDefnShadow *)jarg3; 
-  arg4 = (int)jarg4; 
+  arg2 = (OGRFeatureShadow *)jarg2; 
   {
-    if (!arg3) {
+    if (!arg2) {
       {
         SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
       };
@@ -3972,7 +4120,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_AlterFieldDefn(void * jarg1, int jarg2,
   }
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+    result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4004,15 +4152,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_AlterFieldDefn(void * jarg1, int jarg2,
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_StartTransaction(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateFeature(void * jarg1, void * jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRFeatureShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4044,15 +4201,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_StartTransaction(void * jarg1) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CommitTransaction(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteFeature(void * jarg1, long jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  long arg2 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (long)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4084,7 +4243,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CommitTransaction(void * jarg1) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_RollbackTransaction(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SyncToDisk(void * jarg1) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRErr result;
@@ -4092,7 +4251,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_RollbackTransaction(void * jarg1) {
   arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4124,15 +4283,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_RollbackTransaction(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialRef(void * jarg1) {
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetLayerDefn(void * jarg1) {
   void * jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OSRSpatialReferenceShadow *result = 0 ;
+  OGRFeatureDefnShadow *result = 0 ;
   
   arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+    result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4157,15 +4316,17 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialRef(void * jarg1) {
 }
 
 
-SWIGEXPORT GIntBig SWIGSTDCALL CSharp_Layer_GetFeaturesRead(void * jarg1) {
-  GIntBig jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetFeatureCount(void * jarg1, int jarg2) {
+  int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  GIntBig result;
+  int arg2 = (int) 1 ;
+  int result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = OGRLayerShadow_GetFeaturesRead(arg1);
+    result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4190,17 +4351,19 @@ SWIGEXPORT GIntBig SWIGSTDCALL CSharp_Layer_GetFeaturesRead(void * jarg1) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetIgnoredFields(void * jarg1, void * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_GetExtent(void * jarg1, void * jarg2, int jarg3) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char **arg2 = (char **) 0 ;
+  OGREnvelope *arg2 = (OGREnvelope *) 0 ;
+  int arg3 = (int) 1 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (char **)jarg2; 
+  arg2 = (OGREnvelope *)jarg2; 
+  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+    result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4232,31 +4395,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetIgnoredFields(void * jarg1, void * ja
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Intersection(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
-  int jresult ;
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Layer_TestCapability(void * jarg1, char * jarg2) {
+  unsigned int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
-  OGRErr result;
+  char *arg2 = (char *) 0 ;
+  bool result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
-  }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4276,43 +4432,31 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Intersection(void * jarg1, void * jarg2,
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Union(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateField(void * jarg1, void * jarg2, int jarg3) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+  int arg3 = (int) 1 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
+  arg2 = (OGRFieldDefnShadow *)jarg2; 
+  arg3 = (int)jarg3; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
   }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4344,31 +4488,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Union(void * jarg1, void * jarg2, void *
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SymDifference(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteField(void * jarg1, int jarg2) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  int arg2 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
-  }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4400,31 +4530,19 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SymDifference(void * jarg1, void * jarg2
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Identity(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderField(void * jarg1, int jarg2, int jarg3) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  int arg2 ;
+  int arg3 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
-  }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
+  arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4456,31 +4574,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Identity(void * jarg1, void * jarg2, voi
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Update(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_ReorderFields(void * jarg1, int jarg2, void * jarg3) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
+  arg2 = (int)jarg2; 
+  {
+    /* %typemap(in) (int inout[ANY]) */
+    arg3 = (int *)jarg3;
   }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4512,31 +4621,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Update(void * jarg1, void * jarg2, void
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Clip(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_AlterFieldDefn(void * jarg1, int jarg2, void * jarg3, int jarg4) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  int arg2 ;
+  OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
+  int arg4 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
+  arg2 = (int)jarg2; 
+  arg3 = (OGRFieldDefnShadow *)jarg3; 
+  arg4 = (int)jarg4; 
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
   }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4568,31 +4674,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Clip(void * jarg1, void * jarg2, void *
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Erase(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateGeomField(void * jarg1, void * jarg2, int jarg3) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
-  GDALProgressFunc *argp5 ;
+  OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
+  int arg3 = (int) 1 ;
   OGRErr result;
   
   arg1 = (OGRLayerShadow *)jarg1; 
-  arg2 = (OGRLayerShadow *)jarg2; 
-  arg3 = (OGRLayerShadow *)jarg3; 
-  arg4 = (char **)jarg4; 
-  argp5 = (GDALProgressFunc *)jarg5; 
-  if (!argp5) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null GDALProgressFunc", 0);
-    return 0;
+  arg2 = (OGRGeomFieldDefnShadow *)jarg2; 
+  arg3 = (int)jarg3; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
   }
-  arg5 = *argp5; 
-  arg6 = (void *)jarg6; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4624,13 +4725,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Erase(void * jarg1, void * jarg2, void *
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_delete_Feature(void * jarg1) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_StartTransaction(void * jarg1) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRErr result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    delete_OGRFeatureShadow(arg1);
+    result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4650,58 +4753,27 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_Feature(void * jarg1) {
     
     
   }
-}
-
-
-SWIGEXPORT void * SWIGSTDCALL CSharp_new_Feature(void * jarg1) {
-  void * jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRFeatureShadow *result = 0 ;
-  
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
-    if (!arg1) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
   }
   {
-    CPLErrorReset();
-    result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    /* %typemap(ret) OGRErr */
     
   }
-  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetDefnRef(void * jarg1) {
-  void * jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureDefnShadow *result = 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CommitTransaction(void * jarg1) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRErr result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+    result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4721,22 +4793,27 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetDefnRef(void * jarg1) {
     
     
   }
-  jresult = (void *)result; 
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometry(void * jarg1, void * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_RollbackTransaction(void * jarg1) {
   int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRErr result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (OGRGeometryShadow *)jarg2; 
+  arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4768,17 +4845,19 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometry(void * jarg1, void * jarg2
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometryDirectly(void * jarg1, void * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_FindFieldIndex(void * jarg1, char * jarg2, int jarg3) {
   int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-  OGRErr result;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (OGRGeometryShadow *)jarg2; 
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+    result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4798,27 +4877,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometryDirectly(void * jarg1, void
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeometryRef(void * jarg1) {
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetSpatialRef(void * jarg1) {
   void * jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRGeometryShadow *result = 0 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OSRSpatialReferenceShadow *result = 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRLayerShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4843,15 +4915,1678 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeometryRef(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_Clone(void * jarg1) {
-  void * jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *result = 0 ;
-  
+SWIGEXPORT GIntBig SWIGSTDCALL CSharp_Layer_GetFeaturesRead(void * jarg1) {
+  GIntBig jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  GIntBig result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = OGRLayerShadow_GetFeaturesRead(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SetIgnoredFields(void * jarg1, void * jarg2) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (char **)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Intersection(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Union(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_SymDifference(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Identity(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Update(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Clip(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_Erase(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRLayerShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (char **)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Layer_GetStyleTable(void * jarg1) {
+  void * jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRStyleTableShadow *result = 0 ;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Layer_SetStyleTable(void * jarg1, void * jarg2) {
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (OGRStyleTableShadow *)jarg2; 
+  {
+    CPLErrorReset();
+    OGRLayerShadow_SetStyleTable(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_Feature(void * jarg1) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_OGRFeatureShadow(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_Feature(void * jarg1) {
+  void * jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFeatureShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetDefnRef(void * jarg1) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureDefnShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometry(void * jarg1, void * jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (OGRGeometryShadow *)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeometryDirectly(void * jarg1, void * jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (OGRGeometryShadow *)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeometryRef(void * jarg1) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeomField__SWIG_0(void * jarg1, int jarg2, void * jarg3) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeomField__SWIG_1(void * jarg1, char * jarg2, void * jarg3) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeomFieldDirectly__SWIG_0(void * jarg1, int jarg2, void * jarg3) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetGeomFieldDirectly__SWIG_1(void * jarg1, char * jarg2, void * jarg3) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OGRGeometryShadow *)jarg3; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeomFieldRef__SWIG_0(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeomFieldRef__SWIG_1(void * jarg1, char * jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_Clone(void * jarg1) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_Equal(void * jarg1, void * jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  bool result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (OGRFeatureShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldCount(void * jarg1) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_0(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRFieldDefnShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_1(void * jarg1, char * jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRFieldDefnShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetGeomFieldCount(void * jarg1) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeomFieldDefnRef__SWIG_0(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetGeomFieldDefnRef__SWIG_1(void * jarg1, char * jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_0(void * jarg1, int jarg2) {
+  char * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  char *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_1(void * jarg1, char * jarg2) {
+  char * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_0(void * jarg1, int jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_1(void * jarg1, char * jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_0(void * jarg1, int jarg2) {
+  double jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  double result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_1(void * jarg1, char * jarg2) {
+  double jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  double result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime(void * jarg1, int jarg2, int * jarg3, int * jarg4, int * jarg5, int * jarg6, int * jarg7, int * jarg8, int * jarg9) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  int *arg7 = (int *) 0 ;
+  int *arg8 = (int *) 0 ;
+  int *arg9 = (int *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (int *)jarg3; 
+  arg4 = (int *)jarg4; 
+  arg5 = (int *)jarg5; 
+  arg6 = (int *)jarg6; 
+  arg7 = (int *)jarg7; 
+  arg8 = (int *)jarg8; 
+  arg9 = (int *)jarg9; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsIntegerList(void * jarg1, int jarg2, void * jarg3) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  int *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    /* %typemap(in) (int *hasval) */
+    arg3 = (int *)jarg3;
+  }
+  {
+    CPLErrorReset();
+    result = (int *)OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsDoubleList(void * jarg1, int jarg2, void * jarg3) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  double *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    /* %typemap(in) (int *hasval) */
+    arg3 = (int *)jarg3;
+  }
+  {
+    CPLErrorReset();
+    result = (double *)OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsStringList(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  char **result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_0(void * jarg1, int jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  bool result;
+  
   arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4871,19 +6606,19 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_Clone(void * jarg1) {
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_Equal(void * jarg1, void * jarg2) {
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_1(void * jarg1, char * jarg2) {
   unsigned int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   bool result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (OGRFeatureShadow *)jarg2; 
+  arg2 = (char *)jarg2; 
   {
     if (!arg2) {
       {
@@ -4893,7 +6628,7 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_Equal(void * jarg1, void * ja
   }
   {
     CPLErrorReset();
-    result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4918,15 +6653,99 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_Equal(void * jarg1, void * ja
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldCount(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldIndex(void * jarg1, char * jarg2) {
   int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   int result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+    result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetGeomFieldIndex(void * jarg1, char * jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFID(void * jarg1) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRFeatureShadow_GetFID(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4951,17 +6770,157 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldCount(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_0(void * jarg1, int jarg2) {
-  void * jresult ;
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFID(void * jarg1, int jarg2) {
+  int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRErr result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_DumpReadable(void * jarg1) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_DumpReadable(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_0(void * jarg1, int jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_1(void * jarg1, char * jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_0(void * jarg1, int jarg2, char * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  OGRFieldDefnShadow *result = 0 ;
+  char *arg3 = (char *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (char *)jarg3; 
   {
     CPLErrorReset();
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+    OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -4981,29 +6940,27 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_0(void * jarg
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_1(void * jarg1, char * jarg2) {
-  void * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_1(void * jarg1, char * jarg2, char * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  OGRFieldDefnShadow *result = 0 ;
+  char *arg3 = (char *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+    OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5023,22 +6980,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldDefnRef__SWIG_1(void * jarg
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_0(void * jarg1, int jarg2) {
-  char * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_2(void * jarg1, int jarg2, int jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  char *result = 0 ;
+  int arg3 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+    OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5058,29 +7013,27 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_0(void * jar
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_1(void * jarg1, char * jarg2) {
-  char * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_3(void * jarg1, char * jarg2, int jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  char *result = 0 ;
+  int arg3 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
+  arg3 = (int)jarg3; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+    OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5100,22 +7053,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetFieldAsString__SWIG_1(void * jar
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_0(void * jarg1, int jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_4(void * jarg1, int jarg2, double jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  int result;
+  double arg3 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (double)jarg3; 
   {
     CPLErrorReset();
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+    OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5135,29 +7086,27 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_0(void * jarg1
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_1(void * jarg1, char * jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_5(void * jarg1, char * jarg2, double jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  int result;
+  double arg3 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
+  arg3 = (double)jarg3; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+    OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5177,22 +7126,32 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldAsInteger__SWIG_1(void * jarg1
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_0(void * jarg1, int jarg2) {
-  double jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_6(void * jarg1, int jarg2, int jarg3, int jarg4, int jarg5, int jarg6, int jarg7, int jarg8, int jarg9) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  double result;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  int arg9 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
+  arg4 = (int)jarg4; 
+  arg5 = (int)jarg5; 
+  arg6 = (int)jarg6; 
+  arg7 = (int)jarg7; 
+  arg8 = (int)jarg8; 
+  arg9 = (int)jarg9; 
   {
     CPLErrorReset();
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+    OGRFeatureShadow_SetField__SWIG_6(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5212,29 +7171,39 @@ SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_0(void * jar
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_1(void * jarg1, char * jarg2) {
-  double jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_7(void * jarg1, char * jarg2, int jarg3, int jarg4, int jarg5, int jarg6, int jarg7, int jarg8, int jarg9) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  double result;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  int arg9 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
+  arg3 = (int)jarg3; 
+  arg4 = (int)jarg4; 
+  arg5 = (int)jarg5; 
+  arg6 = (int)jarg6; 
+  arg7 = (int)jarg7; 
+  arg8 = (int)jarg8; 
+  arg9 = (int)jarg9; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+    OGRFeatureShadow_SetField__SWIG_7(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5254,72 +7223,25 @@ SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_1(void * jar
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime(void * jarg1, int jarg2, int * jarg3, int * jarg4, int * jarg5, int * jarg6, int * jarg7, int * jarg8, int * jarg9) {
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldIntegerList(void * jarg1, int jarg2, int jarg3, void * jarg4) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  int *arg3 = (int *) 0 ;
+  int arg3 ;
   int *arg4 = (int *) 0 ;
-  int *arg5 = (int *) 0 ;
-  int *arg6 = (int *) 0 ;
-  int *arg7 = (int *) 0 ;
-  int *arg8 = (int *) 0 ;
-  int *arg9 = (int *) 0 ;
-  
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (int *)jarg3; 
-  arg4 = (int *)jarg4; 
-  arg5 = (int *)jarg5; 
-  arg6 = (int *)jarg6; 
-  arg7 = (int *)jarg7; 
-  arg8 = (int *)jarg8; 
-  arg9 = (int *)jarg9; 
-  {
-    CPLErrorReset();
-    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-  }
-}
-
-
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsIntegerList(void * jarg1, int jarg2, void * jarg3) {
-  void * jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
-  int *result = 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
   {
-    /* %typemap(in) (int *hasval) */
-    arg3 = (int *)jarg3;
+    /* %typemap(in) (int inout[ANY]) */
+    arg4 = (int *)jarg4;
   }
   {
     CPLErrorReset();
-    result = (int *)OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3);
+    OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5339,27 +7261,25 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsIntegerList(void * jarg1,
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsDoubleList(void * jarg1, int jarg2, void * jarg3) {
-  void * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldDoubleList(void * jarg1, int jarg2, int jarg3, void * jarg4) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  int *arg3 = (int *) 0 ;
-  double *result = 0 ;
+  int arg3 ;
+  double *arg4 = (double *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
   {
-    /* %typemap(in) (int *hasval) */
-    arg3 = (int *)jarg3;
+    /* %typemap(in) (double inout[ANY]) */
+    arg4 = (double *)jarg4;
   }
   {
     CPLErrorReset();
-    result = (double *)OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3);
+    OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5379,22 +7299,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsDoubleList(void * jarg1,
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsStringList(void * jarg1, int jarg2) {
-  void * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldStringList(void * jarg1, int jarg2, void * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  char **result = 0 ;
+  char **arg3 = (char **) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (char **)jarg3; 
   {
     CPLErrorReset();
-    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5414,22 +7332,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Feature_GetFieldAsStringList(void * jarg1,
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_0(void * jarg1, int jarg2) {
-  unsigned int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldBinaryFromHexString__SWIG_0(void * jarg1, int jarg2, char * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  bool result;
+  char *arg3 = (char *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
+  arg3 = (char *)jarg3; 
   {
     CPLErrorReset();
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5449,29 +7365,27 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_0(void * jar
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_1(void * jarg1, char * jarg2) {
-  unsigned int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldBinaryFromHexString__SWIG_1(void * jarg1, char * jarg2, char * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  bool result;
+  char *arg3 = (char *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5491,19 +7405,19 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_1(void * jar
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldIndex(void * jarg1, char * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFrom(void * jarg1, void * jarg2, int jarg3) {
   int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  int result;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  int arg3 = (int) 1 ;
+  OGRErr result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
+  arg2 = (OGRFeatureShadow *)jarg2; 
+  arg3 = (int)jarg3; 
   {
     if (!arg2) {
       {
@@ -5513,7 +7427,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldIndex(void * jarg1, char * jar
   }
   {
     CPLErrorReset();
-    result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+    result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5533,20 +7447,45 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldIndex(void * jarg1, char * jar
     
     
   }
-  jresult = result; 
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFID(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFromWithMap(void * jarg1, void * jarg2, int jarg3, int jarg4, void * jarg5) {
   int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int result;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 = (int *) 0 ;
+  OGRErr result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (OGRFeatureShadow *)jarg2; 
+  arg3 = (int)jarg3; 
+  arg4 = (int)jarg4; 
+  {
+    /* %typemap(in) (int inout[ANY]) */
+    arg5 = (int *)jarg5;
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (int)OGRFeatureShadow_GetFID(arg1);
+    result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5566,22 +7505,27 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFID(void * jarg1) {
     
     
   }
-  jresult = result; 
+  {
+    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
+    jresult = result;
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    
+  }
   return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFID(void * jarg1, int jarg2) {
-  int jresult ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetStyleString(void * jarg1) {
+  char * jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  OGRErr result;
+  char *result = 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+    result = (char *)OGRFeatureShadow_GetStyleString(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5601,25 +7545,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFID(void * jarg1, int jarg2) {
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_DumpReadable(void * jarg1) {
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetStyleString(void * jarg1, char * jarg2) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_DumpReadable(arg1);
+    OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5642,15 +7581,17 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_DumpReadable(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_0(void * jarg1, int jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_0(void * jarg1, int jarg2) {
+  int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
+  OGRFieldType result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5670,25 +7611,29 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_0(void * jarg1, int
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_1(void * jarg1, char * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_1(void * jarg1, char * jarg2) {
+  int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
+  OGRFieldType result;
   
   arg1 = (OGRFeatureShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
       };
     }
   }
   {
     CPLErrorReset();
-    OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5708,24 +7653,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_1(void * jarg1, char
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_0(void * jarg1, int jarg2, char * jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  char *arg3 = (char *) 0 ;
-  string str3 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_FeatureDefn(void * jarg1) {
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  {
-    /* %typemap(in) (tostring argin) */
-    arg3 = (char *)jarg3;
-  }
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+    delete_OGRFeatureDefnShadow(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5748,28 +7687,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_0(void * jarg1, int ja
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_1(void * jarg1, char * jarg2, char * jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char *arg3 = (char *) 0 ;
-  string str3 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_FeatureDefn(char * jarg1) {
+  void * jresult ;
+  char *arg1 = (char *) NULL ;
+  OGRFeatureDefnShadow *result = 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    /* %typemap(in) (tostring argin) */
-    arg3 = (char *)jarg3;
-  }
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
-      };
-    }
-  }
+  arg1 = (char *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5789,20 +7715,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_1(void * jarg1, char *
     
     
   }
+  jresult = (void *)result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_2(void * jarg1, int jarg2, int jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_FeatureDefn_GetName(void * jarg1) {
+  char * jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (int)jarg3; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+    result = (char *)OGRFeatureDefnShadow_GetName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5822,27 +7748,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_2(void * jarg1, int ja
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_3(void * jarg1, char * jarg2, int jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  int arg3 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldCount(void * jarg1) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  arg3 = (int)jarg3; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
-      };
-    }
-  }
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+    result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5862,20 +7781,22 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_3(void * jarg1, char *
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_4(void * jarg1, int jarg2, double jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_FeatureDefn_GetFieldDefn(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
-  double arg3 ;
+  OGRFieldDefnShadow *result = 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   arg2 = (int)jarg2; 
-  arg3 = (double)jarg3; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3);
+    result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5895,72 +7816,29 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_4(void * jarg1, int ja
     
     
   }
+  jresult = (void *)result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_5(void * jarg1, char * jarg2, double jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldIndex(void * jarg1, char * jarg2) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  double arg3 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   arg2 = (char *)jarg2; 
-  arg3 = (double)jarg3; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
       };
     }
   }
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3);
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-  }
-}
-
-
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_6(void * jarg1, int jarg2, int jarg3, int jarg4, int jarg5, int jarg6, int jarg7, int jarg8, int jarg9) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
-  int arg6 ;
-  int arg7 ;
-  int arg8 ;
-  int arg9 ;
-  
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (int)jarg3; 
-  arg4 = (int)jarg4; 
-  arg5 = (int)jarg5; 
-  arg6 = (int)jarg6; 
-  arg7 = (int)jarg7; 
-  arg8 = (int)jarg8; 
-  arg9 = (int)jarg9; 
-  {
-    CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_6(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -5980,29 +7858,17 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_6(void * jarg1, int ja
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_7(void * jarg1, char * jarg2, int jarg3, int jarg4, int jarg5, int jarg6, int jarg7, int jarg8, int jarg9) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
-  int arg6 ;
-  int arg7 ;
-  int arg8 ;
-  int arg9 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_AddFieldDefn(void * jarg1, void * jarg2) {
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  arg3 = (int)jarg3; 
-  arg4 = (int)jarg4; 
-  arg5 = (int)jarg5; 
-  arg6 = (int)jarg6; 
-  arg7 = (int)jarg7; 
-  arg8 = (int)jarg8; 
-  arg9 = (int)jarg9; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (OGRFieldDefnShadow *)jarg2; 
   {
     if (!arg2) {
       {
@@ -6012,7 +7878,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_7(void * jarg1, char *
   }
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetField__SWIG_7(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6035,22 +7901,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_7(void * jarg1, char *
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldIntegerList(void * jarg1, int jarg2, int jarg3, void * jarg4) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
-  int *arg4 = (int *) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetGeomFieldCount(void * jarg1) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (int)jarg3; 
-  {
-    /* %typemap(in) (int inout[ANY]) */
-    arg4 = (int *)jarg4;
-  }
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+    result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6070,25 +7929,22 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldIntegerList(void * jarg1, int
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldDoubleList(void * jarg1, int jarg2, int jarg3, void * jarg4) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_FeatureDefn_GetGeomFieldDefn(void * jarg1, int jarg2) {
+  void * jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
-  int arg3 ;
-  double *arg4 = (double *) 0 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   arg2 = (int)jarg2; 
-  arg3 = (int)jarg3; 
-  {
-    /* %typemap(in) (double inout[ANY]) */
-    arg4 = (double *)jarg4;
-  }
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6108,20 +7964,29 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldDoubleList(void * jarg1, int
     
     
   }
+  jresult = (void *)result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldStringList(void * jarg1, int jarg2, void * jarg3) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  char **arg3 = (char **) 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetGeomFieldIndex(void * jarg1, char * jarg2) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
-  arg3 = (char **)jarg3; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+    result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6141,29 +8006,27 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldStringList(void * jarg1, int
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFrom(void * jarg1, void * jarg2, int jarg3) {
-  int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  int arg3 = (int) 1 ;
-  OGRErr result;
+SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_AddGeomFieldDefn(void * jarg1, void * jarg2) {
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (OGRFeatureShadow *)jarg2; 
-  arg3 = (int)jarg3; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (OGRGeomFieldDefnShadow *)jarg2; 
   {
     if (!arg2) {
       {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
       };
     }
   }
   {
     CPLErrorReset();
-    result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+    OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6183,45 +8046,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFrom(void * jarg1, void * jarg2, in
     
     
   }
-  {
-    /* %typemap(out,fragment="OGRErrMessages",canthrow=1) OGRErr */
-    jresult = result;
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    
-  }
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFromWithMap(void * jarg1, void * jarg2, int jarg3, int jarg4, void * jarg5) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_DeleteGeomFieldDefn(void * jarg1, int jarg2) {
   int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  int arg3 ;
-  int arg4 ;
-  int *arg5 = (int *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int arg2 ;
   OGRErr result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (OGRFeatureShadow *)jarg2; 
-  arg3 = (int)jarg3; 
-  arg4 = (int)jarg4; 
-  {
-    /* %typemap(in) (int inout[ANY]) */
-    arg5 = (int *)jarg5;
-  }
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+    result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6253,15 +8091,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_SetFromWithMap(void * jarg1, void * ja
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetStyleString(void * jarg1) {
-  char * jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetGeomType(void * jarg1) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRwkbGeometryType result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+    result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6281,20 +8119,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetStyleString(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetStyleString(void * jarg1, char * jarg2) {
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeomType(void * jarg1, int jarg2) {
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRwkbGeometryType arg2 ;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (OGRwkbGeometryType)jarg2; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+    OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6317,17 +8155,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetStyleString(void * jarg1, char * j
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_0(void * jarg1, int jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetReferenceCount(void * jarg1) {
   int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  OGRFieldType result;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+    result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6352,24 +8188,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_0(void * jarg1, int
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_1(void * jarg1, char * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsGeometryIgnored(void * jarg1) {
   int jresult ;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OGRFieldType result;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int result;
   
-  arg1 = (OGRFeatureShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+    result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6394,13 +8221,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldType__SWIG_1(void * jarg1, cha
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_delete_FeatureDefn(void * jarg1) {
+SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeometryIgnored(void * jarg1, int jarg2) {
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int arg2 ;
   
   arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    delete_OGRFeatureDefnShadow(arg1);
+    OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6423,15 +8252,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_FeatureDefn(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_new_FeatureDefn(char * jarg1) {
-  void * jresult ;
-  char *arg1 = (char *) NULL ;
-  OGRFeatureDefnShadow *result = 0 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsStyleIgnored(void * jarg1) {
+  int jresult ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int result;
   
-  arg1 = (char *)jarg1; 
+  arg1 = (OGRFeatureDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+    result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6451,20 +8280,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_new_FeatureDefn(char * jarg1) {
     
     
   }
-  jresult = (void *)result; 
+  jresult = result; 
   return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_FeatureDefn_GetName(void * jarg1) {
-  char * jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetStyleIgnored(void * jarg1, int jarg2) {
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  char *result = 0 ;
+  int arg2 ;
   
   arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+    OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6484,20 +8313,27 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FeatureDefn_GetName(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldCount(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsSame(void * jarg1, void * jarg2) {
   int jresult ;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFeatureDefnShadow *arg2 = (OGRFeatureDefnShadow *) 0 ;
   int result;
   
   arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg2 = (OGRFeatureDefnShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+    result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6522,17 +8358,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldCount(void * jarg1) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_FeatureDefn_GetFieldDefn(void * jarg1, int jarg2) {
-  void * jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int arg2 ;
-  OGRFieldDefnShadow *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_FieldDefn(void * jarg1) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+    delete_OGRFieldDefnShadow(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6552,29 +8384,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_FeatureDefn_GetFieldDefn(void * jarg1, int
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldIndex(void * jarg1, char * jarg2) {
-  int jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  int result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_FieldDefn(char * jarg1, int jarg2) {
+  void * jresult ;
+  char *arg1 = (char *) "unnamed" ;
+  OGRFieldType arg2 = (OGRFieldType) OFTString ;
+  OGRFieldDefnShadow *result = 0 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
-      };
-    }
-  }
+  arg1 = (char *)jarg1; 
+  arg2 = (OGRFieldType)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+    result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6594,27 +8417,53 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetFieldIndex(void * jarg1, char *
     
     
   }
-  jresult = result; 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_AddFieldDefn(void * jarg1, void * jarg2) {
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetName(void * jarg1) {
+  char * jresult ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
-  arg2 = (OGRFieldDefnShadow *)jarg2; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
-      };
+    CPLErrorReset();
+    result = (char *)OGRFieldDefnShadow_GetName(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
     }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetNameRef(void * jarg1) {
+  char * jresult ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  char *result = 0 ;
+  
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+    result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6634,18 +8483,27 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_AddFieldDefn(void * jarg1, void *
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetGeomType(void * jarg1) {
-  int jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRwkbGeometryType result;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetName(void * jarg1, char * jarg2) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+    OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6665,20 +8523,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetGeomType(void * jarg1) {
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeomType(void * jarg1, int jarg2) {
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRwkbGeometryType arg2 ;
+SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetFieldType(void * jarg1) {
+  int jresult ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldType result;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
-  arg2 = (OGRwkbGeometryType)jarg2; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+    result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6698,18 +8554,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeomType(void * jarg1, int jar
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetReferenceCount(void * jarg1) {
-  int jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int result;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetType(void * jarg1, int jarg2) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldType arg2 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (OGRFieldType)jarg2; 
   {
     CPLErrorReset();
-    result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
+    OGRFieldDefnShadow_SetType(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6729,20 +8587,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_GetReferenceCount(void * jarg1) {
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsGeometryIgnored(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetJustify(void * jarg1) {
   int jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int result;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRJustification result;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+    result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6767,15 +8623,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsGeometryIgnored(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeometryIgnored(void * jarg1, int jarg2) {
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int arg2 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetJustify(void * jarg1, int jarg2) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRJustification arg2 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (OGRJustification)jarg2; 
   {
     CPLErrorReset();
-    OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+    OGRFieldDefnShadow_SetJustify(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6798,15 +8654,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetGeometryIgnored(void * jarg1,
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsStyleIgnored(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetWidth(void * jarg1) {
   int jresult ;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int result;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+    result = (int)OGRFieldDefnShadow_GetWidth(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6831,15 +8687,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FeatureDefn_IsStyleIgnored(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetStyleIgnored(void * jarg1, int jarg2) {
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetWidth(void * jarg1, int jarg2) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   
-  arg1 = (OGRFeatureDefnShadow *)jarg1; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
   arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+    OGRFieldDefnShadow_SetWidth(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6862,13 +8718,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FeatureDefn_SetStyleIgnored(void * jarg1, int
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_delete_FieldDefn(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetPrecision(void * jarg1) {
+  int jresult ;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  int result;
   
   arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    delete_OGRFieldDefnShadow(arg1);
+    result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6888,20 +8746,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_FieldDefn(void * jarg1) {
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_new_FieldDefn(char * jarg1, int jarg2) {
-  void * jresult ;
-  char *arg1 = (char *) "unnamed" ;
-  OGRFieldType arg2 = (OGRFieldType) OFTString ;
-  OGRFieldDefnShadow *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetPrecision(void * jarg1, int jarg2) {
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  int arg2 ;
   
-  arg1 = (char *)jarg1; 
-  arg2 = (OGRFieldType)jarg2; 
+  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+    OGRFieldDefnShadow_SetPrecision(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6921,12 +8779,10 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_new_FieldDefn(char * jarg1, int jarg2) {
     
     
   }
-  jresult = (void *)result; 
-  return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetName(void * jarg1) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetTypeName(void * jarg1) {
   char * jresult ;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   char *result = 0 ;
@@ -6934,7 +8790,7 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetName(void * jarg1) {
   arg1 = (OGRFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRFieldDefnShadow_GetName(arg1);
+    result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6959,15 +8815,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetName(void * jarg1) {
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetNameRef(void * jarg1) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetFieldTypeName(void * jarg1, int jarg2) {
   char * jresult ;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldType arg2 ;
   char *result = 0 ;
   
   arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (OGRFieldType)jarg2; 
   {
     CPLErrorReset();
-    result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+    result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -6992,22 +8850,15 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetNameRef(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetName(void * jarg1, char * jarg2) {
+SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_IsIgnored(void * jarg1) {
+  int jresult ;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  int result;
   
   arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (char *)jarg2; 
-  {
-    if (!arg2) {
-      {
-        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
-      };
-    }
-  }
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+    result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7027,18 +8878,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetName(void * jarg1, char * jarg2)
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetFieldType(void * jarg1) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetIgnored(void * jarg1, int jarg2) {
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRFieldType result;
+  int arg2 ;
   
   arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+    OGRFieldDefnShadow_SetIgnored(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7058,20 +8911,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetFieldType(void * jarg1) {
     
     
   }
-  jresult = result; 
-  return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetType(void * jarg1, int jarg2) {
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRFieldType arg2 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GeomFieldDefn(void * jarg1) {
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (OGRFieldType)jarg2; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetType(arg1,arg2);
+    delete_OGRGeomFieldDefnShadow(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7094,15 +8943,17 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetType(void * jarg1, int jarg2) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetJustify(void * jarg1) {
-  int jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRJustification result;
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GeomFieldDefn(char * jarg1, int jarg2) {
+  void * jresult ;
+  char *arg1 = (char *) "" ;
+  OGRwkbGeometryType arg2 = (OGRwkbGeometryType) wkbUnknown ;
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (char *)jarg1; 
+  arg2 = (OGRwkbGeometryType)jarg2; 
   {
     CPLErrorReset();
-    result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+    result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7122,20 +8973,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetJustify(void * jarg1) {
     
     
   }
-  jresult = result; 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetJustify(void * jarg1, int jarg2) {
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRJustification arg2 ;
+SWIGEXPORT char * SWIGSTDCALL CSharp_GeomFieldDefn_GetName(void * jarg1) {
+  char * jresult ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (OGRJustification)jarg2; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetJustify(arg1,arg2);
+    result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7155,18 +9006,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetJustify(void * jarg1, int jarg2)
     
     
   }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetWidth(void * jarg1) {
-  int jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int result;
+SWIGEXPORT char * SWIGSTDCALL CSharp_GeomFieldDefn_GetNameRef(void * jarg1) {
+  char * jresult ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  char *result = 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+    result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7186,20 +9039,27 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetWidth(void * jarg1) {
     
     
   }
-  jresult = result; 
+  jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetWidth(void * jarg1, int jarg2) {
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int arg2 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_GeomFieldDefn_SetName(void * jarg1, char * jarg2) {
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetWidth(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7222,15 +9082,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetWidth(void * jarg1, int jarg2) {
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetPrecision(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_GeomFieldDefn_GetFieldType(void * jarg1) {
   int jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int result;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OGRwkbGeometryType result;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+    result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7255,15 +9115,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_GetPrecision(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetPrecision(void * jarg1, int jarg2) {
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int arg2 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_GeomFieldDefn_SetType(void * jarg1, int jarg2) {
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OGRwkbGeometryType arg2 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (int)jarg2; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
+  arg2 = (OGRwkbGeometryType)jarg2; 
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetType(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7286,15 +9146,15 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetPrecision(void * jarg1, int jarg
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetTypeName(void * jarg1) {
-  char * jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  char *result = 0 ;
+SWIGEXPORT void * SWIGSTDCALL CSharp_GeomFieldDefn_GetSpatialRef(void * jarg1) {
+  void * jresult ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OSRSpatialReferenceShadow *result = 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+    result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7314,22 +9174,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetTypeName(void * jarg1) {
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
+  jresult = (void *)result; 
   return jresult;
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetFieldTypeName(void * jarg1, int jarg2) {
-  char * jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRFieldType arg2 ;
-  char *result = 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_GeomFieldDefn_SetSpatialRef(void * jarg1, void * jarg2) {
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
-  arg2 = (OGRFieldType)jarg2; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
+  arg2 = (OSRSpatialReferenceShadow *)jarg2; 
   {
     CPLErrorReset();
-    result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7349,20 +9207,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FieldDefn_GetFieldTypeName(void * jarg1, in
     
     
   }
-  jresult = SWIG_csharp_string_callback((const char *)result); 
-  return jresult;
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_IsIgnored(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_GeomFieldDefn_IsIgnored(void * jarg1) {
   int jresult ;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   int result;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   {
     CPLErrorReset();
-    result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+    result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7387,15 +9243,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_FieldDefn_IsIgnored(void * jarg1) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_FieldDefn_SetIgnored(void * jarg1, int jarg2) {
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+SWIGEXPORT void SWIGSTDCALL CSharp_GeomFieldDefn_SetIgnored(void * jarg1, int jarg2) {
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   int arg2 ;
   
-  arg1 = (OGRFieldDefnShadow *)jarg1; 
+  arg1 = (OGRGeomFieldDefnShadow *)jarg1; 
   arg2 = (int)jarg2; 
   {
     CPLErrorReset();
-    OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
diff --git a/swig/csharp/ogr/osr_wrap.cpp b/swig/csharp/ogr/osr_wrap.cpp
index 09232cb..6611f78 100644
--- a/swig/csharp/ogr/osr_wrap.cpp
+++ b/swig/csharp/ogr/osr_wrap.cpp
@@ -466,6 +466,9 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *s
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(OSRSpatialReferenceShadow *self){
+    return OSREPSGTreatsAsNorthingEasting(self);
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAuthority(OSRSpatialReferenceShadow *self,char const *pszTargetKey,char const *pszAuthority,int nCode){
     return OSRSetAuthority( self, pszTargetKey, pszAuthority, nCode );
   }
@@ -1616,6 +1619,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_EPSGTreatsAsLatLong(void * ja
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_EPSGTreatsAsNorthingEasting(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetAuthority(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
diff --git a/swig/csharp/osr/Osr.cs b/swig/csharp/osr/Osr.cs
index 9f47d43..42d9b71 100644
--- a/swig/csharp/osr/Osr.cs
+++ b/swig/csharp/osr/Osr.cs
@@ -30,12 +30,36 @@ public class Osr {
     OsrPINVOKE.DontUseExceptions();
   }
 
+
+  internal static byte[] StringToUtf8Bytes(string str)
+  {
+    if (str == null)
+      return null;
+    
+    int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
+    byte[] bytes = new byte[bytecount + 1];
+    System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
+    return bytes;
+  }
+  
+  internal static string Utf8BytesToString(IntPtr pNativeData)
+  {
+    if (pNativeData == IntPtr.Zero)
+        return null;
+        
+    int length = Marshal.PtrToStringAnsi(pNativeData).Length;
+    byte[] strbuf = new byte[length];  
+    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    return System.Text.Encoding.UTF8.GetString(strbuf);
+  }
+
   internal static void StringListDestroy(IntPtr buffer_ptr) {
     OsrPINVOKE.StringListDestroy(buffer_ptr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
   }
 
 public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
+public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data);
   public static int GetWellKnownGeogCSAsWKT(string name, out string argout) {
     int ret = OsrPINVOKE.GetWellKnownGeogCSAsWKT(name, out argout);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -210,6 +234,44 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_UL_ROD_CONV = "5.02921005842012";
   public const string SRS_UL_LINK_Clarke = "Link_Clarke";
   public const string SRS_UL_LINK_Clarke_CONV = "0.2011661949";
+  public const string SRS_UL_KILOMETER = "Kilometer";
+  public const string SRS_UL_KILOMETER_CONV = "1000.";
+  public const string SRS_UL_DECIMETER = "Decimeter";
+  public const string SRS_UL_DECIMETER_CONV = "0.1";
+  public const string SRS_UL_CENTIMETER = "Centimeter";
+  public const string SRS_UL_CENTIMETER_CONV = "0.01";
+  public const string SRS_UL_MILLIMETER = "Millimeter";
+  public const string SRS_UL_MILLIMETER_CONV = "0.001";
+  public const string SRS_UL_INTL_NAUT_MILE = "Nautical_Mile_International";
+  public const string SRS_UL_INTL_NAUT_MILE_CONV = "1852.0";
+  public const string SRS_UL_INTL_INCH = "Inch_International";
+  public const string SRS_UL_INTL_INCH_CONV = "0.0254";
+  public const string SRS_UL_INTL_FOOT = "Foot_International";
+  public const string SRS_UL_INTL_FOOT_CONV = "0.3048";
+  public const string SRS_UL_INTL_YARD = "Yard_International";
+  public const string SRS_UL_INTL_YARD_CONV = "0.9144";
+  public const string SRS_UL_INTL_STAT_MILE = "Statute_Mile_International";
+  public const string SRS_UL_INTL_STAT_MILE_CONV = "1609.344";
+  public const string SRS_UL_INTL_FATHOM = "Fathom_International";
+  public const string SRS_UL_INTL_FATHOM_CONV = "1.8288";
+  public const string SRS_UL_INTL_CHAIN = "Chain_International";
+  public const string SRS_UL_INTL_CHAIN_CONV = "20.1168";
+  public const string SRS_UL_INTL_LINK = "Link_International";
+  public const string SRS_UL_INTL_LINK_CONV = "0.201168";
+  public const string SRS_UL_US_INCH = "Inch_US_Surveyor";
+  public const string SRS_UL_US_INCH_CONV = "0.025400050800101603";
+  public const string SRS_UL_US_YARD = "Yard_US_Surveyor";
+  public const string SRS_UL_US_YARD_CONV = "0.914401828803658";
+  public const string SRS_UL_US_CHAIN = "Chain_US_Surveyor";
+  public const string SRS_UL_US_CHAIN_CONV = "20.11684023368047";
+  public const string SRS_UL_US_STAT_MILE = "Statute_Mile_US_Surveyor";
+  public const string SRS_UL_US_STAT_MILE_CONV = "1609.347218694437";
+  public const string SRS_UL_INDIAN_YARD = "Yard_Indian";
+  public const string SRS_UL_INDIAN_YARD_CONV = "0.91439523";
+  public const string SRS_UL_INDIAN_FOOT = "Foot_Indian";
+  public const string SRS_UL_INDIAN_FOOT_CONV = "0.30479841";
+  public const string SRS_UL_INDIAN_CHAIN = "Chain_Indian";
+  public const string SRS_UL_INDIAN_CHAIN_CONV = "20.11669506";
   public const string SRS_UA_DEGREE = "degree";
   public const string SRS_UA_DEGREE_CONV = "0.0174532925199433";
   public const string SRS_UA_RADIAN = "radian";
diff --git a/swig/csharp/osr/OsrPINVOKE.cs b/swig/csharp/osr/OsrPINVOKE.cs
index c7873c7..f1a1869 100644
--- a/swig/csharp/osr/OsrPINVOKE.cs
+++ b/swig/csharp/osr/OsrPINVOKE.cs
@@ -274,6 +274,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsLatLong")]
   public static extern int SpatialReference_EPSGTreatsAsLatLong(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsNorthingEasting")]
+  public static extern int SpatialReference_EPSGTreatsAsNorthingEasting(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetAuthority")]
   public static extern int SpatialReference_SetAuthority(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
 
diff --git a/swig/csharp/osr/SpatialReference.cs b/swig/csharp/osr/SpatialReference.cs
index 89044db..7d0b861 100644
--- a/swig/csharp/osr/SpatialReference.cs
+++ b/swig/csharp/osr/SpatialReference.cs
@@ -138,6 +138,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int EPSGTreatsAsNorthingEasting() {
+    int ret = OsrPINVOKE.SpatialReference_EPSGTreatsAsNorthingEasting(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetAuthority(string pszTargetKey, string pszAuthority, int nCode) {
     int ret = OsrPINVOKE.SpatialReference_SetAuthority(swigCPtr, pszTargetKey, pszAuthority, nCode);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/osr/osr_wrap.cpp b/swig/csharp/osr/osr_wrap.cpp
index 09232cb..6611f78 100644
--- a/swig/csharp/osr/osr_wrap.cpp
+++ b/swig/csharp/osr/osr_wrap.cpp
@@ -466,6 +466,9 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *s
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(OSRSpatialReferenceShadow *self){
+    return OSREPSGTreatsAsNorthingEasting(self);
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAuthority(OSRSpatialReferenceShadow *self,char const *pszTargetKey,char const *pszAuthority,int nCode){
     return OSRSetAuthority( self, pszTargetKey, pszAuthority, nCode );
   }
@@ -1616,6 +1619,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_EPSGTreatsAsLatLong(void * ja
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_EPSGTreatsAsNorthingEasting(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetAuthority(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
diff --git a/swig/include/Band.i b/swig/include/Band.i
index 2a1148e..ffe30ae 100644
--- a/swig/include/Band.i
+++ b/swig/include/Band.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Band.i 21773 2011-02-21 19:28:07Z rouault $
+ * $Id: Band.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     Band.i
  * Project:  GDAL Python Interface
@@ -543,6 +543,107 @@ CPLErr SetDefaultHistogram( double min, double max,
   }
 %clear char **papszMetadata;
 
+#if defined(SWIGPYTHON)
+%feature( "kwargs" ) GetVirtualMem;
+%newobject GetVirtualMem;
+  CPLVirtualMemShadow* GetVirtualMem( GDALRWFlag eRWFlag,
+                                      int nXOff, int nYOff,
+                                      int nXSize, int nYSize,
+                                      int nBufXSize, int nBufYSize,
+                                      GDALDataType eBufType,
+                                      size_t nCacheSize,
+                                      size_t nPageSizeHint,
+                                      char **options = NULL )
+    {
+        CPLVirtualMem* vmem = GDALRasterBandGetVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nBufXSize, nBufYSize,
+                                         eBufType,
+                                         0,
+                                         0,
+                                         nCacheSize,
+                                         nPageSizeHint,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = TRUE;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nBufXSize;
+        vmemshadow->nBufYSize = nBufYSize;
+        vmemshadow->nBandCount = 1;
+        return vmemshadow;
+    }
+
+%feature( "kwargs" ) GetVirtualMemAuto;
+%newobject GetVirtualMemAuto;
+  CPLVirtualMemShadow* GetVirtualMemAuto( GDALRWFlag eRWFlag,
+                                          char **options = NULL )
+    {
+        int            nPixelSpace;
+        GIntBig        nLineSpace;
+        CPLVirtualMem* vmem = GDALGetVirtualMemAuto( self,
+                                         eRWFlag,
+                                         &nPixelSpace,
+                                         &nLineSpace,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = GDALGetRasterDataType( self );
+        vmemshadow->bAuto = TRUE;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBandCount = 1;
+        vmemshadow->nPixelSpace = nPixelSpace;
+        vmemshadow->nLineSpace = nLineSpace;
+        vmemshadow->nBufXSize = GDALGetRasterBandXSize(self);
+        vmemshadow->nBufYSize = GDALGetRasterBandYSize(self);
+        return vmemshadow;
+    }
+
+%feature( "kwargs" ) GetTiledVirtualMem;
+%newobject GetTiledVirtualMem;
+  CPLVirtualMemShadow* GetTiledVirtualMem( GDALRWFlag eRWFlag,
+                                      int nXOff, int nYOff,
+                                      int nXSize, int nYSize,
+                                      int nTileXSize, int nTileYSize,
+                                      GDALDataType eBufType,
+                                      size_t nCacheSize,
+                                      char **options = NULL )
+    {
+        CPLVirtualMem* vmem = GDALRasterBandGetTiledVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nTileXSize, nTileYSize,
+                                         eBufType,
+                                         nCacheSize,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = -1;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nXSize;
+        vmemshadow->nBufYSize = nYSize;
+        vmemshadow->eTileOrganization = GTO_BSQ;
+        vmemshadow->nTileXSize = nTileXSize;
+        vmemshadow->nTileYSize = nTileYSize;
+        vmemshadow->nBandCount = 1;
+        return vmemshadow;
+    }
+
+#endif /* #if defined(SWIGPYTHON) */
+
 } /* %extend */
 
 };
diff --git a/swig/include/Dataset.i b/swig/include/Dataset.i
index ce0eba8..ce458f7 100644
--- a/swig/include/Dataset.i
+++ b/swig/include/Dataset.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Dataset.i 25738 2013-03-12 18:39:09Z rouault $
+ * $Id: Dataset.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     Dataset.i
  * Project:  GDAL Python Interface
@@ -195,11 +195,13 @@ static GDALAsyncReaderH AsyncReaderWrapperGetReader(GDALAsyncReaderWrapperH hWra
     return psWrapper->hAsyncReader;
 }
 
+#if defined(SWIGPYTHON)
 static void* AsyncReaderWrapperGetPyObject(GDALAsyncReaderWrapperH hWrapper)
 {
     GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
     return psWrapper->pyObject;
 }
+#endif
 
 static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 {
@@ -730,7 +732,109 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
     GDALEndAsyncReader(self, hReader);
     DisableAsyncReaderWrapper(ario);
   }
-#endif
+
+%feature( "kwargs" ) GetVirtualMem;
+%newobject GetVirtualMem;
+%apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
+  CPLVirtualMemShadow* GetVirtualMem( GDALRWFlag eRWFlag,
+                                      int nXOff, int nYOff,
+                                      int nXSize, int nYSize,
+                                      int nBufXSize, int nBufYSize,
+                                      GDALDataType eBufType,
+                                      int band_list, int *pband_list,
+                                      int bIsBandSequential,
+                                      size_t nCacheSize,
+                                      size_t nPageSizeHint,
+                                      char** options = NULL )
+    {
+        int nPixelSpace;
+        GIntBig nBandSpace;
+        if( bIsBandSequential != 0 && bIsBandSequential != 1 )
+            return NULL;
+        if( band_list == 0 )
+            return NULL;
+        if( bIsBandSequential || band_list == 1 )
+        {
+            nPixelSpace = 0;
+            nBandSpace = 0;
+        }
+        else
+        {
+            nBandSpace = GDALGetDataTypeSize(eBufType) / 8;
+            nPixelSpace  = nBandSpace * band_list;
+        }
+        CPLVirtualMem* vmem = GDALDatasetGetVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nBufXSize, nBufYSize,
+                                         eBufType,
+                                         band_list, pband_list,
+                                         nPixelSpace,
+                                         0,
+                                         nBandSpace,
+                                         nCacheSize,
+                                         nPageSizeHint,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = bIsBandSequential;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nBufXSize;
+        vmemshadow->nBufYSize = nBufYSize;
+        vmemshadow->nBandCount = band_list;
+        return vmemshadow;
+    }
+%clear(int band_list, int *pband_list);
+
+%feature( "kwargs" ) GetTiledVirtualMem;
+%newobject GetTiledVirtualMem;
+%apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
+  CPLVirtualMemShadow* GetTiledVirtualMem( GDALRWFlag eRWFlag,
+                                      int nXOff, int nYOff,
+                                      int nXSize, int nYSize,
+                                      int nTileXSize, int nTileYSize,
+                                      GDALDataType eBufType,
+                                      int band_list, int *pband_list,
+                                      GDALTileOrganization eTileOrganization,
+                                      size_t nCacheSize,
+                                      char** options = NULL )
+    {
+        if( band_list == 0 )
+            return NULL;
+        CPLVirtualMem* vmem = GDALDatasetGetTiledVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nTileXSize, nTileYSize,
+                                         eBufType,
+                                         band_list, pband_list,
+                                         eTileOrganization,
+                                         nCacheSize,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = -1;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nXSize;
+        vmemshadow->nBufYSize = nYSize;
+        vmemshadow->eTileOrganization = eTileOrganization;
+        vmemshadow->nTileXSize = nTileXSize;
+        vmemshadow->nTileYSize = nTileYSize;
+        vmemshadow->nBandCount = band_list;
+        return vmemshadow;
+    }
+%clear(int band_list, int *pband_list);
+
+#endif /* PYTHON */
 
 } /* extend */
 }; /* GDALDatasetShadow */
diff --git a/swig/include/MajorObject.i b/swig/include/MajorObject.i
index e3a0f98..5be76f8 100644
--- a/swig/include/MajorObject.i
+++ b/swig/include/MajorObject.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: MajorObject.i 21979 2011-03-18 22:22:32Z rouault $
+ * $Id: MajorObject.i 26569 2013-10-29 23:51:12Z rouault $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  SWIG Definitions for GDALMajorObject.
@@ -52,6 +52,13 @@ public:
   }
 %clear const char * pszNewDesc;
 
+
+%apply (char **CSL) {(char **)};
+  char ** GetMetadataDomainList( ) {
+    return GDALGetMetadataDomainList( self );
+  }
+%clear char **;
+
 /*
  * GetMetadata methods
  */
diff --git a/swig/include/RasterAttributeTable.i b/swig/include/RasterAttributeTable.i
index 11328d3..104bf01 100644
--- a/swig/include/RasterAttributeTable.i
+++ b/swig/include/RasterAttributeTable.i
@@ -169,6 +169,10 @@ public:
     int GetRowOfValue( double dfValue ) {
         return GDALRATGetRowOfValue( self, dfValue );
     }
+
+    int ChangesAreWrittenToFile() {
+        return GDALRATChangesAreWrittenToFile( self );
+    }
 }
 
 };
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index e3c92b8..d929f33 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 26276 2013-08-08 19:15:31Z rouault $
+ * $Id: cpl.i 26526 2013-10-11 11:49:24Z tamas $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -385,7 +385,9 @@ int VSIRename(const char * pszOld, const char *pszNew );
 
 #if !defined(SWIGJAVA)
 
+#if !defined(SWIGCSHARP)
 typedef void VSILFILE;
+#endif
 
 #if defined(SWIGPERL)
 %apply RETURN_NONE_TRUE_IS_ERROR {RETURN_NONE};
diff --git a/swig/include/cplvirtualmem.i b/swig/include/cplvirtualmem.i
new file mode 100644
index 0000000..b1044c5
--- /dev/null
+++ b/swig/include/cplvirtualmem.i
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * $Id: cplvirtualmem.i 26832 2014-01-15 12:46:08Z rouault $
+ *
+ * Name:     cplvirtualmem.i
+ * Project:  GDAL Python Interface
+ * Purpose:  GDAL Core SWIG Interface declarations.
+ * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+//************************************************************************/
+//
+// Define the extensions for CPLVirtualMem (nee CPLVirtualMemShadow)
+//
+//************************************************************************/
+
+#if defined(SWIGPYTHON)
+%{
+#include "gdal.h"
+
+typedef struct
+{
+    CPLVirtualMem *vmem;
+    int            bAuto;
+    GDALDataType   eBufType;
+    int            bIsBandSequential;
+    int            bReadOnly;
+    int            nBufXSize;
+    int            nBufYSize;
+    int            nBandCount;
+    GDALTileOrganization eTileOrganization;
+    int                  nTileXSize;
+    int                  nTileYSize;
+    int            nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace; /* if bAuto == TRUE */
+} CPLVirtualMemShadow;
+
+%}
+
+%rename (VirtualMem) CPLVirtualMemShadow;
+
+class CPLVirtualMemShadow {
+private:
+  CPLVirtualMemShadow();
+public:
+%extend {
+    ~CPLVirtualMemShadow()
+    {
+        CPLVirtualMemFree( self->vmem );
+        free(self);
+    }
+
+    void GetAddr(void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)
+    {
+        *pptr = CPLVirtualMemGetAddr( self->vmem );
+        *pnsize = CPLVirtualMemGetSize( self->vmem );
+        *pdatatype = self->eBufType;
+        *preadonly = self->bReadOnly;
+    }
+
+    void Pin(size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0 )
+    {
+        if( nsize == 0 || start_offset + nsize >= CPLVirtualMemGetSize( self->vmem ) )
+            nsize = CPLVirtualMemGetSize( self->vmem ) - start_offset;
+        char* start_addr = (char*)CPLVirtualMemGetAddr( self->vmem ) + start_offset;
+        CPLVirtualMemPin(self->vmem, start_addr, nsize, bWriteOp);
+    }
+} /* extend */
+}; /* CPLVirtualMemShadow */ 
+#endif
diff --git a/swig/include/csharp/gdal_csharp.i b/swig/include/csharp/gdal_csharp.i
index 8e2aeb2..90e6934 100644
--- a/swig/include/csharp/gdal_csharp.i
+++ b/swig/include/csharp/gdal_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csharp.i 25791 2013-03-23 21:33:26Z tamas $
+ * $Id: gdal_csharp.i 26526 2013-10-11 11:49:24Z tamas $
  *
  * Name:     gdal_csharp.i
  * Project:  GDAL CSharp Interface
@@ -35,15 +35,12 @@
 
 %include typemaps_csharp.i
 
-%pragma(csharp) modulecode="public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data);"
-
-%typemap(imtype) (GDALProgressFunc callback)  "$module.GDALProgressFuncDelegate"
-%typemap(cstype) (GDALProgressFunc callback) "$module.GDALProgressFuncDelegate"
-%typemap(csin) (GDALProgressFunc callback)  "$csinput"
-%typemap(in) (GDALProgressFunc callback) %{ $1 = ($1_ltype)$input; %}
-%typemap(imtype) (void* callback_data) "string"
-%typemap(cstype) (void* callback_data) "string"
-%typemap(csin) (void* callback_data) "$csinput"
+%apply (int *pList) {int *band_list, int *panHistogram_in};
+%apply (double *OUTPUT) {double *min_ret, double *max_ret};
+%apply (int *nLen) {int *buckets_ret};
+%apply (double *pList) {double *burn_values_list, double *fixedLevels};
+%apply (int **pList) {int **ppanHistogram};
+%apply (void *buffer_ptr) {void *pfnTransformer, void *pTransformArg};
 
 %apply (void *buffer_ptr) {GDAL_GCP const *pGCPs};
 %csmethodmodifiers __SetGCPs "private";
diff --git a/swig/include/csharp/typemaps_csharp.i b/swig/include/csharp/typemaps_csharp.i
index 478c545..f553ccf 100644
--- a/swig/include/csharp/typemaps_csharp.i
+++ b/swig/include/csharp/typemaps_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_csharp.i 21588 2011-01-27 15:42:24Z tamas $
+ * $Id: typemaps_csharp.i 26526 2013-10-11 11:49:24Z tamas $
  *
  * Name:     typemaps_csharp.i
  * Project:  GDAL CSharp Interface
@@ -382,9 +382,48 @@ OPTIONAL_POD(int, int);
 %apply (int inout[ANY]) {int *pList};
 
 /*
+ * Helper to marshal utf8 strings. 
+ */
+
+%pragma(csharp) modulecode=%{
+  internal static byte[] StringToUtf8Bytes(string str)
+  {
+    if (str == null)
+      return null;
+    
+    int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
+    byte[] bytes = new byte[bytecount + 1];
+    System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
+    return bytes;
+  }
+  
+  internal static string Utf8BytesToString(IntPtr pNativeData)
+  {
+    if (pNativeData == IntPtr.Zero)
+        return null;
+        
+    int length = Marshal.PtrToStringAnsi(pNativeData).Length;
+    byte[] strbuf = new byte[length];  
+    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    return System.Text.Encoding.UTF8.GetString(strbuf);
+  }
+%}
+
+/*
  * Typemap for const char *utf8_path. 
  */
-%typemap(csin) (const char *utf8_path)  "System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes($csinput))" 
+%typemap(csin) (const char *utf8_path)  "$module.StringToUtf8Bytes($csinput)" 
+%typemap(imtype, out="IntPtr") (const char *utf8_path) "byte[]"
+%typemap(out) (const char *utf8_path) %{ $result = $1; %}
+%typemap(csout, excode=SWIGEXCODE) (const char *utf8_path) {
+        /* %typemap(csout) (const char *utf8_path) */
+        IntPtr cPtr = $imcall;
+        string ret = $module.Utf8BytesToString(cPtr);
+        $excode
+        return ret;
+}
+
+%apply ( const char *utf8_path ) { const char* GetFieldAsString };
 
 /*
  * Typemap for double *defaultval. 
@@ -477,7 +516,7 @@ OPTIONAL_POD(int, int);
       return ret;
 }
 
-%apply (void *buffer_ptr) {GByte*};
+%apply (void *buffer_ptr) {GByte*, VSILFILE*};
 
 %csmethodmodifiers StringListDestroy "internal";
 %inline %{
@@ -495,3 +534,15 @@ OPTIONAL_POD(int, int);
 %typemap(csin) (CPLErrorHandler)  "$csinput"
 %typemap(in) (CPLErrorHandler) %{ $1 = ($1_ltype)$input; %}
 
+/******************************************************************************
+ * GDALProgressFunc typemaps                                                  *
+ *****************************************************************************/
+%pragma(csharp) modulecode="public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, IntPtr Data);"
+
+%typemap(imtype) (GDALProgressFunc callback)  "$module.GDALProgressFuncDelegate"
+%typemap(cstype) (GDALProgressFunc callback) "$module.GDALProgressFuncDelegate"
+%typemap(csin) (GDALProgressFunc callback)  "$csinput"
+%typemap(in) (GDALProgressFunc callback) %{ $1 = ($1_ltype)$input; %}
+%typemap(imtype) (void* callback_data) "string"
+%typemap(cstype) (void* callback_data) "string"
+%typemap(csin) (void* callback_data) "$csinput"
\ No newline at end of file
diff --git a/swig/include/gdal.i b/swig/include/gdal.i
index c89a1e5..0f2a6cf 100644
--- a/swig/include/gdal.i
+++ b/swig/include/gdal.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.i 25897 2013-04-10 22:30:30Z rouault $
+ * $Id: gdal.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     gdal.i
  * Project:  GDAL Python Interface
@@ -28,6 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+%include constraints.i
+
 #ifdef PERL_CPAN_NAMESPACE
 %module "Geo::GDAL"
 #elif defined(SWIGCSHARP)
@@ -82,6 +84,7 @@ typedef int RETURN_NONE;
 //
 //************************************************************************
 
+typedef int GDALTileOrganization;
 #ifndef SWIGCSHARP
 typedef int GDALPaletteInterp;
 typedef int GDALColorInterp;
@@ -90,6 +93,7 @@ typedef int GDALDataType;
 typedef int CPLErr;
 typedef int GDALResampleAlg;
 typedef int GDALAsyncStatusType;
+typedef int GDALRWFlag;
 #else
 /*! Pixel data types */
 %rename (DataType) GDALDataType;
@@ -480,6 +484,8 @@ RETURN_NONE GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs,
 %clear (RETURN_NONE);
 #endif
 
+%include "cplvirtualmem.i"
+
 //************************************************************************
 //
 // Define the Dataset object.
diff --git a/swig/include/gdal_array.i b/swig/include/gdal_array.i
index 8336085..66cd5e2 100644
--- a/swig/include/gdal_array.i
+++ b/swig/include/gdal_array.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_array.i 19478 2010-04-21 19:49:37Z rouault $
+ * $Id: gdal_array.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     gdal_array.i
  * Project:  GDAL Python Interface
@@ -32,10 +32,15 @@
 
 %module gdal_array
 
+%include constraints.i
+
 %import typemaps_python.i
 
 %import MajorObject.i
 %import Band.i
+%import RasterAttributeTable.i
+
+%include "cplvirtualmem.i"
 
 %init %{
   import_array();
@@ -59,8 +64,10 @@ typedef int CPLErr;
 
 #ifdef DEBUG 
 typedef struct GDALRasterBandHS GDALRasterBandShadow;
+typedef struct RasterAttributeTableHS GDALRasterAttributeTableShadow;
 #else
 typedef void GDALRasterBandShadow;
+typedef void GDALRasterAttributeTableShadow;
 #endif
 
 CPL_C_START
@@ -489,6 +496,361 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
   }
 %}
 
+%typemap(in,numinputs=0) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap) (CPLVirtualMemShadow* virtualmem)
+{
+  $1 = &virtualmem;
+  $2 = 0;
+}
+
+%typemap(argout) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
+{
+    CPLVirtualMemShadow* virtualmem = *($1);
+    void* ptr = CPLVirtualMemGetAddr( virtualmem->vmem );
+    /*size_t nsize = CPLVirtualMemGetSize( virtualmem->vmem );*/
+    GDALDataType datatype = virtualmem->eBufType;
+    int readonly = virtualmem->bReadOnly;
+    GIntBig nBufXSize = virtualmem->nBufXSize;
+    GIntBig nBufYSize = virtualmem->nBufYSize;
+    int nBandCount = virtualmem->nBandCount;
+    int bIsBandSequential = virtualmem->bIsBandSequential;
+    GDALTileOrganization eTileOrganization = virtualmem->eTileOrganization;
+    int nTileXSize = virtualmem->nTileXSize;
+    int nTileYSize = virtualmem->nTileYSize;
+    int bAuto = virtualmem->bAuto;
+    int            nPixelSpace = virtualmem->nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace = virtualmem->nLineSpace; /* if bAuto == TRUE */
+    int numpytype;
+
+    if( datatype == GDT_CInt16 || datatype == GDT_CInt32 )
+    {
+        PyErr_SetString( PyExc_RuntimeError, "GDT_CInt16 and GDT_CInt32 not supported for now" );
+        SWIG_fail;
+    }
+
+    switch(datatype)
+    {
+        case GDT_Byte: numpytype = NPY_UBYTE; break;
+        case GDT_Int16: numpytype = NPY_INT16; break;
+        case GDT_UInt16: numpytype = NPY_UINT16; break;
+        case GDT_Int32: numpytype = NPY_INT32; break;
+        case GDT_UInt32: numpytype = NPY_UINT32; break;
+        case GDT_Float32: numpytype = NPY_FLOAT32; break;
+        case GDT_Float64: numpytype = NPY_FLOAT64; break;
+        //case GDT_CInt16: numpytype = NPY_INT16; break;
+        //case GDT_CInt32: numpytype = NPY_INT32; break;
+        case GDT_CFloat32: numpytype = NPY_CFLOAT; break;
+        case GDT_CFloat64: numpytype = NPY_CDOUBLE; break;
+        default: numpytype = NPY_UBYTE; break;
+    }
+    PyArrayObject* ar;
+    int flags = (readonly) ? 0x1 : 0x1 | 0x0400;
+    int nDataTypeSize = GDALGetDataTypeSize(datatype) / 8;
+    if( bAuto )
+    {
+        if( nBandCount == 1 )
+        {
+            npy_intp shape[2], stride[2];
+            shape[0] = nBufYSize;
+            shape[1] = nBufXSize;
+            stride[1] = nPixelSpace;
+            stride[0] = nLineSpace;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else
+        {
+            PyErr_SetString( PyExc_RuntimeError, "Code update needed for bAuto and nBandCount > 1 !" );
+            SWIG_fail;
+        }
+    }
+    else if( bIsBandSequential >= 0 )
+    {
+        if( nBandCount == 1 )
+        {
+            npy_intp shape[2], stride[2];
+            shape[0] = nBufYSize;
+            shape[1] = nBufXSize;
+            stride[1] = nDataTypeSize;
+            stride[0] = stride[1] * nBufXSize;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else
+        {
+            npy_intp shape[3], stride[3];
+            if( bIsBandSequential )
+            {
+                shape[0] = nBandCount;
+                shape[1] = nBufYSize;
+                shape[2] = nBufXSize;
+                stride[2] = nDataTypeSize;
+                stride[1] = stride[2] * nBufXSize;
+                stride[0] = stride[1] * nBufYSize;
+            }
+            else
+            {
+                shape[0] = nBufYSize;
+                shape[1] = nBufXSize;
+                shape[2] = nBandCount;
+                stride[2] = nDataTypeSize;
+                stride[1] = stride[2] * nBandCount;
+                stride[0] = stride[1] * nBufXSize;
+            }
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 3, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+    }
+    else
+    {
+        int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
+        int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
+        npy_intp shape[5], stride[5];
+        if( nBandCount == 1 )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nTileYSize;
+            shape[3] = nTileXSize;
+            stride[3] = nDataTypeSize;
+            stride[2] = stride[3] * nTileXSize;
+            stride[1] = stride[2] * nTileYSize;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 4, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else if( eTileOrganization == GTO_TIP )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nTileYSize;
+            shape[3] = nTileXSize;
+            shape[4] = nBandCount;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nBandCount;
+            stride[2] = stride[3] * nTileXSize;
+            stride[1] = stride[2] * nTileYSize;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else if( eTileOrganization == GTO_BIT )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nBandCount;
+            shape[3] = nTileYSize;
+            shape[4] = nTileXSize;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nTileXSize;
+            stride[2] = stride[3] * nTileYSize;
+            stride[1] = stride[2] * nBandCount;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else /* GTO_BSQ */
+        {
+            shape[0] = nBandCount;
+            shape[1] = nTilesPerCol;
+            shape[2] = nTilesPerRow;
+            shape[3] = nTileYSize;
+            shape[4] = nTileXSize;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nTileXSize;
+            stride[2] = stride[3] * nTileYSize;
+            stride[1] = stride[2] * nTilesPerRow;
+            stride[0] = stride[1] * nTilesPerCol;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+    }
+
+    /* Keep a reference to the VirtualMem object */
+    ar->base = obj0;
+    Py_INCREF(obj0);
+    $result = (PyObject*) ar;
+}
+
+%apply Pointer NONNULL {CPLVirtualMemShadow* virtualmem};
+%inline %{
+    void VirtualMemGetArray(CPLVirtualMemShadow* virtualmem, CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
+    {
+        *pvirtualmem = virtualmem;
+    }
+%}
+%clear CPLVirtualMemShadow* virtualmem;
+
+%feature( "kwargs" ) RATValuesIONumPyWrite;
+%inline %{
+  // need different functions for read and write
+  // since reading strings requires us to know the 
+  // length of the longest string before creating array
+  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+                       PyArrayObject *psArray) {
+
+    if( PyArray_NDIM(psArray) != 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Illegal numpy array rank %d.\n", 
+                  PyArray_NDIM(psArray) );
+        return CE_Failure;
+    }
+
+    int nLength = PyArray_DIM(psArray, 0);
+    int nType = PyArray_TYPE(psArray);
+    CPLErr retval = CE_None;
+
+    if( nType == NPY_INT32 )
+    {
+        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength, 
+                        (int*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_DOUBLE )
+    {
+        retval = GDALRATValuesIOAsDouble(poRAT, GF_Write, nField, nStart, nLength,
+                        (double*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_STRING )
+    {
+        // have to convert array of strings to a char **
+        char **papszStringData = (char**)CPLCalloc(sizeof(char*), nLength);
+
+        // max size of string
+        int nMaxLen = PyArray_ITEMSIZE(psArray);
+        char *pszBuffer = (char*)CPLMalloc((nMaxLen+1) * sizeof(char));
+        // make sure there is a null char on the end
+        // as there won't be if this string is the maximum size
+        pszBuffer[nMaxLen] = '\0';
+
+        // we can't just use the memory location in the array 
+        // since long strings won't be null terminated
+        for( int i = 0; i < nLength; i++ )
+        {
+            strncpy(pszBuffer, (char*)PyArray_GETPTR1(psArray, i), nMaxLen);
+            papszStringData[i] = CPLStrdup(pszBuffer);
+        }
+        CPLFree(pszBuffer);
+
+        retval = GDALRATValuesIOAsString(poRAT, GF_Write, nField, nStart, nLength,
+                                            papszStringData);
+
+        for( int i = 0; i < nLength; i++ )
+        {
+            CPLFree(papszStringData[i]);
+        }
+        CPLFree(papszStringData);
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Illegal numpy array type %d.\n", 
+                  nType );
+        return CE_Failure;
+    }
+    return retval;
+  }
+%}
+
+%feature( "kwargs" ) RATValuesIONumPyRead;
+%inline %{
+  // need different functions for read and write
+  // since reading strings requires us to know the 
+  // length of the longest string before creating array
+  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+                       int nLength) {
+
+    GDALRATFieldType colType = GDALRATGetTypeOfCol(poRAT, nField);
+    npy_intp dims = nLength;
+    PyObject *pOutArray = NULL;
+    if( colType == GFT_Integer )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_INT32);
+        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength, 
+                        (int*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
+    }
+    else if( colType == GFT_Real )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_DOUBLE);
+        if( GDALRATValuesIOAsDouble(poRAT, GF_Read, nField, nStart, nLength,
+                        (double*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
+    }
+    else if( colType == GFT_String )
+    {
+        // must read the data first to work out max size
+        // of strings to create array
+        int n;
+        char **papszStringList = (char**)CPLCalloc(sizeof(char*), nLength);
+        if( GDALRATValuesIOAsString(poRAT, GF_Read, nField, nStart, nLength, papszStringList) != CE_None )
+        {
+            CPLFree(papszStringList);
+            Py_RETURN_NONE;
+        }
+        int nMaxLen = 0, nLen;
+        for( n = 0; n < nLength; n++ )
+        {
+            // note strlen doesn't include null char
+            // but that is what numpy expects so all good
+            nLen = strlen(papszStringList[n]);
+            if( nLen > nMaxLen )
+                nMaxLen = nLen;
+        }
+        int bZeroLength = FALSE;
+        // numpy can't deal with zero length strings
+        if( nMaxLen == 0 )
+        {
+            nMaxLen = 1;
+            bZeroLength = TRUE;
+        }
+
+        // create the dtype string
+#if PY_VERSION_HEX >= 0x03000000
+        PyObject *pDTypeString = PyUnicode_FromFormat("S%d", nMaxLen);
+#else
+        PyObject *pDTypeString = PyString_FromFormat("S%d", nMaxLen);
+#endif
+        // out type description object
+        PyArray_Descr *pDescr;
+        PyArray_DescrConverter(pDTypeString, &pDescr);
+        Py_DECREF(pDTypeString);
+
+        // create array
+        pOutArray = PyArray_SimpleNewFromDescr(1, &dims, pDescr);
+
+        // copy data in
+        if( !bZeroLength )
+        {
+            for( n = 0; n < nLength; n++ )
+            {
+                // we use strncpy so that we don't go over nMaxLen
+                // which we would if the null char is copied
+                // (which we don't want as numpy 'knows' to interpret the string as nMaxLen long)
+                strncpy((char*)PyArray_GETPTR1(pOutArray, n), papszStringList[n], nMaxLen);
+            }
+        }
+        else
+        {
+            // so there isn't rubbush in the 1 char strings
+            PyArray_FILLWBYTE(pOutArray, 0);
+        }
+
+        // free strings
+        for( n = 0; n < nLength; n++ )
+        {
+            CPLFree(papszStringList[n]);
+        }
+        CPLFree(papszStringList);
+    }
+    return pOutArray;
+  }
+%}
 
 %pythoncode %{
 import numpy
@@ -525,7 +887,7 @@ def OpenArray( array, prototype_ds = None ):
     
     
 def flip_code(code):
-    if isinstance(code, type):
+    if isinstance(code, (numpy.dtype,type)):
         # since several things map to complex64 we must carefully select
         # the opposite that is an exact match (ticket 1518)
         if code == numpy.int8:
@@ -544,7 +906,7 @@ def flip_code(code):
             return None
 
 def NumericTypeCodeToGDALTypeCode(numeric_type):
-    if not isinstance(numeric_type, type):
+    if not isinstance(numeric_type, (numpy.dtype,type)):
         raise TypeError("Input must be a type")
     return flip_code(numeric_type)
 
@@ -684,6 +1046,50 @@ def BandWriteArray( band, array, xoff=0, yoff=0 ):
     return BandRasterIONumPy( band, 1, xoff, yoff, xsize, ysize,
                                 array, datatype )
 
+def RATWriteArray(rat, array, field, start=0):
+    """
+    Pure Python implementation of writing a chunk of the RAT
+    from a numpy array. Type of array is coerced to one of the types
+    (int, double, string) supported. Called from RasterAttributeTable.WriteArray
+    """
+    if array is None:
+        raise ValueError("Expected array of dim 1")
+
+    # if not the array type convert it to handle lists etc
+    if not isinstance(array, numpy.ndarray):
+        array = numpy.array(array)
+
+    if array.ndim != 1:
+        raise ValueError("Expected array of dim 1")
+
+    if (start + array.size) > rat.GetRowCount():
+        raise ValueError("Array too big to fit into RAT from start position")
+
+    if numpy.issubdtype(array.dtype, numpy.integer):
+        # is some type of integer - coerce to standard int
+        # TODO: must check this is fine on all platforms
+        # confusingly numpy.int 64 bit even if native type 32 bit
+        array = array.astype(numpy.int32)
+    elif numpy.issubdtype(array.dtype, numpy.floating):
+        # is some type of floating point - coerce to double
+        array = array.astype(numpy.double)
+    elif numpy.issubdtype(array.dtype, numpy.character):
+        # cast away any kind of Unicode etc
+        array = array.astype(numpy.character)
+    else:
+        raise ValueError("Array not of a supported type (integer, double or string)")
+
+    return RATValuesIONumPyWrite(rat, field, start, array)
+
+def RATReadArray(rat, field, start=0, length=None):
+    """
+    Pure Python implementation of reading a chunk of the RAT
+    into a numpy array. Called from RasterAttributeTable.ReadAsArray
+    """
+    if length is None:
+        length = rat.GetRowCount() - start
+
+    return RATValuesIONumPyRead(rat, field, start, length)
     
 def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
     """
diff --git a/swig/include/gdalconst.i b/swig/include/gdalconst.i
index 10acb57..cf54a24 100644
--- a/swig/include/gdalconst.i
+++ b/swig/include/gdalconst.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalconst.i 25897 2013-04-10 22:30:30Z rouault $
+ * $Id: gdalconst.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     gdalconst.i
  * Project:  GDAL Python Interface
@@ -204,3 +204,9 @@
 %constant GARIO_UPDATE = GARIO_UPDATE;
 %constant GARIO_ERROR = GARIO_ERROR;
 %constant GARIO_COMPLETE = GARIO_COMPLETE;
+
+// GDALTileOrganization
+%constant GTO_TIP  = GTO_TIP;
+%constant GTO_BIT = GTO_BIT;
+%constant GTO_BSQ = GTO_BSQ;
+
diff --git a/swig/include/java/gdal_java.i b/swig/include/java/gdal_java.i
index 4f83fe8..840ba98 100644
--- a/swig/include/java/gdal_java.i
+++ b/swig/include/java/gdal_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_java.i 25808 2013-03-26 21:12:24Z warmerdam $
+ * $Id: gdal_java.i 26749 2013-12-27 10:17:31Z rouault $
  *
  * Name:     gdal_java.i
  * Project:  GDAL SWIG Interface
@@ -200,42 +200,45 @@ import org.gdal.gdalconst.gdalconstConstants;
     }
 %}
 
+%{
 
-%extend GDALDatasetShadow {
-%apply (int nList, int* pList) { (int band_list, int *pband_list) };
-%apply (void* nioBuffer, long nioBufferSize) { (void* nioBuffer, long nioBufferSize) };
-
-%apply (char *regularArrayOut, long nRegularArraySizeOut) { (char *regularArrayOut, long nRegularArraySizeOut) };
-%apply (short *regularArrayOut, long nRegularArraySizeOut) { (short *regularArrayOut, long nRegularArraySizeOut) };
-%apply (int *regularArrayOut, long nRegularArraySizeOut) { (int *regularArrayOut, long nRegularArraySizeOut) };
-%apply (float *regularArrayOut, long nRegularArraySizeOut) { (float *regularArrayOut, long nRegularArraySizeOut) };
-%apply (double *regularArrayOut, long nRegularArraySizeOut) { (double *regularArrayOut, long nRegularArraySizeOut) };
-
-%apply (char *regularArrayIn, long nRegularArraySizeIn) { (char *regularArrayIn, long nRegularArraySizeIn) };
-%apply (short *regularArrayIn, long nRegularArraySizeIn) { (short *regularArrayIn, long nRegularArraySizeIn) };
-%apply (int *regularArrayIn, long nRegularArraySizeIn) { (int *regularArrayIn, long nRegularArraySizeIn) };
-%apply (float *regularArrayIn, long nRegularArraySizeIn) { (float *regularArrayIn, long nRegularArraySizeIn) };
-%apply (double *regularArrayIn, long nRegularArraySizeIn) { (double *regularArrayIn, long nRegularArraySizeIn) };
+static
+GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
+                                int nBands, int* bandMap, int nBandMapArrayLength,
+                                int nPixelSpace, int nLineSpace, int nBandSpace,
+                                int bSpacingShouldBeMultipleOfPixelSize );
 
-  CPLErr ReadRaster_Direct( int xoff, int yoff, int xsize, int ysize,
+static CPLErr DatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
+                            int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
                             GDALDataType buf_type,
-                            void *nioBuffer, long nioBufferSize,
+                            void *regularArray, long nRegularArraySize,
                             int band_list, int *pband_list,
-                            int nPixelSpace = 0, int nLineSpace = 0, int nBandSpace = 0)
+                            int nPixelSpace, int nLineSpace, int nBandSpace,
+                            GDALDataType gdal_type, size_t sizeof_ctype)
 {
+    if ((gdal_type == GDT_Int16 && buf_type != GDT_Int16 && buf_type != GDT_UInt16 && buf_type != GDT_CInt16) ||
+        (gdal_type == GDT_Int32 && buf_type != GDT_Int32 && buf_type != GDT_UInt32 && buf_type != GDT_CInt32) ||
+        (gdal_type == GDT_Float32 && buf_type != GDT_Float32 && buf_type != GDT_CFloat32) ||
+        (gdal_type == GDT_Float64 && buf_type != GDT_Float64 && buf_type != GDT_CFloat64))
+  {
+      CPLError(CE_Failure, CPLE_AppDefined,
+              "Java array type is not compatible with GDAL data type");
+      return CE_Failure;
+  }
+    
   if (band_list == 0)
   {
       if (pband_list != NULL)
           return CE_Failure;
 
-      band_list = GDALGetRasterCount(self);
+      band_list = GDALGetRasterCount(hDS);
   }
 
   GIntBig nMinBufferSizeInBytes = ComputeDatasetRasterIOSize (
                          buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
                          band_list, pband_list, band_list,
-                         nPixelSpace, nLineSpace, nBandSpace, FALSE );
+                         nPixelSpace, nLineSpace, nBandSpace, sizeof_ctype > 1 );
   if (nMinBufferSizeInBytes > 0x7fffffff)
   {
      CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
@@ -243,19 +246,56 @@ import org.gdal.gdalconst.gdalconstConstants;
   }
   if (nMinBufferSizeInBytes == 0)
       return CE_Failure;
-  if (nioBufferSize < nMinBufferSizeInBytes)
+  if (nRegularArraySize < nMinBufferSizeInBytes)
   {
       CPLError(CE_Failure, CPLE_AppDefined,
               "Buffer is too small");
       return CE_Failure;
   }
-  return  GDALDatasetRasterIO( self, GF_Read, xoff, yoff, xsize, ysize,
-                                nioBuffer, buf_xsize, buf_ysize,
+  return  GDALDatasetRasterIO( hDS, GF_Read, xoff, yoff, xsize, ysize,
+                                regularArray, buf_xsize, buf_ysize,
                                 buf_type, band_list, pband_list, nPixelSpace, nLineSpace, nBandSpace );
 
 }
 
 
+%}
+
+
+%extend GDALDatasetShadow {
+%apply (int nList, int* pList) { (int band_list, int *pband_list) };
+%apply (void* nioBuffer, long nioBufferSize) { (void* nioBuffer, long nioBufferSize) };
+
+%apply (char *regularArrayOut, long nRegularArraySizeOut) { (char *regularArrayOut, long nRegularArraySizeOut) };
+%apply (short *regularArrayOut, long nRegularArraySizeOut) { (short *regularArrayOut, long nRegularArraySizeOut) };
+%apply (int *regularArrayOut, long nRegularArraySizeOut) { (int *regularArrayOut, long nRegularArraySizeOut) };
+%apply (float *regularArrayOut, long nRegularArraySizeOut) { (float *regularArrayOut, long nRegularArraySizeOut) };
+%apply (double *regularArrayOut, long nRegularArraySizeOut) { (double *regularArrayOut, long nRegularArraySizeOut) };
+
+%apply (char *regularArrayIn, long nRegularArraySizeIn) { (char *regularArrayIn, long nRegularArraySizeIn) };
+%apply (short *regularArrayIn, long nRegularArraySizeIn) { (short *regularArrayIn, long nRegularArraySizeIn) };
+%apply (int *regularArrayIn, long nRegularArraySizeIn) { (int *regularArrayIn, long nRegularArraySizeIn) };
+%apply (float *regularArrayIn, long nRegularArraySizeIn) { (float *regularArrayIn, long nRegularArraySizeIn) };
+%apply (double *regularArrayIn, long nRegularArraySizeIn) { (double *regularArrayIn, long nRegularArraySizeIn) };
+
+  CPLErr ReadRaster_Direct( int xoff, int yoff, int xsize, int ysize,
+                            int buf_xsize, int buf_ysize,
+                            GDALDataType buf_type,
+                            void *nioBuffer, long nioBufferSize,
+                            int band_list, int *pband_list,
+                            int nPixelSpace = 0, int nLineSpace = 0, int nBandSpace = 0)
+{
+    return DatasetRasterIO( (GDALDatasetH)self, GF_Read,
+                              xoff, yoff, xsize, ysize,
+                              buf_xsize, buf_ysize,
+                              buf_type,
+                              nioBuffer, nioBufferSize,
+                              band_list, pband_list,
+                              nPixelSpace, nLineSpace, nBandSpace,
+                              GDT_Unknown, 0);
+}
+
+
   %define DEFINE_DS_READ_RASTER(ctype, gdal_type)
 CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
@@ -264,45 +304,14 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             int band_list, int *pband_list,
                             int nPixelSpace = 0, int nLineSpace = 0, int nBandSpace = 0)
 {
-    if ((gdal_type == GDT_Int16 && buf_type != GDT_Int16 && buf_type != GDT_UInt16 && buf_type != GDT_CInt16) ||
-        (gdal_type == GDT_Int32 && buf_type != GDT_Int32 && buf_type != GDT_UInt32 && buf_type != GDT_CInt32) ||
-        (gdal_type == GDT_Float32 && buf_type != GDT_Float32 && buf_type != GDT_CFloat32) ||
-        (gdal_type == GDT_Float64 && buf_type != GDT_Float64 && buf_type != GDT_CFloat64))
-  {
-      CPLError(CE_Failure, CPLE_AppDefined,
-              "Java array type is not compatible with GDAL data type");
-      return CE_Failure;
-  }
-    
-  if (band_list == 0)
-  {
-      if (pband_list != NULL)
-          return CE_Failure;
-
-      band_list = GDALGetRasterCount(self);
-  }
-
-  GIntBig nMinBufferSizeInBytes = ComputeDatasetRasterIOSize (
-                         buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                         band_list, pband_list, band_list,
-                         nPixelSpace, nLineSpace, nBandSpace, sizeof(ctype) > 1 );
-  if (nMinBufferSizeInBytes > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nMinBufferSizeInBytes = 0;
-  }
-  if (nMinBufferSizeInBytes == 0)
-      return CE_Failure;
-  if (nRegularArraySizeOut < nMinBufferSizeInBytes)
-  {
-      CPLError(CE_Failure, CPLE_AppDefined,
-              "Buffer is too small");
-      return CE_Failure;
-  }
-  return  GDALDatasetRasterIO( self, GF_Read, xoff, yoff, xsize, ysize,
-                                regularArrayOut, buf_xsize, buf_ysize,
-                                buf_type, band_list, pband_list, nPixelSpace, nLineSpace, nBandSpace );
-
+    return DatasetRasterIO( (GDALDatasetH)self, GF_Read,
+                              xoff, yoff, xsize, ysize,
+                              buf_xsize, buf_ysize,
+                              buf_type,
+                              regularArrayOut, nRegularArraySizeOut,
+                              band_list, pband_list,
+                              nPixelSpace, nLineSpace, nBandSpace,
+                              gdal_type, sizeof(ctype));
 }
   %enddef
   
@@ -320,34 +329,14 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             int band_list, int *pband_list,
                             int nPixelSpace = 0, int nLineSpace = 0, int nBandSpace = 0)
 {
-  if (band_list == 0)
-  {
-      if (pband_list != NULL)
-          return CE_Failure;
-
-      band_list = GDALGetRasterCount(self);
-  }
-
-  GIntBig nMinBufferSizeInBytes = ComputeDatasetRasterIOSize (
-                         buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                         band_list, pband_list, band_list,
-                         nPixelSpace, nLineSpace, nBandSpace, FALSE );
-  if (nMinBufferSizeInBytes > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nMinBufferSizeInBytes = 0;
-  }
-  if (nMinBufferSizeInBytes == 0)
-      return CE_Failure;
-  if (nioBufferSize < nMinBufferSizeInBytes)
-  {
-      CPLError(CE_Failure, CPLE_AppDefined,
-              "Buffer is too small");
-      return CE_Failure;
-  }
-  return  GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                nioBuffer, buf_xsize, buf_ysize,
-                                buf_type, band_list, pband_list, nPixelSpace, nLineSpace, nBandSpace );
+    return DatasetRasterIO( (GDALDatasetH)self, GF_Write,
+                              xoff, yoff, xsize, ysize,
+                              buf_xsize, buf_ysize,
+                              buf_type,
+                              nioBuffer, nioBufferSize,
+                              band_list, pband_list,
+                              nPixelSpace, nLineSpace, nBandSpace,
+                              GDT_Unknown, 0);
 }
 
   %define DEFINE_DS_WRITE_RASTER(ctype, gdal_type)
@@ -358,44 +347,14 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             int band_list, int *pband_list,
                             int nPixelSpace = 0, int nLineSpace = 0, int nBandSpace = 0)
 {
-    if ((gdal_type == GDT_Int16 && buf_type != GDT_Int16 && buf_type != GDT_UInt16 && buf_type != GDT_CInt16) ||
-        (gdal_type == GDT_Int32 && buf_type != GDT_Int32 && buf_type != GDT_UInt32 && buf_type != GDT_CInt32) ||
-        (gdal_type == GDT_Float32 && buf_type != GDT_Float32 && buf_type != GDT_CFloat32) ||
-        (gdal_type == GDT_Float64 && buf_type != GDT_Float64 && buf_type != GDT_CFloat64))
-  {
-      CPLError(CE_Failure, CPLE_AppDefined,
-              "Java array type is not compatible with GDAL data type");
-      return CE_Failure;
-  }
-
-  if (band_list == 0)
-  {
-      if (pband_list != NULL)
-          return CE_Failure;
-
-      band_list = GDALGetRasterCount(self);
-  }
-
-  GIntBig nMinBufferSizeInBytes = ComputeDatasetRasterIOSize (
-                         buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                         band_list, pband_list, band_list,
-                         nPixelSpace, nLineSpace, nBandSpace, sizeof(ctype) > 1 );
-  if (nMinBufferSizeInBytes > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nMinBufferSizeInBytes = 0;
-  }
-  if (nMinBufferSizeInBytes == 0)
-      return CE_Failure;
-  if (nRegularArraySizeIn < nMinBufferSizeInBytes)
-  {
-      CPLError(CE_Failure, CPLE_AppDefined,
-              "Buffer is too small");
-      return CE_Failure;
-  }
-  return  GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                regularArrayIn, buf_xsize, buf_ysize,
-                                buf_type, band_list, pband_list, nPixelSpace, nLineSpace, nBandSpace );
+    return DatasetRasterIO( (GDALDatasetH)self, GF_Write,
+                              xoff, yoff, xsize, ysize,
+                              buf_xsize, buf_ysize,
+                              buf_type,
+                              regularArrayIn, nRegularArraySizeIn,
+                              band_list, pband_list,
+                              nPixelSpace, nLineSpace, nBandSpace,
+                              gdal_type, sizeof(ctype));
 }
  %enddef
     
@@ -409,43 +368,21 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
 
 } /* extend */
 
-%extend GDALRasterBandShadow {
-  CPLErr ReadRaster_Direct( int xoff, int yoff, int xsize, int ysize,
-                            int buf_xsize, int buf_ysize,
-                            GDALDataType buf_type,
-                            void *nioBuffer, long nioBufferSize,
-                            int nPixelSpace = 0, int nLineSpace = 0)
-  {
-    GIntBig nMinBufferSizeInBytes = ComputeBandRasterIOSize (
-                            buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                            nPixelSpace, nLineSpace, FALSE );
-    if (nMinBufferSizeInBytes > 0x7fffffff)
-    {
-       CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-       nMinBufferSizeInBytes = 0;
-    }
-    if (nMinBufferSizeInBytes == 0)
-        return CE_Failure;
-    if (nioBufferSize < nMinBufferSizeInBytes)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "Buffer is too small");
-        return CE_Failure;
-    }
-
-    return GDALRasterIO( self, GF_Read, xoff, yoff, xsize, ysize,
-                                   nioBuffer, buf_xsize, buf_ysize,
-                                   buf_type, nPixelSpace, nLineSpace );
 
-  }
+%{
+static
+GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
+                             int nPixelSpace, int nLineSpace,
+                             int bSpacingShouldBeMultipleOfPixelSize );
 
-  %define DEFINE_READ_RASTER(ctype, gdal_type)
-  CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
-                     int buf_xsize, int buf_ysize,
-                     GDALDataType buf_type,
-                     ctype *regularArrayOut, long nRegularArraySizeOut,
-                     int nPixelSpace = 0, int nLineSpace = 0)
-  {
+static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
+                            int xoff, int yoff, int xsize, int ysize,
+                            int buf_xsize, int buf_ysize,
+                            GDALDataType buf_type,
+                            void *regularArrayOut, long nRegularArraySizeOut,
+                            int nPixelSpace, int nLineSpace,
+                            GDALDataType gdal_type, size_t sizeof_ctype)
+{
     if ((gdal_type == GDT_Int16 && buf_type != GDT_Int16 && buf_type != GDT_UInt16 && buf_type != GDT_CInt16) ||
         (gdal_type == GDT_Int32 && buf_type != GDT_Int32 && buf_type != GDT_UInt32 && buf_type != GDT_CInt32) ||
         (gdal_type == GDT_Float32 && buf_type != GDT_Float32 && buf_type != GDT_CFloat32) ||
@@ -458,7 +395,7 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
   
     GIntBig nMinBufferSizeInBytes = ComputeBandRasterIOSize (
                             buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                            nPixelSpace, nLineSpace, sizeof(ctype) > 1 );
+                            nPixelSpace, nLineSpace, sizeof_ctype > 1 );
     if (nMinBufferSizeInBytes > 0x7fffffff)
     {
        CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
@@ -473,9 +410,43 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
         return CE_Failure;
     }
 
-    return GDALRasterIO( self, GF_Read, xoff, yoff, xsize, ysize,
+    return GDALRasterIO( hBand, eRWFlag, xoff, yoff, xsize, ysize,
                                    regularArrayOut, buf_xsize, buf_ysize,
                                    buf_type, nPixelSpace, nLineSpace );
+}
+
+%}
+
+%extend GDALRasterBandShadow {
+  CPLErr ReadRaster_Direct( int xoff, int yoff, int xsize, int ysize,
+                            int buf_xsize, int buf_ysize,
+                            GDALDataType buf_type,
+                            void *nioBuffer, long nioBufferSize,
+                            int nPixelSpace = 0, int nLineSpace = 0)
+  {
+    return BandRasterIO( self, GF_Read,
+                         xoff, yoff, xsize, ysize,
+                         buf_xsize, buf_ysize,
+                         buf_type,
+                         nioBuffer, nioBufferSize,
+                         nPixelSpace, nLineSpace,
+                         GDT_Unknown, 0 );
+  }
+
+  %define DEFINE_READ_RASTER(ctype, gdal_type)
+  CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
+                     int buf_xsize, int buf_ysize,
+                     GDALDataType buf_type,
+                     ctype *regularArrayOut, long nRegularArraySizeOut,
+                     int nPixelSpace = 0, int nLineSpace = 0)
+  {
+    return BandRasterIO( self, GF_Read,
+                         xoff, yoff, xsize, ysize,
+                         buf_xsize, buf_ysize,
+                         buf_type,
+                         regularArrayOut, nRegularArraySizeOut,
+                         nPixelSpace, nLineSpace,
+                         gdal_type, sizeof(ctype) );
   }
   %enddef
   
@@ -491,26 +462,13 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             void *nioBuffer, long nioBufferSize,
                             int nPixelSpace = 0, int nLineSpace = 0)
   {
-    GIntBig nMinBufferSizeInBytes = ComputeBandRasterIOSize (
-                            buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                            nPixelSpace, nLineSpace, FALSE );
-    if (nMinBufferSizeInBytes > 0x7fffffff)
-    {
-       CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-       nMinBufferSizeInBytes = 0;
-    }
-    if (nMinBufferSizeInBytes == 0)
-        return CE_Failure;
-    if (nioBufferSize < nMinBufferSizeInBytes)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "Buffer is too small");
-        return CE_Failure;
-    }
-
-    return GDALRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                    nioBuffer, buf_xsize, buf_ysize,
-                                    buf_type, nPixelSpace, nLineSpace );
+    return BandRasterIO( self, GF_Write,
+                         xoff, yoff, xsize, ysize,
+                         buf_xsize, buf_ysize,
+                         buf_type,
+                         nioBuffer, nioBufferSize,
+                         nPixelSpace, nLineSpace,
+                         GDT_Unknown, 0 );
   }
   
   %define DEFINE_WRITE_RASTER(ctype, gdal_type)
@@ -520,36 +478,13 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                             ctype *regularArrayIn, long nRegularArraySizeIn,
                             int nPixelSpace = 0, int nLineSpace = 0)
   {
-    if ((gdal_type == GDT_Int16 && buf_type != GDT_Int16 && buf_type != GDT_UInt16 && buf_type != GDT_CInt16) ||
-        (gdal_type == GDT_Int32 && buf_type != GDT_Int32 && buf_type != GDT_UInt32 && buf_type != GDT_CInt32) ||
-        (gdal_type == GDT_Float32 && buf_type != GDT_Float32 && buf_type != GDT_CFloat32) ||
-        (gdal_type == GDT_Float64 && buf_type != GDT_Float64 && buf_type != GDT_CFloat64))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "Java array type is not compatible with GDAL data type");
-        return CE_Failure;
-    }
-    
-    GIntBig nMinBufferSizeInBytes = ComputeBandRasterIOSize (
-                            buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
-                            nPixelSpace, nLineSpace, sizeof(ctype) > 1 );
-    if (nMinBufferSizeInBytes > 0x7fffffff)
-    {
-       CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-       nMinBufferSizeInBytes = 0;
-    }
-    if (nMinBufferSizeInBytes == 0)
-        return CE_Failure;
-    if (nRegularArraySizeIn < nMinBufferSizeInBytes)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "Buffer is too small");
-        return CE_Failure;
-    }
-
-    return GDALRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                    regularArrayIn, buf_xsize, buf_ysize,
-                                    buf_type, nPixelSpace, nLineSpace );
+    return BandRasterIO( self, GF_Write,
+                         xoff, yoff, xsize, ysize,
+                         buf_xsize, buf_ysize,
+                         buf_type,
+                         regularArrayIn, nRegularArraySizeIn,
+                         nPixelSpace, nLineSpace,
+                         gdal_type, sizeof(ctype) );
   }
   %enddef
   
@@ -654,6 +589,24 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
 
 } /* extend */
 
+#ifdef SWIGANDROID
+
+%typemap(javacode) GDALColorTableShadow %{
+  private Object parentReference;
+
+  /* Ensure that the GC doesn't collect any parent instance set from Java */
+  protected void addReference(Object reference) {
+    parentReference = reference;
+  }
+
+  public Object clone()
+  {
+      return Clone();
+  }
+
+%}
+
+#else
 
 %typemap(javaimports) GDALColorTableShadow %{
 /* imports for getIndexColorModel */
@@ -713,6 +666,7 @@ import java.awt.Color;
  }
 %}
 
+#endif
 
 %typemap(javaimports) GDALRasterBandShadow %{
 import org.gdal.gdalconst.gdalconstConstants;
diff --git a/swig/include/java/ogr_java.i b/swig/include/java/ogr_java.i
index b4ac01b..f975412 100644
--- a/swig/include/java/ogr_java.i
+++ b/swig/include/java/ogr_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_java.i 24762 2012-08-11 16:28:26Z rouault $
+ * $Id: ogr_java.i 26302 2013-08-11 16:24:14Z rouault $
  *
  * Name:     ogr_java.i
  * Project:  GDAL SWIG Interface
@@ -70,6 +70,9 @@ import org.gdal.osr.SpatialReference;
 %typemap(javaimports) OGRDataSourceShadow %{
 import org.gdal.osr.SpatialReference;
 %}
+%typemap(javaimports) OGRGeomFieldDefnShadow %{
+import org.gdal.osr.SpatialReference;
+%}
 
 %typemap(javacode) OGRDataSourceShadow %{
 
@@ -270,7 +273,10 @@ import org.gdal.osr.CoordinateTransformation;
                   OGRFeatureDefnShadow* GetDefnRef,
                   OGRFieldDefnShadow* GetFieldDefnRef,
                   OGRFieldDefnShadow* GetFieldDefn,
-                  OGRGeometryShadow* GetGeometryRef {
+                  OGRGeometryDefnShadow* GetGeomFieldDefnRef,
+                  OGRGeometryDefnShadow* GetGeomFieldDefn,
+                  OGRGeometryShadow* GetGeometryRef,
+                  OGRGeometryShadow* GetGeomFieldRef {
     long cPtr = $jnicall;
     $javaclassname ret = null;
     if (cPtr != 0) {
@@ -451,6 +457,7 @@ import org.gdal.ogr.FeatureNative;
 
 SMART_FINALIZER(Geometry)
 
+
 /* ----------------------------------------------------------------- */
 /* End of smart finalizer mechanism                                  */
 /* ----------------------------------------------------------------- */
diff --git a/swig/include/java/typemaps_java.i b/swig/include/java/typemaps_java.i
index abe130d..b9776c2 100644
--- a/swig/include/java/typemaps_java.i
+++ b/swig/include/java/typemaps_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_java.i 22044 2011-03-26 14:47:20Z rouault $
+ * $Id: typemaps_java.i 26068 2013-06-06 20:46:21Z rouault $
  *
  * Name:     typemaps_java.i
  * Project:  GDAL SWIG Interface
@@ -111,6 +111,37 @@
  * Typemaps for (GDALColorEntry *)
  ***************************************************/
 
+#ifdef SWIGANDROID
+
+/* Android Version with int */
+
+%typemap(in) (GDALColorEntry *) (GDALColorEntry tmp) {
+  /* %typemap(in) (GDALColorEntry *) (GDALColorEntry tmp) */
+  tmp.c4 = ($input >> 24) & 0xff;
+  tmp.c1 = ($input >> 16) & 0xff;
+  tmp.c2 = ($input >> 8) & 0xff;
+  tmp.c3 = ($input >> 0) & 0xff;
+  $1 = &tmp;
+}
+
+%typemap(out) (GDALColorEntry *) {
+  /* %typemap(out) (GDALColorEntry *) */
+ /* Android Color is int = (alpha << 24) | (red << 16) | (green << 8) | blue */
+  $result = ($1->c4 << 24) | ($1->c1 << 16) | ($1->c2 << 8) | $1->c3;
+}
+
+%typemap(jni) (GDALColorEntry *) "jint"
+%typemap(jtype) (GDALColorEntry *) "int"
+%typemap(jstype) (GDALColorEntry *) "int"
+%typemap(javain) (GDALColorEntry *) "$javainput"
+%typemap(javaout) (GDALColorEntry *) {
+    return $jnicall;
+  }
+
+#else
+
+/* J2SE Version with java.awt.Color */
+
 %typemap(in) (GDALColorEntry *) (GDALColorEntry tmp) {
   /* %typemap(in) (GDALColorEntry *) (GDALColorEntry tmp) */
   $1 = NULL;
@@ -153,6 +184,7 @@
     return $jnicall;
   }
 
+#endif
 
 /***************************************************
  * Typemaps for (int nGCPs, GDAL_GCP const * pGCPs)
diff --git a/swig/include/ogr.i b/swig/include/ogr.i
index c574a47..fed89cc 100644
--- a/swig/include/ogr.i
+++ b/swig/include/ogr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr.i 25532 2013-01-20 03:56:31Z warmerdam $
+ * $Id: ogr.i 27071 2014-03-21 21:52:46Z rouault $
  *
  * Project:  OGR Core SWIG Interface declarations.
  * Purpose:  OGR declarations.
@@ -149,6 +149,8 @@ typedef void OGRGeometryShadow;
 typedef void OSRCoordinateTransformationShadow;
 typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 %}
 
 #ifdef SWIGJAVA
@@ -228,9 +230,11 @@ typedef void retGetPoints;
 %constant char *OLCFastSetNextByIndex  = "FastSetNextByIndex";
 %constant char *OLCStringsAsUTF8       = "StringsAsUTF8";
 %constant char *OLCIgnoreFields        = "IgnoreFields";
+%constant char *OLCCreateGeomField     = "CreateGeomField";
 
 %constant char *ODsCCreateLayer        = "CreateLayer";
 %constant char *ODsCDeleteLayer        = "DeleteLayer";
+%constant char *ODsCCreateGeomFieldAfterCreateLayer  = "CreateGeomFieldAfterCreateLayer";
 
 %constant char *ODrCCreateDataSource   = "CreateDataSource";
 %constant char *ODrCDeleteDataSource   = "DeleteDataSource";
@@ -257,9 +261,11 @@ typedef int OGRErr;
 #define OLCDeleteFeature       "DeleteFeature"
 #define OLCFastSetNextByIndex  "FastSetNextByIndex"
 #define OLCStringsAsUTF8       "StringsAsUTF8"
+#define OLCCreateGeomField     "CreateGeomField"
 
 #define ODsCCreateLayer        "CreateLayer"
 #define ODsCDeleteLayer        "DeleteLayer"
+#define ODsCCreateGeomFieldAfterCreateLayer   "CreateGeomFieldAfterCreateLayer"
 
 #define ODrCCreateDataSource   "CreateDataSource"
 #define ODrCDeleteDataSource   "DeleteDataSource"
@@ -330,6 +336,62 @@ typedef struct
 #endif
 
 #ifndef GDAL_BINDINGS
+
+/************************************************************************/
+/*                          OGRStyleTable                               */
+/************************************************************************/
+
+%rename (StyleTable) OGRStyleTableShadow;
+class OGRStyleTableShadow {
+public:
+
+%extend {
+
+   OGRStyleTableShadow() {
+        return (OGRStyleTableShadow*) OGR_STBL_Create();
+   }
+
+   ~OGRStyleTableShadow() {
+        OGR_STBL_Destroy( (OGRStyleTableH) self );
+   }
+
+   int AddStyle( const char *pszName, const char *pszStyleString )
+   {
+        return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
+   }
+
+   int LoadStyleTable( const char *utf8_path )
+   {
+        return OGR_STBL_LoadStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+
+   int SaveStyleTable( const char *utf8_path )
+   {
+        return OGR_STBL_SaveStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+
+   const char* Find( const char* pszName )
+   {
+        return OGR_STBL_Find( (OGRStyleTableH) self, pszName );
+   }
+
+   void ResetStyleStringReading()
+   {
+        OGR_STBL_ResetStyleStringReading( (OGRStyleTableH) self );
+   }
+
+   const char *GetNextStyle( )
+   {
+        return OGR_STBL_GetNextStyle( (OGRStyleTableH) self );
+   }
+
+   const char *GetLastStyleName( )
+   {
+        return OGR_STBL_GetLastStyleName( (OGRStyleTableH) self );
+   }
+}
+};
+
 /************************************************************************/
 /*                              OGRDriver                               */
 /************************************************************************/
@@ -536,6 +598,15 @@ public:
     OGR_DS_ReleaseResultSet(self, layer);
   }
 %clear OGRLayerShadow *layer;
+  
+  OGRStyleTableShadow *GetStyleTable() {
+    return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
+  }
+
+  void SetStyleTable(OGRStyleTableShadow* table) {
+    if( table != NULL )
+        OGR_DS_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 
 } /* %extend */
 
@@ -563,16 +634,31 @@ public:
   
   void SetSpatialFilterRect( double minx, double miny,
                              double maxx, double maxy) {
-    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);                          
+    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
+  }
+
+  void SetSpatialFilter(int iGeomField, OGRGeometryShadow* filter) {
+    OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
   }
   
+  void SetSpatialFilterRect( int iGeomField, double minx, double miny,
+                             double maxx, double maxy) {
+    OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
+  }
+
   OGRGeometryShadow *GetSpatialFilter() {
     return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
   }
 
+#ifdef SWIGCSHARP 
+  %apply ( const char *utf8_path ) { (char* filter_string) };
+#endif
   OGRErr SetAttributeFilter(char* filter_string) {
     return OGR_L_SetAttributeFilter((OGRLayerShadow*)self, filter_string);
   }
+#ifdef SWIGCSHARP 
+  %clear (char* filter_string);
+#endif
   
   void ResetReading() {
     OGR_L_ResetReading(self);
@@ -645,8 +731,8 @@ public:
   }
 #elif defined(SWIGPYTHON)
   %feature( "kwargs" ) GetExtent;
-  void GetExtent(double argout[4], int* isvalid = NULL, int force = 1, int can_return_null = 0 ) {
-    OGRErr eErr = OGR_L_GetExtent(self, (OGREnvelope*)argout, force);
+  void GetExtent(double argout[4], int* isvalid = NULL, int force = 1, int can_return_null = 0, int geom_field = 0 ) {
+    OGRErr eErr = OGR_L_GetExtentEx(self, geom_field, (OGREnvelope*)argout, force);
     if (can_return_null)
         *isvalid = (eErr == OGRERR_NONE);
     else
@@ -706,6 +792,15 @@ public:
   }
 %clear OGRFieldDefnShadow *field_def;
 
+#ifndef SWIGJAVA
+  %feature( "kwargs" ) CreateGeomField;
+#endif
+%apply Pointer NONNULL {OGRGeomFieldDefnShadow *field_def};
+  OGRErr CreateGeomField(OGRGeomFieldDefnShadow* field_def, int approx_ok = 1) {
+    return OGR_L_CreateGeomField(self, field_def, approx_ok);
+  }
+%clear OGRGeomFieldDefnShadow *field_def;
+
   OGRErr StartTransaction() {
     return OGR_L_StartTransaction(self);
   }
@@ -717,6 +812,10 @@ public:
   OGRErr RollbackTransaction() {
     return OGR_L_RollbackTransaction(self);
   }
+
+  int FindFieldIndex( const char *pszFieldName, int bExactMatch ) {
+    return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
+  }
   
   %newobject GetSpatialRef;
   OSRSpatialReferenceShadow *GetSpatialRef() {
@@ -813,6 +912,15 @@ public:
                 void* callback_data=NULL ) {
     return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
   }
+  
+  OGRStyleTableShadow *GetStyleTable() {
+    return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
+  }
+
+  void SetStyleTable(OGRStyleTableShadow* table) {
+    if( table != NULL )
+        OGR_L_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 
 } /* %extend */
 
@@ -868,6 +976,58 @@ public:
   OGRGeometryShadow *GetGeometryRef() {
     return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
   }
+
+
+  OGRErr SetGeomField(int iField, OGRGeometryShadow* geom) {
+    return OGR_F_SetGeomField(self, iField, geom);
+  }
+
+  OGRErr SetGeomField(const char* name, OGRGeometryShadow* geom) {
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomField(self, iField, geom);
+  }
+
+/* The feature takes over owernship of the geometry. */
+/* Don't change the 'geom' name as Java bindings depends on it */
+%apply SWIGTYPE *DISOWN {OGRGeometryShadow *geom};
+  OGRErr SetGeomFieldDirectly(int iField, OGRGeometryShadow* geom) {
+    return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+
+  OGRErr SetGeomFieldDirectly(const char* name, OGRGeometryShadow* geom) {
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+%clear OGRGeometryShadow *geom;
+  
+  /* Feature owns its geometry */
+  OGRGeometryShadow *GetGeomFieldRef(int iField) {
+    return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
+  }
+
+  /* Feature owns its geometry */
+  OGRGeometryShadow *GetGeomFieldRef(const char* name) {
+    int i = OGR_F_GetGeomFieldIndex(self, name);
+    if (i == -1)
+    {
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      return NULL;
+    }
+    else
+      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+  }
   
   %newobject Clone;
   OGRFeatureShadow *Clone() {
@@ -899,6 +1059,25 @@ public:
   }
   /* ------------------------------------------- */
 
+  int GetGeomFieldCount() {
+    return OGR_F_GetGeomFieldCount(self);
+  }
+
+  /* ---- GetGeomFieldDefnRef --------------------- */
+  OGRGeomFieldDefnShadow *GetGeomFieldDefnRef(int id) {
+    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+  }
+
+  OGRGeomFieldDefnShadow *GetGeomFieldDefnRef(const char* name) {
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+      return NULL;
+  }
+  /* ------------------------------------------- */
+
   /* ---- GetFieldAsString --------------------- */
 
   const char* GetFieldAsString(int id) {
@@ -1038,6 +1217,10 @@ public:
       return OGR_F_GetFieldIndex(self, name);
   }
 
+  int GetGeomFieldIndex(const char* name) {
+      return OGR_F_GetGeomFieldIndex(self, name);
+  }
+
   int GetFID() {
     return OGR_F_GetFID(self);
   }
@@ -1065,8 +1248,11 @@ public:
 #endif
 
   /* ---- SetField ----------------------------- */
-  
+#ifndef SWIGCSHARP 
   %apply ( tostring argin ) { (const char* value) };
+#else
+  %apply ( const char *utf8_path ) { (const char* value) };
+#endif
   void SetField(int id, const char* value) {
     OGR_F_SetFieldString(self, id, value);
   }
@@ -1146,6 +1332,28 @@ public:
   }
 %clear char**pList;
 
+  void SetFieldBinaryFromHexString(int id, const char* pszValue)
+  {
+     int nBytes;
+     GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+     OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
+     CPLFree(pabyBuf);
+  }
+
+  void SetFieldBinaryFromHexString(const char* name, const char* pszValue)
+  {
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      {
+        int nBytes;
+        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+        CPLFree(pabyBuf);
+      }
+  }
+
   /* ------------------------------------------- */  
   
 #ifndef SWIGJAVA
@@ -1204,6 +1412,38 @@ public:
 /************************************************************************/
 
 %rename (FeatureDefn) OGRFeatureDefnShadow;
+
+
+%{
+    static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
+    {
+        switch(field_type)
+        {
+            case wkbUnknown:
+            case wkbPoint:
+            case wkbLineString:
+            case wkbPolygon:
+            case wkbMultiPoint:
+            case wkbMultiLineString:
+            case wkbMultiPolygon:
+            case wkbGeometryCollection:
+            case wkbNone:
+            /*case wkbLinearRing:*/
+            case wkbPoint25D:
+            case wkbLineString25D:
+            case wkbPolygon25D:
+            case wkbMultiPoint25D:
+            case wkbMultiLineString25D:
+            case wkbMultiPolygon25D:
+            case wkbGeometryCollection25D:
+                return TRUE;
+            default:
+                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
+                return FALSE;
+        }
+    }
+%}
+
 class OGRFeatureDefnShadow {
   OGRFeatureDefnShadow();
 public:
@@ -1246,12 +1486,38 @@ public:
   }
 %clear OGRFieldDefnShadow* defn;
   
+  
+  int GetGeomFieldCount(){
+    return OGR_FD_GetGeomFieldCount(self);
+  }
+  
+  /* FeatureDefns own their GeomFieldDefns */
+  OGRGeomFieldDefnShadow* GetGeomFieldDefn(int i){
+    return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
+  }
+
+  int GetGeomFieldIndex(const char* name) {
+      return OGR_FD_GetGeomFieldIndex(self, name);
+  }
+  
+%apply Pointer NONNULL {OGRGeomFieldDefnShadow* defn};
+  void AddGeomFieldDefn(OGRGeomFieldDefnShadow* defn) {
+    OGR_FD_AddGeomFieldDefn(self, defn);
+  }
+%clear OGRGeomFieldDefnShadow* defn;
+
+  OGRErr DeleteGeomFieldDefn(int idx)
+  {
+    return OGR_FD_DeleteGeomFieldDefn(self, idx);
+  }
+
   OGRwkbGeometryType GetGeomType() {
     return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
   }
   
   void SetGeomType(OGRwkbGeometryType geom_type) {
-    OGR_FD_SetGeomType(self, geom_type);
+    if( ValidateOGRGeometryType(geom_type) )
+        OGR_FD_SetGeomType(self, geom_type);
   }
   
   int GetReferenceCount(){
@@ -1273,7 +1539,12 @@ public:
   void SetStyleIgnored( int bIgnored ) {
     return OGR_FD_SetStyleIgnored(self,bIgnored);
   }
-  
+
+%apply Pointer NONNULL {OGRFeatureDefnShadow* other_defn};
+  int IsSame(OGRFeatureDefnShadow* other_defn) {
+    return OGR_FD_IsSame(self, other_defn);
+  }
+%clear OGRFeatureDefnShadow* other_defn;
 } /* %extend */
 
 
@@ -1398,6 +1669,78 @@ public:
 
 }; /* class OGRFieldDefnShadow */
 
+/************************************************************************/
+/*                          OGRGeomFieldDefn                            */
+/************************************************************************/
+
+%rename (GeomFieldDefn) OGRGeomFieldDefnShadow;
+
+class OGRGeomFieldDefnShadow {
+  OGRGeomFieldDefnShadow();
+public:
+%extend {
+
+  ~OGRGeomFieldDefnShadow() {
+    OGR_GFld_Destroy(self);
+  }
+
+#ifndef SWIGJAVA
+  %feature("kwargs") OGRGeomFieldDefnShadow;
+#endif
+  OGRGeomFieldDefnShadow( const char* name_null_ok="", 
+                          OGRwkbGeometryType field_type = wkbUnknown) {
+    if( ValidateOGRGeometryType(field_type) )
+        return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
+    else
+        return NULL;
+  }
+
+  const char * GetName() {
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+  
+  const char * GetNameRef() {
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+  
+  void SetName( const char* name) {
+    OGR_GFld_SetName(self, name);
+  }
+  
+  OGRwkbGeometryType GetType() {
+    return OGR_GFld_GetType(self);
+  }
+
+  void SetType(OGRwkbGeometryType type) {
+    if( ValidateOGRGeometryType(type) )
+        OGR_GFld_SetType(self, type);
+  }
+
+  %newobject GetSpatialRef;
+  OSRSpatialReferenceShadow *GetSpatialRef() {
+    OGRSpatialReferenceH ref =  OGR_GFld_GetSpatialRef(self);
+    if( ref )
+        OSRReference(ref);
+    return (OSRSpatialReferenceShadow*) ref;
+  }
+
+  void SetSpatialRef(OSRSpatialReferenceShadow* srs)
+  {
+     OGR_GFld_SetSpatialRef( self, (OGRSpatialReferenceH)srs );
+  }
+
+  int IsIgnored() {
+    return OGR_GFld_IsIgnored( self );
+  }
+
+  void SetIgnored(int bIgnored ) {
+    OGR_GFld_SetIgnored( self, bIgnored );
+  }
+
+} /* %extend */
+
+
+}; /* class OGRGeomFieldDefnShadow */
 
 /* -------------------------------------------------------------------- */
 /*      Geometry factory methods.                                       */
diff --git a/swig/include/osr.i b/swig/include/osr.i
index c919583..4f6e38b 100644
--- a/swig/include/osr.i
+++ b/swig/include/osr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr.i 25229 2012-11-16 19:06:58Z rouault $
+ * $Id: osr.i 26938 2014-02-13 20:15:52Z rcoup $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRSpatialReference related declarations.
@@ -259,6 +259,10 @@ public:
     return OSREPSGTreatsAsLatLong(self);
   }
 
+  int EPSGTreatsAsNorthingEasting() {
+    return OSREPSGTreatsAsNorthingEasting(self);
+  }
+
   OGRErr SetAuthority( const char * pszTargetKey,
                        const char * pszAuthority,
                        int nCode ) {
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index ff973f4..4995115 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -115,8 +115,9 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
     # have $VERSION 1.9911 and GDAL 1.11 would have $VERSION 1.992
     # etc.  GDAL 2.0 should then get VERSION 2.000 and 2.1 should get
     # 2.001 etc.
-    our $VERSION = '1.9911';
-    our $GDAL_VERSION = '1.10.1';
+
+    our $VERSION = '1.992';
+    our $GDAL_VERSION = '1.11.0';
     use vars qw/
 	%TYPE_STRING2INT %TYPE_INT2STRING
 	%ACCESS_STRING2INT %ACCESS_INT2STRING
@@ -681,6 +682,7 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 	}
 	return @table;
     }
+    *ColorEntries = *ColorTable;
 
     package Geo::GDAL::RasterAttributeTable;
     use strict;
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index 9cf6148..d038360 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 25101 2012-10-11 20:47:28Z rouault $
+ * $Id: gdal_python.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -269,10 +269,15 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 
 %pythoncode {
 
-  def ReadRaster(self, xoff, yoff, xsize, ysize,
+  def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                    buf_xsize = None, buf_ysize = None, buf_type = None,
                    buf_pixel_space = None, buf_line_space = None ):
 
+      if xsize is None:
+          xsize = self.XSize
+      if ysize is None:
+          ysize = self.YSize
+
       return _gdal.Band_ReadRaster1(self, xoff, yoff, xsize, ysize,
                                     buf_xsize, buf_ysize, buf_type,
                                     buf_pixel_space, buf_line_space)
@@ -290,6 +295,69 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 
       return gdalnumeric.BandWriteArray( self, array, xoff, yoff )
 
+  def GetVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                         xsize=None, ysize=None, bufxsize=None, bufysize=None,
+                         datatype = None,
+                         cache_size = 10 * 1024 * 1024, page_size_hint = 0,
+                         options = None):
+        """Return a NumPy array for the band, seen as a virtual memory mapping.
+           An element is accessed with array[y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.XSize
+        if ysize is None:
+            ysize = self.YSize
+        if bufxsize is None:
+            bufxsize = self.XSize
+        if bufysize is None:
+            bufysize = self.YSize
+        if datatype is None:
+            datatype = self.DataType
+        if options is None:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,cache_size,page_size_hint)
+        else:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,cache_size,page_size_hint,options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+  def GetVirtualMemAutoArray(self, eAccess = gdalconst.GF_Read, options = None):
+        """Return a NumPy array for the band, seen as a virtual memory mapping.
+           An element is accessed with array[y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if options is None:
+            virtualmem = self.GetVirtualMemAuto(eAccess)
+        else:
+            virtualmem = self.GetVirtualMemAuto(eAccess,options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+  def GetTiledVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, tilexsize=256, tileysize=256,
+                           datatype = None,
+                           cache_size = 10 * 1024 * 1024, options = None):
+        """Return a NumPy array for the band, seen as a virtual memory mapping with
+           a tile organization.
+           An element is accessed with array[tiley][tilex][y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.XSize
+        if ysize is None:
+            ysize = self.YSize
+        if datatype is None:
+            datatype = self.DataType
+        if options is None:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,cache_size)
+        else:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,cache_size,options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
   def __get_array_interface__(self):
       shape = [1, self.XSize, self.YSize]
       
@@ -395,11 +463,15 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
                 buf_string, buf_xsize, buf_ysize, buf_type, band_list,
                 buf_pixel_space, buf_line_space, buf_band_space )
 
-    def ReadRaster(self, xoff, yoff, xsize, ysize,
+    def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                    buf_xsize = None, buf_ysize = None, buf_type = None,
                    band_list = None,
                    buf_pixel_space = None, buf_line_space = None, buf_band_space = None ):
 
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
         if band_list is None:
             band_list = range(1,self.RasterCount+1)
         if buf_xsize is None:
@@ -414,6 +486,70 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
                                             buf_xsize, buf_ysize, buf_type,
                                             band_list, buf_pixel_space, buf_line_space, buf_band_space )
 
+    def GetVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, bufxsize=None, bufysize=None,
+                           datatype = None, band_list = None, band_sequential = True,
+                           cache_size = 10 * 1024 * 1024, page_size_hint = 0,
+                           options = None):
+        """Return a NumPy array for the dataset, seen as a virtual memory mapping.
+           If there are several bands and band_sequential = True, an element is
+           accessed with array[band][y][x].
+           If there are several bands and band_sequential = False, an element is
+           accessed with array[y][x][band].
+           If there is only one band, an element is accessed with array[y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
+        if bufxsize is None:
+            bufxsize = self.RasterXSize
+        if bufysize is None:
+            bufysize = self.RasterYSize
+        if datatype is None:
+            datatype = self.GetRasterBand(1).DataType
+        if band_list is None:
+            band_list = range(1,self.RasterCount+1)
+        if options is None:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,band_list,band_sequential,cache_size,page_size_hint)
+        else:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,band_list,band_sequential,cache_size,page_size_hint, options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+    def GetTiledVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, tilexsize=256, tileysize=256,
+                           datatype = None, band_list = None, tile_organization = gdalconst.GTO_BSQ,
+                           cache_size = 10 * 1024 * 1024, options = None):
+        """Return a NumPy array for the dataset, seen as a virtual memory mapping with
+           a tile organization.
+           If there are several bands and tile_organization = gdal.GTO_TIP, an element is
+           accessed with array[tiley][tilex][y][x][band].
+           If there are several bands and tile_organization = gdal.GTO_BIT, an element is
+           accessed with array[tiley][tilex][band][y][x].
+           If there are several bands and tile_organization = gdal.GTO_BSQ, an element is
+           accessed with array[band][tiley][tilex][y][x].
+           If there is only one band, an element is accessed with array[tiley][tilex][y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
+        if datatype is None:
+            datatype = self.GetRasterBand(1).DataType
+        if band_list is None:
+            band_list = range(1,self.RasterCount+1)
+        if options is None:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,band_list,tile_organization,cache_size)
+        else:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,band_list,tile_organization,cache_size, options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
     def GetSubDatasets(self):
         sd_list = []
         
@@ -465,4 +601,18 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
 }
 }
 
+%extend GDALRasterAttributeTableShadow {
+%pythoncode {
+  def WriteArray(self, array, field, start=0):
+      import gdalnumeric
+
+      return gdalnumeric.RATWriteArray(self, array, field, start)
+
+  def ReadAsArray(self, field, start=0, length=None):
+      import gdalnumeric
+
+      return gdalnumeric.RATReadArray(self, field, start, length)
+}
+}
+
 %include "callback.i"
diff --git a/swig/include/python/ogr_python.i b/swig/include/python/ogr_python.i
index 4471bc5..17ab0dd 100644
--- a/swig/include/python/ogr_python.i
+++ b/swig/include/python/ogr_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_python.i 25899 2013-04-11 18:07:32Z rouault $
+ * $Id: ogr_python.i 26302 2013-08-11 16:24:14Z rouault $
  *
  * python specific code for ogr bindings.
  */
@@ -213,29 +213,63 @@ layer[0:4] would return a list of the first four features."""
         """Returns the values of fields by the given name"""
         if key == 'this':
             return self.__dict__[key]
-        try:
-            return self.GetField(key)
-        except:
-            raise AttributeError(key)
+
+        idx = self.GetFieldIndex(key)
+        if idx < 0:
+            idx = self.GetGeomFieldIndex(key)
+            if idx < 0:
+                raise AttributeError(key)
+            else:
+                return self.GetGeomFieldRef(idx)
+        else:
+            return self.GetField(idx)
 
     # This makes it possible to set fields in the form "feature.area". 
     # This has some risk of name collisions.
     def __setattr__(self, key, value):
         """Set the values of fields by the given name"""
-        if key != 'this' and key != 'thisown' and self.GetFieldIndex(key) != -1:
-            return self.SetField2(key,value)
-        else:
+        if key == 'this' or key == 'thisown':
             self.__dict__[key] = value
+        else:
+            idx = self.GetFieldIndex(key)
+            if idx != -1:
+                self.SetField2(idx,value)
+            else:
+                idx = self.GetGeomFieldIndex(key)
+                if idx != -1:
+                    self.SetGeomField(idx, value)
+                else:
+                    self.__dict__[key] = value
 
     # This makes it possible to fetch fields in the form "feature['area']". 
     def __getitem__(self, key):
         """Returns the values of fields by the given name / field_index"""
-        return self.GetField(key)
+        if isinstance(key, str):
+            fld_index = self.GetFieldIndex(key)
+        if fld_index < 0:
+            if isinstance(key, str):
+                fld_index = self.GetGeomFieldIndex(key)
+            if fld_index < 0:
+                raise ValueError("Illegal field requested in GetField()")
+            else:
+                return self.GetGeomFieldRef(fld_index)
+        else:
+            return self.GetField(fld_index)
 
     # This makes it possible to set fields in the form "feature['area'] = 123". 
     def __setitem__(self, key, value):
         """Returns the value of a field by field name / index"""
-        self.SetField2( key, value )    
+        if isinstance(key, str):
+            fld_index = self.GetFieldIndex(key)
+        if fld_index < 0:
+            if isinstance(key, str):
+                fld_index = self.GetGeomFieldIndex(key)
+            if fld_index < 0:
+                raise ValueError("Illegal field requested in SetField()")
+            else:
+                return self.SetGeomField( fld_index, value )
+        else:
+            return self.SetField2( fld_index, value )
 
     def GetField(self, fld_index):
         if isinstance(fld_index, str):
@@ -263,6 +297,8 @@ layer[0:4] would return a list of the first four features."""
     def SetField2(self, fld_index, value):
         if isinstance(fld_index, str):
             fld_index = self.GetFieldIndex(fld_index)
+        if (fld_index < 0) or (fld_index > self.GetFieldCount()):
+            raise ValueError("Illegal field requested in SetField2()")
 
         if value is None:
             self.UnsetField( fld_index )
@@ -394,6 +430,14 @@ layer[0:4] would return a list of the first four features."""
 }
 }
 
+%extend OGRGeomFieldDefnShadow {
+%pythoncode {
+    type = property(GetType, SetType)
+    name = property(GetName, SetName)
+    srs = property(GetSpatialRef, SetSpatialRef)
+}
+}
+
 %extend OGRFeatureDefnShadow {
 %pythoncode {
   def Destroy(self):
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index ffde8ee..1f5098e 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 26276 2013-08-08 19:15:31Z rouault $
+ * $Id: typemaps_python.i 26832 2014-01-15 12:46:08Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -846,7 +846,10 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
 %typemap(in) (char **ignorechange) ( char *val )
 {
   /* %typemap(in) (char **ignorechange) */
-  PyArg_Parse( $input, "s", &val );
+  if( !PyArg_Parse( $input, "s", &val ) ) {
+    PyErr_SetString( PyExc_TypeError, "not a string" );
+    SWIG_fail;
+  }
   $1 = &val;
 }
 
@@ -1656,3 +1659,66 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
   else
     $result = Py_None;
 }
+
+%typemap(in,numinputs=0) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly) (void* ptr, size_t nsize, GDALDataType datatype, int readonly)
+{
+  /* %typemap(in,numinputs=0) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly) */
+  $1 = &ptr;
+  $2 = &nsize;
+  $3 = &datatype;
+  $4 = &readonly;
+}
+%typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)
+{
+%#if PY_VERSION_HEX >= 0x02070000 
+  /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
+  Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
+  if (PyBuffer_FillInfo(buf,  obj0,  *($1), *($2), *($4), PyBUF_ND)) {
+    // error, handle
+  }
+  if( *($3) == GDT_Byte )
+  {
+    buf->format = "B";
+    buf->itemsize = 1;
+  }
+  else if( *($3) == GDT_Int16 )
+  {
+    buf->format = "h";
+    buf->itemsize = 2;
+  }
+  else if( *($3) == GDT_UInt16 )
+  {
+    buf->format = "H";
+    buf->itemsize = 2;
+  }
+  else if( *($3) == GDT_Int32 )
+  {
+    buf->format = "i";
+    buf->itemsize = 4;
+  }
+  else if( *($3) == GDT_UInt32 )
+  {
+    buf->format = "I";
+    buf->itemsize = 4;
+  }
+  else if( *($3) == GDT_Float32 )
+  {
+    buf->format = "f";
+    buf->itemsize = 4;
+  }
+  else if( *($3) == GDT_Float64 )
+  {
+    buf->format = "F";
+    buf->itemsize = 8;
+  }
+  else
+  {
+    buf->format = "B";
+    buf->itemsize = 1;
+  }
+  $result = PyMemoryView_FromBuffer(buf);
+%#else
+  PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
+  SWIG_fail;
+%#endif
+}
diff --git a/swig/java/GNUmakefile b/swig/java/GNUmakefile
index d1636e4..725f1f2 100644
--- a/swig/java/GNUmakefile
+++ b/swig/java/GNUmakefile
@@ -1,5 +1,3 @@
-
-
 include ../../GDALmake.opt
 include java.opt
 
@@ -11,6 +9,11 @@ include ../SWIGmake.base
 SHORT_NAME = $(subst _wrap,,$*)
 SWIGARGS += -outdir "org/gdal/$(SHORT_NAME)" -package "org.gdal.$(SHORT_NAME)"
 
+# Run "make ANDROID=yes" for Android JNI
+ifeq ($(ANDROID),yes)
+SWIGARGS += -DSWIGANDROID
+endif
+
 EXTRA_DIST = org
 
 LINK = $(LD_SHARED)
@@ -36,6 +39,11 @@ JAVA_OBJECTS = gdalconst_wrap.$(OBJ_EXT) gdal_wrap.$(OBJ_EXT) osr_wrap.$(OBJ_EXT
 clean:
 	-rm -f ${JAVA_MODULES}
 	-rm *.$(OBJ_EXT)
+	-rm .libs/*.so
+	-rm .libs/*.dylib
+	-rm *.so
+	-rm *.dylib
+
 	ant clean
 
 veryclean: clean
@@ -43,15 +51,31 @@ veryclean: clean
 	-rm -rf ${EXTRA_DIST}/*
 
 generate: makedir ${WRAPPERS}
-  
+
 build: generate ${JAVA_OBJECTS} ${JAVA_MODULES}
 ifeq ($(HAVE_LIBTOOL),yes)
-	-cp ./.libs/*.so ./
-endif
+
+	if [ -f ".libs/libgdaljni.so" ] ; then \
+		cp .libs/*.so . ; \
+	fi
+
+	echo "$(wildcard .libs/*.dylib)"
+
+	if [ -f ".libs/libgdaljni.dylib" ] ; then \
+		cp .libs/*.dylib . ; \
+	fi
+
+endif # HAVE_LIBTOOL=yes
 	ant
 
-install: generate
-	@echo "No installation to be done"
+install: build
+	if [ -f "libgdaljni.so" ] ; then \
+		for f in *.so; do $(INSTALL_LIB) $$f $(DESTDIR)$(INST_LIB) ; done ; \
+	fi
+
+	if [ -f "libgdaljni.dylib" ] ; then \
+		for f in *.dylib; do $(INSTALL_LIB) $$f $(DESTDIR)$(INST_LIB) ; done ; \
+	fi
 
 JAVA_RUN = java -Djava.library.path=. -cp gdal.jar:build/apps
 
@@ -71,7 +95,7 @@ test:
 	${JAVA_RUN} ogrtindex tmp_test/contour_index.shp tmp_test/contour.shp
 
 $(JAVA_MODULES): lib%jni.$(SO_EXT): %_wrap.$(OBJ_EXT)
-	$(LINK) $(LDFLAGS) $(CONFIG_LIBS) $< -o $@ $(LINK_EXTRAFLAGS)
+	$(LINK) $(LDFLAGS) $< $(CONFIG_LIBS) -o $@ $(LINK_EXTRAFLAGS)
 
 # Do not remove -fno-strict-aliasing while SWIG generates weird code in upcast methods
 # See http://trac.osgeo.org/gdal/changeset/16006
diff --git a/swig/java/add_javadoc.c b/swig/java/add_javadoc.c
index 031c399..d091871 100644
--- a/swig/java/add_javadoc.c
+++ b/swig/java/add_javadoc.c
@@ -7,7 +7,7 @@
 * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
 * 
 *******************************************************************************
-* Copyright (c) 2009, Even Rouault <even dot rouault at mines dash paris dot org>
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
diff --git a/swig/java/apps/multireadtest.java b/swig/java/apps/multireadtest.java
new file mode 100644
index 0000000..08e3c4c
--- /dev/null
+++ b/swig/java/apps/multireadtest.java
@@ -0,0 +1,71 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Name:     multireadtest.java
+ * Project:  GDAL Java Interface
+ * Purpose:  A sample app to stress-test thread-safety
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+import org.gdal.gdal.gdal;
+import org.gdal.gdal.Dataset;
+
+public class multireadtest implements Runnable
+{
+    private String _filename;
+    
+    public multireadtest(String filename)
+    {
+        _filename = filename;
+    }
+    
+    public void run()
+    {
+        for(int i=0;i<100;i++)
+        {
+            Dataset ds = gdal.Open(_filename);
+            ds.GetRasterBand(1).Checksum();
+            //ds.delete();
+        }
+    }
+    
+    public static void main(String[] args) throws InterruptedException
+    {
+        String filename = args[0];
+        
+        gdal.AllRegister();
+
+        Thread t[] = new Thread[4];
+        for(int i=0;i<4;i++)
+        {
+            t[i] = new Thread(new multireadtest(filename));
+            t[i].start();
+        }
+        for(int i=0;i<4;i++)
+        {
+            t[i].join();
+        }
+        //gdal.GDALDestroyDriverManager();
+    }
+}
diff --git a/swig/java/java.opt b/swig/java/java.opt
index e9794bf..848ae2e 100644
--- a/swig/java/java.opt
+++ b/swig/java/java.opt
@@ -1,7 +1,7 @@
 #
 # Java Stuff
 #JAVA_HOME = "C:\Program Files\Java\jdk1.6.0_16"
-JAVA_HOME = /usr/lib/jvm/java-6-openjdk/
+#JAVA_HOME = /usr/lib/jvm/java-6-openjdk/
 JAVADOC=$(JAVA_HOME)/bin/javadoc
 JAVAC=$(JAVA_HOME)/bin/javac
 JAVA=$(JAVA_HOME)/bin/java
diff --git a/swig/perl/Doxyfile b/swig/perl/Doxyfile
index aa00fc0..318463b 100644
--- a/swig/perl/Doxyfile
+++ b/swig/perl/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = Geo::GDAL
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 1.10
+PROJECT_NUMBER         = 1.11
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short.
 
diff --git a/swig/perl/GNUmakefile b/swig/perl/GNUmakefile
index dc428a3..9db3018 100644
--- a/swig/perl/GNUmakefile
+++ b/swig/perl/GNUmakefile
@@ -17,7 +17,7 @@ generate: ${WRAPPERS}
 	if [ -f OGR.pm ]; then mv OGR.pm lib/Geo; fi
 	if [ -f OSR.pm ]; then mv OSR.pm lib/Geo; fi
 
-build: Makefile_Geo__GDAL gdal_wrap.cc
+build: gdal_wrap.cc Makefile_Geo__GDAL
 	$(MAKE) -f Makefile_Geo__GDAL
 	$(MAKE) -f Makefile_Geo__GDAL__Const
 	$(MAKE) -f Makefile_Geo__OGR
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
index 7f96014..cdd8b5b 100644
--- a/swig/perl/gdal_wrap.cpp
+++ b/swig/perl/gdal_wrap.cpp
@@ -2030,6 +2030,9 @@ SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShado
 SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
     GDALSetDescription( self, pszNewDesc );
   }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
+    return GDALGetMetadataDomainList( self );
+  }
 SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
     return GDALGetMetadata( self, pszDomain );
   }
@@ -2409,11 +2412,13 @@ static GDALAsyncReaderH AsyncReaderWrapperGetReader(GDALAsyncReaderWrapperH hWra
     return psWrapper->hAsyncReader;
 }
 
+#if defined(SWIGPYTHON)
 static void* AsyncReaderWrapperGetPyObject(GDALAsyncReaderWrapperH hWrapper)
 {
     GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
     return psWrapper->pyObject;
 }
+#endif
 
 static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 {
@@ -3043,6 +3048,9 @@ SWIGINTERN int GDALRasterAttributeTableShadow_SetLinearBinning(GDALRasterAttribu
 SWIGINTERN int GDALRasterAttributeTableShadow_GetRowOfValue(GDALRasterAttributeTableShadow *self,double dfValue){
         return GDALRATGetRowOfValue( self, dfValue );
     }
+SWIGINTERN int GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(GDALRasterAttributeTableShadow *self){
+        return GDALRATChangesAreWrittenToFile( self );
+    }
 
 #include "gdalgrid.h"
 
@@ -6177,6 +6185,86 @@ XS(_wrap_MajorObject_SetDescription) {
 }
 
 
+XS(_wrap_MajorObject_GetMetadataDomainList) {
+  {
+    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    char **result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: MajorObject_GetMetadataDomainList(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) char **CSL */
+      if (GIMME_V == G_ARRAY) {
+        if (result) {
+          int i;
+          for (i = 0; result[i]; i++) {
+            if (argvi > items-1) EXTEND(SP, 1);
+            SV *sv = newSVpv(result[i], 0);
+            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+            ST(argvi++) = sv_2mortal(sv);
+          }
+          CSLDestroy(result);
+        }
+      } else {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        if (result) {
+          int i;
+          for (i = 0; result[i]; i++) {
+            SV *sv = newSVpv(result[i], 0);
+            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+            if (!av_store(av, i, sv))
+            SvREFCNT_dec(sv);
+          }
+          CSLDestroy(result);
+        }
+        ST(argvi) = newRV((SV*)av);
+        sv_2mortal(ST(argvi));
+        argvi++;
+      }
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_MajorObject_GetMetadata) {
   {
     GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
@@ -18232,6 +18320,57 @@ XS(_wrap_RasterAttributeTable_GetRowOfValue) {
 }
 
 
+XS(_wrap_RasterAttributeTable_ChangesAreWrittenToFile) {
+  {
+    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: RasterAttributeTable_ChangesAreWrittenToFile(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_ChangesAreWrittenToFile" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap__ComputeMedianCutPCT) {
   {
     GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -22364,7 +22503,7 @@ static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayer
 static swig_type_info _swigt__p_VSIStatBufL = {"_p_VSIStatBufL", "VSIStatBufL *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldType *|GDALRATFieldType *|GDALAccess *|int *|OGRwkbByteOrder *|CPLErr *|GDALRATFieldUsage *|OGRJustification *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "GDALRATFieldType *|OGRFieldType *|GDALAccess *|int *|OGRwkbByteOrder *|CPLErr *|GDALRWFlag *|OGRJustification *|GDALRATFieldUsage *|GDALTileOrganization *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_int = {"_p_p_int", "int **", 0, 0, (void*)0, 0};
@@ -22501,6 +22640,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::VSIFReadL", _wrap_VSIFReadL},
 {"Geo::GDALc::MajorObject_GetDescription", _wrap_MajorObject_GetDescription},
 {"Geo::GDALc::MajorObject_SetDescription", _wrap_MajorObject_SetDescription},
+{"Geo::GDALc::MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList},
 {"Geo::GDALc::MajorObject_GetMetadata", _wrap_MajorObject_GetMetadata},
 {"Geo::GDALc::MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata},
 {"Geo::GDALc::MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem},
@@ -22664,6 +22804,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::RasterAttributeTable_GetLinearBinning", _wrap_RasterAttributeTable_GetLinearBinning},
 {"Geo::GDALc::RasterAttributeTable_SetLinearBinning", _wrap_RasterAttributeTable_SetLinearBinning},
 {"Geo::GDALc::RasterAttributeTable_GetRowOfValue", _wrap_RasterAttributeTable_GetRowOfValue},
+{"Geo::GDALc::RasterAttributeTable_ChangesAreWrittenToFile", _wrap_RasterAttributeTable_ChangesAreWrittenToFile},
 {"Geo::GDALc::_ComputeMedianCutPCT", _wrap__ComputeMedianCutPCT},
 {"Geo::GDALc::_DitherRGB2PCT", _wrap__DitherRGB2PCT},
 {"Geo::GDALc::_ReprojectImage", _wrap__ReprojectImage},
diff --git a/swig/perl/gdalconst_wrap.c b/swig/perl/gdalconst_wrap.c
index 6751248..a3df647 100644
--- a/swig/perl/gdalconst_wrap.c
+++ b/swig/perl/gdalconst_wrap.c
@@ -2470,6 +2470,21 @@ XS(SWIG_init) {
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_COMPLETE)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GTO_TIP", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_TIP)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GTO_BIT", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_BIT)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GTO_BSQ", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_BSQ)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
   ST(0) = &PL_sv_yes;
   XSRETURN(1);
 }
diff --git a/swig/perl/index.dox b/swig/perl/index.dox
index f74fca8..57af49b 100644
--- a/swig/perl/index.dox
+++ b/swig/perl/index.dox
@@ -10,6 +10,7 @@ which is extended from the released versions APIs. Old versions:
 <a href="/doc/Geo-GDAL-1.7/html/index.html">1.7</a>
 <a href="/doc/Geo-GDAL-1.8/html/index.html">1.8</a>
 <a href="/doc/Geo-GDAL-1.9/html/index.html">1.9</a>
+<a href="/doc/Geo-GDAL-1.10/html/index.html">1.10</a>
 
 \section index_intro Introduction
 
diff --git a/swig/perl/lib/Geo/GDAL.dox b/swig/perl/lib/Geo/GDAL.dox
index ecdfa6f..f3fbf1c 100644
--- a/swig/perl/lib/Geo/GDAL.dox
+++ b/swig/perl/lib/Geo/GDAL.dox
@@ -899,7 +899,6 @@
 #         last if $yoff >= $H;
 #     }
 #     my $data = $dataset->Band(1)->ReadTile($xoff,$yoff,min($W-$xoff,$w),min($H-$yoff,$h));
-#     my $data = $dataset->Band(1)->ReadTile($xoff,$yoff,$w,$h);
 #     # add your data processing code here
 #     $dataset->Band(1)->WriteTile($data,$xoff,$yoff);
 #     $xoff += $w;
@@ -1087,8 +1086,14 @@
 ## @method $GetCount()
 # @return scalar (count of color entries as int)
 
+## @method @ColorTable(@colortable)
+# Get or set the table of color entries.
+# @param colortable [optional]
+# @return a table of color entries (a list of lists) in a non void context
+
 ## @method @ColorEntries(@color_entries)
-# Get or set the color entries.
+# Get or set the table of color entries.
+# @deprecated use Geo::GDAL::ColorTable::ColorTable
 # @param color_entries [optional]
 # @return a table of color entries (a list of lists) in a non void context
 
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index b86ca2a..7dc5f95 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -165,6 +165,7 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 %OWNER = ();
 *GetDescription = *Geo::GDALc::MajorObject_GetDescription;
 *SetDescription = *Geo::GDALc::MajorObject_SetDescription;
+*GetMetadataDomainList = *Geo::GDALc::MajorObject_GetMetadataDomainList;
 *GetMetadata = *Geo::GDALc::MajorObject_GetMetadata;
 *SetMetadata = *Geo::GDALc::MajorObject_SetMetadata;
 *GetMetadataItem = *Geo::GDALc::MajorObject_GetMetadataItem;
@@ -535,6 +536,7 @@ sub DESTROY {
 *GetLinearBinning = *Geo::GDALc::RasterAttributeTable_GetLinearBinning;
 *SetLinearBinning = *Geo::GDALc::RasterAttributeTable_SetLinearBinning;
 *GetRowOfValue = *Geo::GDALc::RasterAttributeTable_GetRowOfValue;
+*ChangesAreWrittenToFile = *Geo::GDALc::RasterAttributeTable_ChangesAreWrittenToFile;
 sub DISOWN {
     my $self = shift;
     my $ptr = tied(%$self);
@@ -609,8 +611,9 @@ package Geo::GDAL;
     # have $VERSION 1.9911 and GDAL 1.11 would have $VERSION 1.992
     # etc.  GDAL 2.0 should then get VERSION 2.000 and 2.1 should get
     # 2.001 etc.
-    our $VERSION = '1.9911';
-    our $GDAL_VERSION = '1.10.1';
+
+    our $VERSION = '1.992';
+    our $GDAL_VERSION = '1.11.0';
     use vars qw/
 	%TYPE_STRING2INT %TYPE_INT2STRING
 	%ACCESS_STRING2INT %ACCESS_INT2STRING
@@ -1175,6 +1178,7 @@ package Geo::GDAL;
 	}
 	return @table;
     }
+    *ColorEntries = *ColorTable;
 
     package Geo::GDAL::RasterAttributeTable;
     use strict;
diff --git a/swig/perl/lib/Geo/GDAL/Const.pm b/swig/perl/lib/Geo/GDAL/Const.pm
index f628701..1fa2f7b 100644
--- a/swig/perl/lib/Geo/GDAL/Const.pm
+++ b/swig/perl/lib/Geo/GDAL/Const.pm
@@ -164,4 +164,7 @@ package Geo::GDAL::Const;
 *GARIO_UPDATE = *Geo::GDAL::Constc::GARIO_UPDATE;
 *GARIO_ERROR = *Geo::GDAL::Constc::GARIO_ERROR;
 *GARIO_COMPLETE = *Geo::GDAL::Constc::GARIO_COMPLETE;
+*GTO_TIP = *Geo::GDAL::Constc::GTO_TIP;
+*GTO_BIT = *Geo::GDAL::Constc::GTO_BIT;
+*GTO_BSQ = *Geo::GDAL::Constc::GTO_BSQ;
 1;
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index 65cc6c1..62a453d 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -78,6 +78,50 @@ package Geo::OGR;
 *GeneralCmdLineProcessor = *Geo::OGRc::GeneralCmdLineProcessor;
 *TermProgress_nocb = *Geo::OGRc::TermProgress_nocb;
 
+############# Class : Geo::OGR::StyleTable ##############
+
+package Geo::OGR::StyleTable;
+use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
+ at ISA = qw( Geo::OGR );
+%OWNER = ();
+%ITERATORS = ();
+sub new {
+    my $pkg = shift;
+    my $self = Geo::OGRc::new_StyleTable(@_);
+    bless $self, $pkg if defined($self);
+}
+
+sub DESTROY {
+    return unless $_[0]->isa('HASH');
+    my $self = tied(%{$_[0]});
+    return unless defined $self;
+    delete $ITERATORS{$self};
+    if (exists $OWNER{$self}) {
+        Geo::OGRc::delete_StyleTable($self);
+        delete $OWNER{$self};
+    }
+}
+
+*AddStyle = *Geo::OGRc::StyleTable_AddStyle;
+*LoadStyleTable = *Geo::OGRc::StyleTable_LoadStyleTable;
+*SaveStyleTable = *Geo::OGRc::StyleTable_SaveStyleTable;
+*Find = *Geo::OGRc::StyleTable_Find;
+*ResetStyleStringReading = *Geo::OGRc::StyleTable_ResetStyleStringReading;
+*GetNextStyle = *Geo::OGRc::StyleTable_GetNextStyle;
+*GetLastStyleName = *Geo::OGRc::StyleTable_GetLastStyleName;
+sub DISOWN {
+    my $self = shift;
+    my $ptr = tied(%$self);
+    delete $OWNER{$ptr};
+}
+
+sub ACQUIRE {
+    my $self = shift;
+    my $ptr = tied(%$self);
+    $OWNER{$ptr} = 1;
+}
+
+
 ############# Class : Geo::OGR::Driver ##############
 
 package Geo::OGR::Driver;
@@ -148,6 +192,8 @@ sub DESTROY {
 *_TestCapability = *Geo::OGRc::DataSource__TestCapability;
 *_ExecuteSQL = *Geo::OGRc::DataSource__ExecuteSQL;
 *ReleaseResultSet = *Geo::OGRc::DataSource_ReleaseResultSet;
+*GetStyleTable = *Geo::OGRc::DataSource_GetStyleTable;
+*SetStyleTable = *Geo::OGRc::DataSource_SetStyleTable;
 sub DISOWN {
     my $self = shift;
     my $ptr = tied(%$self);
@@ -193,9 +239,11 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *ReorderField = *Geo::OGRc::Layer_ReorderField;
 *ReorderFields = *Geo::OGRc::Layer_ReorderFields;
 *AlterFieldDefn = *Geo::OGRc::Layer_AlterFieldDefn;
+*CreateGeomField = *Geo::OGRc::Layer_CreateGeomField;
 *StartTransaction = *Geo::OGRc::Layer_StartTransaction;
 *CommitTransaction = *Geo::OGRc::Layer_CommitTransaction;
 *RollbackTransaction = *Geo::OGRc::Layer_RollbackTransaction;
+*FindFieldIndex = *Geo::OGRc::Layer_FindFieldIndex;
 *GetSpatialRef = *Geo::OGRc::Layer_GetSpatialRef;
 *GetFeaturesRead = *Geo::OGRc::Layer_GetFeaturesRead;
 *SetIgnoredFields = *Geo::OGRc::Layer_SetIgnoredFields;
@@ -206,6 +254,8 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *Update = *Geo::OGRc::Layer_Update;
 *Clip = *Geo::OGRc::Layer_Clip;
 *Erase = *Geo::OGRc::Layer_Erase;
+*GetStyleTable = *Geo::OGRc::Layer_GetStyleTable;
+*SetStyleTable = *Geo::OGRc::Layer_SetStyleTable;
 sub DISOWN {
     my $self = shift;
     my $ptr = tied(%$self);
@@ -252,10 +302,15 @@ sub new {
 *SetGeometry = *Geo::OGRc::Feature_SetGeometry;
 *_SetGeometryDirectly = *Geo::OGRc::Feature__SetGeometryDirectly;
 *GetGeometryRef = *Geo::OGRc::Feature_GetGeometryRef;
+*SetGeomField = *Geo::OGRc::Feature_SetGeomField;
+*SetGeomFieldDirectly = *Geo::OGRc::Feature_SetGeomFieldDirectly;
+*GetGeomFieldRef = *Geo::OGRc::Feature_GetGeomFieldRef;
 *Clone = *Geo::OGRc::Feature_Clone;
 *Equal = *Geo::OGRc::Feature_Equal;
 *GetFieldCount = *Geo::OGRc::Feature_GetFieldCount;
 *GetFieldDefnRef = *Geo::OGRc::Feature_GetFieldDefnRef;
+*GetGeomFieldCount = *Geo::OGRc::Feature_GetGeomFieldCount;
+*GetGeomFieldDefnRef = *Geo::OGRc::Feature_GetGeomFieldDefnRef;
 *GetFieldAsString = *Geo::OGRc::Feature_GetFieldAsString;
 *GetFieldAsInteger = *Geo::OGRc::Feature_GetFieldAsInteger;
 *GetFieldAsDouble = *Geo::OGRc::Feature_GetFieldAsDouble;
@@ -265,6 +320,7 @@ sub new {
 *GetFieldAsStringList = *Geo::OGRc::Feature_GetFieldAsStringList;
 *IsFieldSet = *Geo::OGRc::Feature_IsFieldSet;
 *GetFieldIndex = *Geo::OGRc::Feature_GetFieldIndex;
+*GetGeomFieldIndex = *Geo::OGRc::Feature_GetGeomFieldIndex;
 *GetFID = *Geo::OGRc::Feature_GetFID;
 *SetFID = *Geo::OGRc::Feature_SetFID;
 *DumpReadable = *Geo::OGRc::Feature_DumpReadable;
@@ -273,6 +329,7 @@ sub new {
 *SetFieldIntegerList = *Geo::OGRc::Feature_SetFieldIntegerList;
 *SetFieldDoubleList = *Geo::OGRc::Feature_SetFieldDoubleList;
 *SetFieldStringList = *Geo::OGRc::Feature_SetFieldStringList;
+*SetFieldBinaryFromHexString = *Geo::OGRc::Feature_SetFieldBinaryFromHexString;
 *_SetFrom = *Geo::OGRc::Feature__SetFrom;
 *SetFromWithMap = *Geo::OGRc::Feature_SetFromWithMap;
 *GetStyleString = *Geo::OGRc::Feature_GetStyleString;
@@ -325,6 +382,11 @@ sub new {
 *GetFieldDefn = *Geo::OGRc::FeatureDefn_GetFieldDefn;
 *GetFieldIndex = *Geo::OGRc::FeatureDefn_GetFieldIndex;
 *AddFieldDefn = *Geo::OGRc::FeatureDefn_AddFieldDefn;
+*GetGeomFieldCount = *Geo::OGRc::FeatureDefn_GetGeomFieldCount;
+*GetGeomFieldDefn = *Geo::OGRc::FeatureDefn_GetGeomFieldDefn;
+*GetGeomFieldIndex = *Geo::OGRc::FeatureDefn_GetGeomFieldIndex;
+*AddGeomFieldDefn = *Geo::OGRc::FeatureDefn_AddGeomFieldDefn;
+*DeleteGeomFieldDefn = *Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn;
 *GetGeomType = *Geo::OGRc::FeatureDefn_GetGeomType;
 *SetGeomType = *Geo::OGRc::FeatureDefn_SetGeomType;
 *GetReferenceCount = *Geo::OGRc::FeatureDefn_GetReferenceCount;
@@ -332,6 +394,7 @@ sub new {
 *SetGeometryIgnored = *Geo::OGRc::FeatureDefn_SetGeometryIgnored;
 *IsStyleIgnored = *Geo::OGRc::FeatureDefn_IsStyleIgnored;
 *SetStyleIgnored = *Geo::OGRc::FeatureDefn_SetStyleIgnored;
+*IsSame = *Geo::OGRc::FeatureDefn_IsSame;
 sub DISOWN {
     my $self = shift;
     my $ptr = tied(%$self);
@@ -402,6 +465,52 @@ sub ACQUIRE {
 }
 
 
+############# Class : Geo::OGR::GeomFieldDefn ##############
+
+package Geo::OGR::GeomFieldDefn;
+use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
+ at ISA = qw( Geo::OGR );
+%OWNER = ();
+%ITERATORS = ();
+sub DESTROY {
+    return unless $_[0]->isa('HASH');
+    my $self = tied(%{$_[0]});
+    return unless defined $self;
+    delete $ITERATORS{$self};
+    if (exists $OWNER{$self}) {
+        Geo::OGRc::delete_GeomFieldDefn($self);
+        delete $OWNER{$self};
+    }
+}
+
+sub new {
+    my $pkg = shift;
+    my $self = Geo::OGRc::new_GeomFieldDefn(@_);
+    bless $self, $pkg if defined($self);
+}
+
+*GetName = *Geo::OGRc::GeomFieldDefn_GetName;
+*GetNameRef = *Geo::OGRc::GeomFieldDefn_GetNameRef;
+*SetName = *Geo::OGRc::GeomFieldDefn_SetName;
+*GetType = *Geo::OGRc::GeomFieldDefn_GetType;
+*SetType = *Geo::OGRc::GeomFieldDefn_SetType;
+*GetSpatialRef = *Geo::OGRc::GeomFieldDefn_GetSpatialRef;
+*SetSpatialRef = *Geo::OGRc::GeomFieldDefn_SetSpatialRef;
+*IsIgnored = *Geo::OGRc::GeomFieldDefn_IsIgnored;
+*SetIgnored = *Geo::OGRc::GeomFieldDefn_SetIgnored;
+sub DISOWN {
+    my $self = shift;
+    my $ptr = tied(%$self);
+    delete $OWNER{$ptr};
+}
+
+sub ACQUIRE {
+    my $self = shift;
+    my $ptr = tied(%$self);
+    $OWNER{$ptr} = 1;
+}
+
+
 ############# Class : Geo::OGR::Geometry ##############
 
 package Geo::OGR::Geometry;
@@ -573,8 +682,10 @@ package Geo::OGR;
 *OLCFastSetNextByIndex = *Geo::OGRc::OLCFastSetNextByIndex;
 *OLCStringsAsUTF8 = *Geo::OGRc::OLCStringsAsUTF8;
 *OLCIgnoreFields = *Geo::OGRc::OLCIgnoreFields;
+*OLCCreateGeomField = *Geo::OGRc::OLCCreateGeomField;
 *ODsCCreateLayer = *Geo::OGRc::ODsCCreateLayer;
 *ODsCDeleteLayer = *Geo::OGRc::ODsCDeleteLayer;
+*ODsCCreateGeomFieldAfterCreateLayer = *Geo::OGRc::ODsCCreateGeomFieldAfterCreateLayer;
 *ODrCCreateDataSource = *Geo::OGRc::ODrCCreateDataSource;
 *ODrCDeleteDataSource = *Geo::OGRc::ODrCDeleteDataSource;
 *TermProgress = *Geo::OGRc::TermProgress;
diff --git a/swig/perl/lib/Geo/OSR.pm b/swig/perl/lib/Geo/OSR.pm
index cd1968b..f8cb864 100644
--- a/swig/perl/lib/Geo/OSR.pm
+++ b/swig/perl/lib/Geo/OSR.pm
@@ -97,6 +97,7 @@ sub DESTROY {
 *IsLocal = *Geo::OSRc::SpatialReference_IsLocal;
 *IsVertical = *Geo::OSRc::SpatialReference_IsVertical;
 *EPSGTreatsAsLatLong = *Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong;
+*EPSGTreatsAsNorthingEasting = *Geo::OSRc::SpatialReference_EPSGTreatsAsNorthingEasting;
 *SetAuthority = *Geo::OSRc::SpatialReference_SetAuthority;
 *GetAttrValue = *Geo::OSRc::SpatialReference_GetAttrValue;
 *SetAttrValue = *Geo::OSRc::SpatialReference_SetAttrValue;
@@ -359,6 +360,44 @@ package Geo::OSR;
 *SRS_UL_ROD_CONV = *Geo::OSRc::SRS_UL_ROD_CONV;
 *SRS_UL_LINK_Clarke = *Geo::OSRc::SRS_UL_LINK_Clarke;
 *SRS_UL_LINK_Clarke_CONV = *Geo::OSRc::SRS_UL_LINK_Clarke_CONV;
+*SRS_UL_KILOMETER = *Geo::OSRc::SRS_UL_KILOMETER;
+*SRS_UL_KILOMETER_CONV = *Geo::OSRc::SRS_UL_KILOMETER_CONV;
+*SRS_UL_DECIMETER = *Geo::OSRc::SRS_UL_DECIMETER;
+*SRS_UL_DECIMETER_CONV = *Geo::OSRc::SRS_UL_DECIMETER_CONV;
+*SRS_UL_CENTIMETER = *Geo::OSRc::SRS_UL_CENTIMETER;
+*SRS_UL_CENTIMETER_CONV = *Geo::OSRc::SRS_UL_CENTIMETER_CONV;
+*SRS_UL_MILLIMETER = *Geo::OSRc::SRS_UL_MILLIMETER;
+*SRS_UL_MILLIMETER_CONV = *Geo::OSRc::SRS_UL_MILLIMETER_CONV;
+*SRS_UL_INTL_NAUT_MILE = *Geo::OSRc::SRS_UL_INTL_NAUT_MILE;
+*SRS_UL_INTL_NAUT_MILE_CONV = *Geo::OSRc::SRS_UL_INTL_NAUT_MILE_CONV;
+*SRS_UL_INTL_INCH = *Geo::OSRc::SRS_UL_INTL_INCH;
+*SRS_UL_INTL_INCH_CONV = *Geo::OSRc::SRS_UL_INTL_INCH_CONV;
+*SRS_UL_INTL_FOOT = *Geo::OSRc::SRS_UL_INTL_FOOT;
+*SRS_UL_INTL_FOOT_CONV = *Geo::OSRc::SRS_UL_INTL_FOOT_CONV;
+*SRS_UL_INTL_YARD = *Geo::OSRc::SRS_UL_INTL_YARD;
+*SRS_UL_INTL_YARD_CONV = *Geo::OSRc::SRS_UL_INTL_YARD_CONV;
+*SRS_UL_INTL_STAT_MILE = *Geo::OSRc::SRS_UL_INTL_STAT_MILE;
+*SRS_UL_INTL_STAT_MILE_CONV = *Geo::OSRc::SRS_UL_INTL_STAT_MILE_CONV;
+*SRS_UL_INTL_FATHOM = *Geo::OSRc::SRS_UL_INTL_FATHOM;
+*SRS_UL_INTL_FATHOM_CONV = *Geo::OSRc::SRS_UL_INTL_FATHOM_CONV;
+*SRS_UL_INTL_CHAIN = *Geo::OSRc::SRS_UL_INTL_CHAIN;
+*SRS_UL_INTL_CHAIN_CONV = *Geo::OSRc::SRS_UL_INTL_CHAIN_CONV;
+*SRS_UL_INTL_LINK = *Geo::OSRc::SRS_UL_INTL_LINK;
+*SRS_UL_INTL_LINK_CONV = *Geo::OSRc::SRS_UL_INTL_LINK_CONV;
+*SRS_UL_US_INCH = *Geo::OSRc::SRS_UL_US_INCH;
+*SRS_UL_US_INCH_CONV = *Geo::OSRc::SRS_UL_US_INCH_CONV;
+*SRS_UL_US_YARD = *Geo::OSRc::SRS_UL_US_YARD;
+*SRS_UL_US_YARD_CONV = *Geo::OSRc::SRS_UL_US_YARD_CONV;
+*SRS_UL_US_CHAIN = *Geo::OSRc::SRS_UL_US_CHAIN;
+*SRS_UL_US_CHAIN_CONV = *Geo::OSRc::SRS_UL_US_CHAIN_CONV;
+*SRS_UL_US_STAT_MILE = *Geo::OSRc::SRS_UL_US_STAT_MILE;
+*SRS_UL_US_STAT_MILE_CONV = *Geo::OSRc::SRS_UL_US_STAT_MILE_CONV;
+*SRS_UL_INDIAN_YARD = *Geo::OSRc::SRS_UL_INDIAN_YARD;
+*SRS_UL_INDIAN_YARD_CONV = *Geo::OSRc::SRS_UL_INDIAN_YARD_CONV;
+*SRS_UL_INDIAN_FOOT = *Geo::OSRc::SRS_UL_INDIAN_FOOT;
+*SRS_UL_INDIAN_FOOT_CONV = *Geo::OSRc::SRS_UL_INDIAN_FOOT_CONV;
+*SRS_UL_INDIAN_CHAIN = *Geo::OSRc::SRS_UL_INDIAN_CHAIN;
+*SRS_UL_INDIAN_CHAIN_CONV = *Geo::OSRc::SRS_UL_INDIAN_CHAIN_CONV;
 *SRS_UA_DEGREE = *Geo::OSRc::SRS_UA_DEGREE;
 *SRS_UA_DEGREE_CONV = *Geo::OSRc::SRS_UA_DEGREE_CONV;
 *SRS_UA_RADIAN = *Geo::OSRc::SRS_UA_RADIAN;
diff --git a/swig/perl/ogr_wrap.cpp b/swig/perl/ogr_wrap.cpp
index cb44cd6..d52ac1e 100644
--- a/swig/perl/ogr_wrap.cpp
+++ b/swig/perl/ogr_wrap.cpp
@@ -1518,20 +1518,22 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #define SWIGTYPE_p_OGRFeatureDefnShadow swig_types[3]
 #define SWIGTYPE_p_OGRFeatureShadow swig_types[4]
 #define SWIGTYPE_p_OGRFieldDefnShadow swig_types[5]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[6]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[7]
-#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[8]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[9]
-#define SWIGTYPE_p_char swig_types[10]
-#define SWIGTYPE_p_double swig_types[11]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[12]
-#define SWIGTYPE_p_int swig_types[13]
-#define SWIGTYPE_p_p_char swig_types[14]
-#define SWIGTYPE_p_p_double swig_types[15]
-#define SWIGTYPE_p_p_int swig_types[16]
-#define SWIGTYPE_p_p_p_char swig_types[17]
-static swig_type_info *swig_types[19];
-static swig_module_info swig_module = {swig_types, 18, 0, 0, 0, 0};
+#define SWIGTYPE_p_OGRGeomFieldDefnShadow swig_types[6]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[7]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[8]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[9]
+#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[10]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[11]
+#define SWIGTYPE_p_char swig_types[12]
+#define SWIGTYPE_p_double swig_types[13]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[14]
+#define SWIGTYPE_p_int swig_types[15]
+#define SWIGTYPE_p_p_char swig_types[16]
+#define SWIGTYPE_p_p_double swig_types[17]
+#define SWIGTYPE_p_p_int swig_types[18]
+#define SWIGTYPE_p_p_p_char swig_types[19]
+static swig_type_info *swig_types[21];
+static swig_module_info swig_module = {swig_types, 20, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1602,6 +1604,8 @@ typedef void OGRGeometryShadow;
 typedef void OSRCoordinateTransformationShadow;
 typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
 SWIGINTERNINLINE SV *
@@ -1782,6 +1786,33 @@ void DontUseExceptions() {
   CPLSetErrorHandler( CPLDefaultErrorHandler );
 }
 
+SWIGINTERN OGRStyleTableShadow *new_OGRStyleTableShadow(){
+        return (OGRStyleTableShadow*) OGR_STBL_Create();
+   }
+SWIGINTERN void delete_OGRStyleTableShadow(OGRStyleTableShadow *self){
+        OGR_STBL_Destroy( (OGRStyleTableH) self );
+   }
+SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const *pszName,char const *pszStyleString){
+        return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
+   }
+SWIGINTERN int OGRStyleTableShadow_LoadStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_LoadStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN int OGRStyleTableShadow_SaveStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_SaveStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_Find(OGRStyleTableShadow *self,char const *pszName){
+        return OGR_STBL_Find( (OGRStyleTableH) self, pszName );
+   }
+SWIGINTERN void OGRStyleTableShadow_ResetStyleStringReading(OGRStyleTableShadow *self){
+        OGR_STBL_ResetStyleStringReading( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetNextStyle(OGRStyleTableShadow *self){
+        return OGR_STBL_GetNextStyle( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetLastStyleName(OGRStyleTableShadow *self){
+        return OGR_STBL_GetLastStyleName( (OGRStyleTableH) self );
+   }
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CreateDataSource(OGRDriverShadow *self,char const *utf8_path,char **options=0){
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
     return ds;
@@ -2028,14 +2059,27 @@ SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_ExecuteSQL(OGRDataSourceShadow *s
 SWIGINTERN void OGRDataSourceShadow_ReleaseResultSet(OGRDataSourceShadow *self,OGRLayerShadow *layer){
     OGR_DS_ReleaseResultSet(self, layer);
   }
+SWIGINTERN OGRStyleTableShadow *OGRDataSourceShadow_GetStyleTable(OGRDataSourceShadow *self){
+    return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
+  }
+SWIGINTERN void OGRDataSourceShadow_SetStyleTable(OGRDataSourceShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_DS_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN int OGRLayerShadow_GetRefCount(OGRLayerShadow *self){
     return OGR_L_GetRefCount(self);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilter(OGRLayerShadow *self,OGRGeometryShadow *filter){
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_0(OGRLayerShadow *self,OGRGeometryShadow *filter){
     OGR_L_SetSpatialFilter (self, filter);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
-    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);                          
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_0(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_1(OGRLayerShadow *self,int iGeomField,OGRGeometryShadow *filter){
+    OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_1(OGRLayerShadow *self,int iGeomField,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
   }
 SWIGINTERN OGRGeometryShadow *OGRLayerShadow_GetSpatialFilter(OGRLayerShadow *self){
     return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
@@ -2127,6 +2171,9 @@ SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,in
 SWIGINTERN OGRErr OGRLayerShadow_AlterFieldDefn(OGRLayerShadow *self,int iField,OGRFieldDefnShadow *field_def,int nFlags){
     return OGR_L_AlterFieldDefn(self, iField, field_def, nFlags);
   }
+SWIGINTERN OGRErr OGRLayerShadow_CreateGeomField(OGRLayerShadow *self,OGRGeomFieldDefnShadow *field_def,int approx_ok=1){
+    return OGR_L_CreateGeomField(self, field_def, approx_ok);
+  }
 SWIGINTERN OGRErr OGRLayerShadow_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -2136,6 +2183,9 @@ SWIGINTERN OGRErr OGRLayerShadow_CommitTransaction(OGRLayerShadow *self){
 SWIGINTERN OGRErr OGRLayerShadow_RollbackTransaction(OGRLayerShadow *self){
     return OGR_L_RollbackTransaction(self);
   }
+SWIGINTERN int OGRLayerShadow_FindFieldIndex(OGRLayerShadow *self,char const *pszFieldName,int bExactMatch){
+    return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
+  }
 SWIGINTERN OSRSpatialReferenceShadow *OGRLayerShadow_GetSpatialRef(OGRLayerShadow *self){
     OGRSpatialReferenceH ref =  OGR_L_GetSpatialRef(self);
     if( ref )
@@ -2169,6 +2219,13 @@ SWIGINTERN OGRErr OGRLayerShadow_Clip(OGRLayerShadow *self,OGRLayerShadow *metho
 SWIGINTERN OGRErr OGRLayerShadow_Erase(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
   }
+SWIGINTERN OGRStyleTableShadow *OGRLayerShadow_GetStyleTable(OGRLayerShadow *self){
+    return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
+  }
+SWIGINTERN void OGRLayerShadow_SetStyleTable(OGRLayerShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_L_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN void delete_OGRFeatureShadow(OGRFeatureShadow *self){
     OGR_F_Destroy(self);
   }
@@ -2187,6 +2244,45 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeometryDirectly(OGRFeatureShadow *self,OG
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeometryRef(OGRFeatureShadow *self){
     return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
   }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
+    return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+    int i = OGR_F_GetGeomFieldIndex(self, name);
+    if (i == -1)
+    {
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      return NULL;
+    }
+    else
+      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+  }
 SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
     return (OGRFeatureShadow*) OGR_F_Clone(self);
   }
@@ -2207,6 +2303,20 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatu
 	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
+    return OGR_F_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+      return NULL;
+  }
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString(OGRFeatureShadow *self,int id){
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
@@ -2275,6 +2385,9 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
       return OGR_F_GetFieldIndex(self, name);
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
+      return OGR_F_GetGeomFieldIndex(self, name);
+  }
 SWIGINTERN int OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
   }
@@ -2310,6 +2423,24 @@ SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList(OGRFeatureShadow *self,int i
 SWIGINTERN void OGRFeatureShadow_SetFieldStringList(OGRFeatureShadow *self,int id,char **pList){
       OGR_F_SetFieldStringList(self, id, pList);
   }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureShadow *self,int id,char const *pszValue){
+     int nBytes;
+     GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+     OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
+     CPLFree(pabyBuf);
+  }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      {
+        int nBytes;
+        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+        CPLFree(pabyBuf);
+      }
+  }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
     return OGR_F_SetFrom(self, other, forgiving);
   }
@@ -2341,6 +2472,35 @@ SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *
 	      OGR_F_GetFieldDefnRef( self,  i )
 	      );
   }
+
+    static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
+    {
+        switch(field_type)
+        {
+            case wkbUnknown:
+            case wkbPoint:
+            case wkbLineString:
+            case wkbPolygon:
+            case wkbMultiPoint:
+            case wkbMultiLineString:
+            case wkbMultiPolygon:
+            case wkbGeometryCollection:
+            case wkbNone:
+            /*case wkbLinearRing:*/
+            case wkbPoint25D:
+            case wkbLineString25D:
+            case wkbPolygon25D:
+            case wkbMultiPoint25D:
+            case wkbMultiLineString25D:
+            case wkbMultiPolygon25D:
+            case wkbGeometryCollection25D:
+                return TRUE;
+            default:
+                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
+                return FALSE;
+        }
+    }
+
 SWIGINTERN void delete_OGRFeatureDefnShadow(OGRFeatureDefnShadow *self){
     /*OGR_FD_Destroy(self);*/
     OGR_FD_Release( OGRFeatureDefnH(self) );
@@ -2365,11 +2525,27 @@ SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,cha
 SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
     OGR_FD_AddFieldDefn(self, defn);
   }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldCount(OGRFeatureDefnShadow *self){
+    return OGR_FD_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn(OGRFeatureDefnShadow *self,int i){
+    return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
+  }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex(OGRFeatureDefnShadow *self,char const *name){
+      return OGR_FD_GetGeomFieldIndex(self, name);
+  }
+SWIGINTERN void OGRFeatureDefnShadow_AddGeomFieldDefn(OGRFeatureDefnShadow *self,OGRGeomFieldDefnShadow *defn){
+    OGR_FD_AddGeomFieldDefn(self, defn);
+  }
+SWIGINTERN OGRErr OGRFeatureDefnShadow_DeleteGeomFieldDefn(OGRFeatureDefnShadow *self,int idx){
+    return OGR_FD_DeleteGeomFieldDefn(self, idx);
+  }
 SWIGINTERN OGRwkbGeometryType OGRFeatureDefnShadow_GetGeomType(OGRFeatureDefnShadow *self){
     return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
   }
 SWIGINTERN void OGRFeatureDefnShadow_SetGeomType(OGRFeatureDefnShadow *self,OGRwkbGeometryType geom_type){
-    OGR_FD_SetGeomType(self, geom_type);
+    if( ValidateOGRGeometryType(geom_type) )
+        OGR_FD_SetGeomType(self, geom_type);
   }
 SWIGINTERN int OGRFeatureDefnShadow_GetReferenceCount(OGRFeatureDefnShadow *self){
     return OGR_FD_GetReferenceCount(self);
@@ -2386,6 +2562,9 @@ SWIGINTERN int OGRFeatureDefnShadow_IsStyleIgnored(OGRFeatureDefnShadow *self){
 SWIGINTERN void OGRFeatureDefnShadow_SetStyleIgnored(OGRFeatureDefnShadow *self,int bIgnored){
     return OGR_FD_SetStyleIgnored(self,bIgnored);
   }
+SWIGINTERN int OGRFeatureDefnShadow_IsSame(OGRFeatureDefnShadow *self,OGRFeatureDefnShadow *other_defn){
+    return OGR_FD_IsSame(self, other_defn);
+  }
 
     static int ValidateOGRFieldType(OGRFieldType field_type)
     {
@@ -2463,6 +2642,46 @@ SWIGINTERN int OGRFieldDefnShadow_IsIgnored(OGRFieldDefnShadow *self){
 SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgnored){
     return OGR_Fld_SetIgnored( self, bIgnored );
   }
+SWIGINTERN void delete_OGRGeomFieldDefnShadow(OGRGeomFieldDefnShadow *self){
+    OGR_GFld_Destroy(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *new_OGRGeomFieldDefnShadow(char const *name_null_ok="",OGRwkbGeometryType field_type=wkbUnknown){
+    if( ValidateOGRGeometryType(field_type) )
+        return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
+    else
+        return NULL;
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetName(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetNameRef(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetName(OGRGeomFieldDefnShadow *self,char const *name){
+    OGR_GFld_SetName(self, name);
+  }
+SWIGINTERN OGRwkbGeometryType OGRGeomFieldDefnShadow_GetType(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_GetType(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetType(OGRGeomFieldDefnShadow *self,OGRwkbGeometryType type){
+    if( ValidateOGRGeometryType(type) )
+        OGR_GFld_SetType(self, type);
+  }
+SWIGINTERN OSRSpatialReferenceShadow *OGRGeomFieldDefnShadow_GetSpatialRef(OGRGeomFieldDefnShadow *self){
+    OGRSpatialReferenceH ref =  OGR_GFld_GetSpatialRef(self);
+    if( ref )
+        OSRReference(ref);
+    return (OSRSpatialReferenceShadow*) ref;
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetSpatialRef(OGRGeomFieldDefnShadow *self,OSRSpatialReferenceShadow *srs){
+     OGR_GFld_SetSpatialRef( self, (OGRSpatialReferenceH)srs );
+  }
+SWIGINTERN int OGRGeomFieldDefnShadow_IsIgnored(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_IsIgnored( self );
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetIgnored(OGRGeomFieldDefnShadow *self,int bIgnored){
+    OGR_GFld_SetIgnored( self, bIgnored );
+  }
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
@@ -3027,26 +3246,18 @@ XS(_wrap_DontUseExceptions) {
 }
 
 
-XS(_wrap_Driver_name_get) {
+XS(_wrap_new_StyleTable) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    OGRStyleTableShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_name_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_name_get" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    if ((items < 0) || (items > 0)) {
+      SWIG_croak("Usage: new_StyleTable();");
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRDriverShadow_name_get(arg1);
+      result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3068,86 +3279,33 @@ XS(_wrap_Driver_name_get) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     XSRETURN(argvi);
   fail:
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Driver_CreateDataSource) {
+XS(_wrap_delete_StyleTable) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char **arg3 = (char **) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
     dXSARGS;
     
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (const char *)"";
-    }
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Driver_CreateDataSource(self,utf8_path,options);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_StyleTable(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, SWIG_POINTER_DISOWN |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_StyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+      delete_OGRStyleTableShadow(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3169,96 +3327,56 @@ XS(_wrap_Driver_CreateDataSource) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
     {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
+      /* %typemap(out) void */
     }
+    
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Driver_CopyDataSource) {
+XS(_wrap_StyleTable_AddStyle) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     char *arg3 = (char *) 0 ;
-    char **arg4 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int res3 ;
+    char *buf3 = 0 ;
+    int alloc3 = 0 ;
     int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg3 = (const char *)"";
-    }
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: Driver_CopyDataSource(self,copy_ds,utf8_path,options);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: StyleTable_AddStyle(self,pszName,pszStyleString);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_AddStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
-    if (items > 2) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(2));
-        arg3 = SvPV_nolen(ST(2));
-      }
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_AddStyle" "', argument " "2"" of type '" "char const *""'");
     }
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
+    arg2 = reinterpret_cast< char * >(buf2);
+    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "StyleTable_AddStyle" "', argument " "3"" of type '" "char const *""'");
     }
+    arg3 = reinterpret_cast< char * >(buf3);
     {
       CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
+      result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3280,51 +3398,42 @@ XS(_wrap_Driver_CopyDataSource) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     XSRETURN(argvi);
   fail:
     
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Driver_Open) {
+XS(_wrap_StyleTable_LoadStyleTable) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     char *arg2 = (char *) 0 ;
-    int arg3 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
     int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
+    int result;
     dXSARGS;
     
     {
       /* %typemap(default) const char * utf8_path */
       arg2 = (const char *)"";
     }
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Driver_Open(self,utf8_path,update);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: StyleTable_LoadStyleTable(self,utf8_path);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_LoadStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     if (items > 1) {
       {
         /* %typemap(in,numinputs=1) (const char* utf8_path) */
@@ -3332,16 +3441,9 @@ XS(_wrap_Driver_Open) {
         arg2 = SvPV_nolen(ST(1));
       }
     }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver_Open" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
     {
       CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
+      result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3363,21 +3465,19 @@ XS(_wrap_Driver_Open) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Driver_DeleteDataSource) {
+XS(_wrap_StyleTable_SaveStyleTable) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
@@ -3390,13 +3490,13 @@ XS(_wrap_Driver_DeleteDataSource) {
       arg2 = (const char *)"";
     }
     if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Driver_DeleteDataSource(self,utf8_path);");
+      SWIG_croak("Usage: StyleTable_SaveStyleTable(self,utf8_path);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_SaveStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     if (items > 1) {
       {
         /* %typemap(in,numinputs=1) (const char* utf8_path) */
@@ -3406,7 +3506,7 @@ XS(_wrap_Driver_DeleteDataSource) {
     }
     {
       CPLErrorReset();
-      result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
+      result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3438,9 +3538,9 @@ XS(_wrap_Driver_DeleteDataSource) {
 }
 
 
-XS(_wrap_Driver__TestCapability) {
+XS(_wrap_StyleTable_Find) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
@@ -3448,30 +3548,25 @@ XS(_wrap_Driver__TestCapability) {
     char *buf2 = 0 ;
     int alloc2 = 0 ;
     int argvi = 0;
-    bool result;
+    char *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Driver__TestCapability(self,cap);");
+      SWIG_croak("Usage: StyleTable_Find(self,pszName);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver__TestCapability" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_Find" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver__TestCapability" "', argument " "2"" of type '" "char const *""'");
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_Find" "', argument " "2"" of type '" "char const *""'");
     }
     arg2 = reinterpret_cast< char * >(buf2);
     {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
       CPLErrorReset();
-      result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
+      result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3493,7 +3588,13 @@ XS(_wrap_Driver__TestCapability) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
     
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
@@ -3505,26 +3606,25 @@ XS(_wrap_Driver__TestCapability) {
 }
 
 
-XS(_wrap_Driver_GetName) {
+XS(_wrap_StyleTable_ResetStyleStringReading) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_GetName(self);");
+      SWIG_croak("Usage: StyleTable_ResetStyleStringReading(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_ResetStyleStringReading" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRDriverShadow_GetName(arg1);
+      OGRStyleTableShadow_ResetStyleStringReading(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3547,11 +3647,7 @@ XS(_wrap_Driver_GetName) {
       
     }
     {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
+      /* %typemap(out) void */
     }
     
     XSRETURN(argvi);
@@ -3562,25 +3658,26 @@ XS(_wrap_Driver_GetName) {
 }
 
 
-XS(_wrap_Driver_Register) {
+XS(_wrap_StyleTable_GetNextStyle) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    char *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Register(self);");
+      SWIG_croak("Usage: StyleTable_GetNextStyle(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetNextStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRDriverShadow_Register(arg1);
+      result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3603,7 +3700,11 @@ XS(_wrap_Driver_Register) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
     XSRETURN(argvi);
@@ -3614,25 +3715,26 @@ XS(_wrap_Driver_Register) {
 }
 
 
-XS(_wrap_Driver_Deregister) {
+XS(_wrap_StyleTable_GetLastStyleName) {
   {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    char *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Deregister(self);");
+      SWIG_croak("Usage: StyleTable_GetLastStyleName(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetLastStyleName" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRDriverShadow_Deregister(arg1);
+      result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3655,7 +3757,11 @@ XS(_wrap_Driver_Deregister) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
     XSRETURN(argvi);
@@ -3666,9 +3772,9 @@ XS(_wrap_Driver_Deregister) {
 }
 
 
-XS(_wrap_DataSource_name_get) {
+XS(_wrap_Driver_name_get) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
@@ -3676,16 +3782,16 @@ XS(_wrap_DataSource_name_get) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_name_get(self);");
+      SWIG_croak("Usage: Driver_name_get(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_name_get" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_name_get" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRDataSourceShadow_name_get(arg1);
+      result = (char *)OGRDriverShadow_name_get(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3723,25 +3829,70 @@ XS(_wrap_DataSource_name_get) {
 }
 
 
-XS(_wrap_delete_DataSource) {
+XS(_wrap_Driver_CreateDataSource) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    char **arg3 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    OGRDataSourceShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_DataSource(self);");
+    {
+      /* %typemap(default) const char * utf8_path */
+      arg2 = (const char *)"";
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_DISOWN |  0 );
+    if ((items < 1) || (items > 3)) {
+      SWIG_croak("Usage: Driver_CreateDataSource(self,utf8_path,options);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_DataSource" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %typemap(in,numinputs=1) (const char* utf8_path) */
+        sv_utf8_upgrade(ST(1));
+        arg2 = SvPV_nolen(ST(1));
+      }
+    }
+    if (items > 2) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(2))) {
+          if (SvROK(ST(2))) {
+            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(2)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg3 = CSLAddString( arg3, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(2));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg3 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      delete_OGRDataSourceShadow(arg1);
+      result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3763,38 +3914,96 @@ XS(_wrap_delete_DataSource) {
       
       
     }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
     {
-      /* %typemap(out) void */
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
     }
-    
     XSRETURN(argvi);
   fail:
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_GetRefCount) {
+XS(_wrap_Driver_CopyDataSource) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
+    char *arg3 = (char *) 0 ;
+    char **arg4 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    int result;
+    OGRDataSourceShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetRefCount(self);");
+    {
+      /* %typemap(default) const char * utf8_path */
+      arg3 = (const char *)"";
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    if ((items < 2) || (items > 4)) {
+      SWIG_croak("Usage: Driver_CopyDataSource(self,copy_ds,utf8_path,options);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
+    if (items > 2) {
+      {
+        /* %typemap(in,numinputs=1) (const char* utf8_path) */
+        sv_utf8_upgrade(ST(2));
+        arg3 = SvPV_nolen(ST(2));
+      }
+    }
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+      result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3816,36 +4025,68 @@ XS(_wrap_DataSource_GetRefCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
-    XSRETURN(argvi);
-  fail:
     
-    SWIG_croak_null();
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_GetSummaryRefCount) {
+XS(_wrap_Driver_Open) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    int arg3 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
-    int result;
+    OGRDataSourceShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetSummaryRefCount(self);");
+    {
+      /* %typemap(default) const char * utf8_path */
+      arg2 = (const char *)"";
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    if ((items < 1) || (items > 3)) {
+      SWIG_croak("Usage: Driver_Open(self,utf8_path,update);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetSummaryRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %typemap(in,numinputs=1) (const char* utf8_path) */
+        sv_utf8_upgrade(ST(1));
+        arg2 = SvPV_nolen(ST(1));
+      }
+    }
+    if (items > 2) {
+      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver_Open" "', argument " "3"" of type '" "int""'");
+      } 
+      arg3 = static_cast< int >(val3);
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+      result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3867,36 +4108,50 @@ XS(_wrap_DataSource_GetSummaryRefCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_GetLayerCount) {
+XS(_wrap_Driver_DeleteDataSource) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetLayerCount(self);");
+    {
+      /* %typemap(default) const char * utf8_path */
+      arg2 = (const char *)"";
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: Driver_DeleteDataSource(self,utf8_path);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %typemap(in,numinputs=1) (const char* utf8_path) */
+        sv_utf8_upgrade(ST(1));
+        arg2 = SvPV_nolen(ST(1));
+      }
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
+      result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3928,26 +4183,40 @@ XS(_wrap_DataSource_GetLayerCount) {
 }
 
 
-XS(_wrap_DataSource__GetDriver) {
+XS(_wrap_Driver__TestCapability) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
     int argvi = 0;
-    OGRDriverShadow *result = 0 ;
+    bool result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource__GetDriver(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Driver__TestCapability(self,cap);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetDriver" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver__TestCapability" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver__TestCapability" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+      result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -3969,19 +4238,21 @@ XS(_wrap_DataSource__GetDriver) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_GetName) {
+XS(_wrap_Driver_GetName) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
@@ -3989,16 +4260,16 @@ XS(_wrap_DataSource_GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetName(self);");
+      SWIG_croak("Usage: Driver_GetName(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRDataSourceShadow_GetName(arg1);
+      result = (char *)OGRDriverShadow_GetName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4036,34 +4307,25 @@ XS(_wrap_DataSource_GetName) {
 }
 
 
-XS(_wrap_DataSource__DeleteLayer) {
+XS(_wrap_Driver_Register) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    int arg2 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__DeleteLayer(self,index);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Driver_Register(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__DeleteLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource__DeleteLayer" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+      OGRDriverShadow_Register(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4086,44 +4348,36 @@ XS(_wrap_DataSource__DeleteLayer) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_SyncToDisk) {
+XS(_wrap_Driver_Deregister) {
   {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_SyncToDisk(self);");
+      SWIG_croak("Usage: Driver_Deregister(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+      OGRDriverShadow_Deregister(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4146,12 +4400,7 @@ XS(_wrap_DataSource_SyncToDisk) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
     XSRETURN(argvi);
@@ -4162,89 +4411,82 @@ XS(_wrap_DataSource_SyncToDisk) {
 }
 
 
-XS(_wrap_DataSource__CreateLayer) {
+XS(_wrap_DataSource_name_get) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
-    OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
-    char **arg5 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
     int argvi = 0;
-    OGRLayerShadow *result = 0 ;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: DataSource__CreateLayer(self,name,srs,geom_type,options);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_name_get(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__CreateLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_name_get" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      CPLErrorReset();
+      result = (char *)OGRDataSourceShadow_name_get(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
       }
-      arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
     }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "DataSource__CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
-      } 
-      arg4 = static_cast< OGRwkbGeometryType >(val4);
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_delete_DataSource) {
+  {
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_DataSource(self);");
     }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_DataSource" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+      delete_OGRDataSourceShadow(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4266,102 +4508,38 @@ XS(_wrap_DataSource__CreateLayer) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    
     {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
+      /* %typemap(out) void */
     }
+    
     XSRETURN(argvi);
   fail:
     
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_CopyLayer) {
+XS(_wrap_DataSource_GetRefCount) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char **arg4 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
     int argvi = 0;
-    OGRLayerShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: DataSource_CopyLayer(self,src_layer,new_name,options);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_GetRefCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CopyLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CopyLayer" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
     {
       CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      result = (int)OGRDataSourceShadow_GetRefCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4383,58 +4561,36 @@ XS(_wrap_DataSource_CopyLayer) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
     XSRETURN(argvi);
   fail:
     
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource__GetLayerByIndex) {
+XS(_wrap_DataSource_GetSummaryRefCount) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    int arg2 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRLayerShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__GetLayerByIndex(self,index);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_GetSummaryRefCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetLayerByIndex" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetSummaryRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource__GetLayerByIndex" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
     {
       CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+      result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4456,44 +4612,36 @@ XS(_wrap_DataSource__GetLayerByIndex) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource__GetLayerByName) {
+XS(_wrap_DataSource_GetLayerCount) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRLayerShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__GetLayerByName(self,layer_name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_GetLayerCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetLayerByName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* layer_name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
       CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+      result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4515,7 +4663,7 @@ XS(_wrap_DataSource__GetLayerByName) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -4525,40 +4673,26 @@ XS(_wrap_DataSource__GetLayerByName) {
 }
 
 
-XS(_wrap_DataSource__TestCapability) {
+XS(_wrap_DataSource__GetDriver) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
-    bool result;
+    OGRDriverShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__TestCapability(self,cap);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource__GetDriver(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__TestCapability" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetDriver" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__TestCapability" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
     {
       CPLErrorReset();
-      result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+      result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4580,73 +4714,36 @@ XS(_wrap_DataSource__TestCapability) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource__ExecuteSQL) {
+XS(_wrap_DataSource_GetName) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
-    char *arg4 = (char *) "" ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
     int argvi = 0;
-    OGRLayerShadow *result = 0 ;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: DataSource__ExecuteSQL(self,statement,spatialFilter,dialect);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_GetName(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__ExecuteSQL" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-      }
-      arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
-    }
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DataSource__ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
     {
       CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+      result = (char *)OGRDataSourceShadow_GetName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4668,47 +4765,50 @@ XS(_wrap_DataSource__ExecuteSQL) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
     
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_DataSource_ReleaseResultSet) {
+XS(_wrap_DataSource__DeleteLayer) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource_ReleaseResultSet(self,layer);");
+      SWIG_croak("Usage: DataSource__DeleteLayer(self,index);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ReleaseResultSet" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__DeleteLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource__DeleteLayer" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+      result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4731,7 +4831,12 @@ XS(_wrap_DataSource_ReleaseResultSet) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
@@ -4744,26 +4849,26 @@ XS(_wrap_DataSource_ReleaseResultSet) {
 }
 
 
-XS(_wrap_Layer_GetRefCount) {
+XS(_wrap_DataSource_SyncToDisk) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetRefCount(self);");
+      SWIG_croak("Usage: DataSource_SyncToDisk(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetRefCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRLayerShadow_GetRefCount(arg1);
+      result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4785,7 +4890,14 @@ XS(_wrap_Layer_GetRefCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
     
     XSRETURN(argvi);
   fail:
@@ -4795,33 +4907,89 @@ XS(_wrap_Layer_GetRefCount) {
 }
 
 
-XS(_wrap_Layer_SetSpatialFilter) {
+XS(_wrap_DataSource__CreateLayer) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
+    OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
+    char **arg5 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
     int argvi = 0;
+    OGRLayerShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilter(self,filter);");
+    if ((items < 2) || (items > 5)) {
+      SWIG_croak("Usage: DataSource__CreateLayer(self,name,srs,geom_type,options);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__CreateLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    if (items > 2) {
+      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+      if (!SWIG_IsOK(res3)) {
+        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      }
+      arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
+    }
+    if (items > 3) {
+      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+      if (!SWIG_IsOK(ecode4)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "DataSource__CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
+      } 
+      arg4 = static_cast< OGRwkbGeometryType >(val4);
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(4)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg5 = CSLAddString( arg5, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(4));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg5 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
     {
       CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilter(arg1,arg2);
+      result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4843,132 +5011,175 @@ XS(_wrap_Layer_SetSpatialFilter) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
     
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg5) CSLDestroy( arg5 );
+    }
     XSRETURN(argvi);
   fail:
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg5) CSLDestroy( arg5 );
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SetSpatialFilterRect) {
+XS(_wrap_DataSource_CopyLayer) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    char *arg3 = (char *) 0 ;
+    char **arg4 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int res3 ;
+    char *buf3 = 0 ;
+    int alloc3 = 0 ;
     int argvi = 0;
+    OGRLayerShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilterRect(self,minx,miny,maxx,maxy);");
+    if ((items < 3) || (items > 4)) {
+      SWIG_croak("Usage: DataSource_CopyLayer(self,src_layer,new_name,options);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CopyLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilterRect(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CopyLayer" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
       }
-      
-      
     }
     {
-      /* %typemap(out) void */
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     
-    
-    
-    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
     XSRETURN(argvi);
   fail:
     
     
-    
-    
-    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetSpatialFilter) {
+XS(_wrap_DataSource__GetLayerByIndex) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    int arg2 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
+    OGRLayerShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetSpatialFilter(self);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: DataSource__GetLayerByIndex(self,index);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetLayerByIndex" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    if (items > 1) {
+      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+      if (!SWIG_IsOK(ecode2)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource__GetLayerByIndex" "', argument " "2"" of type '" "int""'");
+      } 
+      arg2 = static_cast< int >(val2);
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -4990,45 +5201,44 @@ XS(_wrap_Layer_GetSpatialFilter) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SetAttributeFilter) {
+XS(_wrap_DataSource__GetLayerByName) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    OGRLayerShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetAttributeFilter(self,filter_string);");
+      SWIG_croak("Usage: DataSource__GetLayerByName(self,layer_name);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetAttributeFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetLayerByName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetAttributeFilter" "', argument " "2"" of type '" "char *""'");
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* layer_name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5050,44 +5260,50 @@ XS(_wrap_Layer_SetAttributeFilter) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_ResetReading) {
+XS(_wrap_DataSource__TestCapability) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
     int argvi = 0;
+    bool result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_ResetReading(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: DataSource__TestCapability(self,cap);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ResetReading" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__TestCapability" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__TestCapability" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRLayerShadow_ResetReading(arg1);
+      result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5109,38 +5325,73 @@ XS(_wrap_Layer_ResetReading) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetName) {
+XS(_wrap_DataSource__ExecuteSQL) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
+    char *arg4 = (char *) "" ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
+    int res4 ;
+    char *buf4 = 0 ;
+    int alloc4 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    OGRLayerShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetName(self);");
+    if ((items < 2) || (items > 4)) {
+      SWIG_croak("Usage: DataSource__ExecuteSQL(self,statement,spatialFilter,dialect);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetName" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__ExecuteSQL" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    if (items > 2) {
+      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+      if (!SWIG_IsOK(res3)) {
+        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+      }
+      arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+    }
+    if (items > 3) {
+      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
+      if (!SWIG_IsOK(res4)) {
+        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DataSource__ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
+      }
+      arg4 = reinterpret_cast< char * >(buf4);
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetName(arg1);
+      result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5162,42 +5413,47 @@ XS(_wrap_Layer_GetName) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
-    XSRETURN(argvi);
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+    XSRETURN(argvi);
   fail:
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetGeomType) {
+XS(_wrap_DataSource_ReleaseResultSet) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    OGRwkbGeometryType result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetGeomType(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: DataSource_ReleaseResultSet(self,layer);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeomType" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ReleaseResultSet" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+      OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5219,36 +5475,40 @@ XS(_wrap_Layer_GetGeomType) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetGeometryColumn) {
+XS(_wrap_DataSource_GetStyleTable) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    OGRStyleTableShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetGeometryColumn(self);");
+      SWIG_croak("Usage: DataSource_GetStyleTable(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeometryColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+      result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5270,13 +5530,7 @@ XS(_wrap_Layer_GetGeometryColumn) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -5286,26 +5540,33 @@ XS(_wrap_Layer_GetGeometryColumn) {
 }
 
 
-XS(_wrap_Layer_GetFIDColumn) {
+XS(_wrap_DataSource_SetStyleTable) {
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetFIDColumn(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: DataSource_SetStyleTable(self,table);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFIDColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
     {
       CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+      OGRDataSourceShadow_SetStyleTable(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5328,49 +5589,39 @@ XS(_wrap_Layer_GetFIDColumn) {
       
     }
     {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
+      /* %typemap(out) void */
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetFeature) {
+XS(_wrap_Layer_GetRefCount) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    long arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    long val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetFeature(self,fid);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetRefCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetRefCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeature" "', argument " "2"" of type '" "long""'");
-    } 
-    arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+      result = (int)OGRLayerShadow_GetRefCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5392,38 +5643,43 @@ XS(_wrap_Layer_GetFeature) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetNextFeature) {
+XS(_wrap_Layer_SetSpatialFilter__SWIG_0) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetNextFeature(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_SetSpatialFilter(self,filter);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetNextFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
     {
       CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
+      OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5445,44 +5701,71 @@ XS(_wrap_Layer_GetNextFeature) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SetNextByIndex) {
+XS(_wrap_Layer_SetSpatialFilterRect__SWIG_0) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    long arg2 ;
+    double arg2 ;
+    double arg3 ;
+    double arg4 ;
+    double arg5 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    long val2 ;
+    double val2 ;
     int ecode2 = 0 ;
+    double val3 ;
+    int ecode3 = 0 ;
+    double val4 ;
+    int ecode4 = 0 ;
+    double val5 ;
+    int ecode5 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetNextByIndex(self,new_index);");
+    if ((items < 5) || (items > 5)) {
+      SWIG_croak("Usage: Layer_SetSpatialFilterRect(self,minx,miny,maxx,maxy);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetNextByIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetNextByIndex" "', argument " "2"" of type '" "long""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "double""'");
     } 
-    arg2 = static_cast< long >(val2);
+    arg2 = static_cast< double >(val2);
+    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
+    } 
+    arg3 = static_cast< double >(val3);
+    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
+    } 
+    arg4 = static_cast< double >(val4);
+    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
+    } 
+    arg5 = static_cast< double >(val5);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+      OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5505,57 +5788,60 @@ XS(_wrap_Layer_SetNextByIndex) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
     
+    
+    
+    
     XSRETURN(argvi);
   fail:
     
     
+    
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SetFeature) {
+XS(_wrap_Layer_SetSpatialFilter__SWIG_1) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetFeature(self,feature);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Layer_SetSpatialFilter(self,iGeomField,filter);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SetSpatialFilter" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
     }
+    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+      OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5578,125 +5864,170 @@ XS(_wrap_Layer_SetFeature) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
     
+    
     XSRETURN(argvi);
   fail:
     
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_CreateFeature) {
+XS(_wrap_Layer_SetSpatialFilter) {
+  dXSARGS;
+  
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_CreateFeature(self,feature);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+        _v = SWIG_CheckState(res);
       }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(1), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
       }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
       }
     }
+  check_1:
     
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
     
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilter__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilter__SWIG_1); return;
+    }
   }
+  
+  croak("No matching function for overloaded 'Layer_SetSpatialFilter'");
+  XSRETURN(0);
 }
 
 
-XS(_wrap_Layer_DeleteFeature) {
+XS(_wrap_Layer_SetSpatialFilterRect__SWIG_1) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    long arg2 ;
+    int arg2 ;
+    double arg3 ;
+    double arg4 ;
+    double arg5 ;
+    double arg6 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    long val2 ;
+    int val2 ;
     int ecode2 = 0 ;
+    double val3 ;
+    int ecode3 = 0 ;
+    double val4 ;
+    int ecode4 = 0 ;
+    double val5 ;
+    int ecode5 = 0 ;
+    double val6 ;
+    int ecode6 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_DeleteFeature(self,fid);");
+    if ((items < 6) || (items > 6)) {
+      SWIG_croak("Usage: Layer_SetSpatialFilterRect(self,iGeomField,minx,miny,maxx,maxy);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteFeature" "', argument " "2"" of type '" "long""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "int""'");
     } 
-    arg2 = static_cast< long >(val2);
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
+    } 
+    arg3 = static_cast< double >(val3);
+    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
+    } 
+    arg4 = static_cast< double >(val4);
+    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
+    } 
+    arg5 = static_cast< double >(val5);
+    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
+    if (!SWIG_IsOK(ecode6)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Layer_SetSpatialFilterRect" "', argument " "6"" of type '" "double""'");
+    } 
+    arg6 = static_cast< double >(val6);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+      OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5719,163 +6050,199 @@ XS(_wrap_Layer_DeleteFeature) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
     
-    XSRETURN(argvi);
-  fail:
     
     
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SyncToDisk) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_SyncToDisk(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SyncToDisk" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
     
     XSRETURN(argvi);
   fail:
     
+    
+    
+    
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetLayerDefn) {
+XS(_wrap_Layer_SetSpatialFilterRect) {
+  dXSARGS;
+  
   {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetLayerDefn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetLayerDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 5) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+        _v = SWIG_CheckState(res);
       }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
       }
-      
-      
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+  check_1:
     
-    XSRETURN(argvi);
-  fail:
+    if (items == 6) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
     
-    SWIG_croak_null();
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilterRect__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilterRect__SWIG_1); return;
+    }
   }
+  
+  croak("No matching function for overloaded 'Layer_SetSpatialFilterRect'");
+  XSRETURN(0);
 }
 
 
-XS(_wrap_Layer_GetFeatureCount) {
+XS(_wrap_Layer_GetSpatialFilter) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    int result;
+    OGRGeometryShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetFeatureCount(self,force);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetSpatialFilter(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeatureCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeatureCount" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
     {
       CPLErrorReset();
-      result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
+      result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5897,54 +6264,45 @@ XS(_wrap_Layer_GetFeatureCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetExtent) {
+XS(_wrap_Layer_SetAttributeFilter) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    double *arg2 ;
-    int arg3 = (int) 1 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    double argout2[4] ;
-    int val3 ;
-    int ecode3 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetExtent(self,force);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_SetAttributeFilter(self,filter_string);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetAttributeFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_GetExtent" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetAttributeFilter" "', argument " "2"" of type '" "char *""'");
     }
+    arg2 = reinterpret_cast< char * >(buf2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
+      result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5974,66 +6332,36 @@ XS(_wrap_Layer_GetExtent) {
         SWIG_croak( OGRErrMessages(result) );
       }
     }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+4-items+1);
-        for (i = 0; i < 4; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
-        argvi++;
-      }  
-    }
-    
-    
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    
-    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer__TestCapability) {
+XS(_wrap_Layer_ResetReading) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
-    bool result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer__TestCapability(self,cap);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_ResetReading(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__TestCapability" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ResetReading" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__TestCapability" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
     {
       CPLErrorReset();
-      result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+      OGRLayerShadow_ResetReading(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6055,61 +6383,38 @@ XS(_wrap_Layer__TestCapability) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer__CreateField) {
+XS(_wrap_Layer_GetName) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
-    int arg3 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Layer__CreateField(self,field_def,approx_ok);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetName(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__CreateField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetName" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__CreateField" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer__CreateField" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+      result = (char *)OGRLayerShadow_GetName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6132,54 +6437,41 @@ XS(_wrap_Layer__CreateField) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
-    
-    
     XSRETURN(argvi);
   fail:
     
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer__DeleteField) {
+XS(_wrap_Layer_GetGeomType) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    OGRwkbGeometryType result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer__DeleteField(self,iField);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetGeomType(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__DeleteField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeomType" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer__DeleteField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+      result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6201,61 +6493,36 @@ XS(_wrap_Layer__DeleteField) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_ReorderField) {
+XS(_wrap_Layer_GetGeometryColumn) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Layer_ReorderField(self,iOldFieldPos,iNewFieldPos);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetGeometryColumn(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeometryColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_ReorderField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_ReorderField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+      result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6278,60 +6545,41 @@ XS(_wrap_Layer_ReorderField) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
-    
-    
     XSRETURN(argvi);
   fail:
     
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_ReorderFields) {
+XS(_wrap_Layer_GetFIDColumn) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_ReorderFields(self,nList,pList);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetFIDColumn(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFIDColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      arg3 = (int*) malloc(arg2*sizeof(int));
-      for( int i = 0; i<arg2; i++ ) {
-        SV **sv = av_fetch(av, i, 0);
-        arg3[i] =  SvIV(*sv);
-      }
-    }
-    {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+      result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6354,81 +6602,49 @@ XS(_wrap_Layer_ReorderFields) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg3)
-      free((void*) arg3);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg3)
-      free((void*) arg3);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_AlterFieldDefn) {
+XS(_wrap_Layer_GetFeature) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
-    int arg4 ;
+    long arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
+    long val2 ;
     int ecode2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    OGRFeatureShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Layer_AlterFieldDefn(self,iField,field_def,nFlags);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_GetFeature(self,fid);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_AlterFieldDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_AlterFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_AlterFieldDefn" "', argument " "3"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRFieldDefnShadow * >(argp3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_AlterFieldDefn" "', argument " "4"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeature" "', argument " "2"" of type '" "long""'");
     } 
-    arg4 = static_cast< int >(val4);
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+      result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6450,49 +6666,38 @@ XS(_wrap_Layer_AlterFieldDefn) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     
     XSRETURN(argvi);
   fail:
     
     
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_StartTransaction) {
+XS(_wrap_Layer_GetNextFeature) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    OGRFeatureShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_StartTransaction(self);");
+      SWIG_croak("Usage: Layer_GetNextFeature(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetNextFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+      result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6514,14 +6719,7 @@ XS(_wrap_Layer_StartTransaction) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -6531,26 +6729,34 @@ XS(_wrap_Layer_StartTransaction) {
 }
 
 
-XS(_wrap_Layer_CommitTransaction) {
+XS(_wrap_Layer_SetNextByIndex) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    long arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    long val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_CommitTransaction(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_SetNextByIndex(self,new_index);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetNextByIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetNextByIndex" "', argument " "2"" of type '" "long""'");
+    } 
+    arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+      result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6581,34 +6787,49 @@ XS(_wrap_Layer_CommitTransaction) {
       }
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_RollbackTransaction) {
+XS(_wrap_Layer_SetFeature) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_RollbackTransaction(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_SetFeature(self,feature);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_RollbackTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+      result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6639,34 +6860,49 @@ XS(_wrap_Layer_RollbackTransaction) {
       }
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetSpatialRef) {
+XS(_wrap_Layer_CreateFeature) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetSpatialRef(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_CreateFeature(self,feature);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
     {
       CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+      result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6688,36 +6924,53 @@ XS(_wrap_Layer_GetSpatialRef) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_GetFeaturesRead) {
+XS(_wrap_Layer_DeleteFeature) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    long arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    long val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    GIntBig result;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetFeaturesRead(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_DeleteFeature(self,fid);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeaturesRead" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteFeature" "', argument " "2"" of type '" "long""'");
+    } 
+    arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = OGRLayerShadow_GetFeaturesRead(arg1);
+      result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6740,70 +6993,44 @@ XS(_wrap_Layer_GetFeaturesRead) {
       
     }
     {
-      /* %typemap(out) GIntBig */
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi), (IV) result);
-      argvi++;
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SetIgnoredFields) {
+XS(_wrap_Layer_SyncToDisk) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetIgnoredFields(self,options);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_SyncToDisk(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetIgnoredFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SyncToDisk" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-        } else
-        SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-      }
-    }
-    {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+      result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6834,121 +7061,34 @@ XS(_wrap_Layer_SetIgnoredFields) {
       }
     }
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Intersection) {
+XS(_wrap_Layer_GetLayerDefn) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    OGRFeatureDefnShadow *result = 0 ;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Intersection(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetLayerDefn(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Intersection" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetLayerDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Intersection" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Intersection" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -6970,136 +7110,46 @@ XS(_wrap_Layer_Intersection) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Union) {
+XS(_wrap_Layer_GetFeatureCount) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    int arg2 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    int result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Union(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: Layer_GetFeatureCount(self,force);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Union" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeatureCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Union" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Union" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
+    if (items > 1) {
+      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+      if (!SWIG_IsOK(ecode2)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeatureCount" "', argument " "2"" of type '" "int""'");
+      } 
+      arg2 = static_cast< int >(val2);
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7121,136 +7171,54 @@ XS(_wrap_Layer_Union) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
     
     XSRETURN(argvi);
   fail:
     
     
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_SymDifference) {
+XS(_wrap_Layer_GetExtent) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    double *arg2 ;
+    int arg3 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    double argout2[4] ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_SymDifference(self,method_layer,result_layer,options,callback,callback_data);");
+    {
+      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+      arg2 = argout2;
+    }
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: Layer_GetExtent(self,force);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SymDifference" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SymDifference" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SymDifference" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
+    if (items > 1) {
+      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_GetExtent" "', argument " "3"" of type '" "int""'");
+      } 
+      arg3 = static_cast< int >(val3);
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7280,128 +7248,66 @@ XS(_wrap_Layer_SymDifference) {
         SWIG_croak( OGRErrMessages(result) );
       }
     }
-    
-    
-    
     {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
+      /* %typemap(argout) (double argout[ANY]) */
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+4-items+1);
+        for (i = 0; i < 4; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
+        argvi++;
+      }  
     }
     
+    
+    
     XSRETURN(argvi);
   fail:
     
     
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Identity) {
+XS(_wrap_Layer__TestCapability) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
     int argvi = 0;
-    OGRErr result;
+    bool result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Identity(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer__TestCapability(self,cap);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Identity" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__TestCapability" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Identity" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Identity" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__TestCapability" "', argument " "2"" of type '" "char const *""'");
     }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7423,136 +7329,61 @@ XS(_wrap_Layer_Identity) {
       
       
     }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Update) {
+XS(_wrap_Layer__CreateField) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+    int arg3 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     void *argp2 = 0 ;
     int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Update(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 2) || (items > 3)) {
+      SWIG_croak("Usage: Layer__CreateField(self,field_def,approx_ok);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Update" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__CreateField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Update" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Update" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__CreateField" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
+    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
+    if (items > 2) {
+      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer__CreateField" "', argument " "3"" of type '" "int""'");
+      } 
+      arg3 = static_cast< int >(val3);
     }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7585,125 +7416,44 @@ XS(_wrap_Layer_Update) {
     
     
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     XSRETURN(argvi);
   fail:
     
     
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Clip) {
+XS(_wrap_Layer__DeleteField) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Clip(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer__DeleteField(self,iField);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Clip" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__DeleteField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Clip" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Clip" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer__DeleteField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7735,126 +7485,51 @@ XS(_wrap_Layer_Clip) {
     }
     
     
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     XSRETURN(argvi);
   fail:
     
     
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Layer_Erase) {
+XS(_wrap_Layer_ReorderField) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
+    int arg2 ;
+    int arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Erase(self,method_layer,result_layer,options,callback,callback_data);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Layer_ReorderField(self,iOldFieldPos,iNewFieldPos);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Erase" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Erase" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Erase" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_ReorderField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_ReorderField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+      result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7887,45 +7562,50 @@ XS(_wrap_Layer_Erase) {
     
     
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     XSRETURN(argvi);
   fail:
     
     
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_delete_Feature) {
+XS(_wrap_Layer_ReorderFields) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_Feature(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_ReorderFields(self,nList,pList);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_DISOWN |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Feature" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (int nList, int* pList) */
+      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
+      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
+      AV *av = (AV*)(SvRV(ST(1)));
+      arg2 = av_len(av)+1;
+      arg3 = (int*) malloc(arg2*sizeof(int));
+      for( int i = 0; i<arg2; i++ ) {
+        SV **sv = av_fetch(av, i, 0);
+        arg3[i] =  SvIV(*sv);
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
       CPLErrorReset();
-      delete_OGRFeatureShadow(arg1);
+      result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -7948,42 +7628,81 @@ XS(_wrap_delete_Feature) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg3)
+      free((void*) arg3);
+    }
     XSRETURN(argvi);
   fail:
     
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg3)
+      free((void*) arg3);
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_new_Feature) {
+XS(_wrap_Layer_AlterFieldDefn) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    int arg2 ;
+    OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
+    int arg4 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
     int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: new_Feature(feature_def);");
+    if ((items < 4) || (items > 4)) {
+      SWIG_croak("Usage: Layer_AlterFieldDefn(self,iField,field_def,nFlags);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Feature" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_AlterFieldDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    {
-      CPLErrorReset();
-      result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_AlterFieldDefn" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_AlterFieldDefn" "', argument " "3"" of type '" "OGRFieldDefnShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRFieldDefnShadow * >(argp3);
+    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_AlterFieldDefn" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+    {
+      if (!arg3) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8005,36 +7724,72 @@ XS(_wrap_new_Feature) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
+    
     
     XSRETURN(argvi);
   fail:
     
+    
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetDefnRef) {
+XS(_wrap_Layer_CreateGeomField) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
+    int arg3 = (int) 1 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetDefnRef(self);");
+    if ((items < 2) || (items > 3)) {
+      SWIG_croak("Usage: Layer_CreateGeomField(self,field_def,approx_ok);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateGeomField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateGeomField" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
+    if (items > 2) {
+      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_CreateGeomField" "', argument " "3"" of type '" "int""'");
+      } 
+      arg3 = static_cast< int >(val3);
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+      result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8056,49 +7811,47 @@ XS(_wrap_Feature_GetDefnRef) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
     
     XSRETURN(argvi);
   fail:
     
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetGeometry) {
+XS(_wrap_Layer_StartTransaction) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetGeometry(self,geom);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_StartTransaction(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometry" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      /* %typemap(check) (OGRGeometryShadow *geom) */
-      if (!arg2)
-      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+      result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8129,47 +7882,34 @@ XS(_wrap_Feature_SetGeometry) {
       }
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetGeometryDirectly) {
+XS(_wrap_Layer_CommitTransaction) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__SetGeometryDirectly(self,geom);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_CommitTransaction(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetGeometryDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
-    }
-    {
-      /* %typemap(check) (OGRGeometryShadow *geom) */
-      if (!arg2)
-      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+      result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8200,36 +7940,34 @@ XS(_wrap_Feature__SetGeometryDirectly) {
       }
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetGeometryRef) {
+XS(_wrap_Layer_RollbackTransaction) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetGeometryRef(self);");
+      SWIG_croak("Usage: Layer_RollbackTransaction(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeometryRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_RollbackTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+      result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8251,7 +7989,14 @@ XS(_wrap_Feature_GetGeometryRef) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
     
     XSRETURN(argvi);
   fail:
@@ -8261,26 +8006,43 @@ XS(_wrap_Feature_GetGeometryRef) {
 }
 
 
-XS(_wrap_Feature_Clone) {
+XS(_wrap_Layer_FindFieldIndex) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    int arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_Clone(self);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Layer_FindFieldIndex(self,pszFieldName,bExactMatch);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Clone" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_FindFieldIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_FindFieldIndex" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_FindFieldIndex" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
     {
       CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+      result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8302,49 +8064,40 @@ XS(_wrap_Feature_Clone) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_Equal) {
+XS(_wrap_Layer_GetSpatialRef) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
     int argvi = 0;
-    bool result;
+    OSRSpatialReferenceShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_Equal(self,feature);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetSpatialRef(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Equal" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_Equal" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+      result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8366,38 +8119,36 @@ XS(_wrap_Feature_Equal) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldCount) {
+XS(_wrap_Layer_GetFeaturesRead) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    GIntBig result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetFieldCount(self);");
+      SWIG_croak("Usage: Layer_GetFeaturesRead(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeaturesRead" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+      result = OGRLayerShadow_GetFeaturesRead(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8419,7 +8170,12 @@ XS(_wrap_Feature_GetFieldCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) GIntBig */
+      ST(argvi) = sv_newmortal();
+      sv_setiv(ST(argvi), (IV) result);
+      argvi++;
+    }
     
     XSRETURN(argvi);
   fail:
@@ -8429,34 +8185,56 @@ XS(_wrap_Feature_GetFieldCount) {
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
+XS(_wrap_Layer_SetIgnoredFields) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    char **arg2 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,id);");
+      SWIG_croak("Usage: Layer_SetIgnoredFields(self,options);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetIgnoredFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    {
+      /* %typemap(in) char **options */
+      if (SvOK(ST(1))) {
+        if (SvROK(ST(1))) {
+          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
+            AV *av = (AV*)(SvRV(ST(1)));
+            for (int i = 0; i < av_len(av)+1; i++) {
+              SV *sv = *(av_fetch(av, i, 0));
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+              char *pszItem = SvPV_nolen(sv);
+              arg2 = CSLAddString( arg2, pszItem );
+            }
+          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
+            HV *hv = (HV*)SvRV(ST(1));
+            SV *sv;
+            char *key;
+            I32 klen;
+            arg2 = NULL;
+            hv_iterinit(hv);
+            while(sv = hv_iternextsv(hv,&key,&klen)) {
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
+            }
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+        } else
+        SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+      result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8478,49 +8256,130 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
     XSRETURN(argvi);
   fail:
     
-    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
+XS(_wrap_Layer_Intersection) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,name);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Intersection(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Intersection" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Intersection" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
     }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Intersection" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
       }
     }
     {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8542,124 +8401,136 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
     
     XSRETURN(argvi);
   fail:
     
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef) {
-  dXSARGS;
-  
+XS(_wrap_Layer_Union) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Union(self,method_layer,result_layer,options,callback,callback_data);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Union" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Union" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Union" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
       {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
+    }
+    if (items > 4) {
       {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
       }
     }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldDefnRef'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldAsString) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsString(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetFieldAsString(arg1,arg2);
+      result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8682,116 +8553,139 @@ XS(_wrap_Feature_GetFieldAsString) {
       
     }
     {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldAsInteger(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
     
     XSRETURN(argvi);
   fail:
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDouble) {
+XS(_wrap_Layer_SymDifference) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
-    double result;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,id);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_SymDifference(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SymDifference" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (double)OGRFeatureShadow_GetFieldAsDouble(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SymDifference" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SymDifference" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
         
         
         
@@ -8809,73 +8703,136 @@ XS(_wrap_Feature_GetFieldAsDouble) {
       
       
     }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
     
     XSRETURN(argvi);
   fail:
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDateTime) {
+XS(_wrap_Layer_Identity) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    int *arg6 = (int *) 0 ;
-    int *arg7 = (int *) 0 ;
-    int *arg8 = (int *) 0 ;
-    int *arg9 = (int *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    int temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int temp7 ;
-    int res7 = SWIG_TMPOBJ ;
-    int temp8 ;
-    int res8 = SWIG_TMPOBJ ;
-    int temp9 ;
-    int res9 = SWIG_TMPOBJ ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    arg7 = &temp7;
-    arg8 = &temp8;
-    arg9 = &temp9;
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,id);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Identity(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Identity" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Identity" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Identity" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -8898,111 +8855,135 @@ XS(_wrap_Feature_GetFieldAsDateTime) {
       
     }
     {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
+    
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
     }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res7)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res8)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res9)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    
-    
     
     XSRETURN(argvi);
   fail:
     
     
     
-    
-    
-    
-    
-    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsIntegerList) {
+XS(_wrap_Layer_Update) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int **arg4 = (int **) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    int *pList3 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,id,pList);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Update(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Update" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Update" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Update" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
+      result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9025,133 +9006,286 @@ XS(_wrap_Feature_GetFieldAsIntegerList) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
+    
+    
+    
     {
-      /* %typemap(argout) (int *nLen, const int **pList) */
-      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
-      argvi++;
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
     }
     
-    
     XSRETURN(argvi);
   fail:
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDoubleList) {
+XS(_wrap_Layer_Clip) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    double **arg4 = (double **) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    double *pList3 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,id,pList);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Clip(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Clip" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Clip" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
     }
-    {
-      /* %typemap(out) void */
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Clip" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
     }
-    {
-      /* %typemap(argout) (int *nLen, const double **pList) */
-      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
-      argvi++;
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     XSRETURN(argvi);
   fail:
     
     
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsStringList) {
+XS(_wrap_Layer_Erase) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char ***arg3 = (char ***) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+    char **arg4 = (char **) NULL ;
+    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+    void *arg6 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    char **pList3 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (char ***pList3) */
-      arg3 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,id);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 3) || (items > 6)) {
+      SWIG_croak("Usage: Layer_Erase(self,method_layer,result_layer,options,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Erase" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Erase" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Erase" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
+                arg4 = CSLAddString( arg4, pszItem );
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
+              }
+            } else
+            SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+        }
+      }
+    }
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsStringList(arg1,arg2,arg3);
+      result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9174,54 +9308,56 @@ XS(_wrap_Feature_GetFieldAsStringList) {
       
     }
     {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (char ***pList) */
-      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
-      argvi++;
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     XSRETURN(argvi);
   fail:
     
     
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_IsFieldSet__SWIG_0) {
+XS(_wrap_Layer_GetStyleTable) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    bool result;
+    OGRStyleTableShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,id);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Layer_GetStyleTable(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+      result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9243,49 +9379,43 @@ XS(_wrap_Feature_IsFieldSet__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_IsFieldSet__SWIG_1) {
+XS(_wrap_Layer_SetStyleTable) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    bool result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,name);");
+      SWIG_croak("Usage: Layer_SetStyleTable(self,table);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
     }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
     }
+    arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
     {
       CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+      OGRLayerShadow_SetStyleTable(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9307,127 +9437,97 @@ XS(_wrap_Feature_IsFieldSet__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_IsFieldSet) {
-  dXSARGS;
-  
+XS(_wrap_delete_Feature) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_Feature(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Feature" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      delete_OGRFeatureShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_1); return;
+    {
+      /* %typemap(out) void */
     }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_IsFieldSet'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldIndex) {
+XS(_wrap_new_Feature) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    OGRFeatureShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldIndex(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: new_Feature(feature_def);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Feature" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
-      if (!arg2) {
+      if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+      result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9449,7 +9549,7 @@ XS(_wrap_Feature_GetFieldIndex) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -9459,26 +9559,26 @@ XS(_wrap_Feature_GetFieldIndex) {
 }
 
 
-XS(_wrap_Feature_GetFID) {
+XS(_wrap_Feature_GetDefnRef) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    OGRFeatureDefnShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetFID(self);");
+      SWIG_croak("Usage: Feature_GetDefnRef(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFID(arg1);
+      result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9500,7 +9600,7 @@ XS(_wrap_Feature_GetFID) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -9510,34 +9610,39 @@ XS(_wrap_Feature_GetFID) {
 }
 
 
-XS(_wrap_Feature_SetFID) {
+XS(_wrap_Feature_SetGeometry) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
+    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetFID(self,fid);");
+      SWIG_croak("Usage: Feature_SetGeometry(self,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometry" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFID" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
+    {
+      /* %typemap(check) (OGRGeometryShadow *geom) */
+      if (!arg2)
+      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
+    }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+      result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9578,25 +9683,37 @@ XS(_wrap_Feature_SetFID) {
 }
 
 
-XS(_wrap_Feature_DumpReadable) {
+XS(_wrap_Feature__SetGeometryDirectly) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_DumpReadable(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature__SetGeometryDirectly(self,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetGeometryDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
+    }
+    {
+      /* %typemap(check) (OGRGeometryShadow *geom) */
+      if (!arg2)
+      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
+    }
     {
       CPLErrorReset();
-      OGRFeatureShadow_DumpReadable(arg1);
+      result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9619,44 +9736,44 @@ XS(_wrap_Feature_DumpReadable) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__UnsetField) {
+XS(_wrap_Feature_GetGeometryRef) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
+    OGRGeometryShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__UnsetField(self,id);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetGeometryRef(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeometryRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__UnsetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_UnsetField(arg1,arg2);
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9678,53 +9795,52 @@ XS(_wrap_Feature__UnsetField) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetField__SWIG_0) {
+XS(_wrap_Feature_SetGeomField__SWIG_0) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    char *arg3 = (char *) 0 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+      SWIG_croak("Usage: Feature_SetGeomField(self,iField,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomField" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) (tostring argin) */
-      sv_utf8_upgrade(ST(2)); /* GDAL expects UTF-8 */
-      arg3 = SvPV_nolen( ST(2) ); 
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
     }
+    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9747,54 +9863,65 @@ XS(_wrap_Feature__SetField__SWIG_0) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
+    
     XSRETURN(argvi);
   fail:
     
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetField__SWIG_1) {
+XS(_wrap_Feature_SetGeomField__SWIG_1) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
+    char *arg2 = (char *) 0 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+      SWIG_croak("Usage: Feature_SetGeomField(self,name,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_1(arg1,arg2,arg3);
+      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9817,56 +9944,156 @@ XS(_wrap_Feature__SetField__SWIG_1) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
-    
     XSRETURN(argvi);
   fail:
     
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetField__SWIG_2) {
+XS(_wrap_Feature_SetGeomField) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomField__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomField__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_SetGeomField'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_0) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    double arg3 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+      SWIG_croak("Usage: Feature_SetGeomFieldDirectly(self,iField,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
+    res3 = SWIG_ConvertPtr(ST(2), SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
+    }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9889,7 +10116,12 @@ XS(_wrap_Feature__SetField__SWIG_2) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
@@ -9904,89 +10136,43 @@ XS(_wrap_Feature__SetField__SWIG_2) {
 }
 
 
-XS(_wrap_Feature__SetField__SWIG_3) {
+XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    int arg7 ;
-    int arg8 ;
-    int arg9 ;
+    char *arg2 = (char *) 0 ;
+    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int val7 ;
-    int ecode7 = 0 ;
-    int val8 ;
-    int ecode8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
+    int res3 = 0 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,year,month,day,hour,minute,second,tzflag);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetGeomFieldDirectly(self,name,geom);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
-    } 
-    arg6 = static_cast< int >(val6);
-    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
-    } 
-    arg7 = static_cast< int >(val7);
-    ecode8 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "int""'");
-    } 
-    arg8 = static_cast< int >(val8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    res3 = SWIG_ConvertPtr(ST(2), SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_3(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10009,34 +10195,25 @@ XS(_wrap_Feature__SetField__SWIG_3) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
     }
     
     
-    
-    
-    
-    
-    
-    
-    
     XSRETURN(argvi);
   fail:
     
     
-    
-    
-    
-    
-    
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetField) {
+XS(_wrap_Feature_SetGeomFieldDirectly) {
   dXSARGS;
   
   {
@@ -10067,10 +10244,9 @@ XS(_wrap_Feature__SetField) {
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
-          _v = 1;
-        }
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
       }
       if (!_v) goto check_1;
       _ranki += _v*_pi;
@@ -10098,20 +10274,17 @@ XS(_wrap_Feature__SetField) {
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
       }
       if (!_v) goto check_2;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
       }
       if (!_v) goto check_2;
       _ranki += _v*_pi;
@@ -10124,7 +10297,150 @@ XS(_wrap_Feature__SetField) {
     }
   check_2:
     
-    if (items == 3) {
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomFieldDirectly__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_SetGeomFieldDirectly'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_GetGeomFieldRef__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRGeometryShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldRef(self,iField);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldRef" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldRef__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRGeometryShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldRef(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldRef) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
       SWIG_TypeRank _ranki = 0;
       SWIG_TypeRank _rankm = 0;
       SWIG_TypeRank _pi = 1;
@@ -10134,7 +10450,7 @@ XS(_wrap_Feature__SetField) {
         int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
         _v = SWIG_CheckState(res);
       }
-      if (!_v) goto check_3;
+      if (!_v) goto check_1;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
@@ -10144,28 +10460,18 @@ XS(_wrap_Feature__SetField) {
           _v = SWIG_CheckState(res);
         }
       }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_3;
+      if (!_v) goto check_1;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 3;
+        _rank = _ranki; _index = 1;
         if (_rank == _rankm) goto dispatch;
       }
     }
-  check_3:
+  check_1:
     
-    if (items == 9) {
+    if (items == 2) {
       SWIG_TypeRank _ranki = 0;
       SWIG_TypeRank _rankm = 0;
       SWIG_TypeRank _pi = 1;
@@ -10175,156 +10481,3832 @@ XS(_wrap_Feature__SetField) {
         int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
         _v = SWIG_CheckState(res);
       }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
+      if (!_v) goto check_2;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
       }
-      if (!_v) goto check_4;
+      if (!_v) goto check_2;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
       }
-      if (!_v) goto check_4;
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldRef__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldRef__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_GetGeomFieldRef'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_Clone) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRFeatureShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_Clone(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Clone" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_Equal) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int argvi = 0;
+    bool result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_Equal(self,feature);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Equal" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_Equal" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldCount) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetFieldCount(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRFieldDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRFieldDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldDefnRef) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_GetFieldDefnRef'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_GetGeomFieldCount) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldCount(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRGeomFieldDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRGeomFieldDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldDefnRef) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_GetGeomFieldDefnRef'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_GetFieldAsString) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    char *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsString(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (char *)OGRFeatureShadow_GetFieldAsString(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsInteger) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetFieldAsInteger(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsDouble) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    double result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (double)OGRFeatureShadow_GetFieldAsDouble(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsDateTime) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    int *arg4 = (int *) 0 ;
+    int *arg5 = (int *) 0 ;
+    int *arg6 = (int *) 0 ;
+    int *arg7 = (int *) 0 ;
+    int *arg8 = (int *) 0 ;
+    int *arg9 = (int *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int temp3 ;
+    int res3 = SWIG_TMPOBJ ;
+    int temp4 ;
+    int res4 = SWIG_TMPOBJ ;
+    int temp5 ;
+    int res5 = SWIG_TMPOBJ ;
+    int temp6 ;
+    int res6 = SWIG_TMPOBJ ;
+    int temp7 ;
+    int res7 = SWIG_TMPOBJ ;
+    int temp8 ;
+    int res8 = SWIG_TMPOBJ ;
+    int temp9 ;
+    int res9 = SWIG_TMPOBJ ;
+    int argvi = 0;
+    dXSARGS;
+    
+    arg3 = &temp3;
+    arg4 = &temp4;
+    arg5 = &temp5;
+    arg6 = &temp6;
+    arg7 = &temp7;
+    arg8 = &temp8;
+    arg9 = &temp9;
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    if (SWIG_IsTmpObj(res3)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res4)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res5)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res6)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res7)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res8)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res9)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsIntegerList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    int **arg4 = (int **) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int nLen3 ;
+    int *pList3 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
+      arg3 = &nLen3;
+      arg4 = &pList3;
+    }
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,id,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    {
+      /* %typemap(argout) (int *nLen, const int **pList) */
+      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
+      argvi++;
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsDoubleList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    double **arg4 = (double **) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int nLen3 ;
+    double *pList3 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
+      arg3 = &nLen3;
+      arg4 = &pList3;
+    }
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,id,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    {
+      /* %typemap(argout) (int *nLen, const double **pList) */
+      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
+      argvi++;
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFieldAsStringList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    char ***arg3 = (char ***) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    char **pList3 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    {
+      /* %typemap(in,numinputs=0) (char ***pList3) */
+      arg3 = &pList3;
+    }
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_GetFieldAsStringList(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    {
+      /* %typemap(argout) (char ***pList) */
+      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
+      argvi++;
+    }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_IsFieldSet__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    bool result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_IsFieldSet(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_IsFieldSet__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    bool result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_IsFieldSet(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_IsFieldSet) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_IsFieldSet'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_GetFieldIndex) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldIndex(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetGeomFieldIndex) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldIndex(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetFID) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetFID(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetFID(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFID) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_SetFID(self,fid);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFID" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_DumpReadable) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_DumpReadable(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_DumpReadable(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__UnsetField) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature__UnsetField(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__UnsetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_UnsetField(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__SetField__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    char *arg3 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      /* %typemap(in) (tostring argin) */
+      sv_utf8_upgrade(ST(2)); /* GDAL expects UTF-8 */
+      arg3 = SvPV_nolen( ST(2) ); 
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__SetField__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int arg3 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetField__SWIG_1(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__SetField__SWIG_2) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    double arg3 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    double val3 ;
+    int ecode3 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
+    } 
+    arg3 = static_cast< double >(val3);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__SetField__SWIG_3) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int arg3 ;
+    int arg4 ;
+    int arg5 ;
+    int arg6 ;
+    int arg7 ;
+    int arg8 ;
+    int arg9 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
+    int val5 ;
+    int ecode5 = 0 ;
+    int val6 ;
+    int ecode6 = 0 ;
+    int val7 ;
+    int ecode7 = 0 ;
+    int val8 ;
+    int ecode8 = 0 ;
+    int val9 ;
+    int ecode9 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 9) || (items > 9)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,year,month,day,hour,minute,second,tzflag);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
+    } 
+    arg5 = static_cast< int >(val5);
+    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
+    if (!SWIG_IsOK(ecode6)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
+    } 
+    arg6 = static_cast< int >(val6);
+    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
+    if (!SWIG_IsOK(ecode7)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
+    } 
+    arg7 = static_cast< int >(val7);
+    ecode8 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
+    if (!SWIG_IsOK(ecode8)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "int""'");
+    } 
+    arg8 = static_cast< int >(val8);
+    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
+    if (!SWIG_IsOK(ecode9)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
+    } 
+    arg9 = static_cast< int >(val9);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetField__SWIG_3(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__SetField) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
+          _v = 1;
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_3;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_3;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_3;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 3;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_3:
+    
+    if (items == 9) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 4;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_4:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_1); return;
+    case 3:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_2); return;
+    case 4:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_3); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature__SetField'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature_SetFieldIntegerList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int arg3 ;
+    int *arg4 = (int *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,id,nList,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      /* %typemap(in,numinputs=1) (int nList, int* pList) */
+      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
+      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
+      AV *av = (AV*)(SvRV(ST(2)));
+      arg3 = av_len(av)+1;
+      arg4 = (int*) malloc(arg3*sizeof(int));
+      for( int i = 0; i<arg3; i++ ) {
+        SV **sv = av_fetch(av, i, 0);
+        arg4[i] =  SvIV(*sv);
+      }
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg4)
+      free((void*) arg4);
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg4)
+      free((void*) arg4);
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFieldDoubleList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    int arg3 ;
+    double *arg4 = (double *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,id,nList,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      /* %typemap(in,numinputs=1) (int nList, double* pList) */
+      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
+      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
+      AV *av = (AV*)(SvRV(ST(2)));
+      arg3 = av_len(av)+1;
+      arg4 = (double*) malloc(arg3*sizeof(double));
+      for( int i = 0; i<arg3; i++ ) {
+        SV **sv = av_fetch(av, i, 0);
+        arg4[i] =  SvNV(*sv);
+      }
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    {
+      /* %typemap(freearg) (int nList, double* pList) */
+      if (arg4)
+      free((void*) arg4);
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    {
+      /* %typemap(freearg) (int nList, double* pList) */
+      if (arg4)
+      free((void*) arg4);
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFieldStringList) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    char **arg3 = (char **) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldStringList(self,id,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      /* %typemap(in) char **options */
+      if (SvOK(ST(2))) {
+        if (SvROK(ST(2))) {
+          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
+            AV *av = (AV*)(SvRV(ST(2)));
+            for (int i = 0; i < av_len(av)+1; i++) {
+              SV *sv = *(av_fetch(av, i, 0));
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+              char *pszItem = SvPV_nolen(sv);
+              arg3 = CSLAddString( arg3, pszItem );
+            }
+          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
+            HV *hv = (HV*)SvRV(ST(2));
+            SV *sv;
+            char *key;
+            I32 klen;
+            arg3 = NULL;
+            hv_iterinit(hv);
+            while(sv = hv_iternextsv(hv,&key,&klen)) {
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+              arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
+            }
+          } else
+          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
+        } else
+        SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+      }
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    char *arg3 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int res3 ;
+    char *buf3 = 0 ;
+    int alloc3 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,id,pszValue);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    XSRETURN(argvi);
+  fail:
+    
+    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    char *arg3 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int res3 ;
+    char *buf3 = 0 ;
+    int alloc3 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,name,pszValue);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    XSRETURN(argvi);
+  fail:
+    
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFieldBinaryFromHexString) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature_SetFieldBinaryFromHexString'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Feature__SetFrom) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+    int arg3 = (int) 1 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetFrom(self,other,forgiving);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetFrom" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetFrom" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+    if (items > 2) {
+      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetFrom" "', argument " "3"" of type '" "int""'");
+      } 
+      arg3 = static_cast< int >(val3);
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetFromWithMap) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+    int arg3 ;
+    int arg4 ;
+    int *arg5 = (int *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 4) || (items > 4)) {
+      SWIG_croak("Usage: Feature_SetFromWithMap(self,other,forgiving,nList,pList);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFromWithMap" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFromWithMap" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFromWithMap" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+    {
+      /* %typemap(in,numinputs=1) (int nList, int* pList) */
+      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
+      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
+      AV *av = (AV*)(SvRV(ST(3)));
+      arg4 = av_len(av)+1;
+      arg5 = (int*) malloc(arg4*sizeof(int));
+      for( int i = 0; i<arg4; i++ ) {
+        SV **sv = av_fetch(av, i, 0);
+        arg5[i] =  SvIV(*sv);
+      }
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    
+    
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg5)
+      free((void*) arg5);
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    {
+      /* %typemap(freearg) (int nList, int* pList) */
+      if (arg5)
+      free((void*) arg5);
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_GetStyleString) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    char *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetStyleString(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature_SetStyleString) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_SetStyleString(self,the_string);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetStyleString" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    XSRETURN(argvi);
+  fail:
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__GetFieldType__SWIG_0) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRFieldType result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature__GetFieldType(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__GetFieldType" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__GetFieldType__SWIG_1) {
+  {
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRFieldType result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature__GetFieldType(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Feature__GetFieldType) {
+  dXSARGS;
+  
+  {
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
         {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
           _v = SWIG_CheckState(res);
         }
       }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
-          _v = SWIG_CheckState(res);
-        }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 2) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__GetFieldType__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__GetFieldType__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Feature__GetFieldType'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_delete_FeatureDefn) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_FeatureDefn(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FeatureDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    {
+      CPLErrorReset();
+      delete_OGRFeatureDefnShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_new_FeatureDefn) {
+  {
+    char *arg1 = (char *) NULL ;
+    int res1 ;
+    char *buf1 = 0 ;
+    int alloc1 = 0 ;
+    int argvi = 0;
+    OGRFeatureDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 0) || (items > 1)) {
+      SWIG_croak("Usage: new_FeatureDefn(name_null_ok);");
+    }
+    if (items > 0) {
+      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
+      if (!SWIG_IsOK(res1)) {
+        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FeatureDefn" "', argument " "1"" of type '" "char const *""'");
+      }
+      arg1 = reinterpret_cast< char * >(buf1);
+    }
+    {
+      CPLErrorReset();
+      result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    XSRETURN(argvi);
+  fail:
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FeatureDefn_GetName) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    char *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_GetName(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FeatureDefn_GetFieldCount) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_GetFieldCount(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
-          _v = SWIG_CheckState(res);
-        }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FeatureDefn_GetFieldDefn) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRFieldDefnShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_GetFieldDefn(self,i);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
-          _v = SWIG_CheckState(res);
-        }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 4;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FeatureDefn_GetFieldIndex) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_GetFieldIndex(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
-  check_4:
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_1); return;
-    case 3:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_2); return;
-    case 4:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_3); return;
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FeatureDefn_AddFieldDefn) {
+  {
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_AddFieldDefn(self,defn);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
     }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature__SetField'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_SetFieldIntegerList) {
+XS(_wrap_FeatureDefn_GetGeomFieldCount) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int *arg4 = (int *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,id,nList,pList);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_GetGeomFieldCount(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (int*) malloc(arg3*sizeof(int));
-      for( int i = 0; i<arg3; i++ ) {
-        SV **sv = av_fetch(av, i, 0);
-        arg4[i] =  SvIV(*sv);
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10346,71 +14328,44 @@ XS(_wrap_Feature_SetFieldIntegerList) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg4)
-      free((void*) arg4);
-    }
     XSRETURN(argvi);
   fail:
     
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg4)
-      free((void*) arg4);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldDoubleList) {
+XS(_wrap_FeatureDefn_GetGeomFieldDefn) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     int arg2 ;
-    int arg3 ;
-    double *arg4 = (double *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
+    OGRGeomFieldDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,id,nList,pList);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_GetGeomFieldDefn(self,i);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (double*) malloc(arg3*sizeof(double));
-      for( int i = 0; i<arg3; i++ ) {
-        SV **sv = av_fetch(av, i, 0);
-        arg4[i] =  SvNV(*sv);
-      }
-    }
-    {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10432,87 +14387,49 @@ XS(_wrap_Feature_SetFieldDoubleList) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      if (arg4)
-      free((void*) arg4);
-    }
     XSRETURN(argvi);
   fail:
     
     
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      if (arg4)
-      free((void*) arg4);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldStringList) {
+XS(_wrap_FeatureDefn_GetGeomFieldIndex) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char **arg3 = (char **) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldStringList(self,id,pList);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_GetGeomFieldIndex(self,name);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(2))) {
-        if (SvROK(ST(2))) {
-          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(2)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg3 = CSLAddString( arg3, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(2));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg3 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference to an array or hash");
-        } else
-        SWIG_croak("the 'options' argument to a Geo::GDAL method is not a reference");   
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10534,63 +14451,40 @@ XS(_wrap_Feature_SetFieldStringList) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
-    
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
     XSRETURN(argvi);
   fail:
     
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__SetFrom) {
+XS(_wrap_FeatureDefn_AddGeomFieldDefn) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    int arg3 = (int) 1 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     void *argp2 = 0 ;
     int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
     int argvi = 0;
-    OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetFrom(self,other,forgiving);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_AddGeomFieldDefn(self,defn);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetFrom" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetFrom" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetFrom" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
+    arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10598,7 +14492,7 @@ XS(_wrap_Feature__SetFrom) {
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+      OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10621,81 +14515,47 @@ XS(_wrap_Feature__SetFrom) {
       
     }
     {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
+      /* %typemap(out) void */
     }
     
     
-    
     XSRETURN(argvi);
   fail:
     
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFromWithMap) {
+XS(_wrap_FeatureDefn_DeleteGeomFieldDefn) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    int arg3 ;
-    int arg4 ;
-    int *arg5 = (int *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Feature_SetFromWithMap(self,other,forgiving,nList,pList);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_DeleteGeomFieldDefn(self,idx);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFromWithMap" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFromWithMap" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFromWithMap" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-      SWIG_croak("expected a reference to an array as an argument to a Geo::GDAL method");
-      AV *av = (AV*)(SvRV(ST(3)));
-      arg4 = av_len(av)+1;
-      arg5 = (int*) malloc(arg4*sizeof(int));
-      for( int i = 0; i<arg4; i++ ) {
-        SV **sv = av_fetch(av, i, 0);
-        arg5[i] =  SvIV(*sv);
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+      result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10727,47 +14587,35 @@ XS(_wrap_Feature_SetFromWithMap) {
     }
     
     
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg5)
-      free((void*) arg5);
-    }
     XSRETURN(argvi);
   fail:
     
     
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      if (arg5)
-      free((void*) arg5);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetStyleString) {
+XS(_wrap_FeatureDefn_GetGeomType) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    OGRwkbGeometryType result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetStyleString(self);");
+      SWIG_croak("Usage: FeatureDefn_GetGeomType(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+      result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10789,13 +14637,7 @@ XS(_wrap_Feature_GetStyleString) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -10805,34 +14647,33 @@ XS(_wrap_Feature_GetStyleString) {
 }
 
 
-XS(_wrap_Feature_SetStyleString) {
+XS(_wrap_FeatureDefn_SetGeomType) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRwkbGeometryType arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetStyleString(self,the_string);");
+      SWIG_croak("Usage: FeatureDefn_SetGeomType(self,geom_type);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetStyleString" "', argument " "2"" of type '" "char const *""'");
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg2 = reinterpret_cast< char * >(buf2);
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeomType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+    } 
+    arg2 = static_cast< OGRwkbGeometryType >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+      OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10858,44 +14699,36 @@ XS(_wrap_Feature_SetStyleString) {
       /* %typemap(out) void */
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__GetFieldType__SWIG_0) {
+XS(_wrap_FeatureDefn_GetReferenceCount) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
-    OGRFieldType result;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__GetFieldType(self,id);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_GetReferenceCount(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetReferenceCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__GetFieldType" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+      result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10919,47 +14752,34 @@ XS(_wrap_Feature__GetFieldType__SWIG_0) {
     }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature__GetFieldType__SWIG_1) {
+XS(_wrap_FeatureDefn_IsGeometryIgnored) {
   {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRFieldType result;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__GetFieldType(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_IsGeometryIgnored(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -10991,105 +14811,88 @@ XS(_wrap_Feature__GetFieldType__SWIG_1) {
 }
 
 
-XS(_wrap_Feature__GetFieldType) {
-  dXSARGS;
-  
+XS(_wrap_FeatureDefn_SetGeometryIgnored) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_SetGeometryIgnored(self,bIgnored);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__GetFieldType__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__GetFieldType__SWIG_1); return;
+    {
+      /* %typemap(out) void */
     }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature__GetFieldType'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_delete_FeatureDefn) {
+XS(_wrap_FeatureDefn_IsStyleIgnored) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_FeatureDefn(self);");
+      SWIG_croak("Usage: FeatureDefn_IsStyleIgnored(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_DISOWN |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FeatureDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      delete_OGRFeatureDefnShadow(arg1);
+      result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11111,9 +14914,7 @@ XS(_wrap_delete_FeatureDefn) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -11123,29 +14924,33 @@ XS(_wrap_delete_FeatureDefn) {
 }
 
 
-XS(_wrap_new_FeatureDefn) {
+XS(_wrap_FeatureDefn_SetStyleIgnored) {
   {
-    char *arg1 = (char *) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
+    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: new_FeatureDefn(name_null_ok);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_SetStyleIgnored(self,bIgnored);");
     }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FeatureDefn" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+      OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11167,36 +14972,53 @@ XS(_wrap_new_FeatureDefn) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    {
+      /* %typemap(out) void */
+    }
+    
+    
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetName) {
+XS(_wrap_FeatureDefn_IsSame) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFeatureDefnShadow *arg2 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetName(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FeatureDefn_IsSame(self,other_defn);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsSame" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_IsSame" "', argument " "2"" of type '" "OGRFeatureDefnShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRFeatureDefnShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
     {
       CPLErrorReset();
-      result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+      result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11218,42 +15040,37 @@ XS(_wrap_FeatureDefn_GetName) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldCount) {
+XS(_wrap_delete_FieldDefn) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldCount(self);");
+      SWIG_croak("Usage: delete_FieldDefn(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FieldDefn" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+      delete_OGRFieldDefnShadow(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11275,7 +15092,9 @@ XS(_wrap_FeatureDefn_GetFieldCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
     
     XSRETURN(argvi);
   fail:
@@ -11285,34 +15104,39 @@ XS(_wrap_FeatureDefn_GetFieldCount) {
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldDefn) {
+XS(_wrap_new_FieldDefn) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
+    char *arg1 = (char *) "unnamed" ;
+    OGRFieldType arg2 = (OGRFieldType) OFTString ;
+    int res1 ;
+    char *buf1 = 0 ;
+    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
     OGRFieldDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldDefn(self,i);");
+    if ((items < 0) || (items > 2)) {
+      SWIG_croak("Usage: new_FieldDefn(name_null_ok,field_type);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    if (items > 0) {
+      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
+      if (!SWIG_IsOK(res1)) {
+        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FieldDefn" "', argument " "1"" of type '" "char const *""'");
+      }
+      arg1 = reinterpret_cast< char * >(buf1);
+    }
+    if (items > 1) {
+      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+      if (!SWIG_IsOK(ecode2)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_FieldDefn" "', argument " "2"" of type '" "OGRFieldType""'");
+      } 
+      arg2 = static_cast< OGRFieldType >(val2);
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+      result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11334,49 +15158,95 @@ XS(_wrap_FeatureDefn_GetFieldDefn) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldIndex) {
+XS(_wrap_FieldDefn_GetName) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldIndex(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FieldDefn_GetName(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
+      CPLErrorReset();
+      result = (char *)OGRFieldDefnShadow_GetName(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
     }
     {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_FieldDefn_GetNameRef) {
+  {
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    char *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FieldDefn_GetNameRef(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+      result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11398,7 +15268,13 @@ XS(_wrap_FeatureDefn_GetFieldIndex) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
     
     XSRETURN(argvi);
   fail:
@@ -11408,30 +15284,28 @@ XS(_wrap_FeatureDefn_GetFieldIndex) {
 }
 
 
-XS(_wrap_FeatureDefn_AddFieldDefn) {
+XS(_wrap_FieldDefn_SetName) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_AddFieldDefn(self,defn);");
+      SWIG_croak("Usage: FieldDefn_SetName(self,name);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -11439,7 +15313,7 @@ XS(_wrap_FeatureDefn_AddFieldDefn) {
     }
     {
       CPLErrorReset();
-      OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+      OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11465,36 +15339,34 @@ XS(_wrap_FeatureDefn_AddFieldDefn) {
       /* %typemap(out) void */
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetGeomType) {
+XS(_wrap_FieldDefn_GetType) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    OGRwkbGeometryType result;
+    OGRFieldType result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomType(self);");
+      SWIG_croak("Usage: FieldDefn_GetType(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+      result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11526,10 +15398,10 @@ XS(_wrap_FeatureDefn_GetGeomType) {
 }
 
 
-XS(_wrap_FeatureDefn_SetGeomType) {
+XS(_wrap_FieldDefn_SetType) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRwkbGeometryType arg2 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRFieldType arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
@@ -11538,21 +15410,21 @@ XS(_wrap_FeatureDefn_SetGeomType) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetGeomType(self,geom_type);");
+      SWIG_croak("Usage: FieldDefn_SetType(self,type);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeomType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetType" "', argument " "2"" of type '" "OGRFieldType""'");
     } 
-    arg2 = static_cast< OGRwkbGeometryType >(val2);
+    arg2 = static_cast< OGRFieldType >(val2);
     {
       CPLErrorReset();
-      OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+      OGRFieldDefnShadow_SetType(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11588,77 +15460,26 @@ XS(_wrap_FeatureDefn_SetGeomType) {
 }
 
 
-XS(_wrap_FeatureDefn_GetReferenceCount) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetReferenceCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetReferenceCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_IsGeometryIgnored) {
+XS(_wrap_FieldDefn_GetJustify) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    OGRJustification result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_IsGeometryIgnored(self);");
+      SWIG_croak("Usage: FieldDefn_GetJustify(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+      result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11690,10 +15511,10 @@ XS(_wrap_FeatureDefn_IsGeometryIgnored) {
 }
 
 
-XS(_wrap_FeatureDefn_SetGeometryIgnored) {
+XS(_wrap_FieldDefn_SetJustify) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRJustification arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
@@ -11702,21 +15523,21 @@ XS(_wrap_FeatureDefn_SetGeometryIgnored) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetGeometryIgnored(self,bIgnored);");
+      SWIG_croak("Usage: FieldDefn_SetJustify(self,justify);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetJustify" "', argument " "2"" of type '" "OGRJustification""'");
     } 
-    arg2 = static_cast< int >(val2);
+    arg2 = static_cast< OGRJustification >(val2);
     {
       CPLErrorReset();
-      OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+      OGRFieldDefnShadow_SetJustify(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11752,9 +15573,9 @@ XS(_wrap_FeatureDefn_SetGeometryIgnored) {
 }
 
 
-XS(_wrap_FeatureDefn_IsStyleIgnored) {
+XS(_wrap_FieldDefn_GetWidth) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
@@ -11762,16 +15583,16 @@ XS(_wrap_FeatureDefn_IsStyleIgnored) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_IsStyleIgnored(self);");
+      SWIG_croak("Usage: FieldDefn_GetWidth(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+      result = (int)OGRFieldDefnShadow_GetWidth(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11803,9 +15624,9 @@ XS(_wrap_FeatureDefn_IsStyleIgnored) {
 }
 
 
-XS(_wrap_FeatureDefn_SetStyleIgnored) {
+XS(_wrap_FieldDefn_SetWidth) {
   {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
@@ -11815,21 +15636,21 @@ XS(_wrap_FeatureDefn_SetStyleIgnored) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetStyleIgnored(self,bIgnored);");
+      SWIG_croak("Usage: FieldDefn_SetWidth(self,width);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetWidth" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+      OGRFieldDefnShadow_SetWidth(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11865,25 +15686,26 @@ XS(_wrap_FeatureDefn_SetStyleIgnored) {
 }
 
 
-XS(_wrap_delete_FieldDefn) {
+XS(_wrap_FieldDefn_GetPrecision) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_FieldDefn(self);");
+      SWIG_croak("Usage: FieldDefn_GetPrecision(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FieldDefn" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      delete_OGRFieldDefnShadow(arg1);
+      result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11905,9 +15727,7 @@ XS(_wrap_delete_FieldDefn) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -11917,39 +15737,33 @@ XS(_wrap_delete_FieldDefn) {
 }
 
 
-XS(_wrap_new_FieldDefn) {
+XS(_wrap_FieldDefn_SetPrecision) {
   {
-    char *arg1 = (char *) "unnamed" ;
-    OGRFieldType arg2 = (OGRFieldType) OFTString ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
+    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: new_FieldDefn(name_null_ok,field_type);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FieldDefn" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FieldDefn_SetPrecision(self,precision);");
     }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_FieldDefn" "', argument " "2"" of type '" "OGRFieldType""'");
-      } 
-      arg2 = static_cast< OGRFieldType >(val2);
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
+    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetPrecision" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+      OGRFieldDefnShadow_SetPrecision(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -11971,19 +15785,21 @@ XS(_wrap_new_FieldDefn) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    {
+      /* %typemap(out) void */
+    }
+    
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+    
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_GetName) {
+XS(_wrap_FieldDefn_GetTypeName) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
@@ -11993,16 +15809,16 @@ XS(_wrap_FieldDefn_GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetName(self);");
+      SWIG_croak("Usage: FieldDefn_GetTypeName(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetName(arg1);
+      result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12040,26 +15856,34 @@ XS(_wrap_FieldDefn_GetName) {
 }
 
 
-XS(_wrap_FieldDefn_GetNameRef) {
+XS(_wrap_FieldDefn_GetFieldTypeName) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRFieldType arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     char *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetNameRef(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FieldDefn_GetFieldTypeName(self,type);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "2"" of type '" "OGRFieldType""'");
+    } 
+    arg2 = static_cast< OGRFieldType >(val2);
     {
       CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+      result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12089,44 +15913,36 @@ XS(_wrap_FieldDefn_GetNameRef) {
       argvi++;
     }
     
+    
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_SetName) {
+XS(_wrap_FieldDefn_IsIgnored) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetName(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FieldDefn_IsIgnored(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+      result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12148,9 +15964,7 @@ XS(_wrap_FieldDefn_SetName) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -12160,26 +15974,33 @@ XS(_wrap_FieldDefn_SetName) {
 }
 
 
-XS(_wrap_FieldDefn_GetType) {
+XS(_wrap_FieldDefn_SetIgnored) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRFieldType result;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetType(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: FieldDefn_SetIgnored(self,bIgnored);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+      OGRFieldDefnShadow_SetIgnored(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12201,43 +16022,39 @@ XS(_wrap_FieldDefn_GetType) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_SetType) {
+XS(_wrap_delete_GeomFieldDefn) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRFieldType arg2 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetType(self,type);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_GeomFieldDefn(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GeomFieldDefn" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetType" "', argument " "2"" of type '" "OGRFieldType""'");
-    } 
-    arg2 = static_cast< OGRFieldType >(val2);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetType(arg1,arg2);
+      delete_OGRGeomFieldDefnShadow(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12263,36 +16080,47 @@ XS(_wrap_FieldDefn_SetType) {
       /* %typemap(out) void */
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_GetJustify) {
+XS(_wrap_new_GeomFieldDefn) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
+    char *arg1 = (char *) "" ;
+    OGRwkbGeometryType arg2 = (OGRwkbGeometryType) wkbUnknown ;
+    int res1 ;
+    char *buf1 = 0 ;
+    int alloc1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRJustification result;
+    OGRGeomFieldDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetJustify(self);");
+    if ((items < 0) || (items > 2)) {
+      SWIG_croak("Usage: new_GeomFieldDefn(name_null_ok,field_type);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    if (items > 0) {
+      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
+      if (!SWIG_IsOK(res1)) {
+        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_GeomFieldDefn" "', argument " "1"" of type '" "char const *""'");
+      }
+      arg1 = reinterpret_cast< char * >(buf1);
+    }
+    if (items > 1) {
+      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+      if (!SWIG_IsOK(ecode2)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_GeomFieldDefn" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+      } 
+      arg2 = static_cast< OGRwkbGeometryType >(val2);
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+      result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12314,43 +16142,38 @@ XS(_wrap_FieldDefn_GetJustify) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
+    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_SetJustify) {
+XS(_wrap_GeomFieldDefn_GetName) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRJustification arg2 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
+    char *result = 0 ;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetJustify(self,justify);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: GeomFieldDefn_GetName(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetJustify" "', argument " "2"" of type '" "OGRJustification""'");
-    } 
-    arg2 = static_cast< OGRJustification >(val2);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetJustify(arg1,arg2);
+      result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12373,39 +16196,41 @@ XS(_wrap_FieldDefn_SetJustify) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_GetWidth) {
+XS(_wrap_GeomFieldDefn_GetNameRef) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    char *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetWidth(self);");
+      SWIG_croak("Usage: GeomFieldDefn_GetNameRef(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+      result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12427,7 +16252,13 @@ XS(_wrap_FieldDefn_GetWidth) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
     
     XSRETURN(argvi);
   fail:
@@ -12437,33 +16268,36 @@ XS(_wrap_FieldDefn_GetWidth) {
 }
 
 
-XS(_wrap_FieldDefn_SetWidth) {
+XS(_wrap_GeomFieldDefn_SetName) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetWidth(self,width);");
+      SWIG_croak("Usage: GeomFieldDefn_SetName(self,name);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetWidth" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetWidth(arg1,arg2);
+      OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12489,36 +16323,34 @@ XS(_wrap_FieldDefn_SetWidth) {
       /* %typemap(out) void */
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FieldDefn_GetPrecision) {
+XS(_wrap_GeomFieldDefn_GetType) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
+    OGRwkbGeometryType result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetPrecision(self);");
+      SWIG_croak("Usage: GeomFieldDefn_GetType(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+      result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12550,10 +16382,10 @@ XS(_wrap_FieldDefn_GetPrecision) {
 }
 
 
-XS(_wrap_FieldDefn_SetPrecision) {
+XS(_wrap_GeomFieldDefn_SetType) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+    OGRwkbGeometryType arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
@@ -12562,21 +16394,21 @@ XS(_wrap_FieldDefn_SetPrecision) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetPrecision(self,precision);");
+      SWIG_croak("Usage: GeomFieldDefn_SetType(self,type);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetPrecision" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
     } 
-    arg2 = static_cast< int >(val2);
+    arg2 = static_cast< OGRwkbGeometryType >(val2);
     {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+      OGRGeomFieldDefnShadow_SetType(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12612,26 +16444,26 @@ XS(_wrap_FieldDefn_SetPrecision) {
 }
 
 
-XS(_wrap_FieldDefn_GetTypeName) {
+XS(_wrap_GeomFieldDefn_GetSpatialRef) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    OSRSpatialReferenceShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetTypeName(self);");
+      SWIG_croak("Usage: GeomFieldDefn_GetSpatialRef(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+      result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12653,13 +16485,7 @@ XS(_wrap_FieldDefn_GetTypeName) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -12669,34 +16495,33 @@ XS(_wrap_FieldDefn_GetTypeName) {
 }
 
 
-XS(_wrap_FieldDefn_GetFieldTypeName) {
+XS(_wrap_GeomFieldDefn_SetSpatialRef) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRFieldType arg2 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_GetFieldTypeName(self,type);");
+      SWIG_croak("Usage: GeomFieldDefn_SetSpatialRef(self,srs);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "2"" of type '" "OGRFieldType""'");
-    } 
-    arg2 = static_cast< OGRFieldType >(val2);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
     {
       CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+      OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12719,11 +16544,7 @@ XS(_wrap_FieldDefn_GetFieldTypeName) {
       
     }
     {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
+      /* %typemap(out) void */
     }
     
     
@@ -12736,9 +16557,9 @@ XS(_wrap_FieldDefn_GetFieldTypeName) {
 }
 
 
-XS(_wrap_FieldDefn_IsIgnored) {
+XS(_wrap_GeomFieldDefn_IsIgnored) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
@@ -12746,16 +16567,16 @@ XS(_wrap_FieldDefn_IsIgnored) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_IsIgnored(self);");
+      SWIG_croak("Usage: GeomFieldDefn_IsIgnored(self);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     {
       CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+      result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12787,9 +16608,9 @@ XS(_wrap_FieldDefn_IsIgnored) {
 }
 
 
-XS(_wrap_FieldDefn_SetIgnored) {
+XS(_wrap_GeomFieldDefn_SetIgnored) {
   {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
     int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
@@ -12799,21 +16620,21 @@ XS(_wrap_FieldDefn_SetIgnored) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetIgnored(self,bIgnored);");
+      SWIG_croak("Usage: GeomFieldDefn_SetIgnored(self,bIgnored);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+      OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -18929,8 +22750,10 @@ static swig_type_info _swigt__p_OGRDriverShadow = {"_p_OGRDriverShadow", "OGRDri
 static swig_type_info _swigt__p_OGRFeatureDefnShadow = {"_p_OGRFeatureDefnShadow", "OGRFeatureDefnShadow *", 0, 0, (void*)"Geo::OGR::FeatureDefn", 0};
 static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)"Geo::OGR::Feature", 0};
 static swig_type_info _swigt__p_OGRFieldDefnShadow = {"_p_OGRFieldDefnShadow", "OGRFieldDefnShadow *", 0, 0, (void*)"Geo::OGR::FieldDefn", 0};
+static swig_type_info _swigt__p_OGRGeomFieldDefnShadow = {"_p_OGRGeomFieldDefnShadow", "OGRGeomFieldDefnShadow *", 0, 0, (void*)"Geo::OGR::GeomFieldDefn", 0};
 static swig_type_info _swigt__p_OGRGeometryShadow = {"_p_OGRGeometryShadow", "OGRGeometryShadow *", 0, 0, (void*)"Geo::OGR::Geometry", 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
+static swig_type_info _swigt__p_OGRStyleTableShadow = {"_p_OGRStyleTableShadow", "OGRStyleTableShadow *", 0, 0, (void*)"Geo::OGR::StyleTable", 0};
 static swig_type_info _swigt__p_OSRCoordinateTransformationShadow = {"_p_OSRCoordinateTransformationShadow", "OSRCoordinateTransformationShadow *", 0, 0, (void*)"Geo::OSR::CoordinateTransformation", 0};
 static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)"Geo::OSR::SpatialReference", 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
@@ -18949,8 +22772,10 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_OGRFeatureDefnShadow,
   &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRFieldDefnShadow,
+  &_swigt__p_OGRGeomFieldDefnShadow,
   &_swigt__p_OGRGeometryShadow,
   &_swigt__p_OGRLayerShadow,
+  &_swigt__p_OGRStyleTableShadow,
   &_swigt__p_OSRCoordinateTransformationShadow,
   &_swigt__p_OSRSpatialReferenceShadow,
   &_swigt__p_char,
@@ -18969,8 +22794,10 @@ static swig_cast_info _swigc__p_OGRDriverShadow[] = {  {&_swigt__p_OGRDriverShad
 static swig_cast_info _swigc__p_OGRFeatureDefnShadow[] = {  {&_swigt__p_OGRFeatureDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFieldDefnShadow[] = {  {&_swigt__p_OGRFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRGeomFieldDefnShadow[] = {  {&_swigt__p_OGRGeomFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRGeometryShadow[] = {  {&_swigt__p_OGRGeometryShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRStyleTableShadow[] = {  {&_swigt__p_OGRStyleTableShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRCoordinateTransformationShadow[] = {  {&_swigt__p_OSRCoordinateTransformationShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
@@ -18989,8 +22816,10 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_OGRFeatureDefnShadow,
   _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRFieldDefnShadow,
+  _swigc__p_OGRGeomFieldDefnShadow,
   _swigc__p_OGRGeometryShadow,
   _swigc__p_OGRLayerShadow,
+  _swigc__p_OGRStyleTableShadow,
   _swigc__p_OSRCoordinateTransformationShadow,
   _swigc__p_OSRSpatialReferenceShadow,
   _swigc__p_char,
@@ -19019,6 +22848,15 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::callback_d_cp_vp", _wrap_callback_d_cp_vp},
 {"Geo::OGRc::UseExceptions", _wrap_UseExceptions},
 {"Geo::OGRc::DontUseExceptions", _wrap_DontUseExceptions},
+{"Geo::OGRc::new_StyleTable", _wrap_new_StyleTable},
+{"Geo::OGRc::delete_StyleTable", _wrap_delete_StyleTable},
+{"Geo::OGRc::StyleTable_AddStyle", _wrap_StyleTable_AddStyle},
+{"Geo::OGRc::StyleTable_LoadStyleTable", _wrap_StyleTable_LoadStyleTable},
+{"Geo::OGRc::StyleTable_SaveStyleTable", _wrap_StyleTable_SaveStyleTable},
+{"Geo::OGRc::StyleTable_Find", _wrap_StyleTable_Find},
+{"Geo::OGRc::StyleTable_ResetStyleStringReading", _wrap_StyleTable_ResetStyleStringReading},
+{"Geo::OGRc::StyleTable_GetNextStyle", _wrap_StyleTable_GetNextStyle},
+{"Geo::OGRc::StyleTable_GetLastStyleName", _wrap_StyleTable_GetLastStyleName},
 {"Geo::OGRc::Driver_name_get", _wrap_Driver_name_get},
 {"Geo::OGRc::Driver_CreateDataSource", _wrap_Driver_CreateDataSource},
 {"Geo::OGRc::Driver_CopyDataSource", _wrap_Driver_CopyDataSource},
@@ -19044,6 +22882,8 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::DataSource__TestCapability", _wrap_DataSource__TestCapability},
 {"Geo::OGRc::DataSource__ExecuteSQL", _wrap_DataSource__ExecuteSQL},
 {"Geo::OGRc::DataSource_ReleaseResultSet", _wrap_DataSource_ReleaseResultSet},
+{"Geo::OGRc::DataSource_GetStyleTable", _wrap_DataSource_GetStyleTable},
+{"Geo::OGRc::DataSource_SetStyleTable", _wrap_DataSource_SetStyleTable},
 {"Geo::OGRc::Layer_GetRefCount", _wrap_Layer_GetRefCount},
 {"Geo::OGRc::Layer_SetSpatialFilter", _wrap_Layer_SetSpatialFilter},
 {"Geo::OGRc::Layer_SetSpatialFilterRect", _wrap_Layer_SetSpatialFilterRect},
@@ -19070,9 +22910,11 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Layer_ReorderField", _wrap_Layer_ReorderField},
 {"Geo::OGRc::Layer_ReorderFields", _wrap_Layer_ReorderFields},
 {"Geo::OGRc::Layer_AlterFieldDefn", _wrap_Layer_AlterFieldDefn},
+{"Geo::OGRc::Layer_CreateGeomField", _wrap_Layer_CreateGeomField},
 {"Geo::OGRc::Layer_StartTransaction", _wrap_Layer_StartTransaction},
 {"Geo::OGRc::Layer_CommitTransaction", _wrap_Layer_CommitTransaction},
 {"Geo::OGRc::Layer_RollbackTransaction", _wrap_Layer_RollbackTransaction},
+{"Geo::OGRc::Layer_FindFieldIndex", _wrap_Layer_FindFieldIndex},
 {"Geo::OGRc::Layer_GetSpatialRef", _wrap_Layer_GetSpatialRef},
 {"Geo::OGRc::Layer_GetFeaturesRead", _wrap_Layer_GetFeaturesRead},
 {"Geo::OGRc::Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields},
@@ -19083,16 +22925,23 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Layer_Update", _wrap_Layer_Update},
 {"Geo::OGRc::Layer_Clip", _wrap_Layer_Clip},
 {"Geo::OGRc::Layer_Erase", _wrap_Layer_Erase},
+{"Geo::OGRc::Layer_GetStyleTable", _wrap_Layer_GetStyleTable},
+{"Geo::OGRc::Layer_SetStyleTable", _wrap_Layer_SetStyleTable},
 {"Geo::OGRc::delete_Feature", _wrap_delete_Feature},
 {"Geo::OGRc::new_Feature", _wrap_new_Feature},
 {"Geo::OGRc::Feature_GetDefnRef", _wrap_Feature_GetDefnRef},
 {"Geo::OGRc::Feature_SetGeometry", _wrap_Feature_SetGeometry},
 {"Geo::OGRc::Feature__SetGeometryDirectly", _wrap_Feature__SetGeometryDirectly},
 {"Geo::OGRc::Feature_GetGeometryRef", _wrap_Feature_GetGeometryRef},
+{"Geo::OGRc::Feature_SetGeomField", _wrap_Feature_SetGeomField},
+{"Geo::OGRc::Feature_SetGeomFieldDirectly", _wrap_Feature_SetGeomFieldDirectly},
+{"Geo::OGRc::Feature_GetGeomFieldRef", _wrap_Feature_GetGeomFieldRef},
 {"Geo::OGRc::Feature_Clone", _wrap_Feature_Clone},
 {"Geo::OGRc::Feature_Equal", _wrap_Feature_Equal},
 {"Geo::OGRc::Feature_GetFieldCount", _wrap_Feature_GetFieldCount},
 {"Geo::OGRc::Feature_GetFieldDefnRef", _wrap_Feature_GetFieldDefnRef},
+{"Geo::OGRc::Feature_GetGeomFieldCount", _wrap_Feature_GetGeomFieldCount},
+{"Geo::OGRc::Feature_GetGeomFieldDefnRef", _wrap_Feature_GetGeomFieldDefnRef},
 {"Geo::OGRc::Feature_GetFieldAsString", _wrap_Feature_GetFieldAsString},
 {"Geo::OGRc::Feature_GetFieldAsInteger", _wrap_Feature_GetFieldAsInteger},
 {"Geo::OGRc::Feature_GetFieldAsDouble", _wrap_Feature_GetFieldAsDouble},
@@ -19102,6 +22951,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Feature_GetFieldAsStringList", _wrap_Feature_GetFieldAsStringList},
 {"Geo::OGRc::Feature_IsFieldSet", _wrap_Feature_IsFieldSet},
 {"Geo::OGRc::Feature_GetFieldIndex", _wrap_Feature_GetFieldIndex},
+{"Geo::OGRc::Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex},
 {"Geo::OGRc::Feature_GetFID", _wrap_Feature_GetFID},
 {"Geo::OGRc::Feature_SetFID", _wrap_Feature_SetFID},
 {"Geo::OGRc::Feature_DumpReadable", _wrap_Feature_DumpReadable},
@@ -19110,6 +22960,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Feature_SetFieldIntegerList", _wrap_Feature_SetFieldIntegerList},
 {"Geo::OGRc::Feature_SetFieldDoubleList", _wrap_Feature_SetFieldDoubleList},
 {"Geo::OGRc::Feature_SetFieldStringList", _wrap_Feature_SetFieldStringList},
+{"Geo::OGRc::Feature_SetFieldBinaryFromHexString", _wrap_Feature_SetFieldBinaryFromHexString},
 {"Geo::OGRc::Feature__SetFrom", _wrap_Feature__SetFrom},
 {"Geo::OGRc::Feature_SetFromWithMap", _wrap_Feature_SetFromWithMap},
 {"Geo::OGRc::Feature_GetStyleString", _wrap_Feature_GetStyleString},
@@ -19122,6 +22973,11 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::FeatureDefn_GetFieldDefn", _wrap_FeatureDefn_GetFieldDefn},
 {"Geo::OGRc::FeatureDefn_GetFieldIndex", _wrap_FeatureDefn_GetFieldIndex},
 {"Geo::OGRc::FeatureDefn_AddFieldDefn", _wrap_FeatureDefn_AddFieldDefn},
+{"Geo::OGRc::FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount},
+{"Geo::OGRc::FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn},
+{"Geo::OGRc::FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex},
+{"Geo::OGRc::FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn},
+{"Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn},
 {"Geo::OGRc::FeatureDefn_GetGeomType", _wrap_FeatureDefn_GetGeomType},
 {"Geo::OGRc::FeatureDefn_SetGeomType", _wrap_FeatureDefn_SetGeomType},
 {"Geo::OGRc::FeatureDefn_GetReferenceCount", _wrap_FeatureDefn_GetReferenceCount},
@@ -19129,6 +22985,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::FeatureDefn_SetGeometryIgnored", _wrap_FeatureDefn_SetGeometryIgnored},
 {"Geo::OGRc::FeatureDefn_IsStyleIgnored", _wrap_FeatureDefn_IsStyleIgnored},
 {"Geo::OGRc::FeatureDefn_SetStyleIgnored", _wrap_FeatureDefn_SetStyleIgnored},
+{"Geo::OGRc::FeatureDefn_IsSame", _wrap_FeatureDefn_IsSame},
 {"Geo::OGRc::delete_FieldDefn", _wrap_delete_FieldDefn},
 {"Geo::OGRc::new_FieldDefn", _wrap_new_FieldDefn},
 {"Geo::OGRc::FieldDefn_GetName", _wrap_FieldDefn_GetName},
@@ -19146,6 +23003,17 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::FieldDefn_GetFieldTypeName", _wrap_FieldDefn_GetFieldTypeName},
 {"Geo::OGRc::FieldDefn_IsIgnored", _wrap_FieldDefn_IsIgnored},
 {"Geo::OGRc::FieldDefn_SetIgnored", _wrap_FieldDefn_SetIgnored},
+{"Geo::OGRc::delete_GeomFieldDefn", _wrap_delete_GeomFieldDefn},
+{"Geo::OGRc::new_GeomFieldDefn", _wrap_new_GeomFieldDefn},
+{"Geo::OGRc::GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName},
+{"Geo::OGRc::GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef},
+{"Geo::OGRc::GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName},
+{"Geo::OGRc::GeomFieldDefn_GetType", _wrap_GeomFieldDefn_GetType},
+{"Geo::OGRc::GeomFieldDefn_SetType", _wrap_GeomFieldDefn_SetType},
+{"Geo::OGRc::GeomFieldDefn_GetSpatialRef", _wrap_GeomFieldDefn_GetSpatialRef},
+{"Geo::OGRc::GeomFieldDefn_SetSpatialRef", _wrap_GeomFieldDefn_SetSpatialRef},
+{"Geo::OGRc::GeomFieldDefn_IsIgnored", _wrap_GeomFieldDefn_IsIgnored},
+{"Geo::OGRc::GeomFieldDefn_SetIgnored", _wrap_GeomFieldDefn_SetIgnored},
 {"Geo::OGRc::CreateGeometryFromWkb", _wrap_CreateGeometryFromWkb},
 {"Geo::OGRc::CreateGeometryFromWkt", _wrap_CreateGeometryFromWkt},
 {"Geo::OGRc::CreateGeometryFromGML", _wrap_CreateGeometryFromGML},
@@ -19821,6 +23689,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "OLCCreateGeomField", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("CreateGeomField"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "ODsCCreateLayer", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("CreateLayer"));
     SvREADONLY_on(sv);
@@ -19831,6 +23704,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ODsCCreateGeomFieldAfterCreateLayer", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "ODrCCreateDataSource", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("CreateDataSource"));
     SvREADONLY_on(sv);
@@ -19848,12 +23726,14 @@ XS(SWIG_init) {
   }
   
   
+  SWIG_TypeClientData(SWIGTYPE_p_OGRStyleTableShadow, (void*) "Geo::OGR::StyleTable");
   SWIG_TypeClientData(SWIGTYPE_p_OGRDriverShadow, (void*) "Geo::OGR::Driver");
   SWIG_TypeClientData(SWIGTYPE_p_OGRDataSourceShadow, (void*) "Geo::OGR::DataSource");
   SWIG_TypeClientData(SWIGTYPE_p_OGRLayerShadow, (void*) "Geo::OGR::Layer");
   SWIG_TypeClientData(SWIGTYPE_p_OGRFeatureShadow, (void*) "Geo::OGR::Feature");
   SWIG_TypeClientData(SWIGTYPE_p_OGRFeatureDefnShadow, (void*) "Geo::OGR::FeatureDefn");
   SWIG_TypeClientData(SWIGTYPE_p_OGRFieldDefnShadow, (void*) "Geo::OGR::FieldDefn");
+  SWIG_TypeClientData(SWIGTYPE_p_OGRGeomFieldDefnShadow, (void*) "Geo::OGR::GeomFieldDefn");
   SWIG_TypeClientData(SWIGTYPE_p_OGRGeometryShadow, (void*) "Geo::OGR::Geometry");
   /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "TermProgress", TRUE | 0x2 | GV_ADDMULTI);
diff --git a/swig/perl/osr_wrap.cpp b/swig/perl/osr_wrap.cpp
index 0c34071..a845a27 100644
--- a/swig/perl/osr_wrap.cpp
+++ b/swig/perl/osr_wrap.cpp
@@ -1790,6 +1790,9 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *s
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(OSRSpatialReferenceShadow *self){
+    return OSREPSGTreatsAsNorthingEasting(self);
+  }
 
 #include <limits.h>
 #if !defined(SWIG_NO_LLONG_MAX)
@@ -3568,6 +3571,57 @@ XS(_wrap_SpatialReference_EPSGTreatsAsLatLong) {
 }
 
 
+XS(_wrap_SpatialReference_EPSGTreatsAsNorthingEasting) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: SpatialReference_EPSGTreatsAsNorthingEasting(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_EPSGTreatsAsNorthingEasting" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_SpatialReference_SetAuthority) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -13162,6 +13216,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference_IsLocal", _wrap_SpatialReference_IsLocal},
 {"Geo::OSRc::SpatialReference_IsVertical", _wrap_SpatialReference_IsVertical},
 {"Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong", _wrap_SpatialReference_EPSGTreatsAsLatLong},
+{"Geo::OSRc::SpatialReference_EPSGTreatsAsNorthingEasting", _wrap_SpatialReference_EPSGTreatsAsNorthingEasting},
 {"Geo::OSRc::SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority},
 {"Geo::OSRc::SpatialReference_GetAttrValue", _wrap_SpatialReference_GetAttrValue},
 {"Geo::OSRc::SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue},
@@ -14089,6 +14144,196 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_KILOMETER", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Kilometer"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_KILOMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("1000."));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_DECIMETER", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Decimeter"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_DECIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.1"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CENTIMETER", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Centimeter"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CENTIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.01"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_MILLIMETER", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Millimeter"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_MILLIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.001"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_NAUT_MILE", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Nautical_Mile_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_NAUT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("1852.0"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_INCH", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Inch_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_INCH_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.0254"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FOOT", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Foot_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.3048"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_YARD", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Yard_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.9144"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_STAT_MILE", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Statute_Mile_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_STAT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("1609.344"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FATHOM", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Fathom_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FATHOM_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("1.8288"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Chain_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("20.1168"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_LINK", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Link_International"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_LINK_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.201168"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_INCH", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Inch_US_Surveyor"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_INCH_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.025400050800101603"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_YARD", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Yard_US_Surveyor"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.914401828803658"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Chain_US_Surveyor"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("20.11684023368047"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_STAT_MILE", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Statute_Mile_US_Surveyor"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_STAT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("1609.347218694437"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_YARD", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Yard_Indian"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.91439523"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_FOOT", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Foot_Indian"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.30479841"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Chain_Indian"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("20.11669506"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig2.0/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_DEGREE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("degree"));
     SvREADONLY_on(sv);
diff --git a/swig/perl/pdl.dox b/swig/perl/pdl.dox
new file mode 100644
index 0000000..7f7feb2
--- /dev/null
+++ b/swig/perl/pdl.dox
@@ -0,0 +1,62 @@
+/*! \page band_to_pdl Making a piddle from data in a band
+
+The code here does not have any warranty. It is recommended that
+before using any of this code, you look into it and try to understand
+what it does, what input it needs, etc. Do not blindly execute
+anything!
+
+\code
+use Carp;
+use Geo::GDAL;
+use PDL;
+
+my $filename = 'xxx';
+my $update = undef;
+
+my $dataset = Geo::GDAL::Open($filename, $update);
+my $band = $dataset->Band(1);
+
+my($xoff,$yoff) = (1000,4000);
+my($w,$h) = (1000,1000);
+
+my $data = $band->ReadRaster($xoff,$yoff,$w,$h);
+
+my $pdl = PDL->new;
+
+# PDL data types:
+# 0 = unsigned char
+# 1 = short
+# 2 = unsigned short
+# 3 = int
+# 4 = long long
+# 5 = float
+# 6 = double
+
+# GDAL data types: Byte UInt16 Int16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64
+# obtained with $band->DataType
+
+my %map = ( 
+    Byte => 0,
+    UInt16 => 2,
+    Int16 => 1,
+    UInt32 => -1,
+    Int32 => 3,
+    Float32 => 5,
+    Float64 => 6,
+    CInt16 => -1,
+    CInt32 => -1,
+    CFloat32 => -1,
+    CFloat64 => -1
+    );
+
+my $datatype = $map{$band->DataType};
+croak "there is no direct mapping between the band datatype and PDL" if $datatype < 0;
+$pdl->set_datatype($datatype);
+$pdl->setdims([1,$w,$h]);
+my $dref = $pdl->get_dataref();
+# this is not optimal, but the best what we can do in Perl:
+$$dref = $data;
+$pdl->upd_data;
+\endcode
+
+*/
diff --git a/swig/python/README.txt b/swig/python/README.txt
index 6e608e1..3da0fca 100644
--- a/swig/python/README.txt
+++ b/swig/python/README.txt
@@ -8,7 +8,7 @@ two libraries -- GDAL for manipulating geospatial raster data and OGR for
 manipulating geospatial vector data -- but we'll refer to the entire package 
 as the GDAL library for the purposes of this document.
 
-The GDAL project (primarily Howard Butler) maintains SWIG generated Python 
+The GDAL project (primarily Even Rouault) maintains SWIG generated Python 
 bindings for GDAL and OGR. Generally speaking the classes and methods mostly 
 match those of the GDAL and OGR C++ classes. There is no Python specific 
 reference documentation, but the `GDAL API Tutorial`_ includes Python examples.
@@ -16,7 +16,7 @@ reference documentation, but the `GDAL API Tutorial`_ includes Python examples.
 Dependencies
 ------------
  
- * libgdal (1.7.0 or greater) and header files (gdal-devel)
+ * libgdal (1.10.0 or greater) and header files (gdal-devel)
  * numpy (1.0.0 or greater) and header files (numpy-devel) (not explicitly 
    required, but many examples and utilities will not work without it)
 
@@ -92,13 +92,7 @@ Windows
 You will need the following items to complete an install of the GDAL Python
 bindings on Windows:
 
-* `GDAL Windows Binaries`_ The basic install requires the gdalwin32exe###.zip 
-  (### is the version number).  Other files you see in the directory are 
-  for various optional plugins and development headers/include files. After 
-  downloading the zip file, extract it to the directory of your choosing.
-
-* GDAL Python Bindings available at the `Python Cheeseshop`_.  An executable 
-  installer is available for both Python 2.4 or 2.5 or as a Python egg.
+* `GDAL Windows Binaries`_ Download the package that best matches your environment. 
 
 As explained in the README_EXE.txt file, after unzipping the GDAL binaries you 
 will need to modify your system path and variables. If you're not sure how to 
@@ -126,8 +120,8 @@ SWIG
 ----
 
 The GDAL Python package is built using SWIG_. The earliest version of SWIG_ 
-that is supported to generate the wrapper code is 1.3.39.  It is possible 
-that usable bindings will build with a version earlier than 1.3.39, but no 
+that is supported to generate the wrapper code is 1.3.40.  It is possible 
+that usable bindings will build with a version earlier than 1.3.40, but no 
 development efforts are targeted at versions below it.  You should not have 
 to run SWIG in your development tree to generate the binding code, as it 
 is usually included with the source.  However, if you do need to regenerate, 
@@ -184,21 +178,6 @@ match up exactly with what you are seeing from Python, but they should be
 enough to get you going.  Docstrings for GDAL and OSR are planned for a future 
 release.
 
-The History of Using GDAL/OGR in Python
----------------------------------------
-
-Python was the first set of bindings supported by GDAL/OGR and though the 
-bindings were generated with SWIG (1.1 series), the process was very Python 
-specific and contained a significant amount of hand written wrapper code. In 
-2005, Kevin Ruland launched an effort for a set of next generation bindings 
-generated with SWIG (1.3 series) and supported by a variety of languages. 
-With GDAL 1.4.0 the various bindings became fairly mature, and for GDAL 1.5.0, 
-the "next-generation" bindings become the default bindings.  The previous, 
-"old-generation," bindings will continue to be available, but they will not 
-be widely supported and no new development will be targeted at them.  From 
-the viewpoint of a user, with GDAL 1.7.0 and above, you should not have to 
-worry very much about the distinction between these two development efforts.
-
 Numpy/Numeric
 -------------
 
@@ -229,7 +208,7 @@ the data are explicitly subsetted as part of the function call. For large
 data, this approach is expected to be prohibitively memory intensive.
 
 .. _GDAL API Tutorial: http://www.gdal.org/gdal_tutorial.html
-.. _GDAL Windows Binaries: http://download.osgeo.org/gdal/win32/1.5/
+.. _GDAL Windows Binaries: http://vbkto.dyndns.org/sdk/
 .. _Microsoft KnowledgeBase doc: http://support.microsoft.com/kb/310519
 .. _Python Cheeseshop: http://pypi.python.org/pypi/GDAL/
 .. _val_repl.py: http://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/samples/val_repl.py
diff --git a/swig/python/extensions/gdal_array_wrap.cpp b/swig/python/extensions/gdal_array_wrap.cpp
index e2585ba..ab86ea8 100644
--- a/swig/python/extensions/gdal_array_wrap.cpp
+++ b/swig/python/extensions/gdal_array_wrap.cpp
@@ -2717,14 +2717,23 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
 
 
 
+  #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) 
+
+
 /* -------- TYPES TABLE (BEGIN) -------- */
 
-#define SWIGTYPE_p_GDALRasterBandShadow swig_types[0]
-#define SWIGTYPE_p_PyArrayObject swig_types[1]
-#define SWIGTYPE_p_char swig_types[2]
-#define SWIGTYPE_p_int swig_types[3]
-static swig_type_info *swig_types[5];
-static swig_module_info swig_module = {swig_types, 4, 0, 0, 0, 0};
+#define SWIGTYPE_p_CPLVirtualMemShadow swig_types[0]
+#define SWIGTYPE_p_GDALDataType swig_types[1]
+#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[2]
+#define SWIGTYPE_p_GDALRasterBandShadow swig_types[3]
+#define SWIGTYPE_p_PyArrayObject swig_types[4]
+#define SWIGTYPE_p_char swig_types[5]
+#define SWIGTYPE_p_int swig_types[6]
+#define SWIGTYPE_p_p_CPLVirtualMemShadow swig_types[7]
+#define SWIGTYPE_p_p_void swig_types[8]
+#define SWIGTYPE_p_size_t swig_types[9]
+static swig_type_info *swig_types[11];
+static swig_module_info swig_module = {swig_types, 10, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -2821,6 +2830,242 @@ namespace swig {
 }
 
 
+#include "gdal.h"
+
+typedef struct
+{
+    CPLVirtualMem *vmem;
+    int            bAuto;
+    GDALDataType   eBufType;
+    int            bIsBandSequential;
+    int            bReadOnly;
+    int            nBufXSize;
+    int            nBufYSize;
+    int            nBandCount;
+    GDALTileOrganization eTileOrganization;
+    int                  nTileXSize;
+    int                  nTileYSize;
+    int            nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace; /* if bAuto == TRUE */
+} CPLVirtualMemShadow;
+
+
+SWIGINTERN void delete_CPLVirtualMemShadow(CPLVirtualMemShadow *self){
+        CPLVirtualMemFree( self->vmem );
+        free(self);
+    }
+SWIGINTERN void CPLVirtualMemShadow_GetAddr(CPLVirtualMemShadow *self,void **pptr,size_t *pnsize,GDALDataType *pdatatype,int *preadonly){
+        *pptr = CPLVirtualMemGetAddr( self->vmem );
+        *pnsize = CPLVirtualMemGetSize( self->vmem );
+        *pdatatype = self->eBufType;
+        *preadonly = self->bReadOnly;
+    }
+
+SWIGINTERN int
+SWIG_AsVal_double (PyObject *obj, double *val)
+{
+  int res = SWIG_TypeError;
+  if (PyFloat_Check(obj)) {
+    if (val) *val = PyFloat_AsDouble(obj);
+    return SWIG_OK;
+  } else if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    double v = PyLong_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    double d = PyFloat_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = d;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      long v = PyLong_AsLong(obj);
+      if (!PyErr_Occurred()) {
+	if (val) *val = v;
+	return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
+      } else {
+	PyErr_Clear();
+      }
+    }
+  }
+#endif
+  return res;
+}
+
+
+#include <float.h>
+
+
+#include <math.h>
+
+
+SWIGINTERNINLINE int
+SWIG_CanCastAsInteger(double *d, double min, double max) {
+  double x = *d;
+  if ((min <= x && x <= max)) {
+   double fx = floor(x);
+   double cx = ceil(x);
+   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
+   if ((errno == EDOM) || (errno == ERANGE)) {
+     errno = 0;
+   } else {
+     double summ, reps, diff;
+     if (rd < x) {
+       diff = x - rd;
+     } else if (rd > x) {
+       diff = rd - x;
+     } else {
+       return 1;
+     }
+     summ = rd + x;
+     reps = diff/summ;
+     if (reps < 8*DBL_EPSILON) {
+       *d = rd;
+       return 1;
+     }
+   }
+  }
+  return 0;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
+{
+  if (PyInt_Check(obj)) {
+    long v = PyInt_AsLong(obj);
+    if (v >= 0) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      return SWIG_OverflowError;
+    }
+  } else if (PyLong_Check(obj)) {
+    unsigned long v = PyLong_AsUnsignedLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    unsigned long v = PyLong_AsUnsignedLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+	if (val) *val = (unsigned long)(d);
+	return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERNINLINE int
+SWIG_AsVal_size_t (PyObject * obj, size_t *val)
+{
+  unsigned long v;
+  int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0);
+  if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v);
+  return res;
+}
+
+
+#include <limits.h>
+#if !defined(SWIG_NO_LLONG_MAX)
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
+#   define LLONG_MAX __LONG_LONG_MAX__
+#   define LLONG_MIN (-LLONG_MAX - 1LL)
+#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+# endif
+#endif
+
+
+SWIGINTERN int
+SWIG_AsVal_long (PyObject *obj, long* val)
+{
+  if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    long v = PyLong_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    long v = PyInt_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+	if (val) *val = (long)(d);
+	return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_int (PyObject * obj, int *val)
+{
+  long v;
+  int res = SWIG_AsVal_long (obj, &v);
+  if (SWIG_IsOK(res)) {
+    if ((v < INT_MIN || v > INT_MAX)) {
+      return SWIG_OverflowError;
+    } else {
+      if (val) *val = static_cast< int >(v);
+    }
+  }  
+  return res;
+}
+
+SWIGINTERN void CPLVirtualMemShadow_Pin__SWIG_0(CPLVirtualMemShadow *self,size_t start_offset=0,size_t nsize=0,int bWriteOp=0){
+        if( nsize == 0 || start_offset + nsize >= CPLVirtualMemGetSize( self->vmem ) )
+            nsize = CPLVirtualMemGetSize( self->vmem ) - start_offset;
+        char* start_addr = (char*)CPLVirtualMemGetAddr( self->vmem ) + start_offset;
+        CPLVirtualMemPin(self->vmem, start_addr, nsize, bWriteOp);
+    }
+
 
 /* Return a PyObject* from a NULL terminated C String */
 static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
@@ -2900,8 +3145,10 @@ static void GDALPythonFreeCStr(void* ptr, int bToFree)
 
 #ifdef DEBUG 
 typedef struct GDALRasterBandHS GDALRasterBandShadow;
+typedef struct RasterAttributeTableHS GDALRasterAttributeTableShadow;
 #else
 typedef void GDALRasterBandShadow;
+typedef void GDALRasterAttributeTableShadow;
 #endif
 
 CPL_C_START
@@ -3313,163 +3560,541 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
   }
 
 
-#include <limits.h>
-#if !defined(SWIG_NO_LLONG_MAX)
-# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
-#   define LLONG_MAX __LONG_LONG_MAX__
-#   define LLONG_MIN (-LLONG_MAX - 1LL)
-#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
-# endif
-#endif
+  #define SWIG_From_long   PyInt_FromLong 
 
 
-SWIGINTERN int
-SWIG_AsVal_double (PyObject *obj, double *val)
-{
-  int res = SWIG_TypeError;
-  if (PyFloat_Check(obj)) {
-    if (val) *val = PyFloat_AsDouble(obj);
-    return SWIG_OK;
-  } else if (PyInt_Check(obj)) {
-    if (val) *val = PyInt_AsLong(obj);
-    return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
-    double v = PyLong_AsDouble(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = v;
-      return SWIG_OK;
-    } else {
-      PyErr_Clear();
-    }
-  }
-#ifdef SWIG_PYTHON_CAST_MODE
-  {
-    int dispatch = 0;
-    double d = PyFloat_AsDouble(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = d;
-      return SWIG_AddCast(SWIG_OK);
-    } else {
-      PyErr_Clear();
-    }
-    if (!dispatch) {
-      long v = PyLong_AsLong(obj);
-      if (!PyErr_Occurred()) {
-	if (val) *val = v;
-	return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
-      } else {
-	PyErr_Clear();
-      }
-    }
-  }
-#endif
-  return res;
+SWIGINTERNINLINE PyObject *
+SWIG_From_int  (int value)
+{    
+  return SWIG_From_long  (value);
 }
 
 
-#include <float.h>
-
+    void VirtualMemGetArray(CPLVirtualMemShadow* virtualmem, CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
+    {
+        *pvirtualmem = virtualmem;
+    }
 
-#include <math.h>
 
+  // need different functions for read and write
+  // since reading strings requires us to know the 
+  // length of the longest string before creating array
+  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+                       PyArrayObject *psArray) {
 
-SWIGINTERNINLINE int
-SWIG_CanCastAsInteger(double *d, double min, double max) {
-  double x = *d;
-  if ((min <= x && x <= max)) {
-   double fx = floor(x);
-   double cx = ceil(x);
-   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
-   if ((errno == EDOM) || (errno == ERANGE)) {
-     errno = 0;
-   } else {
-     double summ, reps, diff;
-     if (rd < x) {
-       diff = x - rd;
-     } else if (rd > x) {
-       diff = rd - x;
-     } else {
-       return 1;
-     }
-     summ = rd + x;
-     reps = diff/summ;
-     if (reps < 8*DBL_EPSILON) {
-       *d = rd;
-       return 1;
-     }
-   }
-  }
-  return 0;
-}
+    if( PyArray_NDIM(psArray) != 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Illegal numpy array rank %d.\n", 
+                  PyArray_NDIM(psArray) );
+        return CE_Failure;
+    }
 
+    int nLength = PyArray_DIM(psArray, 0);
+    int nType = PyArray_TYPE(psArray);
+    CPLErr retval = CE_None;
 
-SWIGINTERN int
-SWIG_AsVal_long (PyObject *obj, long* val)
-{
-  if (PyInt_Check(obj)) {
-    if (val) *val = PyInt_AsLong(obj);
-    return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
-    long v = PyLong_AsLong(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = v;
-      return SWIG_OK;
-    } else {
-      PyErr_Clear();
+    if( nType == NPY_INT32 )
+    {
+        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength, 
+                        (int*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_DOUBLE )
+    {
+        retval = GDALRATValuesIOAsDouble(poRAT, GF_Write, nField, nStart, nLength,
+                        (double*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_STRING )
+    {
+        // have to convert array of strings to a char **
+        char **papszStringData = (char**)CPLCalloc(sizeof(char*), nLength);
+
+        // max size of string
+        int nMaxLen = PyArray_ITEMSIZE(psArray);
+        char *pszBuffer = (char*)CPLMalloc((nMaxLen+1) * sizeof(char));
+        // make sure there is a null char on the end
+        // as there won't be if this string is the maximum size
+        pszBuffer[nMaxLen] = '\0';
+
+        // we can't just use the memory location in the array 
+        // since long strings won't be null terminated
+        for( int i = 0; i < nLength; i++ )
+        {
+            strncpy(pszBuffer, (char*)PyArray_GETPTR1(psArray, i), nMaxLen);
+            papszStringData[i] = CPLStrdup(pszBuffer);
+        }
+        CPLFree(pszBuffer);
+
+        retval = GDALRATValuesIOAsString(poRAT, GF_Write, nField, nStart, nLength,
+                                            papszStringData);
+
+        for( int i = 0; i < nLength; i++ )
+        {
+            CPLFree(papszStringData[i]);
+        }
+        CPLFree(papszStringData);
     }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Illegal numpy array type %d.\n", 
+                  nType );
+        return CE_Failure;
+    }
+    return retval;
   }
-#ifdef SWIG_PYTHON_CAST_MODE
-  {
-    int dispatch = 0;
-    long v = PyInt_AsLong(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = v;
-      return SWIG_AddCast(SWIG_OK);
-    } else {
-      PyErr_Clear();
+
+
+  // need different functions for read and write
+  // since reading strings requires us to know the 
+  // length of the longest string before creating array
+  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+                       int nLength) {
+
+    GDALRATFieldType colType = GDALRATGetTypeOfCol(poRAT, nField);
+    npy_intp dims = nLength;
+    PyObject *pOutArray = NULL;
+    if( colType == GFT_Integer )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_INT32);
+        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength, 
+                        (int*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
     }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
-	return res;
-      }
+    else if( colType == GFT_Real )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_DOUBLE);
+        if( GDALRATValuesIOAsDouble(poRAT, GF_Read, nField, nStart, nLength,
+                        (double*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
     }
+    else if( colType == GFT_String )
+    {
+        // must read the data first to work out max size
+        // of strings to create array
+        int n;
+        char **papszStringList = (char**)CPLCalloc(sizeof(char*), nLength);
+        if( GDALRATValuesIOAsString(poRAT, GF_Read, nField, nStart, nLength, papszStringList) != CE_None )
+        {
+            CPLFree(papszStringList);
+            Py_RETURN_NONE;
+        }
+        int nMaxLen = 0, nLen;
+        for( n = 0; n < nLength; n++ )
+        {
+            // note strlen doesn't include null char
+            // but that is what numpy expects so all good
+            nLen = strlen(papszStringList[n]);
+            if( nLen > nMaxLen )
+                nMaxLen = nLen;
+        }
+        int bZeroLength = FALSE;
+        // numpy can't deal with zero length strings
+        if( nMaxLen == 0 )
+        {
+            nMaxLen = 1;
+            bZeroLength = TRUE;
+        }
+
+        // create the dtype string
+#if PY_VERSION_HEX >= 0x03000000
+        PyObject *pDTypeString = PyUnicode_FromFormat("S%d", nMaxLen);
+#else
+        PyObject *pDTypeString = PyString_FromFormat("S%d", nMaxLen);
+#endif
+        // out type description object
+        PyArray_Descr *pDescr;
+        PyArray_DescrConverter(pDTypeString, &pDescr);
+        Py_DECREF(pDTypeString);
+
+        // create array
+        pOutArray = PyArray_SimpleNewFromDescr(1, &dims, pDescr);
+
+        // copy data in
+        if( !bZeroLength )
+        {
+            for( n = 0; n < nLength; n++ )
+            {
+                // we use strncpy so that we don't go over nMaxLen
+                // which we would if the null char is copied
+                // (which we don't want as numpy 'knows' to interpret the string as nMaxLen long)
+                strncpy((char*)PyArray_GETPTR1(pOutArray, n), papszStringList[n], nMaxLen);
+            }
+        }
+        else
+        {
+            // so there isn't rubbush in the 1 char strings
+            PyArray_FILLWBYTE(pOutArray, 0);
+        }
+
+        // free strings
+        for( n = 0; n < nLength; n++ )
+        {
+            CPLFree(papszStringList[n]);
+        }
+        CPLFree(papszStringList);
+    }
+    return pOutArray;
   }
+
+#ifdef __cplusplus
+extern "C" {
 #endif
-  return SWIG_TypeError;
+SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_VirtualMem",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_VirtualMem" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  delete_CPLVirtualMemShadow(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
 }
 
 
-SWIGINTERN int
-SWIG_AsVal_int (PyObject * obj, int *val)
-{
-  long v;
-  int res = SWIG_AsVal_long (obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< int >(v);
+SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  void **arg2 = (void **) 0 ;
+  size_t *arg3 = (size_t *) 0 ;
+  GDALDataType *arg4 = (GDALDataType *) 0 ;
+  int *arg5 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *ptr2 ;
+  size_t nsize2 ;
+  GDALDataType datatype2 ;
+  int readonly2 ;
+  PyObject * obj0 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly) */
+    arg2 = &ptr2;
+    arg3 = &nsize2;
+    arg4 = &datatype2;
+    arg5 = &readonly2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:VirtualMem_GetAddr",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_GetAddr" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  {
+#if PY_VERSION_HEX >= 0x02070000 
+    /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
+    Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
+    if (PyBuffer_FillInfo(buf,  obj0,  *(arg2), *(arg3), *(arg5), PyBUF_ND)) {
+      // error, handle
     }
-  }  
-  return res;
+    if( *(arg4) == GDT_Byte )
+    {
+      buf->format = "B";
+      buf->itemsize = 1;
+    }
+    else if( *(arg4) == GDT_Int16 )
+    {
+      buf->format = "h";
+      buf->itemsize = 2;
+    }
+    else if( *(arg4) == GDT_UInt16 )
+    {
+      buf->format = "H";
+      buf->itemsize = 2;
+    }
+    else if( *(arg4) == GDT_Int32 )
+    {
+      buf->format = "i";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_UInt32 )
+    {
+      buf->format = "I";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_Float32 )
+    {
+      buf->format = "f";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_Float64 )
+    {
+      buf->format = "F";
+      buf->itemsize = 8;
+    }
+    else
+    {
+      buf->format = "B";
+      buf->itemsize = 1;
+    }
+    resultobj = PyMemoryView_FromBuffer(buf);
+#else
+    PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
+    SWIG_fail;
+#endif
+  }
+  return resultobj;
+fail:
+  return NULL;
 }
 
 
-  #define SWIG_From_long   PyInt_FromLong 
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  size_t arg2 ;
+  size_t arg3 ;
+  int arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:VirtualMem_Pin",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  ecode2 = SWIG_AsVal_size_t(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VirtualMem_Pin" "', argument " "2"" of type '" "size_t""'");
+  } 
+  arg2 = static_cast< size_t >(val2);
+  ecode3 = SWIG_AsVal_size_t(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VirtualMem_Pin" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VirtualMem_Pin" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3,arg4);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
 
 
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  size_t arg2 ;
+  size_t arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:VirtualMem_Pin",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  ecode2 = SWIG_AsVal_size_t(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VirtualMem_Pin" "', argument " "2"" of type '" "size_t""'");
+  } 
+  arg2 = static_cast< size_t >(val2);
+  ecode3 = SWIG_AsVal_size_t(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VirtualMem_Pin" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  size_t arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:VirtualMem_Pin",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  ecode2 = SWIG_AsVal_size_t(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VirtualMem_Pin" "', argument " "2"" of type '" "size_t""'");
+  } 
+  arg2 = static_cast< size_t >(val2);
+  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:VirtualMem_Pin",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  CPLVirtualMemShadow_Pin__SWIG_0(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[5];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 4); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_CPLVirtualMemShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_VirtualMem_Pin__SWIG_3(self, args);
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_CPLVirtualMemShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_size_t(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_VirtualMem_Pin__SWIG_2(self, args);
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_CPLVirtualMemShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_size_t(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_size_t(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          return _wrap_VirtualMem_Pin__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 4) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_CPLVirtualMemShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_size_t(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_size_t(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            return _wrap_VirtualMem_Pin__SWIG_0(self, args);
+          }
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'VirtualMem_Pin'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    Pin(CPLVirtualMemShadow *,size_t,size_t,int)\n"
+    "    Pin(CPLVirtualMemShadow *,size_t,size_t)\n"
+    "    Pin(CPLVirtualMemShadow *,size_t)\n"
+    "    Pin(CPLVirtualMemShadow *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *VirtualMem_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_CPLVirtualMemShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
 }
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 SWIGINTERN PyObject *_wrap_GetArrayFilename(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PyArrayObject *arg1 = (PyArrayObject *) 0 ;
@@ -3597,41 +4222,392 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_VirtualMemGetArray(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  CPLVirtualMemShadow **arg2 = (CPLVirtualMemShadow **) 0 ;
+  int arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  CPLVirtualMemShadow *virtualmem2 ;
+  PyObject * obj0 = 0 ;
+  
+  {
+    arg2 = &virtualmem2;
+    arg3 = 0;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:VirtualMemGetArray",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMemGetArray" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  VirtualMemGetArray(arg1,arg2,arg3);
+  resultobj = SWIG_Py_Void();
+  {
+    CPLVirtualMemShadow* virtualmem = *(arg2);
+    void* ptr = CPLVirtualMemGetAddr( virtualmem->vmem );
+    /*size_t nsize = CPLVirtualMemGetSize( virtualmem->vmem );*/
+    GDALDataType datatype = virtualmem->eBufType;
+    int readonly = virtualmem->bReadOnly;
+    GIntBig nBufXSize = virtualmem->nBufXSize;
+    GIntBig nBufYSize = virtualmem->nBufYSize;
+    int nBandCount = virtualmem->nBandCount;
+    int bIsBandSequential = virtualmem->bIsBandSequential;
+    GDALTileOrganization eTileOrganization = virtualmem->eTileOrganization;
+    int nTileXSize = virtualmem->nTileXSize;
+    int nTileYSize = virtualmem->nTileYSize;
+    int bAuto = virtualmem->bAuto;
+    int            nPixelSpace = virtualmem->nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace = virtualmem->nLineSpace; /* if bAuto == TRUE */
+    int numpytype;
+    
+    if( datatype == GDT_CInt16 || datatype == GDT_CInt32 )
+    {
+      PyErr_SetString( PyExc_RuntimeError, "GDT_CInt16 and GDT_CInt32 not supported for now" );
+      SWIG_fail;
+    }
+    
+    switch(datatype)
+    {
+      case GDT_Byte: numpytype = NPY_UBYTE; break;
+      case GDT_Int16: numpytype = NPY_INT16; break;
+      case GDT_UInt16: numpytype = NPY_UINT16; break;
+      case GDT_Int32: numpytype = NPY_INT32; break;
+      case GDT_UInt32: numpytype = NPY_UINT32; break;
+      case GDT_Float32: numpytype = NPY_FLOAT32; break;
+      case GDT_Float64: numpytype = NPY_FLOAT64; break;
+      //case GDT_CInt16: numpytype = NPY_INT16; break;
+      //case GDT_CInt32: numpytype = NPY_INT32; break;
+      case GDT_CFloat32: numpytype = NPY_CFLOAT; break;
+      case GDT_CFloat64: numpytype = NPY_CDOUBLE; break;
+      default: numpytype = NPY_UBYTE; break;
+    }
+    PyArrayObject* ar;
+    int flags = (readonly) ? 0x1 : 0x1 | 0x0400;
+    int nDataTypeSize = GDALGetDataTypeSize(datatype) / 8;
+    if( bAuto )
+    {
+      if( nBandCount == 1 )
+      {
+        npy_intp shape[2], stride[2];
+        shape[0] = nBufYSize;
+        shape[1] = nBufXSize;
+        stride[1] = nPixelSpace;
+        stride[0] = nLineSpace;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+      else
+      {
+        PyErr_SetString( PyExc_RuntimeError, "Code update needed for bAuto and nBandCount > 1 !" );
+        SWIG_fail;
+      }
+    }
+    else if( bIsBandSequential >= 0 )
+    {
+      if( nBandCount == 1 )
+      {
+        npy_intp shape[2], stride[2];
+        shape[0] = nBufYSize;
+        shape[1] = nBufXSize;
+        stride[1] = nDataTypeSize;
+        stride[0] = stride[1] * nBufXSize;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+      else
+      {
+        npy_intp shape[3], stride[3];
+        if( bIsBandSequential )
+        {
+          shape[0] = nBandCount;
+          shape[1] = nBufYSize;
+          shape[2] = nBufXSize;
+          stride[2] = nDataTypeSize;
+          stride[1] = stride[2] * nBufXSize;
+          stride[0] = stride[1] * nBufYSize;
+        }
+        else
+        {
+          shape[0] = nBufYSize;
+          shape[1] = nBufXSize;
+          shape[2] = nBandCount;
+          stride[2] = nDataTypeSize;
+          stride[1] = stride[2] * nBandCount;
+          stride[0] = stride[1] * nBufXSize;
+        }
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 3, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+    }
+    else
+    {
+      int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
+      int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
+      npy_intp shape[5], stride[5];
+      if( nBandCount == 1 )
+      {
+        shape[0] = nTilesPerCol;
+        shape[1] = nTilesPerRow;
+        shape[2] = nTileYSize;
+        shape[3] = nTileXSize;
+        stride[3] = nDataTypeSize;
+        stride[2] = stride[3] * nTileXSize;
+        stride[1] = stride[2] * nTileYSize;
+        stride[0] = stride[1] * nTilesPerRow;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 4, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+      else if( eTileOrganization == GTO_TIP )
+      {
+        shape[0] = nTilesPerCol;
+        shape[1] = nTilesPerRow;
+        shape[2] = nTileYSize;
+        shape[3] = nTileXSize;
+        shape[4] = nBandCount;
+        stride[4] = nDataTypeSize;
+        stride[3] = stride[4] * nBandCount;
+        stride[2] = stride[3] * nTileXSize;
+        stride[1] = stride[2] * nTileYSize;
+        stride[0] = stride[1] * nTilesPerRow;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+      else if( eTileOrganization == GTO_BIT )
+      {
+        shape[0] = nTilesPerCol;
+        shape[1] = nTilesPerRow;
+        shape[2] = nBandCount;
+        shape[3] = nTileYSize;
+        shape[4] = nTileXSize;
+        stride[4] = nDataTypeSize;
+        stride[3] = stride[4] * nTileXSize;
+        stride[2] = stride[3] * nTileYSize;
+        stride[1] = stride[2] * nBandCount;
+        stride[0] = stride[1] * nTilesPerRow;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+      else /* GTO_BSQ */
+      {
+        shape[0] = nBandCount;
+        shape[1] = nTilesPerCol;
+        shape[2] = nTilesPerRow;
+        shape[3] = nTileYSize;
+        shape[4] = nTileXSize;
+        stride[4] = nDataTypeSize;
+        stride[3] = stride[4] * nTileXSize;
+        stride[2] = stride[3] * nTileYSize;
+        stride[1] = stride[2] * nTilesPerRow;
+        stride[0] = stride[1] * nTilesPerCol;
+        ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+          numpytype, stride, ptr, 0, flags , NULL);
+      }
+    }
+    
+    /* Keep a reference to the VirtualMem object */
+    ar->base = obj0;
+    Py_INCREF(obj0);
+    resultobj = (PyObject*) ar;
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_RATValuesIONumPyWrite(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  PyArrayObject *arg4 = (PyArrayObject *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "poRAT",(char *) "nField",(char *) "nStart",(char *) "psArray", NULL 
+  };
+  CPLErr result;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO:RATValuesIONumPyWrite",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RATValuesIONumPyWrite" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RATValuesIONumPyWrite" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RATValuesIONumPyWrite" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    /* %typemap(in,numinputs=1) (PyArrayObject  *psArray) */
+    if (obj3 != NULL && PyArray_Check(obj3))
+    {
+      arg4 = (PyArrayObject*)(obj3);
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a numpy array");
+      SWIG_fail;
+    }
+  }
+  result = (CPLErr)RATValuesIONumPyWrite(arg1,arg2,arg3,arg4);
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_RATValuesIONumPyRead(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "poRAT",(char *) "nField",(char *) "nStart",(char *) "nLength", NULL 
+  };
+  PyObject *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO:RATValuesIONumPyRead",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RATValuesIONumPyRead" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RATValuesIONumPyRead" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RATValuesIONumPyRead" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "RATValuesIONumPyRead" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  result = (PyObject *)RATValuesIONumPyRead(arg1,arg2,arg3,arg4);
+  resultobj = result;
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+	 { (char *)"delete_VirtualMem", _wrap_delete_VirtualMem, METH_VARARGS, (char *)"delete_VirtualMem(VirtualMem self)"},
+	 { (char *)"VirtualMem_GetAddr", _wrap_VirtualMem_GetAddr, METH_VARARGS, (char *)"VirtualMem_GetAddr(VirtualMem self)"},
+	 { (char *)"VirtualMem_Pin", _wrap_VirtualMem_Pin, METH_VARARGS, (char *)"\n"
+		"Pin(size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)\n"
+		"Pin(size_t start_offset = 0, size_t nsize = 0)\n"
+		"Pin(size_t start_offset = 0)\n"
+		"VirtualMem_Pin(VirtualMem self)\n"
+		""},
+	 { (char *)"VirtualMem_swigregister", VirtualMem_swigregister, METH_VARARGS, NULL},
 	 { (char *)"GetArrayFilename", _wrap_GetArrayFilename, METH_VARARGS, (char *)"GetArrayFilename(PyArrayObject psArray) -> retStringAndCPLFree"},
 	 { (char *)"BandRasterIONumPy", (PyCFunction) _wrap_BandRasterIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"BandRasterIONumPy(Band band, int bWrite, int xoff, int yoff, int xsize, \n"
 		"    int ysize, PyArrayObject psArray, int buf_type) -> CPLErr\n"
 		""},
+	 { (char *)"VirtualMemGetArray", _wrap_VirtualMemGetArray, METH_VARARGS, (char *)"VirtualMemGetArray(VirtualMem virtualmem)"},
+	 { (char *)"RATValuesIONumPyWrite", (PyCFunction) _wrap_RATValuesIONumPyWrite, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, \n"
+		"    PyArrayObject psArray) -> CPLErr\n"
+		""},
+	 { (char *)"RATValuesIONumPyRead", (PyCFunction) _wrap_RATValuesIONumPyRead, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, \n"
+		"    int nLength) -> PyObject\n"
+		""},
 	 { NULL, NULL, 0, NULL }
 };
 
 
 /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
 
+static swig_type_info _swigt__p_CPLVirtualMemShadow = {"_p_CPLVirtualMemShadow", "CPLVirtualMemShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALDataType = {"_p_GDALDataType", "GDALDataType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALRasterAttributeTableShadow = {"_p_GDALRasterAttributeTableShadow", "GDALRasterAttributeTableShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALRasterBandShadow = {"_p_GDALRasterBandShadow", "GDALRasterBandShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_PyArrayObject = {"_p_PyArrayObject", "PyArrayObject *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|int *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "GDALRATFieldType *|CPLErr *|int *|GDALRATFieldUsage *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_CPLVirtualMemShadow = {"_p_p_CPLVirtualMemShadow", "CPLVirtualMemShadow **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_void = {"_p_p_void", "void **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_size_t = {"_p_size_t", "size_t *", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
+  &_swigt__p_CPLVirtualMemShadow,
+  &_swigt__p_GDALDataType,
+  &_swigt__p_GDALRasterAttributeTableShadow,
   &_swigt__p_GDALRasterBandShadow,
   &_swigt__p_PyArrayObject,
   &_swigt__p_char,
   &_swigt__p_int,
+  &_swigt__p_p_CPLVirtualMemShadow,
+  &_swigt__p_p_void,
+  &_swigt__p_size_t,
 };
 
+static swig_cast_info _swigc__p_CPLVirtualMemShadow[] = {  {&_swigt__p_CPLVirtualMemShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALDataType[] = {  {&_swigt__p_GDALDataType, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALRasterAttributeTableShadow[] = {  {&_swigt__p_GDALRasterAttributeTableShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALRasterBandShadow[] = {  {&_swigt__p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_PyArrayObject[] = {  {&_swigt__p_PyArrayObject, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_CPLVirtualMemShadow[] = {  {&_swigt__p_p_CPLVirtualMemShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_void[] = {  {&_swigt__p_p_void, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_size_t[] = {  {&_swigt__p_size_t, 0, 0, 0},{0, 0, 0, 0}};
 
 static swig_cast_info *swig_cast_initial[] = {
+  _swigc__p_CPLVirtualMemShadow,
+  _swigc__p_GDALDataType,
+  _swigc__p_GDALRasterAttributeTableShadow,
   _swigc__p_GDALRasterBandShadow,
   _swigc__p_PyArrayObject,
   _swigc__p_char,
   _swigc__p_int,
+  _swigc__p_p_CPLVirtualMemShadow,
+  _swigc__p_p_void,
+  _swigc__p_size_t,
 };
 
 
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index c1c8ead..be8339f 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -2723,34 +2723,36 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
 /* -------- TYPES TABLE (BEGIN) -------- */
 
 #define SWIGTYPE_p_CPLErrorHandler swig_types[0]
-#define SWIGTYPE_p_CPLXMLNode swig_types[1]
-#define SWIGTYPE_p_GByte swig_types[2]
-#define SWIGTYPE_p_GDALAsyncReaderShadow swig_types[3]
-#define SWIGTYPE_p_GDALColorEntry swig_types[4]
-#define SWIGTYPE_p_GDALColorTableShadow swig_types[5]
-#define SWIGTYPE_p_GDALDatasetShadow swig_types[6]
-#define SWIGTYPE_p_GDALDriverShadow swig_types[7]
-#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[8]
-#define SWIGTYPE_p_GDALProgressFunc swig_types[9]
-#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[10]
-#define SWIGTYPE_p_GDALRasterBandShadow swig_types[11]
-#define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[12]
-#define SWIGTYPE_p_GDAL_GCP swig_types[13]
-#define SWIGTYPE_p_GIntBig swig_types[14]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[15]
-#define SWIGTYPE_p_StatBuf swig_types[16]
-#define SWIGTYPE_p_char swig_types[17]
-#define SWIGTYPE_p_double swig_types[18]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[19]
-#define SWIGTYPE_p_int swig_types[20]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[21]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[22]
-#define SWIGTYPE_p_p_char swig_types[23]
-#define SWIGTYPE_p_p_int swig_types[24]
-#define SWIGTYPE_p_p_void swig_types[25]
-#define SWIGTYPE_p_void swig_types[26]
-static swig_type_info *swig_types[28];
-static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0};
+#define SWIGTYPE_p_CPLVirtualMemShadow swig_types[1]
+#define SWIGTYPE_p_CPLXMLNode swig_types[2]
+#define SWIGTYPE_p_GByte swig_types[3]
+#define SWIGTYPE_p_GDALAsyncReaderShadow swig_types[4]
+#define SWIGTYPE_p_GDALColorEntry swig_types[5]
+#define SWIGTYPE_p_GDALColorTableShadow swig_types[6]
+#define SWIGTYPE_p_GDALDatasetShadow swig_types[7]
+#define SWIGTYPE_p_GDALDriverShadow swig_types[8]
+#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[9]
+#define SWIGTYPE_p_GDALProgressFunc swig_types[10]
+#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[11]
+#define SWIGTYPE_p_GDALRasterBandShadow swig_types[12]
+#define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[13]
+#define SWIGTYPE_p_GDAL_GCP swig_types[14]
+#define SWIGTYPE_p_GIntBig swig_types[15]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[16]
+#define SWIGTYPE_p_StatBuf swig_types[17]
+#define SWIGTYPE_p_char swig_types[18]
+#define SWIGTYPE_p_double swig_types[19]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[20]
+#define SWIGTYPE_p_int swig_types[21]
+#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[22]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[23]
+#define SWIGTYPE_p_p_char swig_types[24]
+#define SWIGTYPE_p_p_int swig_types[25]
+#define SWIGTYPE_p_p_void swig_types[26]
+#define SWIGTYPE_p_size_t swig_types[27]
+#define SWIGTYPE_p_void swig_types[28]
+static swig_type_info *swig_types[30];
+static swig_module_info swig_module = {swig_types, 29, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -3509,6 +3511,9 @@ SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShado
 SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
     GDALSetDescription( self, pszNewDesc );
   }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
+    return GDALGetMetadataDomainList( self );
+  }
 SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
     return GDALGetMetadata( self, pszDomain );
   }
@@ -3741,6 +3746,97 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
 }
 
 
+#include "gdal.h"
+
+typedef struct
+{
+    CPLVirtualMem *vmem;
+    int            bAuto;
+    GDALDataType   eBufType;
+    int            bIsBandSequential;
+    int            bReadOnly;
+    int            nBufXSize;
+    int            nBufYSize;
+    int            nBandCount;
+    GDALTileOrganization eTileOrganization;
+    int                  nTileXSize;
+    int                  nTileYSize;
+    int            nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace; /* if bAuto == TRUE */
+} CPLVirtualMemShadow;
+
+
+SWIGINTERN void delete_CPLVirtualMemShadow(CPLVirtualMemShadow *self){
+        CPLVirtualMemFree( self->vmem );
+        free(self);
+    }
+SWIGINTERN void CPLVirtualMemShadow_GetAddr(CPLVirtualMemShadow *self,void **pptr,size_t *pnsize,GDALDataType *pdatatype,int *preadonly){
+        *pptr = CPLVirtualMemGetAddr( self->vmem );
+        *pnsize = CPLVirtualMemGetSize( self->vmem );
+        *pdatatype = self->eBufType;
+        *preadonly = self->bReadOnly;
+    }
+
+SWIGINTERN int
+SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
+{
+  if (PyInt_Check(obj)) {
+    long v = PyInt_AsLong(obj);
+    if (v >= 0) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      return SWIG_OverflowError;
+    }
+  } else if (PyLong_Check(obj)) {
+    unsigned long v = PyLong_AsUnsignedLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    unsigned long v = PyLong_AsUnsignedLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+	if (val) *val = (unsigned long)(d);
+	return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERNINLINE int
+SWIG_AsVal_size_t (PyObject * obj, size_t *val)
+{
+  unsigned long v;
+  int res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0);
+  if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v);
+  return res;
+}
+
+SWIGINTERN void CPLVirtualMemShadow_Pin(CPLVirtualMemShadow *self,size_t start_offset=0,size_t nsize=0,int bWriteOp=0){
+        if( nsize == 0 || start_offset + nsize >= CPLVirtualMemGetSize( self->vmem ) )
+            nsize = CPLVirtualMemGetSize( self->vmem ) - start_offset;
+        char* start_addr = (char*)CPLVirtualMemGetAddr( self->vmem ) + start_offset;
+        CPLVirtualMemPin(self->vmem, start_addr, nsize, bWriteOp);
+    }
+
 /* Returned size is in bytes or 0 if an error occured */
 static
 GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
@@ -3845,11 +3941,13 @@ static GDALAsyncReaderH AsyncReaderWrapperGetReader(GDALAsyncReaderWrapperH hWra
     return psWrapper->hAsyncReader;
 }
 
+#if defined(SWIGPYTHON)
 static void* AsyncReaderWrapperGetPyObject(GDALAsyncReaderWrapperH hWrapper)
 {
     GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
     return psWrapper->pyObject;
 }
+#endif
 
 static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 {
@@ -4119,6 +4217,78 @@ SWIGINTERN void GDALDatasetShadow_EndAsyncReader(GDALDatasetShadow *self,GDALAsy
     GDALEndAsyncReader(self, hReader);
     DisableAsyncReaderWrapper(ario);
   }
+SWIGINTERN CPLVirtualMemShadow *GDALDatasetShadow_GetVirtualMem(GDALDatasetShadow *self,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eBufType,int band_list,int *pband_list,int bIsBandSequential,size_t nCacheSize,size_t nPageSizeHint,char **options=NULL){
+        int nPixelSpace;
+        GIntBig nBandSpace;
+        if( bIsBandSequential != 0 && bIsBandSequential != 1 )
+            return NULL;
+        if( band_list == 0 )
+            return NULL;
+        if( bIsBandSequential || band_list == 1 )
+        {
+            nPixelSpace = 0;
+            nBandSpace = 0;
+        }
+        else
+        {
+            nBandSpace = GDALGetDataTypeSize(eBufType) / 8;
+            nPixelSpace  = nBandSpace * band_list;
+        }
+        CPLVirtualMem* vmem = GDALDatasetGetVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nBufXSize, nBufYSize,
+                                         eBufType,
+                                         band_list, pband_list,
+                                         nPixelSpace,
+                                         0,
+                                         nBandSpace,
+                                         nCacheSize,
+                                         nPageSizeHint,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = bIsBandSequential;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nBufXSize;
+        vmemshadow->nBufYSize = nBufYSize;
+        vmemshadow->nBandCount = band_list;
+        return vmemshadow;
+    }
+SWIGINTERN CPLVirtualMemShadow *GDALDatasetShadow_GetTiledVirtualMem(GDALDatasetShadow *self,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,int nTileXSize,int nTileYSize,GDALDataType eBufType,int band_list,int *pband_list,GDALTileOrganization eTileOrganization,size_t nCacheSize,char **options=NULL){
+        if( band_list == 0 )
+            return NULL;
+        CPLVirtualMem* vmem = GDALDatasetGetTiledVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nTileXSize, nTileYSize,
+                                         eBufType,
+                                         band_list, pband_list,
+                                         eTileOrganization,
+                                         nCacheSize,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = -1;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nXSize;
+        vmemshadow->nBufYSize = nYSize;
+        vmemshadow->eTileOrganization = eTileOrganization;
+        vmemshadow->nTileXSize = nTileXSize;
+        vmemshadow->nTileYSize = nTileYSize;
+        vmemshadow->nBandCount = band_list;
+        return vmemshadow;
+    }
 SWIGINTERN CPLErr GDALDatasetShadow_ReadRaster1(GDALDatasetShadow *self,int xoff,int yoff,int xsize,int ysize,void **buf,int *buf_xsize=0,int *buf_ysize=0,GDALDataType *buf_type=0,int band_list=0,int *pband_list=0,int *buf_pixel_space=0,int *buf_line_space=0,int *buf_band_space=0){
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
@@ -4446,6 +4616,78 @@ SWIGINTERN char **GDALRasterBandShadow_GetCategoryNames(GDALRasterBandShadow *se
 SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *self,char **papszCategoryNames){
     return GDALSetRasterCategoryNames( self, papszCategoryNames );
   }
+SWIGINTERN CPLVirtualMemShadow *GDALRasterBandShadow_GetVirtualMem(GDALRasterBandShadow *self,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eBufType,size_t nCacheSize,size_t nPageSizeHint,char **options=NULL){
+        CPLVirtualMem* vmem = GDALRasterBandGetVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nBufXSize, nBufYSize,
+                                         eBufType,
+                                         0,
+                                         0,
+                                         nCacheSize,
+                                         nPageSizeHint,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = TRUE;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nBufXSize;
+        vmemshadow->nBufYSize = nBufYSize;
+        vmemshadow->nBandCount = 1;
+        return vmemshadow;
+    }
+SWIGINTERN CPLVirtualMemShadow *GDALRasterBandShadow_GetVirtualMemAuto(GDALRasterBandShadow *self,GDALRWFlag eRWFlag,char **options=NULL){
+        int            nPixelSpace;
+        GIntBig        nLineSpace;
+        CPLVirtualMem* vmem = GDALGetVirtualMemAuto( self,
+                                         eRWFlag,
+                                         &nPixelSpace,
+                                         &nLineSpace,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = GDALGetRasterDataType( self );
+        vmemshadow->bAuto = TRUE;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBandCount = 1;
+        vmemshadow->nPixelSpace = nPixelSpace;
+        vmemshadow->nLineSpace = nLineSpace;
+        vmemshadow->nBufXSize = GDALGetRasterBandXSize(self);
+        vmemshadow->nBufYSize = GDALGetRasterBandYSize(self);
+        return vmemshadow;
+    }
+SWIGINTERN CPLVirtualMemShadow *GDALRasterBandShadow_GetTiledVirtualMem(GDALRasterBandShadow *self,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,int nTileXSize,int nTileYSize,GDALDataType eBufType,size_t nCacheSize,char **options=NULL){
+        CPLVirtualMem* vmem = GDALRasterBandGetTiledVirtualMem( self,
+                                         eRWFlag,
+                                         nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nTileXSize, nTileYSize,
+                                         eBufType,
+                                         nCacheSize,
+                                         FALSE,
+                                         options );
+        if( vmem == NULL )
+            return NULL;
+        CPLVirtualMemShadow* vmemshadow = (CPLVirtualMemShadow*)calloc(1, sizeof(CPLVirtualMemShadow));
+        vmemshadow->vmem = vmem;
+        vmemshadow->eBufType = eBufType;
+        vmemshadow->bIsBandSequential = -1;
+        vmemshadow->bReadOnly = (eRWFlag == GF_Read);
+        vmemshadow->nBufXSize = nXSize;
+        vmemshadow->nBufYSize = nYSize;
+        vmemshadow->eTileOrganization = GTO_BSQ;
+        vmemshadow->nTileXSize = nTileXSize;
+        vmemshadow->nTileYSize = nTileYSize;
+        vmemshadow->nBandCount = 1;
+        return vmemshadow;
+    }
 SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,void **buf,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,int *buf_pixel_space=0,int *buf_line_space=0){
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
@@ -4621,6 +4863,9 @@ SWIGINTERN int GDALRasterAttributeTableShadow_SetLinearBinning(GDALRasterAttribu
 SWIGINTERN int GDALRasterAttributeTableShadow_GetRowOfValue(GDALRasterAttributeTableShadow *self,double dfValue){
         return GDALRATGetRowOfValue( self, dfValue );
     }
+SWIGINTERN int GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(GDALRasterAttributeTableShadow *self){
+        return GDALRATChangesAreWrittenToFile( self );
+    }
 
 #include "gdalgrid.h"
 
@@ -5869,6 +6114,11 @@ SWIGINTERN PyObject *_wrap_PushFinderLocation(PyObject *SWIGUNUSEDPARM(self), Py
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -5969,6 +6219,11 @@ SWIGINTERN PyObject *_wrap_FindFile(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     }
   }
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6015,6 +6270,11 @@ SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6075,6 +6335,11 @@ SWIGINTERN PyObject *_wrap_ReadDirRecursive(PyObject *SWIGUNUSEDPARM(self), PyOb
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6415,6 +6680,11 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
 #endif
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6471,6 +6741,11 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6548,6 +6823,11 @@ SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
   } 
   arg2 = static_cast< int >(val2);
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6592,6 +6872,11 @@ SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6888,6 +7173,11 @@ SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     arg3 = static_cast< int >(val3);
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -6950,6 +7240,11 @@ SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -7324,6 +7619,55 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:MajorObject_GetMetadataDomainList",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
@@ -8073,6 +8417,11 @@ SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObjec
     }
   }
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -8249,6 +8598,11 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
     }
   }
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if (!arg3) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
@@ -8327,6 +8681,11 @@ SWIGINTERN PyObject *_wrap_Driver_Delete(PyObject *SWIGUNUSEDPARM(self), PyObjec
     }
   }
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -10941,24 +11300,24 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_AsyncReader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_AsyncReader",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_VirtualMem",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_AsyncReader" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_VirtualMem" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
   }
-  arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALAsyncReaderShadow(arg1);
+    delete_CPLVirtualMemShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10973,50 +11332,39 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
-  double arg2 ;
-  int *arg3 = (int *) 0 ;
-  int *arg4 = (int *) 0 ;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  void **arg2 = (void **) 0 ;
+  size_t *arg3 = (size_t *) 0 ;
+  GDALDataType *arg4 = (GDALDataType *) 0 ;
   int *arg5 = (int *) 0 ;
-  int *arg6 = (int *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  int temp3 ;
-  int res3 = SWIG_TMPOBJ ;
-  int temp4 ;
-  int res4 = SWIG_TMPOBJ ;
-  int temp5 ;
-  int res5 = SWIG_TMPOBJ ;
-  int temp6 ;
-  int res6 = SWIG_TMPOBJ ;
+  void *ptr2 ;
+  size_t nsize2 ;
+  GDALDataType datatype2 ;
+  int readonly2 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  GDALAsyncStatusType result;
   
-  arg3 = &temp3;
-  arg4 = &temp4;
-  arg5 = &temp5;
-  arg6 = &temp6;
-  if (!PyArg_ParseTuple(args,(char *)"OO:AsyncReader_GetNextUpdatedRegion",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, 0 |  0 );
+  {
+    /* %typemap(in,numinputs=0) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly) */
+    arg2 = &ptr2;
+    arg3 = &nsize2;
+    arg4 = &datatype2;
+    arg5 = &readonly2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:VirtualMem_GetAddr",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_GetAddr" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
   }
-  arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11024,15 +11372,230 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSED
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if (SWIG_IsTmpObj(res3)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
+  resultobj = SWIG_Py_Void();
+  {
+#if PY_VERSION_HEX >= 0x02070000 
+    /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
+    Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
+    if (PyBuffer_FillInfo(buf,  obj0,  *(arg2), *(arg3), *(arg5), PyBUF_ND)) {
+      // error, handle
+    }
+    if( *(arg4) == GDT_Byte )
+    {
+      buf->format = "B";
+      buf->itemsize = 1;
+    }
+    else if( *(arg4) == GDT_Int16 )
+    {
+      buf->format = "h";
+      buf->itemsize = 2;
+    }
+    else if( *(arg4) == GDT_UInt16 )
+    {
+      buf->format = "H";
+      buf->itemsize = 2;
+    }
+    else if( *(arg4) == GDT_Int32 )
+    {
+      buf->format = "i";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_UInt32 )
+    {
+      buf->format = "I";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_Float32 )
+    {
+      buf->format = "f";
+      buf->itemsize = 4;
+    }
+    else if( *(arg4) == GDT_Float64 )
+    {
+      buf->format = "F";
+      buf->itemsize = 8;
+    }
+    else
+    {
+      buf->format = "B";
+      buf->itemsize = 1;
+    }
+    resultobj = PyMemoryView_FromBuffer(buf);
+#else
+    PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
+    SWIG_fail;
+#endif
   }
-  if (SWIG_IsTmpObj(res4)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
+  size_t arg2 = (size_t) 0 ;
+  size_t arg3 = (size_t) 0 ;
+  int arg4 = (int) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|OOO:VirtualMem_Pin",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CPLVirtualMemShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_size_t(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VirtualMem_Pin" "', argument " "2"" of type '" "size_t""'");
+    } 
+    arg2 = static_cast< size_t >(val2);
+  }
+  if (obj2) {
+    ecode3 = SWIG_AsVal_size_t(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VirtualMem_Pin" "', argument " "3"" of type '" "size_t""'");
+    } 
+    arg3 = static_cast< size_t >(val3);
+  }
+  if (obj3) {
+    ecode4 = SWIG_AsVal_int(obj3, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VirtualMem_Pin" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    CPLVirtualMemShadow_Pin(arg1,arg2,arg3,arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *VirtualMem_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_CPLVirtualMemShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_delete_AsyncReader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_AsyncReader",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_AsyncReader" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALAsyncReaderShadow(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
+  double arg2 ;
+  int *arg3 = (int *) 0 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  int temp3 ;
+  int res3 = SWIG_TMPOBJ ;
+  int temp4 ;
+  int res4 = SWIG_TMPOBJ ;
+  int temp5 ;
+  int res5 = SWIG_TMPOBJ ;
+  int temp6 ;
+  int res6 = SWIG_TMPOBJ ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  GDALAsyncStatusType result;
+  
+  arg3 = &temp3;
+  arg4 = &temp4;
+  arg5 = &temp5;
+  arg6 = &temp6;
+  if (!PyArg_ParseTuple(args,(char *)"OO:AsyncReader_GetNextUpdatedRegion",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (SWIG_IsTmpObj(res3)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res4)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
@@ -12852,22 +13415,23 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-  int arg2 ;
+  GDALRWFlag arg2 ;
   int arg3 ;
   int arg4 ;
   int arg5 ;
-  void **arg6 = (void **) 0 ;
-  int *arg7 = (int *) 0 ;
-  int *arg8 = (int *) 0 ;
-  GDALDataType *arg9 = (GDALDataType *) 0 ;
-  int arg10 = (int) 0 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  GDALDataType arg9 ;
+  int arg10 ;
   int *arg11 = (int *) 0 ;
-  int *arg12 = (int *) 0 ;
-  int *arg13 = (int *) 0 ;
-  int *arg14 = (int *) 0 ;
+  int arg12 ;
+  size_t arg13 ;
+  size_t arg14 ;
+  char **arg15 = (char **) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -12878,13 +13442,20 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
   int ecode4 = 0 ;
   int val5 ;
   int ecode5 = 0 ;
-  void *pyObject6 = NULL ;
+  int val6 ;
+  int ecode6 = 0 ;
   int val7 ;
+  int ecode7 = 0 ;
   int val8 ;
+  int ecode8 = 0 ;
   int val9 ;
+  int ecode9 = 0 ;
   int val12 ;
-  int val13 ;
-  int val14 ;
+  int ecode12 = 0 ;
+  size_t val13 ;
+  int ecode13 = 0 ;
+  size_t val14 ;
+  int ecode14 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
@@ -12897,93 +13468,526 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
   PyObject * obj9 = 0 ;
   PyObject * obj10 = 0 ;
   PyObject * obj11 = 0 ;
+  PyObject * obj12 = 0 ;
+  PyObject * obj13 = 0 ;
   char *  kwnames[] = {
-    (char *) "self",(char *) "xoff",(char *) "yoff",(char *) "xsize",(char *) "ysize",(char *) "buf_xsize",(char *) "buf_ysize",(char *) "buf_type",(char *) "band_list",(char *) "buf_pixel_space",(char *) "buf_line_space",(char *) "buf_band_space", NULL 
+    (char *) "self",(char *) "eRWFlag",(char *) "nXOff",(char *) "nYOff",(char *) "nXSize",(char *) "nYSize",(char *) "nBufXSize",(char *) "nBufYSize",(char *) "eBufType",(char *) "band_list",(char *) "bIsBandSequential",(char *) "nCacheSize",(char *) "nPageSizeHint",(char *) "options", NULL 
   };
-  CPLErr result;
+  CPLVirtualMemShadow *result = 0 ;
   
-  {
-    /* %typemap(in,numinputs=0) ( void **outPythonObject ) ( void *pyObject6 = NULL ) */
-    arg6 = &pyObject6;
-  }
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOO|OOOOOOO:Dataset_ReadRaster1",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10,&obj11)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOOOOOOOOO|O:Dataset_GetVirtualMem",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10,&obj11,&obj12,&obj13)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_ReadRaster1" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetVirtualMem" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_ReadRaster1" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_GetVirtualMem" "', argument " "2"" of type '" "GDALRWFlag""'");
   } 
-  arg2 = static_cast< int >(val2);
+  arg2 = static_cast< GDALRWFlag >(val2);
   ecode3 = SWIG_AsVal_int(obj2, &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset_ReadRaster1" "', argument " "3"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset_GetVirtualMem" "', argument " "3"" of type '" "int""'");
   } 
   arg3 = static_cast< int >(val3);
   ecode4 = SWIG_AsVal_int(obj3, &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset_ReadRaster1" "', argument " "4"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset_GetVirtualMem" "', argument " "4"" of type '" "int""'");
   } 
   arg4 = static_cast< int >(val4);
   ecode5 = SWIG_AsVal_int(obj4, &val5);
   if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset_ReadRaster1" "', argument " "5"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset_GetVirtualMem" "', argument " "5"" of type '" "int""'");
   } 
   arg5 = static_cast< int >(val5);
-  if (obj5) {
-    {
-      /* %typemap(in) (int *optional_##int) */
-      if ( obj5 == Py_None ) {
-        arg7 = 0;
-      }
-      else if ( PyArg_Parse( obj5,"i" ,&val7 ) ) {
-        arg7 = (int *) &val7;
-      }
-      else {
-        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
-        SWIG_fail;
-      }
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Dataset_GetVirtualMem" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Dataset_GetVirtualMem" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Dataset_GetVirtualMem" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Dataset_GetVirtualMem" "', argument " "9"" of type '" "GDALDataType""'");
+  } 
+  arg9 = static_cast< GDALDataType >(val9);
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj9) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
     }
-  }
-  if (obj6) {
-    {
-      /* %typemap(in) (int *optional_##int) */
-      if ( obj6 == Py_None ) {
-        arg8 = 0;
-      }
-      else if ( PyArg_Parse( obj6,"i" ,&val8 ) ) {
-        arg8 = (int *) &val8;
-      }
-      else {
-        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
+    arg10 = PySequence_Size(obj9);
+    arg11 = (int*) malloc(arg10*sizeof(int));
+    for( int i = 0; i<arg10; i++ ) {
+      PyObject *o = PySequence_GetItem(obj9,i);
+      if ( !PyArg_Parse(o,"i",&arg11[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
         SWIG_fail;
       }
+      Py_DECREF(o);
     }
   }
-  if (obj7) {
+  ecode12 = SWIG_AsVal_int(obj10, &val12);
+  if (!SWIG_IsOK(ecode12)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode12), "in method '" "Dataset_GetVirtualMem" "', argument " "12"" of type '" "int""'");
+  } 
+  arg12 = static_cast< int >(val12);
+  ecode13 = SWIG_AsVal_size_t(obj11, &val13);
+  if (!SWIG_IsOK(ecode13)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode13), "in method '" "Dataset_GetVirtualMem" "', argument " "13"" of type '" "size_t""'");
+  } 
+  arg13 = static_cast< size_t >(val13);
+  ecode14 = SWIG_AsVal_size_t(obj12, &val14);
+  if (!SWIG_IsOK(ecode14)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode14), "in method '" "Dataset_GetVirtualMem" "', argument " "14"" of type '" "size_t""'");
+  } 
+  arg14 = static_cast< size_t >(val14);
+  if (obj13) {
     {
-      /* %typemap(in) (int *optional_##int) */
-      if ( obj7 == Py_None ) {
-        arg9 = 0;
-      }
-      else if ( PyArg_Parse( obj7,"i" ,&val9 ) ) {
-        arg9 = (GDALDataType *) &val9;
-      }
-      else {
-        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj13) || PyUnicode_Check(obj13)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj13)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
         SWIG_fail;
       }
-    }
-  }
-  if (obj8) {
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList)*/
-      /* check if is List */
-      if ( !PySequence_Check(obj8) ) {
-        PyErr_SetString(PyExc_TypeError, "not a sequence");
-        SWIG_fail;
+      
+      int size = PySequence_Size(obj13);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj13,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg15 = CSLAddString( arg15, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg15 = CSLAddString( arg15, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg15 = CSLAddString( arg15, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg11) {
+      free((void*) arg11);
+    }
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg15 );
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg11) {
+      free((void*) arg11);
+    }
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg15 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALRWFlag arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  GDALDataType arg9 ;
+  int arg10 ;
+  int *arg11 = (int *) 0 ;
+  GDALTileOrganization arg12 ;
+  size_t arg13 ;
+  char **arg14 = (char **) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  int val8 ;
+  int ecode8 = 0 ;
+  int val9 ;
+  int ecode9 = 0 ;
+  int val12 ;
+  int ecode12 = 0 ;
+  size_t val13 ;
+  int ecode13 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  PyObject * obj9 = 0 ;
+  PyObject * obj10 = 0 ;
+  PyObject * obj11 = 0 ;
+  PyObject * obj12 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "eRWFlag",(char *) "nXOff",(char *) "nYOff",(char *) "nXSize",(char *) "nYSize",(char *) "nTileXSize",(char *) "nTileYSize",(char *) "eBufType",(char *) "band_list",(char *) "eTileOrganization",(char *) "nCacheSize",(char *) "options", NULL 
+  };
+  CPLVirtualMemShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOOOOOOOO|O:Dataset_GetTiledVirtualMem",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10,&obj11,&obj12)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "2"" of type '" "GDALRWFlag""'");
+  } 
+  arg2 = static_cast< GDALRWFlag >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "9"" of type '" "GDALDataType""'");
+  } 
+  arg9 = static_cast< GDALDataType >(val9);
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj9) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    arg10 = PySequence_Size(obj9);
+    arg11 = (int*) malloc(arg10*sizeof(int));
+    for( int i = 0; i<arg10; i++ ) {
+      PyObject *o = PySequence_GetItem(obj9,i);
+      if ( !PyArg_Parse(o,"i",&arg11[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      Py_DECREF(o);
+    }
+  }
+  ecode12 = SWIG_AsVal_int(obj10, &val12);
+  if (!SWIG_IsOK(ecode12)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode12), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "12"" of type '" "GDALTileOrganization""'");
+  } 
+  arg12 = static_cast< GDALTileOrganization >(val12);
+  ecode13 = SWIG_AsVal_size_t(obj11, &val13);
+  if (!SWIG_IsOK(ecode13)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode13), "in method '" "Dataset_GetTiledVirtualMem" "', argument " "13"" of type '" "size_t""'");
+  } 
+  arg13 = static_cast< size_t >(val13);
+  if (obj12) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj12) || PyUnicode_Check(obj12)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj12)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj12);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj12,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg14 = CSLAddString( arg14, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg14 = CSLAddString( arg14, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg14 = CSLAddString( arg14, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg11) {
+      free((void*) arg11);
+    }
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg14 );
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg11) {
+      free((void*) arg11);
+    }
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg14 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  void **arg6 = (void **) 0 ;
+  int *arg7 = (int *) 0 ;
+  int *arg8 = (int *) 0 ;
+  GDALDataType *arg9 = (GDALDataType *) 0 ;
+  int arg10 = (int) 0 ;
+  int *arg11 = (int *) 0 ;
+  int *arg12 = (int *) 0 ;
+  int *arg13 = (int *) 0 ;
+  int *arg14 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  void *pyObject6 = NULL ;
+  int val7 ;
+  int val8 ;
+  int val9 ;
+  int val12 ;
+  int val13 ;
+  int val14 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  PyObject * obj9 = 0 ;
+  PyObject * obj10 = 0 ;
+  PyObject * obj11 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "xoff",(char *) "yoff",(char *) "xsize",(char *) "ysize",(char *) "buf_xsize",(char *) "buf_ysize",(char *) "buf_type",(char *) "band_list",(char *) "buf_pixel_space",(char *) "buf_line_space",(char *) "buf_band_space", NULL 
+  };
+  CPLErr result;
+  
+  {
+    /* %typemap(in,numinputs=0) ( void **outPythonObject ) ( void *pyObject6 = NULL ) */
+    arg6 = &pyObject6;
+  }
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOO|OOOOOOO:Dataset_ReadRaster1",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10,&obj11)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_ReadRaster1" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_ReadRaster1" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset_ReadRaster1" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset_ReadRaster1" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset_ReadRaster1" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  if (obj5) {
+    {
+      /* %typemap(in) (int *optional_##int) */
+      if ( obj5 == Py_None ) {
+        arg7 = 0;
+      }
+      else if ( PyArg_Parse( obj5,"i" ,&val7 ) ) {
+        arg7 = (int *) &val7;
+      }
+      else {
+        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
+        SWIG_fail;
+      }
+    }
+  }
+  if (obj6) {
+    {
+      /* %typemap(in) (int *optional_##int) */
+      if ( obj6 == Py_None ) {
+        arg8 = 0;
+      }
+      else if ( PyArg_Parse( obj6,"i" ,&val8 ) ) {
+        arg8 = (int *) &val8;
+      }
+      else {
+        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
+        SWIG_fail;
+      }
+    }
+  }
+  if (obj7) {
+    {
+      /* %typemap(in) (int *optional_##int) */
+      if ( obj7 == Py_None ) {
+        arg9 = 0;
+      }
+      else if ( PyArg_Parse( obj7,"i" ,&val9 ) ) {
+        arg9 = (GDALDataType *) &val9;
+      }
+      else {
+        PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
+        SWIG_fail;
+      }
+    }
+  }
+  if (obj8) {
+    {
+      /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+      /* check if is List */
+      if ( !PySequence_Check(obj8) ) {
+        PyErr_SetString(PyExc_TypeError, "not a sequence");
+        SWIG_fail;
       }
       arg10 = PySequence_Size(obj8);
       arg11 = (int*) malloc(arg10*sizeof(int));
@@ -15661,7 +16665,193 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+    result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    int i;
+    PyObject *psList = NULL;
+    
+    Py_XDECREF(resultobj);
+    
+    if (panHistogram)
+    {
+      psList = PyList_New(buckets_val);
+      for( i = 0; i < buckets_val; i++ )
+      PyList_SetItem(psList, i, Py_BuildValue("i", panHistogram[i] ));
+      
+      CPLFree( panHistogram );
+      
+      resultobj = Py_BuildValue( "(ddiO)", min_val, max_val, buckets_val, psList );
+      Py_XDECREF(psList);
+    }
+    else
+    {
+      resultobj = Py_None;
+      Py_INCREF(resultobj);
+    }
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  int arg4 ;
+  int *arg5 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:Band_SetDefaultHistogram",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetDefaultHistogram" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetDefaultHistogram" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_SetDefaultHistogram" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj3) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    arg4 = PySequence_Size(obj3);
+    arg5 = (int*) malloc(arg4*sizeof(int));
+    for( int i = 0; i<arg4; i++ ) {
+      PyObject *o = PySequence_GetItem(obj3,i);
+      if ( !PyArg_Parse(o,"i",&arg5[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      Py_DECREF(o);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg5) {
+      free((void*) arg5);
+    }
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg5) {
+      free((void*) arg5);
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Band_HasArbitraryOverviews",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_HasArbitraryOverviews" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Band_GetCategoryNames",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -15669,107 +16859,93 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
   {
-    int i;
-    PyObject *psList = NULL;
-    
-    Py_XDECREF(resultobj);
-    
-    if (panHistogram)
-    {
-      psList = PyList_New(buckets_val);
-      for( i = 0; i < buckets_val; i++ )
-      PyList_SetItem(psList, i, Py_BuildValue("i", panHistogram[i] ));
-      
-      CPLFree( panHistogram );
-      
-      resultobj = Py_BuildValue( "(ddiO)", min_val, max_val, buckets_val, psList );
-      Py_XDECREF(psList);
-    }
-    else
-    {
+    /* %typemap(out) char **options -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
       resultobj = Py_None;
-      Py_INCREF(resultobj);
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
     }
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-  double arg2 ;
-  double arg3 ;
-  int arg4 ;
-  int *arg5 = (int *) 0 ;
+  char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  double val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
   CPLErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:Band_SetDefaultHistogram",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Band_SetCategoryNames",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetDefaultHistogram" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetDefaultHistogram" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  ecode3 = SWIG_AsVal_double(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_SetDefaultHistogram" "', argument " "3"" of type '" "double""'");
-  } 
-  arg3 = static_cast< double >(val3);
   {
-    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
-    /* check if is List */
-    if ( !PySequence_Check(obj3) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj1)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
       SWIG_fail;
     }
-    arg4 = PySequence_Size(obj3);
-    arg5 = (int*) malloc(arg4*sizeof(int));
-    for( int i = 0; i<arg4; i++ ) {
-      PyObject *o = PySequence_GetItem(obj3,i);
-      if ( !PyArg_Parse(o,"i",&arg5[i]) ) {
-        PyErr_SetString(PyExc_TypeError, "not an integer");
-        Py_DECREF(o);
+    
+    int size = PySequence_Size(obj1);
+    for (int i = 0; i < size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj1,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg2 = CSLAddString( arg2, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
         SWIG_fail;
       }
-      Py_DECREF(o);
+      Py_DECREF(pyObj);
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5);
+    result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -15779,42 +16955,179 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg5) {
-      free((void*) arg5);
-    }
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
   }
   return resultobj;
 fail:
   {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg5) {
-      free((void*) arg5);
-    }
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
   }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Band_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  GDALRWFlag arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  GDALDataType arg9 ;
+  size_t arg10 ;
+  size_t arg11 ;
+  char **arg12 = (char **) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  int val8 ;
+  int ecode8 = 0 ;
+  int val9 ;
+  int ecode9 = 0 ;
+  size_t val10 ;
+  int ecode10 = 0 ;
+  size_t val11 ;
+  int ecode11 = 0 ;
   PyObject * obj0 = 0 ;
-  bool result;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  PyObject * obj9 = 0 ;
+  PyObject * obj10 = 0 ;
+  PyObject * obj11 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "eRWFlag",(char *) "nXOff",(char *) "nYOff",(char *) "nXSize",(char *) "nYSize",(char *) "nBufXSize",(char *) "nBufYSize",(char *) "eBufType",(char *) "nCacheSize",(char *) "nPageSizeHint",(char *) "options", NULL 
+  };
+  CPLVirtualMemShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Band_HasArbitraryOverviews",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOOOOOOO|O:Band_GetVirtualMem",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10,&obj11)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_HasArbitraryOverviews" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetVirtualMem" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetVirtualMem" "', argument " "2"" of type '" "GDALRWFlag""'");
+  } 
+  arg2 = static_cast< GDALRWFlag >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_GetVirtualMem" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_GetVirtualMem" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_GetVirtualMem" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Band_GetVirtualMem" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Band_GetVirtualMem" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Band_GetVirtualMem" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Band_GetVirtualMem" "', argument " "9"" of type '" "GDALDataType""'");
+  } 
+  arg9 = static_cast< GDALDataType >(val9);
+  ecode10 = SWIG_AsVal_size_t(obj9, &val10);
+  if (!SWIG_IsOK(ecode10)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "Band_GetVirtualMem" "', argument " "10"" of type '" "size_t""'");
+  } 
+  arg10 = static_cast< size_t >(val10);
+  ecode11 = SWIG_AsVal_size_t(obj10, &val11);
+  if (!SWIG_IsOK(ecode11)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode11), "in method '" "Band_GetVirtualMem" "', argument " "11"" of type '" "size_t""'");
+  } 
+  arg11 = static_cast< size_t >(val11);
+  if (obj11) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj11) || PyUnicode_Check(obj11)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj11)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj11);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj11,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg12 = CSLAddString( arg12, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg12 = CSLAddString( arg12, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg12 = CSLAddString( arg12, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
+    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -15822,32 +17135,100 @@ SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg12 );
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg12 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Band_GetVirtualMemAuto(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  GDALRWFlag arg2 ;
+  char **arg3 = (char **) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  char **result = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "eRWFlag",(char *) "options", NULL 
+  };
+  CPLVirtualMemShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Band_GetCategoryNames",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Band_GetVirtualMemAuto",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetVirtualMemAuto" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetVirtualMemAuto" "', argument " "2"" of type '" "GDALRWFlag""'");
+  } 
+  arg2 = static_cast< GDALRWFlag >(val2);
+  if (obj2) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj2)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj2);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj2,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg3 = CSLAddString( arg3, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
+    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMemAuto(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -15855,93 +17236,172 @@ SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
-    /* %typemap(out) char **options -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
-    }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
-    }
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
   }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Band_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-  char **arg2 = (char **) 0 ;
+  GDALRWFlag arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  GDALDataType arg9 ;
+  size_t arg10 ;
+  char **arg11 = (char **) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  int val8 ;
+  int ecode8 = 0 ;
+  int val9 ;
+  int ecode9 = 0 ;
+  size_t val10 ;
+  int ecode10 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  CPLErr result;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  PyObject * obj9 = 0 ;
+  PyObject * obj10 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "eRWFlag",(char *) "nXOff",(char *) "nYOff",(char *) "nXSize",(char *) "nYSize",(char *) "nTileXSize",(char *) "nTileYSize",(char *) "eBufType",(char *) "nCacheSize",(char *) "options", NULL 
+  };
+  CPLVirtualMemShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Band_SetCategoryNames",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOOOOOO|O:Band_GetTiledVirtualMem",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetTiledVirtualMem" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-  {
-    /* %typemap(in) char **options */
-    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetTiledVirtualMem" "', argument " "2"" of type '" "GDALRWFlag""'");
+  } 
+  arg2 = static_cast< GDALRWFlag >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_GetTiledVirtualMem" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_GetTiledVirtualMem" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_GetTiledVirtualMem" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Band_GetTiledVirtualMem" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Band_GetTiledVirtualMem" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Band_GetTiledVirtualMem" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Band_GetTiledVirtualMem" "', argument " "9"" of type '" "GDALDataType""'");
+  } 
+  arg9 = static_cast< GDALDataType >(val9);
+  ecode10 = SWIG_AsVal_size_t(obj9, &val10);
+  if (!SWIG_IsOK(ecode10)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "Band_GetTiledVirtualMem" "', argument " "10"" of type '" "size_t""'");
+  } 
+  arg10 = static_cast< size_t >(val10);
+  if (obj10) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj10) || PyUnicode_Check(obj10)
   #if PY_VERSION_HEX < 0x03000000
-      || PyString_Check(obj1)
+        || PyString_Check(obj10)
   #endif
-      ) {
-      PyErr_SetString(PyExc_TypeError,"not a sequence");
-      SWIG_fail;
-    }
-    
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
-      PyObject* pyObj = PySequence_GetItem(obj1,i);
-      if (PyUnicode_Check(pyObj))
-      {
-        char *pszStr;
-        Py_ssize_t nLen;
-        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj10);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj10,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
 #if PY_VERSION_HEX >= 0x03000000
-        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
 #else
-        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
 #endif
-        arg2 = CSLAddString( arg2, pszStr );
-        Py_XDECREF(pyUTF8Str);
-      }
+          arg11 = CSLAddString( arg11, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
 #if PY_VERSION_HEX >= 0x03000000
-      else if (PyBytes_Check(pyObj))
-      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+        else if (PyBytes_Check(pyObj))
+        arg11 = CSLAddString( arg11, PyBytes_AsString(pyObj) );
 #else
-      else if (PyString_Check(pyObj))
-      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+        else if (PyString_Check(pyObj))
+        arg11 = CSLAddString( arg11, PyString_AsString(pyObj) );
 #endif
-      else
-      {
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
         Py_DECREF(pyObj);
-        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-        SWIG_fail;
       }
-      Py_DECREF(pyObj);
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2);
+    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -15949,16 +17409,16 @@ SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    CSLDestroy( arg11 );
   }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    CSLDestroy( arg11 );
   }
   return NULL;
 }
@@ -17606,6 +19066,39 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_RasterAttributeTable_ChangesAreWrittenToFile(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:RasterAttributeTable_ChangesAreWrittenToFile",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_ChangesAreWrittenToFile" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *RasterAttributeTable_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
@@ -21235,6 +22728,11 @@ SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     arg2 = static_cast< GDALAccess >(val2);
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -21290,6 +22788,11 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
     arg2 = static_cast< GDALAccess >(val2);
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -21382,6 +22885,11 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
     }
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -21572,6 +23080,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(int nLen, int size, int memb, VSILFILE f) -> int"},
 	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char"},
 	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char pszNewDesc)"},
+	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char"},
 	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char pszDomain = \"\") -> char"},
 	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char pszDomain = \"\") -> char"},
 	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, (char *)"\n"
@@ -21661,6 +23170,13 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GDAL_GCP_get_Id", _wrap_GDAL_GCP_get_Id, METH_VARARGS, (char *)"GDAL_GCP_get_Id(GCP gcp) -> char"},
 	 { (char *)"GDAL_GCP_set_Id", _wrap_GDAL_GCP_set_Id, METH_VARARGS, (char *)"GDAL_GCP_set_Id(GCP gcp, char pszId)"},
 	 { (char *)"GCPsToGeoTransform", _wrap_GCPsToGeoTransform, METH_VARARGS, (char *)"GCPsToGeoTransform(int nGCPs, int bApproxOK = 1) -> RETURN_NONE"},
+	 { (char *)"delete_VirtualMem", _wrap_delete_VirtualMem, METH_VARARGS, (char *)"delete_VirtualMem(VirtualMem self)"},
+	 { (char *)"VirtualMem_GetAddr", _wrap_VirtualMem_GetAddr, METH_VARARGS, (char *)"VirtualMem_GetAddr(VirtualMem self)"},
+	 { (char *)"VirtualMem_Pin", _wrap_VirtualMem_Pin, METH_VARARGS, (char *)"\n"
+		"VirtualMem_Pin(VirtualMem self, size_t start_offset = 0, size_t nsize = 0, \n"
+		"    int bWriteOp = 0)\n"
+		""},
+	 { (char *)"VirtualMem_swigregister", VirtualMem_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_AsyncReader", _wrap_delete_AsyncReader, METH_VARARGS, (char *)"delete_AsyncReader(AsyncReader self)"},
 	 { (char *)"AsyncReader_GetNextUpdatedRegion", _wrap_AsyncReader_GetNextUpdatedRegion, METH_VARARGS, (char *)"AsyncReader_GetNextUpdatedRegion(AsyncReader self, double timeout) -> GDALAsyncStatusType"},
 	 { (char *)"AsyncReader_GetBuffer", _wrap_AsyncReader_GetBuffer, METH_VARARGS, (char *)"AsyncReader_GetBuffer(AsyncReader self)"},
@@ -21706,6 +23222,20 @@ static PyMethodDef SwigMethods[] = {
 		"    int nBandSpace = 0, char options = None) -> AsyncReader\n"
 		""},
 	 { (char *)"Dataset_EndAsyncReader", _wrap_Dataset_EndAsyncReader, METH_VARARGS, (char *)"Dataset_EndAsyncReader(Dataset self, AsyncReader ario)"},
+	 { (char *)"Dataset_GetVirtualMem", (PyCFunction) _wrap_Dataset_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Dataset_GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
+		"    int nXSize, int nYSize, int nBufXSize, int nBufYSize, \n"
+		"    GDALDataType eBufType, int band_list, \n"
+		"    int bIsBandSequential, size_t nCacheSize, \n"
+		"    size_t nPageSizeHint, char options = None) -> VirtualMem\n"
+		""},
+	 { (char *)"Dataset_GetTiledVirtualMem", (PyCFunction) _wrap_Dataset_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Dataset_GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
+		"    int nXSize, int nYSize, int nTileXSize, \n"
+		"    int nTileYSize, GDALDataType eBufType, int band_list, \n"
+		"    GDALTileOrganization eTileOrganization, \n"
+		"    size_t nCacheSize, char options = None) -> VirtualMem\n"
+		""},
 	 { (char *)"Dataset_ReadRaster1", (PyCFunction) _wrap_Dataset_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"Dataset_ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, \n"
 		"    int buf_xsize = None, int buf_ysize = None, \n"
@@ -21782,6 +23312,19 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_HasArbitraryOverviews", _wrap_Band_HasArbitraryOverviews, METH_VARARGS, (char *)"Band_HasArbitraryOverviews(Band self) -> bool"},
 	 { (char *)"Band_GetCategoryNames", _wrap_Band_GetCategoryNames, METH_VARARGS, (char *)"Band_GetCategoryNames(Band self) -> char"},
 	 { (char *)"Band_SetCategoryNames", _wrap_Band_SetCategoryNames, METH_VARARGS, (char *)"Band_SetCategoryNames(Band self, char papszCategoryNames) -> CPLErr"},
+	 { (char *)"Band_GetVirtualMem", (PyCFunction) _wrap_Band_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Band_GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
+		"    int nXSize, int nYSize, int nBufXSize, int nBufYSize, \n"
+		"    GDALDataType eBufType, size_t nCacheSize, \n"
+		"    size_t nPageSizeHint, char options = None) -> VirtualMem\n"
+		""},
+	 { (char *)"Band_GetVirtualMemAuto", (PyCFunction) _wrap_Band_GetVirtualMemAuto, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char options = None) -> VirtualMem"},
+	 { (char *)"Band_GetTiledVirtualMem", (PyCFunction) _wrap_Band_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Band_GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
+		"    int nXSize, int nYSize, int nTileXSize, int nTileYSize, \n"
+		"    GDALDataType eBufType, size_t nCacheSize, \n"
+		"    char options = None) -> VirtualMem\n"
+		""},
 	 { (char *)"Band_ReadRaster1", (PyCFunction) _wrap_Band_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"Band_ReadRaster1(Band self, int xoff, int yoff, int xsize, int ysize, \n"
 		"    int buf_xsize = None, int buf_ysize = None, \n"
@@ -21826,6 +23369,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"RasterAttributeTable_GetLinearBinning", _wrap_RasterAttributeTable_GetLinearBinning, METH_VARARGS, (char *)"RasterAttributeTable_GetLinearBinning(RasterAttributeTable self) -> bool"},
 	 { (char *)"RasterAttributeTable_SetLinearBinning", _wrap_RasterAttributeTable_SetLinearBinning, METH_VARARGS, (char *)"RasterAttributeTable_SetLinearBinning(RasterAttributeTable self, double dfRow0Min, double dfBinSize) -> int"},
 	 { (char *)"RasterAttributeTable_GetRowOfValue", _wrap_RasterAttributeTable_GetRowOfValue, METH_VARARGS, (char *)"RasterAttributeTable_GetRowOfValue(RasterAttributeTable self, double dfValue) -> int"},
+	 { (char *)"RasterAttributeTable_ChangesAreWrittenToFile", _wrap_RasterAttributeTable_ChangesAreWrittenToFile, METH_VARARGS, (char *)"RasterAttributeTable_ChangesAreWrittenToFile(RasterAttributeTable self) -> int"},
 	 { (char *)"RasterAttributeTable_swigregister", RasterAttributeTable_swigregister, METH_VARARGS, NULL},
 	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"},
 	 { (char *)"ComputeMedianCutPCT", (PyCFunction) _wrap_ComputeMedianCutPCT, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
@@ -21948,6 +23492,7 @@ static void *_p_GDALRasterBandShadowTo_p_GDALMajorObjectShadow(void *x, int *SWI
     return (void *)((GDALMajorObjectShadow *)  ((GDALRasterBandShadow *) x));
 }
 static swig_type_info _swigt__p_CPLErrorHandler = {"_p_CPLErrorHandler", "CPLErrorHandler *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_CPLVirtualMemShadow = {"_p_CPLVirtualMemShadow", "CPLVirtualMemShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_CPLXMLNode = {"_p_CPLXMLNode", "CPLXMLNode *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GByte = {"_p_GByte", "GByte *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALAsyncReaderShadow = {"_p_GDALAsyncReaderShadow", "GDALAsyncReaderShadow *", 0, 0, (void*)0, 0};
@@ -21967,16 +23512,18 @@ static swig_type_info _swigt__p_StatBuf = {"_p_StatBuf", "StatBuf *", 0, 0, (voi
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_f_double_p_q_const__char_p_void__int = {"_p_f_double_p_q_const__char_p_void__int", "int (*)(double,char const *,void *)", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|GDALRATFieldType *|int *|GDALColorInterp *|GDALAccess *|GDALPaletteInterp *|GDALDataType *|GDALAsyncStatusType *|GDALRATFieldUsage *|GDALResampleAlg *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|GDALRATFieldType *|int *|GDALColorInterp *|GDALAccess *|GDALPaletteInterp *|GDALDataType *|GDALAsyncStatusType *|GDALRWFlag *|GDALTileOrganization *|GDALRATFieldUsage *|GDALResampleAlg *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDALRasterBandShadow = {"_p_p_GDALRasterBandShadow", "GDALRasterBandShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_int = {"_p_p_int", "int **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_void = {"_p_p_void", "void **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_size_t = {"_p_size_t", "size_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_void = {"_p_void", "VSILFILE *|void *", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
   &_swigt__p_CPLErrorHandler,
+  &_swigt__p_CPLVirtualMemShadow,
   &_swigt__p_CPLXMLNode,
   &_swigt__p_GByte,
   &_swigt__p_GDALAsyncReaderShadow,
@@ -22002,10 +23549,12 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_p_char,
   &_swigt__p_p_int,
   &_swigt__p_p_void,
+  &_swigt__p_size_t,
   &_swigt__p_void,
 };
 
 static swig_cast_info _swigc__p_CPLErrorHandler[] = {  {&_swigt__p_CPLErrorHandler, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_CPLVirtualMemShadow[] = {  {&_swigt__p_CPLVirtualMemShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_CPLXMLNode[] = {  {&_swigt__p_CPLXMLNode, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GByte[] = {  {&_swigt__p_GByte, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALAsyncReaderShadow[] = {  {&_swigt__p_GDALAsyncReaderShadow, 0, 0, 0},{0, 0, 0, 0}};
@@ -22031,10 +23580,12 @@ static swig_cast_info _swigc__p_p_GDAL_GCP[] = {  {&_swigt__p_p_GDAL_GCP, 0, 0,
 static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_int[] = {  {&_swigt__p_p_int, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_void[] = {  {&_swigt__p_p_void, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_size_t[] = {  {&_swigt__p_size_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_void[] = {  {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}};
 
 static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_CPLErrorHandler,
+  _swigc__p_CPLVirtualMemShadow,
   _swigc__p_CPLXMLNode,
   _swigc__p_GByte,
   _swigc__p_GDALAsyncReaderShadow,
@@ -22060,6 +23611,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_p_char,
   _swigc__p_p_int,
   _swigc__p_p_void,
+  _swigc__p_size_t,
   _swigc__p_void,
 };
 
diff --git a/swig/python/extensions/gdalconst_wrap.c b/swig/python/extensions/gdalconst_wrap.c
index 7f0e252..f3b89c9 100644
--- a/swig/python/extensions/gdalconst_wrap.c
+++ b/swig/python/extensions/gdalconst_wrap.c
@@ -3509,6 +3509,9 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "GARIO_UPDATE",SWIG_From_int((int)(GARIO_UPDATE)));
   SWIG_Python_SetConstant(d, "GARIO_ERROR",SWIG_From_int((int)(GARIO_ERROR)));
   SWIG_Python_SetConstant(d, "GARIO_COMPLETE",SWIG_From_int((int)(GARIO_COMPLETE)));
+  SWIG_Python_SetConstant(d, "GTO_TIP",SWIG_From_int((int)(GTO_TIP)));
+  SWIG_Python_SetConstant(d, "GTO_BIT",SWIG_From_int((int)(GTO_BIT)));
+  SWIG_Python_SetConstant(d, "GTO_BSQ",SWIG_From_int((int)(GTO_BSQ)));
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/ogr_wrap.cpp b/swig/python/extensions/ogr_wrap.cpp
index b3592a7..c79f9b4 100644
--- a/swig/python/extensions/ogr_wrap.cpp
+++ b/swig/python/extensions/ogr_wrap.cpp
@@ -2729,19 +2729,21 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
 #define SWIGTYPE_p_OGRFeatureDefnShadow swig_types[4]
 #define SWIGTYPE_p_OGRFeatureShadow swig_types[5]
 #define SWIGTYPE_p_OGRFieldDefnShadow swig_types[6]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[7]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[8]
-#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[9]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[10]
-#define SWIGTYPE_p_char swig_types[11]
-#define SWIGTYPE_p_double swig_types[12]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[13]
-#define SWIGTYPE_p_int swig_types[14]
-#define SWIGTYPE_p_p_char swig_types[15]
-#define SWIGTYPE_p_p_double swig_types[16]
-#define SWIGTYPE_p_p_int swig_types[17]
-static swig_type_info *swig_types[19];
-static swig_module_info swig_module = {swig_types, 18, 0, 0, 0, 0};
+#define SWIGTYPE_p_OGRGeomFieldDefnShadow swig_types[7]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[8]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[9]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[10]
+#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[11]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[12]
+#define SWIGTYPE_p_char swig_types[13]
+#define SWIGTYPE_p_double swig_types[14]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[15]
+#define SWIGTYPE_p_int swig_types[16]
+#define SWIGTYPE_p_p_char swig_types[17]
+#define SWIGTYPE_p_p_double swig_types[18]
+#define SWIGTYPE_p_p_int swig_types[19]
+static swig_type_info *swig_types[21];
+static swig_module_info swig_module = {swig_types, 20, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -2873,6 +2875,8 @@ typedef void OGRGeometryShadow;
 typedef void OSRCoordinateTransformationShadow;
 typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
   #define SWIG_From_long   PyInt_FromLong 
@@ -3100,6 +3104,12 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     return bContinue;    
 }
 
+SWIGINTERN OGRStyleTableShadow *new_OGRStyleTableShadow(){
+        return (OGRStyleTableShadow*) OGR_STBL_Create();
+   }
+SWIGINTERN void delete_OGRStyleTableShadow(OGRStyleTableShadow *self){
+        OGR_STBL_Destroy( (OGRStyleTableH) self );
+   }
 
 SWIGINTERN int
 SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
@@ -3179,6 +3189,27 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 
 
 
+SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const *pszName,char const *pszStyleString){
+        return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
+   }
+SWIGINTERN int OGRStyleTableShadow_LoadStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_LoadStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN int OGRStyleTableShadow_SaveStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
+        return OGR_STBL_SaveStyleTable( (OGRStyleTableH) self, utf8_path );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_Find(OGRStyleTableShadow *self,char const *pszName){
+        return OGR_STBL_Find( (OGRStyleTableH) self, pszName );
+   }
+SWIGINTERN void OGRStyleTableShadow_ResetStyleStringReading(OGRStyleTableShadow *self){
+        OGR_STBL_ResetStyleStringReading( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetNextStyle(OGRStyleTableShadow *self){
+        return OGR_STBL_GetNextStyle( (OGRStyleTableH) self );
+   }
+SWIGINTERN char const *OGRStyleTableShadow_GetLastStyleName(OGRStyleTableShadow *self){
+        return OGR_STBL_GetLastStyleName( (OGRStyleTableH) self );
+   }
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CreateDataSource(OGRDriverShadow *self,char const *utf8_path,char **options=0){
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
     return ds;
@@ -3460,14 +3491,27 @@ SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_ExecuteSQL(OGRDataSourceShadow *s
 SWIGINTERN void OGRDataSourceShadow_ReleaseResultSet(OGRDataSourceShadow *self,OGRLayerShadow *layer){
     OGR_DS_ReleaseResultSet(self, layer);
   }
+SWIGINTERN OGRStyleTableShadow *OGRDataSourceShadow_GetStyleTable(OGRDataSourceShadow *self){
+    return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
+  }
+SWIGINTERN void OGRDataSourceShadow_SetStyleTable(OGRDataSourceShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_DS_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN int OGRLayerShadow_GetRefCount(OGRLayerShadow *self){
     return OGR_L_GetRefCount(self);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilter(OGRLayerShadow *self,OGRGeometryShadow *filter){
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_0(OGRLayerShadow *self,OGRGeometryShadow *filter){
     OGR_L_SetSpatialFilter (self, filter);
   }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
-    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);                          
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_0(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_1(OGRLayerShadow *self,int iGeomField,OGRGeometryShadow *filter){
+    OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
+  }
+SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_1(OGRLayerShadow *self,int iGeomField,double minx,double miny,double maxx,double maxy){
+    OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
   }
 SWIGINTERN OGRGeometryShadow *OGRLayerShadow_GetSpatialFilter(OGRLayerShadow *self){
     return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
@@ -3517,8 +3561,8 @@ SWIGINTERN OGRFeatureDefnShadow *OGRLayerShadow_GetLayerDefn(OGRLayerShadow *sel
 SWIGINTERN int OGRLayerShadow_GetFeatureCount(OGRLayerShadow *self,int force=1){
     return OGR_L_GetFeatureCount(self, force);
   }
-SWIGINTERN void OGRLayerShadow_GetExtent(OGRLayerShadow *self,double argout[4],int *isvalid=NULL,int force=1,int can_return_null=0){
-    OGRErr eErr = OGR_L_GetExtent(self, (OGREnvelope*)argout, force);
+SWIGINTERN void OGRLayerShadow_GetExtent(OGRLayerShadow *self,double argout[4],int *isvalid=NULL,int force=1,int can_return_null=0,int geom_field=0){
+    OGRErr eErr = OGR_L_GetExtentEx(self, geom_field, (OGREnvelope*)argout, force);
     if (can_return_null)
         *isvalid = (eErr == OGRERR_NONE);
     else
@@ -3550,6 +3594,9 @@ SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,in
 SWIGINTERN OGRErr OGRLayerShadow_AlterFieldDefn(OGRLayerShadow *self,int iField,OGRFieldDefnShadow *field_def,int nFlags){
     return OGR_L_AlterFieldDefn(self, iField, field_def, nFlags);
   }
+SWIGINTERN OGRErr OGRLayerShadow_CreateGeomField(OGRLayerShadow *self,OGRGeomFieldDefnShadow *field_def,int approx_ok=1){
+    return OGR_L_CreateGeomField(self, field_def, approx_ok);
+  }
 SWIGINTERN OGRErr OGRLayerShadow_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -3559,6 +3606,9 @@ SWIGINTERN OGRErr OGRLayerShadow_CommitTransaction(OGRLayerShadow *self){
 SWIGINTERN OGRErr OGRLayerShadow_RollbackTransaction(OGRLayerShadow *self){
     return OGR_L_RollbackTransaction(self);
   }
+SWIGINTERN int OGRLayerShadow_FindFieldIndex(OGRLayerShadow *self,char const *pszFieldName,int bExactMatch){
+    return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
+  }
 SWIGINTERN OSRSpatialReferenceShadow *OGRLayerShadow_GetSpatialRef(OGRLayerShadow *self){
     OGRSpatialReferenceH ref =  OGR_L_GetSpatialRef(self);
     if( ref )
@@ -3592,6 +3642,13 @@ SWIGINTERN OGRErr OGRLayerShadow_Clip(OGRLayerShadow *self,OGRLayerShadow *metho
 SWIGINTERN OGRErr OGRLayerShadow_Erase(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
   }
+SWIGINTERN OGRStyleTableShadow *OGRLayerShadow_GetStyleTable(OGRLayerShadow *self){
+    return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
+  }
+SWIGINTERN void OGRLayerShadow_SetStyleTable(OGRLayerShadow *self,OGRStyleTableShadow *table){
+    if( table != NULL )
+        OGR_L_SetStyleTable(self, (OGRStyleTableH) table);
+  }
 SWIGINTERN void delete_OGRFeatureShadow(OGRFeatureShadow *self){
     OGR_F_Destroy(self);
   }
@@ -3610,6 +3667,45 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeometryDirectly(OGRFeatureShadow *self,OG
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeometryRef(OGRFeatureShadow *self){
     return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
   }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomField(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
+    return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
+      int iField = OGR_F_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+      {
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        return OGRERR_FAILURE;
+      }
+      else
+        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
+    return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
+  }
+SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+    int i = OGR_F_GetGeomFieldIndex(self, name);
+    if (i == -1)
+    {
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      return NULL;
+    }
+    else
+      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+  }
 SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
     return (OGRFeatureShadow*) OGR_F_Clone(self);
   }
@@ -3630,6 +3726,20 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatu
 	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
+    return OGR_F_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+      return NULL;
+  }
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShadow *self,int id){
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
@@ -3694,6 +3804,9 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
       return OGR_F_GetFieldIndex(self, name);
   }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
+      return OGR_F_GetGeomFieldIndex(self, name);
+  }
 SWIGINTERN int OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
   }
@@ -3766,6 +3879,24 @@ SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList(OGRFeatureShadow *self,int i
 SWIGINTERN void OGRFeatureShadow_SetFieldStringList(OGRFeatureShadow *self,int id,char **pList){
       OGR_F_SetFieldStringList(self, id, pList);
   }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureShadow *self,int id,char const *pszValue){
+     int nBytes;
+     GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+     OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
+     CPLFree(pabyBuf);
+  }
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+      else
+      {
+        int nBytes;
+        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+        CPLFree(pabyBuf);
+      }
+  }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
     return OGR_F_SetFrom(self, other, forgiving);
   }
@@ -3797,6 +3928,35 @@ SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *
 	      OGR_F_GetFieldDefnRef( self,  i )
 	      );
   }
+
+    static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
+    {
+        switch(field_type)
+        {
+            case wkbUnknown:
+            case wkbPoint:
+            case wkbLineString:
+            case wkbPolygon:
+            case wkbMultiPoint:
+            case wkbMultiLineString:
+            case wkbMultiPolygon:
+            case wkbGeometryCollection:
+            case wkbNone:
+            /*case wkbLinearRing:*/
+            case wkbPoint25D:
+            case wkbLineString25D:
+            case wkbPolygon25D:
+            case wkbMultiPoint25D:
+            case wkbMultiLineString25D:
+            case wkbMultiPolygon25D:
+            case wkbGeometryCollection25D:
+                return TRUE;
+            default:
+                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
+                return FALSE;
+        }
+    }
+
 SWIGINTERN void delete_OGRFeatureDefnShadow(OGRFeatureDefnShadow *self){
     /*OGR_FD_Destroy(self);*/
     OGR_FD_Release( OGRFeatureDefnH(self) );
@@ -3821,11 +3981,27 @@ SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,cha
 SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
     OGR_FD_AddFieldDefn(self, defn);
   }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldCount(OGRFeatureDefnShadow *self){
+    return OGR_FD_GetGeomFieldCount(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn(OGRFeatureDefnShadow *self,int i){
+    return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
+  }
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex(OGRFeatureDefnShadow *self,char const *name){
+      return OGR_FD_GetGeomFieldIndex(self, name);
+  }
+SWIGINTERN void OGRFeatureDefnShadow_AddGeomFieldDefn(OGRFeatureDefnShadow *self,OGRGeomFieldDefnShadow *defn){
+    OGR_FD_AddGeomFieldDefn(self, defn);
+  }
+SWIGINTERN OGRErr OGRFeatureDefnShadow_DeleteGeomFieldDefn(OGRFeatureDefnShadow *self,int idx){
+    return OGR_FD_DeleteGeomFieldDefn(self, idx);
+  }
 SWIGINTERN OGRwkbGeometryType OGRFeatureDefnShadow_GetGeomType(OGRFeatureDefnShadow *self){
     return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
   }
 SWIGINTERN void OGRFeatureDefnShadow_SetGeomType(OGRFeatureDefnShadow *self,OGRwkbGeometryType geom_type){
-    OGR_FD_SetGeomType(self, geom_type);
+    if( ValidateOGRGeometryType(geom_type) )
+        OGR_FD_SetGeomType(self, geom_type);
   }
 SWIGINTERN int OGRFeatureDefnShadow_GetReferenceCount(OGRFeatureDefnShadow *self){
     return OGR_FD_GetReferenceCount(self);
@@ -3842,6 +4018,9 @@ SWIGINTERN int OGRFeatureDefnShadow_IsStyleIgnored(OGRFeatureDefnShadow *self){
 SWIGINTERN void OGRFeatureDefnShadow_SetStyleIgnored(OGRFeatureDefnShadow *self,int bIgnored){
     return OGR_FD_SetStyleIgnored(self,bIgnored);
   }
+SWIGINTERN int OGRFeatureDefnShadow_IsSame(OGRFeatureDefnShadow *self,OGRFeatureDefnShadow *other_defn){
+    return OGR_FD_IsSame(self, other_defn);
+  }
 
     static int ValidateOGRFieldType(OGRFieldType field_type)
     {
@@ -3919,6 +4098,46 @@ SWIGINTERN int OGRFieldDefnShadow_IsIgnored(OGRFieldDefnShadow *self){
 SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgnored){
     return OGR_Fld_SetIgnored( self, bIgnored );
   }
+SWIGINTERN void delete_OGRGeomFieldDefnShadow(OGRGeomFieldDefnShadow *self){
+    OGR_GFld_Destroy(self);
+  }
+SWIGINTERN OGRGeomFieldDefnShadow *new_OGRGeomFieldDefnShadow(char const *name_null_ok="",OGRwkbGeometryType field_type=wkbUnknown){
+    if( ValidateOGRGeometryType(field_type) )
+        return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
+    else
+        return NULL;
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetName(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN char const *OGRGeomFieldDefnShadow_GetNameRef(OGRGeomFieldDefnShadow *self){
+    return (const char *) OGR_GFld_GetNameRef(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetName(OGRGeomFieldDefnShadow *self,char const *name){
+    OGR_GFld_SetName(self, name);
+  }
+SWIGINTERN OGRwkbGeometryType OGRGeomFieldDefnShadow_GetType(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_GetType(self);
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetType(OGRGeomFieldDefnShadow *self,OGRwkbGeometryType type){
+    if( ValidateOGRGeometryType(type) )
+        OGR_GFld_SetType(self, type);
+  }
+SWIGINTERN OSRSpatialReferenceShadow *OGRGeomFieldDefnShadow_GetSpatialRef(OGRGeomFieldDefnShadow *self){
+    OGRSpatialReferenceH ref =  OGR_GFld_GetSpatialRef(self);
+    if( ref )
+        OSRReference(ref);
+    return (OSRSpatialReferenceShadow*) ref;
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetSpatialRef(OGRGeomFieldDefnShadow *self,OSRSpatialReferenceShadow *srs){
+     OGR_GFld_SetSpatialRef( self, (OGRSpatialReferenceH)srs );
+  }
+SWIGINTERN int OGRGeomFieldDefnShadow_IsIgnored(OGRGeomFieldDefnShadow *self){
+    return OGR_GFld_IsIgnored( self );
+  }
+SWIGINTERN void OGRGeomFieldDefnShadow_SetIgnored(OGRGeomFieldDefnShadow *self,int bIgnored){
+    OGR_GFld_SetIgnored( self, bIgnored );
+  }
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
@@ -4425,25 +4644,48 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)":new_StyleTable")) SWIG_fail;
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Driver_name_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_StyleTable",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_name_get" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_StyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDriverShadow_name_get(arg1);
+    delete_OGRStyleTableShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4451,35 +4693,87 @@ SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObj
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_StyleTable_AddStyle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  char **arg3 = (char **) 0 ;
+  char *arg3 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int bToFree2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "utf8_path",(char *) "options", NULL 
-  };
-  OGRDataSourceShadow *result = 0 ;
+  int result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Driver_CreateDataSource",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OOO:StyleTable_AddStyle",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_AddStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_AddStyle" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "StyleTable_AddStyle" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_StyleTable_LoadStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int bToFree2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:StyleTable_LoadStyleTable",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_LoadStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     /* %typemap(in) (const char *utf8_path) */
     arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
@@ -4489,57 +4783,11 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
       SWIG_fail;
     }
   }
-  if (obj2) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj2)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj2,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg3 = CSLAddString( arg3, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+    result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4547,234 +4795,38 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg3 );
-  }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg3 );
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_StyleTable_SaveStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
-  char *arg3 = (char *) 0 ;
-  char **arg4 = (char **) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int bToFree3 = 0 ;
+  int bToFree2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "copy_ds",(char *) "utf8_path",(char *) "options", NULL 
-  };
-  OGRDataSourceShadow *result = 0 ;
+  int result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:Driver_CopyDataSource",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:StyleTable_SaveStyleTable",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_SaveStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
-  {
-    /* %typemap(in) (const char *utf8_path) */
-    arg3 = GDALPythonObjectToCStr( obj2, &bToFree3 );
-    if (arg3 == NULL)
-    {
-      PyErr_SetString( PyExc_RuntimeError, "not a string" );
-      SWIG_fail;
-    }
-  }
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
-  {
-    /* %typemap(freearg) (const char *utf8_path) */
-    GDALPythonFreeCStr(arg3, bToFree3);
-  }
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  return resultobj;
-fail:
-  {
-    /* %typemap(freearg) (const char *utf8_path) */
-    GDALPythonFreeCStr(arg3, bToFree3);
-  }
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Driver_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  int arg3 = (int) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int bToFree2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "utf8_path",(char *) "update", NULL 
-  };
-  OGRDataSourceShadow *result = 0 ;
-  
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Driver_Open",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-  {
-    /* %typemap(in) (const char *utf8_path) */
-    arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
-    if (arg2 == NULL)
-    {
-      PyErr_SetString( PyExc_RuntimeError, "not a string" );
-      SWIG_fail;
-    }
-  }
-  if (obj2) {
-    ecode3 = SWIG_AsVal_int(obj2, &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver_Open" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
-  {
-    /* %typemap(freearg) (const char *utf8_path) */
-    GDALPythonFreeCStr(arg2, bToFree2);
-  }
-  return resultobj;
-fail:
-  {
-    /* %typemap(freearg) (const char *utf8_path) */
-    GDALPythonFreeCStr(arg2, bToFree2);
-  }
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Driver_DeleteDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int bToFree2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Driver_DeleteDataSource",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     /* %typemap(in) (const char *utf8_path) */
     arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
@@ -4788,7 +4840,7 @@ SWIGINTERN PyObject *_wrap_Driver_DeleteDataSource(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
+    result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4811,9 +4863,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_StyleTable_Find(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4822,29 +4874,24 @@ SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self),
   int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  bool result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Driver_TestCapability",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:StyleTable_Find",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_TestCapability" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_Find" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_TestCapability" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_Find" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
-  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
+    result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4852,7 +4899,7 @@ SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
@@ -4861,25 +4908,24 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_StyleTable_ResetStyleStringReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Driver_GetName",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:StyleTable_ResetStyleStringReading",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_ResetStyleStringReading" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDriverShadow_GetName(arg1);
+    OGRStyleTableShadow_ResetStyleStringReading(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4887,31 +4933,32 @@ SWIGINTERN PyObject *_wrap_Driver_GetName(PyObject *SWIGUNUSEDPARM(self), PyObje
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_StyleTable_GetNextStyle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Driver_Register",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:StyleTable_GetNextStyle",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetNextStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDriverShadow_Register(arg1);
+    result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4919,31 +4966,32 @@ SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObj
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_StyleTable_GetLastStyleName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Driver_Deregister",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:StyleTable_GetLastStyleName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetLastStyleName" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDriverShadow_Deregister(arg1);
+    result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4951,39 +4999,39 @@ SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyO
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *Driver_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *StyleTable_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRDriverShadow, SWIG_NewClientData(obj));
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRStyleTableShadow, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_DataSource_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_name_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:Driver_name_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_name_get" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_name_get" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDataSourceShadow_name_get(arg1);
+    result = (char *)OGRDriverShadow_name_get(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -4998,24 +5046,88 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char **arg3 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int bToFree2 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "utf8_path",(char *) "options", NULL 
+  };
+  OGRDataSourceShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_DataSource",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Driver_CreateDataSource",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_DataSource" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
+    if (arg2 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  if (obj2) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj2)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj2);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj2,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg3 = CSLAddString( arg3, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRDataSourceShadow(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5023,32 +5135,120 @@ SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyO
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int bToFree3 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "copy_ds",(char *) "utf8_path",(char *) "options", NULL 
+  };
+  OGRDataSourceShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetRefCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:Driver_CopyDataSource",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg3 = GDALPythonObjectToCStr( obj2, &bToFree3 );
+    if (arg3 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5056,32 +5256,74 @@ SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int bToFree2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "utf8_path",(char *) "update", NULL 
+  };
+  OGRDataSourceShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetSummaryRefCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Driver_Open",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetSummaryRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
+    if (arg2 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  if (obj2) {
+    ecode3 = SWIG_AsVal_int(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver_Open" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+    result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5089,65 +5331,108 @@ SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPAR
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetLayerCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_DeleteDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int bToFree2 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetLayerCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:Driver_DeleteDataSource",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+    /* %typemap(in) (const char *utf8_path) */
+    arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
+    if (arg2 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRDriverShadow *result = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetDriver",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:Driver_TestCapability",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetDriver" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_TestCapability" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_TestCapability" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+    result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5155,32 +5440,34 @@ SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetName",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:Driver_GetName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDataSourceShadow_GetName(arg1);
+    result = (char *)OGRDriverShadow_GetName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5195,34 +5482,24 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int arg2 ;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_DeleteLayer",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:Driver_Register",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_DeleteLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_DeleteLayer" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+    OGRDriverShadow_Register(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5230,48 +5507,71 @@ SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Driver_Deregister",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
   {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
+    if ( bUseExceptions ) {
+      CPLErrorReset();
     }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+    OGRDriverShadow_Deregister(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
   }
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *Driver_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRDriverShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_DataSource_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRErr result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_SyncToDisk",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_name_get",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_name_get" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+    result = (char *)OGRDataSourceShadow_name_get(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5279,136 +5579,97 @@ SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_DataSource",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_DataSource" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
+    if ( bUseExceptions ) {
+      CPLErrorReset();
     }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+    delete_OGRDataSourceShadow(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
   }
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
-  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
-  char **arg5 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
-  int val4 ;
-  int ecode4 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "name",(char *) "srs",(char *) "geom_type",(char *) "options", NULL 
-  };
-  OGRLayerShadow *result = 0 ;
+  int result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OOO:DataSource_CreateLayer",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetRefCount",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CreateLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CreateLayer" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  if (obj2) {
-    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
-    arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
-  }
-  if (obj3) {
-    ecode4 = SWIG_AsVal_int(obj3, &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "DataSource_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg4 = static_cast< OGRwkbGeometryType >(val4);
   }
-  if (obj4) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj4) || PyUnicode_Check(obj4)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj4)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj4,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg5 = CSLAddString( arg5, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg5 = CSLAddString( arg5, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg5 = CSLAddString( arg5, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetSummaryRefCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetSummaryRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+    result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5416,117 +5677,32 @@ SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg5 );
-  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg5 );
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_DataSource_GetLayerCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  char *arg3 = (char *) 0 ;
-  char **arg4 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int res3 ;
-  char *buf3 = 0 ;
-  int alloc3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "src_layer",(char *) "new_name",(char *) "options", NULL 
-  };
-  OGRLayerShadow *result = 0 ;
+  int result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:DataSource_CopyLayer",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetLayerCount",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CopyLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CopyLayer" "', argument " "3"" of type '" "char const *""'");
-  }
-  arg3 = reinterpret_cast< char * >(buf3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+    result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5534,53 +5710,32 @@ SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  int arg2 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRLayerShadow *result = 0 ;
+  OGRDriverShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O|O:DataSource_GetLayerByIndex",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetDriver",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByIndex" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetDriver" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  if (obj1) {
-    ecode2 = SWIG_AsVal_int(obj1, &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_GetLayerByIndex" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+    result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5588,42 +5743,32 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRLayerShadow *result = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_GetLayerByName",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetName",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_GetLayerByName" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+    result = (char *)OGRDataSourceShadow_GetName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5631,49 +5776,41 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(se
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  bool result;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_TestCapability",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_DeleteLayer",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_TestCapability" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_DeleteLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_TestCapability" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_DeleteLayer" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+    result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5681,21 +5818,85 @@ SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(se
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return resultobj;
-fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_SyncToDisk",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
-  char *arg4 = (char *) "" ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
+  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
+  char **arg5 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int res2 ;
@@ -5703,42 +5904,88 @@ SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self),
   int alloc2 = 0 ;
   void *argp3 = 0 ;
   int res3 = 0 ;
-  int res4 ;
-  char *buf4 = 0 ;
-  int alloc4 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
   PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
   char *  kwnames[] = {
-    (char *) "self",(char *) "statement",(char *) "spatialFilter",(char *) "dialect", NULL 
+    (char *) "self",(char *) "name",(char *) "srs",(char *) "geom_type",(char *) "options", NULL 
   };
   OGRLayerShadow *result = 0 ;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OO:DataSource_ExecuteSQL",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OOO:DataSource_CreateLayer",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ExecuteSQL" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CreateLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CreateLayer" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
   if (obj2) {
-    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
-    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+    arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
   }
   if (obj3) {
-    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DataSource_ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
+    ecode4 = SWIG_AsVal_int(obj3, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "DataSource_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
+    } 
+    arg4 = static_cast< OGRwkbGeometryType >(val4);
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj4) || PyUnicode_Check(obj4)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj4)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj4);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj4,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg5 = CSLAddString( arg5, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
     }
-    arg4 = reinterpret_cast< char * >(buf4);
   }
   {
     if (!arg2) {
@@ -5749,7 +5996,7 @@ SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5759,40 +6006,115 @@ SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self),
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
   int res2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "src_layer",(char *) "new_name",(char *) "options", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_ReleaseResultSet",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:DataSource_CopyLayer",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ReleaseResultSet" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CopyLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CopyLayer" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5800,39 +6122,53 @@ SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
   return resultobj;
 fail:
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *DataSource_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRDataSourceShadow, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  int arg2 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  PyObject * obj1 = 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetRefCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O|O:DataSource_GetLayerByIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetRefCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByIndex" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_GetLayerByIndex" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRLayerShadow_GetRefCount(arg1);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5840,40 +6176,42 @@ SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyO
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  OGRLayerShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetSpatialFilter",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_GetLayerByName",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_GetLayerByName" "', argument " "2"" of type '" "char const *""'");
   }
-  arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
+  arg2 = reinterpret_cast< char * >(buf2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilter(arg1,arg2);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5881,67 +6219,49 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  double arg2 ;
-  double arg3 ;
-  double arg4 ;
-  double arg5 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  double val3 ;
-  int ecode3 = 0 ;
-  double val4 ;
-  int ecode4 = 0 ;
-  double val5 ;
-  int ecode5 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
+  bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:Layer_SetSpatialFilterRect",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_TestCapability",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_TestCapability" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_TestCapability" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  ecode3 = SWIG_AsVal_double(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
-  } 
-  arg3 = static_cast< double >(val3);
-  ecode4 = SWIG_AsVal_double(obj3, &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
-  } 
-  arg4 = static_cast< double >(val4);
-  ecode5 = SWIG_AsVal_double(obj4, &val5);
-  if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
-  } 
-  arg5 = static_cast< double >(val5);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilterRect(arg1,arg2,arg3,arg4,arg5);
+    result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5949,32 +6269,75 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
+  char *arg4 = (char *) "" ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  int res4 ;
+  char *buf4 = 0 ;
+  int alloc4 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRGeometryShadow *result = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "statement",(char *) "spatialFilter",(char *) "dialect", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetSpatialFilter",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OO:DataSource_ExecuteSQL",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ExecuteSQL" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  if (obj2) {
+    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+  }
+  if (obj3) {
+    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DataSource_ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
+    }
+    arg4 = reinterpret_cast< char * >(buf4);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+    result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5982,42 +6345,42 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetAttributeFilter",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_ReleaseResultSet",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetAttributeFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_ReleaseResultSet" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetAttributeFilter" "', argument " "2"" of type '" "char *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
   }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+    OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6025,49 +6388,32 @@ SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  OGRStyleTableShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_ResetReading",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:DataSource_GetStyleTable",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ResetReading" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_ResetReading(arg1);
+    result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6075,32 +6421,40 @@ SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), Py
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DataSource_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
+  PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetName",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:DataSource_SetStyleTable",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetName" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetName(arg1);
+    OGRDataSourceShadow_SetStyleTable(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6108,32 +6462,39 @@ SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObjec
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *DataSource_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRDataSourceShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRwkbGeometryType result;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetGeomType",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetRefCount",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeomType" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetRefCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+    result = (int)OGRLayerShadow_GetRefCount(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6148,25 +6509,33 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
+  PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetGeometryColumn",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetSpatialFilter",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeometryColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+    OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6174,32 +6543,67 @@ SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetFIDColumn",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:Layer_SetSpatialFilterRect",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFIDColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+    OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6207,41 +6611,49 @@ SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), Py
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
+  int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  long val2 ;
+  int val2 ;
   int ecode2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRFeatureShadow *result = 0 ;
+  PyObject * obj2 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_GetFeature",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Layer_SetSpatialFilter",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_long(obj1, &val2);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeature" "', argument " "2"" of type '" "long""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "int""'");
   } 
-  arg2 = static_cast< long >(val2);
+  arg2 = static_cast< int >(val2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SetSpatialFilter" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6249,74 +6661,130 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetNextFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRFeatureShadow *result = 0 ;
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[4];
+  int ii;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetNextFeature",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetNextFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Layer_SetSpatialFilter__SWIG_0(self, args);
+      }
     }
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(argv[2], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Layer_SetSpatialFilter__SWIG_1(self, args);
+        }
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
-  return resultobj;
+  
 fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Layer_SetSpatialFilter'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetSpatialFilter(OGRLayerShadow *,OGRGeometryShadow *)\n"
+    "    SetSpatialFilter(OGRLayerShadow *,int,OGRGeometryShadow *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  double arg6 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  long val2 ;
+  int val2 ;
   int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  double val6 ;
+  int ecode6 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRErr result;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetNextByIndex",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOO:Layer_SetSpatialFilterRect",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetNextByIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_long(obj1, &val2);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetNextByIndex" "', argument " "2"" of type '" "long""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "int""'");
   } 
-  arg2 = static_cast< long >(val2);
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_double(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Layer_SetSpatialFilterRect" "', argument " "6"" of type '" "double""'");
+  } 
+  arg6 = static_cast< double >(val6);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+    OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6324,62 +6792,124 @@ SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRErr result;
+SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[7];
+  int ii;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetFeature",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 6); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
-  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  if (argc == 5) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_double(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_double(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_double(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              int res = SWIG_AsVal_double(argv[4], NULL);
+              _v = SWIG_CheckState(res);
+            }
+            if (_v) {
+              return _wrap_Layer_SetSpatialFilterRect__SWIG_0(self, args);
+            }
+          }
+        }
+      }
+    }
   }
-  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+  if (argc == 6) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_double(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_double(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              int res = SWIG_AsVal_double(argv[4], NULL);
+              _v = SWIG_CheckState(res);
+            }
+            if (_v) {
+              {
+                int res = SWIG_AsVal_double(argv[5], NULL);
+                _v = SWIG_CheckState(res);
+              }
+              if (_v) {
+                return _wrap_Layer_SetSpatialFilterRect__SWIG_1(self, args);
+              }
+            }
+          }
+        }
+      }
     }
   }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Layer_SetSpatialFilterRect'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetSpatialFilterRect(OGRLayerShadow *,double,double,double,double)\n"
+    "    SetSpatialFilterRect(OGRLayerShadow *,int,double,double,double,double)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetSpatialFilter",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+    result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6387,62 +6917,42 @@ SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_CreateFeature",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetAttributeFilter",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetAttributeFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetAttributeFilter" "', argument " "2"" of type '" "char *""'");
   }
+  arg2 = reinterpret_cast< char * >(buf2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6457,6 +6967,7 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
       SWIG_fail;
     }
   }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
@@ -6469,38 +6980,29 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
   }
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  long arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  long val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_DeleteFeature",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_ResetReading",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ResetReading" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_long(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteFeature" "', argument " "2"" of type '" "long""'");
-  } 
-  arg2 = static_cast< long >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+    OGRLayerShadow_ResetReading(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6508,48 +7010,32 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), P
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRErr result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_SyncToDisk",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetName",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SyncToDisk" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetName" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
+    result = (char *)OGRLayerShadow_GetName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6557,48 +7043,32 @@ SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyOb
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRFeatureDefnShadow *result = 0 ;
+  OGRwkbGeometryType result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetLayerDefn",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetGeomType",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetLayerDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeomType" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
+    result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6606,46 +7076,32 @@ SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), Py
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 = (int) 1 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "force", NULL 
-  };
-  int result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Layer_GetFeatureCount",kwnames,&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetGeometryColumn",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeatureCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeometryColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  if (obj1) {
-    ecode2 = SWIG_AsVal_int(obj1, &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeatureCount" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
+    result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6653,65 +7109,32 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  double *arg2 ;
-  int *arg3 = (int *) NULL ;
-  int arg4 = (int) 1 ;
-  int arg5 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  double argout2[6] ;
-  int isvalid2 ;
-  int val4 ;
-  int ecode4 = 0 ;
-  int val5 ;
-  int ecode5 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "force",(char *) "can_return_null", NULL 
-  };
+  char *result = 0 ;
   
-  {
-    /* %typemap(in) (double argout2[4], int* isvalid2) */
-    arg2 = argout2;
-    arg3 = &isvalid2;
-  }
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OO:Layer_GetExtent",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetFIDColumn",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFIDColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  if (obj1) {
-    ecode4 = SWIG_AsVal_int(obj1, &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_GetExtent" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-  }
-  if (obj2) {
-    ecode5 = SWIG_AsVal_int(obj2, &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_GetExtent" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5);
+    result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6719,59 +7142,74 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(argout) (double argout[4], int* isvalid)  */
-    PyObject *r;
-    if ( !*arg3 ) {
-      Py_INCREF(Py_None);
-      r = Py_None;
-    }
-    else {
-      r = CreateTupleFromDoubleArray(arg2, 4);
-    }
-    resultobj = t_output_helper(resultobj,r);
-  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  long arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  long val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  bool result;
+  OGRFeatureShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_TestCapability",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_GetFeature",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_TestCapability" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_TestCapability" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
+  ecode2 = SWIG_AsVal_long(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeature" "', argument " "2"" of type '" "long""'");
+  } 
+  arg2 = static_cast< long >(val2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
   }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_GetNextFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRFeatureShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetNextFeature",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetNextFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+    result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6779,62 +7217,41 @@ SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
-  int arg3 = (int) 1 ;
+  long arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
+  long val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "field_def",(char *) "approx_ok", NULL 
-  };
   OGRErr result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Layer_CreateField",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetNextByIndex",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetNextByIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateField" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
-  if (obj2) {
-    ecode3 = SWIG_AsVal_int(obj2, &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_CreateField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
+  ecode2 = SWIG_AsVal_long(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetNextByIndex" "', argument " "2"" of type '" "long""'");
+  } 
+  arg2 = static_cast< long >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+    result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6865,34 +7282,39 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_DeleteField",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetFeature",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteField" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6923,43 +7345,39 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Layer_ReorderField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_CreateFeature",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_ReorderField" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_ReorderField" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+    result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6990,47 +7408,34 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
+  long arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  long val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_ReorderFields",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_DeleteFeature",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  {
-    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
-    /* check if is List */
-    if ( !PySequence_Check(obj1) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
-      SWIG_fail;
-    }
-    arg2 = PySequence_Size(obj1);
-    arg3 = (int*) malloc(arg2*sizeof(int));
-    for( int i = 0; i<arg2; i++ ) {
-      PyObject *o = PySequence_GetItem(obj1,i);
-      if ( !PyArg_Parse(o,"i",&arg3[i]) ) {
-        PyErr_SetString(PyExc_TypeError, "not an integer");
-        Py_DECREF(o);
-        SWIG_fail;
-      }
-      Py_DECREF(o);
-    }
-  }
+  ecode2 = SWIG_AsVal_long(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteFeature" "', argument " "2"" of type '" "long""'");
+  } 
+  arg2 = static_cast< long >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+    result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7046,12 +7451,6 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
     }
   }
   {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg3) {
-      free((void*) arg3);
-    }
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -7063,67 +7462,29 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg3) {
-      free((void*) arg3);
-    }
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  int arg2 ;
-  OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
-  int arg4 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
-  int val4 ;
-  int ecode4 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:Layer_AlterFieldDefn",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_SyncToDisk",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_AlterFieldDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SyncToDisk" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_AlterFieldDefn" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_AlterFieldDefn" "', argument " "3"" of type '" "OGRFieldDefnShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRFieldDefnShadow * >(argp3);
-  ecode4 = SWIG_AsVal_int(obj3, &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_AlterFieldDefn" "', argument " "4"" of type '" "int""'");
-  } 
-  arg4 = static_cast< int >(val4);
-  {
-    if (!arg3) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+    result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7154,25 +7515,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRErr result;
+  OGRFeatureDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_StartTransaction",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetLayerDefn",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetLayerDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+    result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7180,48 +7541,46 @@ SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 = (int) 1 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRErr result;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "force", NULL 
+  };
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_CommitTransaction",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Layer_GetFeatureCount",kwnames,&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeatureCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeatureCount" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+    result = (int)OGRLayerShadow_GetFeatureCount(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7229,48 +7588,76 @@ SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  double *arg2 ;
+  int *arg3 = (int *) NULL ;
+  int arg4 = (int) 1 ;
+  int arg5 = (int) 0 ;
+  int arg6 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  double argout2[6] ;
+  int isvalid2 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRErr result;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "force",(char *) "can_return_null",(char *) "geom_field", NULL 
+  };
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_RollbackTransaction",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) (double argout2[4], int* isvalid2) */
+    arg2 = argout2;
+    arg3 = &isvalid2;
+  }
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OOO:Layer_GetExtent",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_RollbackTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  if (obj1) {
+    ecode4 = SWIG_AsVal_int(obj1, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_GetExtent" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+  }
+  if (obj2) {
+    ecode5 = SWIG_AsVal_int(obj2, &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_GetExtent" "', argument " "5"" of type '" "int""'");
+    } 
+    arg5 = static_cast< int >(val5);
+  }
+  if (obj3) {
+    ecode6 = SWIG_AsVal_int(obj3, &val6);
+    if (!SWIG_IsOK(ecode6)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Layer_GetExtent" "', argument " "6"" of type '" "int""'");
+    } 
+    arg6 = static_cast< int >(val6);
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+    OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7278,22 +7665,18 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
       }
     }
   }
+  resultobj = SWIG_Py_Void();
   {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
+    /* %typemap(argout) (double argout[4], int* isvalid)  */
+    PyObject *r;
+    if ( !*arg3 ) {
+      Py_INCREF(Py_None);
+      r = Py_None;
     }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+    else {
+      r = CreateTupleFromDoubleArray(arg2, 4);
     }
+    resultobj = t_output_helper(resultobj,r);
   }
   return resultobj;
 fail:
@@ -7301,25 +7684,40 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  OSRSpatialReferenceShadow *result = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetSpatialRef",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_TestCapability",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_TestCapability" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_TestCapability" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+    result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7327,32 +7725,62 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), P
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+  int arg3 = (int) 1 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
-  GIntBig result;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "field_def",(char *) "approx_ok", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetFeaturesRead",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Layer_CreateField",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeaturesRead" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateField" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
+  if (obj2) {
+    ecode3 = SWIG_AsVal_int(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_CreateField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRLayerShadow_GetFeaturesRead(arg1);
+    result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7360,78 +7788,57 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_NewPointerObj((new GIntBig(static_cast< const GIntBig& >(result))), SWIGTYPE_p_GIntBig, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  char **arg2 = (char **) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetIgnoredFields",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_DeleteField",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetIgnoredFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  {
-    /* %typemap(in) char **options */
-    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
-  #if PY_VERSION_HEX < 0x03000000
-      || PyString_Check(obj1)
-  #endif
-      ) {
-      PyErr_SetString(PyExc_TypeError,"not a sequence");
-      SWIG_fail;
-    }
-    
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
-      PyObject* pyObj = PySequence_GetItem(obj1,i);
-      if (PyUnicode_Check(pyObj))
-      {
-        char *pszStr;
-        Py_ssize_t nLen;
-        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-        arg2 = CSLAddString( arg2, pszStr );
-        Py_XDECREF(pyUTF8Str);
-      }
-#if PY_VERSION_HEX >= 0x03000000
-      else if (PyBytes_Check(pyObj))
-      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
-#else
-      else if (PyString_Check(pyObj))
-      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
-#endif
-      else
-      {
-        Py_DECREF(pyObj);
-        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-        SWIG_fail;
-      }
-      Py_DECREF(pyObj);
-    }
-  }
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_DeleteField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7447,10 +7854,6 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -7462,146 +7865,47 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
+  int arg2 ;
+  int arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
-  };
   OGRErr result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Intersection",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Layer_ReorderField",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Intersection" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Intersection" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Intersection" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
-      }
-      
-    }
-  }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
-    }
-  }
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_ReorderField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_ReorderField" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7617,16 +7921,6 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -7638,152 +7932,51 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
-  };
   OGRErr result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Union",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_ReorderFields",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Union" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Union" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Union" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj1) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
     }
-  }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
+    arg2 = PySequence_Size(obj1);
+    arg3 = (int*) malloc(arg2*sizeof(int));
+    for( int i = 0; i<arg2; i++ ) {
+      PyObject *o = PySequence_GetItem(obj1,i);
+      if ( !PyArg_Parse(o,"i",&arg3[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
+        SWIG_fail;
       }
-      
-    }
-  }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
+      Py_DECREF(o);
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7799,14 +7992,10 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg3) {
+      free((void*) arg3);
+    }
   }
   {
     /* %typemap(ret) OGRErr */
@@ -7821,151 +8010,143 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
   return resultobj;
 fail:
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg3) {
+      free((void*) arg3);
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
+  int arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:Layer_AlterFieldDefn",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_AlterFieldDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_AlterFieldDefn" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_AlterFieldDefn" "', argument " "3"" of type '" "OGRFieldDefnShadow *""'"); 
   }
+  arg3 = reinterpret_cast< OGRFieldDefnShadow * >(argp3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_AlterFieldDefn" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
   {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
   }
+  return resultobj;
+fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
+  OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
+  int arg3 = (int) 1 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   void *argp2 = 0 ;
   int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
   char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+    (char *) "self",(char *) "field_def",(char *) "approx_ok", NULL 
   };
   OGRErr result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_SymDifference",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Layer_CreateGeomField",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SymDifference" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateGeomField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SymDifference" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateGeomField" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SymDifference" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
-      }
-      
-    }
+  arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
+  if (obj2) {
+    ecode3 = SWIG_AsVal_int(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_CreateGeomField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
   }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7981,16 +8162,6 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -8002,152 +8173,29 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
-  };
   OGRErr result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Identity",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_StartTransaction",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Identity" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Identity" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Identity" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
-      }
-    }
-  }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
-      }
-      
-    }
-  }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8163,16 +8211,6 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -8184,152 +8222,78 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
-  };
   OGRErr result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Update",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_CommitTransaction",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Update" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Update" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Update" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
-      }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
-      }
-      
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
     }
   }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_RollbackTransaction",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_RollbackTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8345,16 +8309,6 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
     }
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
-  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -8366,152 +8320,195 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
   }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_FindFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-  char **arg4 = (char **) NULL ;
-  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-  void *arg6 = (void *) NULL ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
-  };
-  OGRErr result;
+  int result;
   
-  /* %typemap(arginit) ( const char* callback_data=NULL)  */
-  PyProgressData *psProgressInfo;
-  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
-  psProgressInfo->nLastReported = -1;
-  psProgressInfo->psPyCallback = NULL;
-  psProgressInfo->psPyCallbackData = NULL;
-  arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Clip",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Layer_FindFieldIndex",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Clip" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_FindFieldIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Clip" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_FindFieldIndex" "', argument " "2"" of type '" "char const *""'");
   }
-  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Clip" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-  }
-  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-  if (obj3) {
-    {
-      /* %typemap(in) char **options */
-      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
-  #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj3)
-  #endif
-        ) {
-        PyErr_SetString(PyExc_TypeError,"not a sequence");
-        SWIG_fail;
+  arg2 = reinterpret_cast< char * >(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_FindFieldIndex" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
-      
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj3,i);
-        if (PyUnicode_Check(pyObj))
-        {
-          char *pszStr;
-          Py_ssize_t nLen;
-          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-          arg4 = CSLAddString( arg4, pszStr );
-          Py_XDECREF(pyUTF8Str);
-        }
-#if PY_VERSION_HEX >= 0x03000000
-        else if (PyBytes_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
-#else
-        else if (PyString_Check(pyObj))
-        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
-#endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        Py_DECREF(pyObj);
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OSRSpatialReferenceShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetSpatialRef",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  if (obj4) {
-    {
-      /* %typemap(in) (GDALProgressFunc callback = NULL) */
-      /* callback_func typemap */
-      if (obj4 && obj4 != Py_None ) {
-        void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
-        
-        if ( cbfunction == GDALTermProgress ) {
-          arg5 = GDALTermProgress;
-        } else {
-          if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
-              "Object given is not a Python function" );
-            SWIG_fail;
-          }
-          psProgressInfo->psPyCallback = obj4;
-          arg5 = PyProgressProxy;
-        }
-        
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  GIntBig result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetFeaturesRead",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeaturesRead" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = OGRLayerShadow_GetFeaturesRead(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
-      
     }
   }
-  if (obj5) {
-    {
-      /* %typemap(in) ( void* callback_data=NULL)  */
-      psProgressInfo->psPyCallbackData = obj5 ;
+  resultobj = SWIG_NewPointerObj((new GIntBig(static_cast< const GIntBig& >(result))), SWIGTYPE_p_GIntBig, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetIgnoredFields",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetIgnoredFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj1)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    int size = PySequence_Size(obj1);
+    for (int i = 0; i < size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj1,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg2 = CSLAddString( arg2, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8528,13 +8525,7 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
+    CSLDestroy( arg2 );
   }
   {
     /* %typemap(ret) OGRErr */
@@ -8550,19 +8541,13 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
 fail:
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg4 );
-  }
-  {
-    /* %typemap(freearg) ( void* callback_data=NULL)  */
-    
-    CPLFree(psProgressInfo);
-    
+    CSLDestroy( arg2 );
   }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
@@ -8594,20 +8579,20 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
   psProgressInfo->psPyCallback = NULL;
   psProgressInfo->psPyCallbackData = NULL;
   arg6 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Erase",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Intersection",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Erase" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Intersection" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Erase" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Intersection" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
   }
   arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
   res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Erase" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Intersection" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
   }
   arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
   if (obj3) {
@@ -8693,7 +8678,7 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+    result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8744,147 +8729,138 @@ fail:
 }
 
 
-SWIGINTERN PyObject *Layer_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRLayerShadow, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *_wrap_delete_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_Feature",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_DISOWN |  0 );
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Union",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Feature" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    delete_OGRFeatureShadow(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Union" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  char *  kwnames[] = {
-    (char *) "feature_def", NULL 
-  };
-  OGRFeatureShadow *result = 0 ;
-  
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:new_Feature",kwnames,&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Feature" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Union" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  {
-    if (!arg1) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Union" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
   }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetDefnRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRFeatureDefnShadow *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetDefnRef",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
       }
+      
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRErr result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetGeometry",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometry" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
   }
-  arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8900,6 +8876,16 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
     }
   }
   {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -8911,85 +8897,152 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
   }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  void *argp2 = 0 ;
   int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetGeometryDirectly",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_SymDifference",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometryDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SymDifference" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SymDifference" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
   }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SymDifference" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
     }
   }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
     }
   }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRGeometryShadow *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetGeometryRef",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeometryRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+    result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -8997,154 +9050,181 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRFeatureShadow *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_Clone",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Clone" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_Equal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  bool result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_Equal",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Equal" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_Equal" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
     }
-    result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
   return resultobj;
 fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetFieldCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (int)OGRFeatureShadow_GetFieldCount(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
-fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRFieldDefnShadow *result = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldDefnRef",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Identity",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Identity" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Identity" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Identity" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9152,139 +9232,181 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDP
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRFieldDefnShadow *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldDefnRef",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "char const *""'");
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
     }
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
-  
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_GetFieldDefnRef__SWIG_0(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_GetFieldDefnRef__SWIG_1(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldDefnRef'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GetFieldDefnRef(OGRFeatureShadow *,int)\n"
-    "    GetFieldDefnRef(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char *result = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsString",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Update",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Update" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Update" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Update" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9292,139 +9414,181 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSED
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  char *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsString",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "char const *""'");
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
     }
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
-  
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_GetFieldAsString__SWIG_0(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_GetFieldAsString__SWIG_1(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsString'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsString(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsString(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  int result;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Clip",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Clip" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Clip" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Clip" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9432,139 +9596,181 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSE
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "char const *""'");
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
     }
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
-  
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_GetFieldAsInteger__SWIG_0(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_GetFieldAsInteger__SWIG_1(self, args);
-      }
-    }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsInteger'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsInteger(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsInteger(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  char **arg4 = (char **) NULL ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  double result;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "method_layer",(char *) "result_layer",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDouble",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|OOO:Layer_Erase",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Erase" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Erase" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Erase" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      int size = PySequence_Size(obj3);
+      for (int i = 0; i < size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj4 && obj4 != Py_None ) {
+        void* cbfunction = NULL;
+        SWIG_ConvertPtr( obj4, 
+          (void**)&cbfunction,
+          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+          SWIG_POINTER_EXCEPTION | 0 );
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj4)) {
+            PyErr_SetString( PyExc_RuntimeError, 
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj4;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj5 ;
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+    result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9572,47 +9778,68 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSED
       }
     }
   }
-  resultobj = SWIG_From_double(static_cast< double >(result));
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  double result;
+  OGRStyleTableShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDouble",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetStyleTable",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+    result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9620,118 +9847,79 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSED
       }
     }
   }
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+SWIGINTERN PyObject *_wrap_Layer_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  if (!PyArg_ParseTuple(args,(char *)"OO:Layer_SetStyleTable",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_GetFieldAsDouble__SWIG_0(self, args);
-      }
-    }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_GetFieldAsDouble__SWIG_1(self, args);
+  arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRLayerShadow_SetStyleTable(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  
+  resultobj = SWIG_Py_Void();
+  return resultobj;
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsDouble'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsDouble(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsDouble(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *Layer_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRLayerShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_delete_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
-  int *arg4 = (int *) 0 ;
-  int *arg5 = (int *) 0 ;
-  int *arg6 = (int *) 0 ;
-  int *arg7 = (int *) 0 ;
-  int *arg8 = (int *) 0 ;
-  int *arg9 = (int *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int temp3 ;
-  int res3 = SWIG_TMPOBJ ;
-  int temp4 ;
-  int res4 = SWIG_TMPOBJ ;
-  int temp5 ;
-  int res5 = SWIG_TMPOBJ ;
-  int temp6 ;
-  int res6 = SWIG_TMPOBJ ;
-  int temp7 ;
-  int res7 = SWIG_TMPOBJ ;
-  int temp8 ;
-  int res8 = SWIG_TMPOBJ ;
-  int temp9 ;
-  int res9 = SWIG_TMPOBJ ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
   
-  arg3 = &temp3;
-  arg4 = &temp4;
-  arg5 = &temp5;
-  arg6 = &temp6;
-  arg7 = &temp7;
-  arg8 = &temp8;
-  arg9 = &temp9;
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDateTime",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_Feature",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Feature" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    delete_OGRFeatureShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9740,90 +9928,39 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *SWIGUNUSEDPARM(s
     }
   }
   resultobj = SWIG_Py_Void();
-  if (SWIG_IsTmpObj(res3)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res4)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res5)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg5)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res6)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg6)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res7)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg7)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res8)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg8)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_int, new_flags));
-  }
-  if (SWIG_IsTmpObj(res9)) {
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg9)));
-  } else {
-    int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
-    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags));
-  }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
-  int **arg4 = (int **) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int nLen3 ;
-  int *pList3 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "feature_def", NULL 
+  };
+  OGRFeatureShadow *result = 0 ;
   
-  {
-    /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) (int nLen3, int *pList3) */
-    arg3 = &nLen3;
-    arg4 = &pList3;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsIntegerList",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:new_Feature",kwnames,&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Feature" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
+    result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9831,59 +9968,32 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *SWIGUNUSEDPAR
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(argout) (int *nLen, const int **pList ) */
-    Py_DECREF(resultobj);
-    PyObject *out = PyList_New( *arg3 );
-    for( int i=0; i<*arg3; i++ ) {
-      PyObject *val = PyInt_FromLong( (*arg4)[i] );
-      PyList_SetItem( out, i, val );
-    }
-    resultobj = out;
-  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_NEW |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetDefnRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
-  double **arg4 = (double **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int nLen3 ;
-  double *pList3 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  OGRFeatureDefnShadow *result = 0 ;
   
-  {
-    /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) (int nLen3, double *pList3) */
-    arg3 = &nLen3;
-    arg4 = &pList3;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDoubleList",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetDefnRef",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
+    result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9891,51 +10001,41 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *SWIGUNUSEDPARM
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(argout) (int *nLen, const double **pList ) */
-    Py_DECREF(resultobj);
-    PyObject *out = PyList_New( *arg3 );
-    for( int i=0; i<*arg3; i++ ) {
-      PyObject *val = PyFloat_FromDouble( (*arg4)[i] );
-      PyList_SetItem( out, i, val );
-    }
-    resultobj = out;
-  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char **result = 0 ;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsStringList",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetGeometry",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometry" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -9944,19 +10044,20 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM
     }
   }
   {
-    /* %typemap(out) char **options -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
     }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
     }
   }
   return resultobj;
@@ -9965,34 +10066,32 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  bool result;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSet",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetGeometryDirectly",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometryDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  res2 = SWIG_ConvertPtr(obj1, SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+    result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10000,47 +10099,48 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  bool result;
+  OGRGeometryShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSet",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetGeometryRef",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeometryRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10048,87 +10148,113 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_IsFieldSet(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  OGRErr result;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetGeomField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_IsFieldSet__SWIG_0(self, args);
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_IsFieldSet__SWIG_1(self, args);
-      }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
     }
   }
-  
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_IsFieldSet'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    IsFieldSet(OGRFeatureShadow *,int)\n"
-    "    IsFieldSet(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  int result;
+  PyObject * obj2 = 0 ;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldIndex",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetGeomField",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeomField" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10138,7 +10264,7 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10146,8 +10272,24 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10155,67 +10297,99 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  int result;
+SWIGINTERN PyObject *_wrap_Feature_SetGeomField(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[4];
+  int ii;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetFID",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(argv[2], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetGeomField__SWIG_0(self, args);
+        }
+      }
     }
-    result = (int)OGRFeatureShadow_GetFID(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(argv[2], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetGeomField__SWIG_1(self, args);
+        }
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
+  
 fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetGeomField'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetGeomField(OGRFeatureShadow *,int,OGRGeometryShadow *)\n"
+    "    SetGeomField(OGRFeatureShadow *,char const *,OGRGeometryShadow *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetFID",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetGeomFieldDirectly",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFID" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
+  res3 = SWIG_ConvertPtr(obj2, SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10246,24 +10420,47 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_DumpReadable",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetGeomFieldDirectly",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_ConvertPtr(obj2, SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_DumpReadable(arg1);
+    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10271,14 +10468,90 @@ SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  return resultobj;
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[4];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(argv[2], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetGeomFieldDirectly__SWIG_0(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(argv[2], &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetGeomFieldDirectly__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetGeomFieldDirectly'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetGeomFieldDirectly(OGRFeatureShadow *,int,OGRGeometryShadow *)\n"
+    "    SetGeomFieldDirectly(OGRFeatureShadow *,char const *,OGRGeometryShadow *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
@@ -10288,23 +10561,24 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(s
   int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  OGRGeometryShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_UnsetField",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetGeomFieldRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_UnsetField" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldRef" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10312,14 +10586,14 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
@@ -10330,16 +10604,17 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(s
   int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  OGRGeometryShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_UnsetField",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetGeomFieldRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_UnsetField" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetGeomFieldRef" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
@@ -10351,7 +10626,7 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10359,7 +10634,7 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
@@ -10368,7 +10643,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef(PyObject *self, PyObject *args) {
   int argc;
   PyObject *argv[3];
   int ii;
@@ -10389,7 +10664,7 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
         _v = SWIG_CheckState(res);
       }
       if (_v) {
-        return _wrap_Feature_UnsetField__SWIG_0(self, args);
+        return _wrap_Feature_GetGeomFieldRef__SWIG_0(self, args);
       }
     }
   }
@@ -10402,61 +10677,39 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
       int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
       _v = SWIG_CheckState(res);
       if (_v) {
-        return _wrap_Feature_UnsetField__SWIG_1(self, args);
+        return _wrap_Feature_GetGeomFieldRef__SWIG_1(self, args);
       }
     }
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_UnsetField'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetGeomFieldRef'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    UnsetField(OGRFeatureShadow *,int)\n"
-    "    UnsetField(OGRFeatureShadow *,char const *)\n");
+    "    GetGeomFieldRef(OGRFeatureShadow *,int)\n"
+    "    GetGeomFieldRef(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  char *arg3 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  PyObject *str3 = 0 ;
-  int bToFree3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRFeatureShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_Clone",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Clone" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  {
-    /* %typemap(in) (tostring argin) */
-    str3 = PyObject_Str( obj2 );
-    if ( str3 == 0 ) {
-      PyErr_SetString( PyExc_RuntimeError, "Unable to format argument as string");
-      SWIG_fail;
-    }
-    
-    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+    result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10464,66 +10717,36 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(freearg) (tostring argin) */
-    if ( str3 != NULL)
-    {
-      Py_DECREF(str3);
-    }
-    GDALPythonFreeCStr(arg3, bToFree3);
-  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) (tostring argin) */
-    if ( str3 != NULL)
-    {
-      Py_DECREF(str3);
-    }
-    GDALPythonFreeCStr(arg3, bToFree3);
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_Equal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char *arg3 = (char *) 0 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject *str3 = 0 ;
-  int bToFree3 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_Equal",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Equal" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    /* %typemap(in) (tostring argin) */
-    str3 = PyObject_Str( obj2 );
-    if ( str3 == 0 ) {
-      PyErr_SetString( PyExc_RuntimeError, "Unable to format argument as string");
-      SWIG_fail;
-    }
-    
-    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_Equal" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
   }
+  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10533,7 +10756,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10541,67 +10764,74 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(freearg) (tostring argin) */
-    if ( str3 != NULL)
-    {
-      Py_DECREF(str3);
-    }
-    GDALPythonFreeCStr(arg3, bToFree3);
-  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetFieldCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   {
-    /* %typemap(freearg) (tostring argin) */
-    if ( str3 != NULL)
-    {
-      Py_DECREF(str3);
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
-    GDALPythonFreeCStr(arg3, bToFree3);
   }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  int arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldDefnRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10609,45 +10839,37 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  int arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldDefnRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10657,7 +10879,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10665,7 +10887,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
@@ -10674,42 +10896,115 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetFieldDefnRef__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetFieldDefnRef__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldDefnRef'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetFieldDefnRef(OGRFeatureShadow *,int)\n"
+    "    GetFieldDefnRef(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetGeomFieldCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  double val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetGeomFieldDefnRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_double(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "double""'");
-  } 
-  arg3 = static_cast< double >(val3);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3);
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10717,45 +11012,37 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  double arg3 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
-  double val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetGeomFieldDefnRef",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
-  ecode3 = SWIG_AsVal_double(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "double""'");
-  } 
-  arg3 = static_cast< double >(val3);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10765,7 +11052,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3);
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10773,7 +11060,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
@@ -10782,96 +11069,82 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetGeomFieldDefnRef__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetGeomFieldDefnRef__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetGeomFieldDefnRef'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetGeomFieldDefnRef(OGRFeatureShadow *,int)\n"
+    "    GetGeomFieldDefnRef(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
-  int arg6 ;
-  int arg7 ;
-  int arg8 ;
-  int arg9 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  int val4 ;
-  int ecode4 = 0 ;
-  int val5 ;
-  int ecode5 = 0 ;
-  int val6 ;
-  int ecode6 = 0 ;
-  int val7 ;
-  int ecode7 = 0 ;
-  int val8 ;
-  int ecode8 = 0 ;
-  int val9 ;
-  int ecode9 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  PyObject * obj6 = 0 ;
-  PyObject * obj7 = 0 ;
-  PyObject * obj8 = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:Feature_SetField",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsString",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
-  ecode4 = SWIG_AsVal_int(obj3, &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature_SetField" "', argument " "4"" of type '" "int""'");
-  } 
-  arg4 = static_cast< int >(val4);
-  ecode5 = SWIG_AsVal_int(obj4, &val5);
-  if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature_SetField" "', argument " "5"" of type '" "int""'");
-  } 
-  arg5 = static_cast< int >(val5);
-  ecode6 = SWIG_AsVal_int(obj5, &val6);
-  if (!SWIG_IsOK(ecode6)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature_SetField" "', argument " "6"" of type '" "int""'");
-  } 
-  arg6 = static_cast< int >(val6);
-  ecode7 = SWIG_AsVal_int(obj6, &val7);
-  if (!SWIG_IsOK(ecode7)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature_SetField" "', argument " "7"" of type '" "int""'");
-  } 
-  arg7 = static_cast< int >(val7);
-  ecode8 = SWIG_AsVal_int(obj7, &val8);
-  if (!SWIG_IsOK(ecode8)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature_SetField" "', argument " "8"" of type '" "int""'");
-  } 
-  arg8 = static_cast< int >(val8);
-  ecode9 = SWIG_AsVal_int(obj8, &val9);
-  if (!SWIG_IsOK(ecode9)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature_SetField" "', argument " "9"" of type '" "int""'");
-  } 
-  arg9 = static_cast< int >(val9);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_6(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10879,99 +11152,37 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_6(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
-  int arg6 ;
-  int arg7 ;
-  int arg8 ;
-  int arg9 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  int val4 ;
-  int ecode4 = 0 ;
-  int val5 ;
-  int ecode5 = 0 ;
-  int val6 ;
-  int ecode6 = 0 ;
-  int val7 ;
-  int ecode7 = 0 ;
-  int val8 ;
-  int ecode8 = 0 ;
-  int val9 ;
-  int ecode9 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  PyObject * obj4 = 0 ;
-  PyObject * obj5 = 0 ;
-  PyObject * obj6 = 0 ;
-  PyObject * obj7 = 0 ;
-  PyObject * obj8 = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:Feature_SetField",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsString",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "char const *""'");
   }
   arg2 = reinterpret_cast< char * >(buf2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
-  ecode4 = SWIG_AsVal_int(obj3, &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature_SetField" "', argument " "4"" of type '" "int""'");
-  } 
-  arg4 = static_cast< int >(val4);
-  ecode5 = SWIG_AsVal_int(obj4, &val5);
-  if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature_SetField" "', argument " "5"" of type '" "int""'");
-  } 
-  arg5 = static_cast< int >(val5);
-  ecode6 = SWIG_AsVal_int(obj5, &val6);
-  if (!SWIG_IsOK(ecode6)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature_SetField" "', argument " "6"" of type '" "int""'");
-  } 
-  arg6 = static_cast< int >(val6);
-  ecode7 = SWIG_AsVal_int(obj6, &val7);
-  if (!SWIG_IsOK(ecode7)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature_SetField" "', argument " "7"" of type '" "int""'");
-  } 
-  arg7 = static_cast< int >(val7);
-  ecode8 = SWIG_AsVal_int(obj7, &val8);
-  if (!SWIG_IsOK(ecode8)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature_SetField" "', argument " "8"" of type '" "int""'");
-  } 
-  arg8 = static_cast< int >(val8);
-  ecode9 = SWIG_AsVal_int(obj8, &val9);
-  if (!SWIG_IsOK(ecode9)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature_SetField" "', argument " "9"" of type '" "int""'");
-  } 
-  arg9 = static_cast< int >(val9);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10981,7 +11192,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_7(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_7(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -10989,7 +11200,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_7(PyObject *SWIGUNUSEDPARM(sel
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
@@ -10998,17 +11209,17 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString(PyObject *self, PyObject *args) {
   int argc;
-  PyObject *argv[10];
+  PyObject *argv[3];
   int ii;
   
   if (!PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 9); ii++) {
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
-  if (argc == 3) {
+  if (argc == 2) {
     int _v;
     void *vptr = 0;
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
@@ -11019,95 +11230,151 @@ SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
         _v = SWIG_CheckState(res);
       }
       if (_v) {
-        {
-          int res = SWIG_AsVal_int(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_2(self, args);
-        }
+        return _wrap_Feature_GetFieldAsString__SWIG_0(self, args);
       }
     }
   }
-  if (argc == 3) {
+  if (argc == 2) {
     int _v;
     void *vptr = 0;
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
       if (_v) {
-        {
-          int res = SWIG_AsVal_double(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_4(self, args);
-        }
+        return _wrap_Feature_GetFieldAsString__SWIG_1(self, args);
       }
     }
   }
-  if (argc == 3) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_0(self, args);
-        }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsString'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetFieldAsString(OGRFeatureShadow *,int)\n"
+    "    GetFieldAsString(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  if (argc == 3) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        {
-          int res = SWIG_AsVal_int(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_3(self, args);
-        }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  if (argc == 3) {
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
     int _v;
     void *vptr = 0;
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
       if (_v) {
-        {
-          int res = SWIG_AsVal_double(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_5(self, args);
-        }
+        return _wrap_Feature_GetFieldAsInteger__SWIG_0(self, args);
       }
     }
   }
-  if (argc == 3) {
+  if (argc == 2) {
     int _v;
     void *vptr = 0;
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
@@ -11116,72 +11383,138 @@ SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
       int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
       _v = SWIG_CheckState(res);
       if (_v) {
-        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-        if (_v) {
-          return _wrap_Feature_SetField__SWIG_1(self, args);
-        }
+        return _wrap_Feature_GetFieldAsInteger__SWIG_1(self, args);
       }
     }
   }
-  if (argc == 9) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsInteger'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetFieldAsInteger(OGRFeatureShadow *,int)\n"
+    "    GetFieldAsInteger(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  double result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDouble",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  double result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDouble",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
         _v = SWIG_CheckState(res);
       }
       if (_v) {
-        {
-          int res = SWIG_AsVal_int(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          {
-            int res = SWIG_AsVal_int(argv[3], NULL);
-            _v = SWIG_CheckState(res);
-          }
-          if (_v) {
-            {
-              int res = SWIG_AsVal_int(argv[4], NULL);
-              _v = SWIG_CheckState(res);
-            }
-            if (_v) {
-              {
-                int res = SWIG_AsVal_int(argv[5], NULL);
-                _v = SWIG_CheckState(res);
-              }
-              if (_v) {
-                {
-                  int res = SWIG_AsVal_int(argv[6], NULL);
-                  _v = SWIG_CheckState(res);
-                }
-                if (_v) {
-                  {
-                    int res = SWIG_AsVal_int(argv[7], NULL);
-                    _v = SWIG_CheckState(res);
-                  }
-                  if (_v) {
-                    {
-                      int res = SWIG_AsVal_int(argv[8], NULL);
-                      _v = SWIG_CheckState(res);
-                    }
-                    if (_v) {
-                      return _wrap_Feature_SetField__SWIG_6(self, args);
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
+        return _wrap_Feature_GetFieldAsDouble__SWIG_0(self, args);
       }
     }
   }
-  if (argc == 9) {
+  if (argc == 2) {
     int _v;
     void *vptr = 0;
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
@@ -11190,117 +11523,2763 @@ SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
       int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
       _v = SWIG_CheckState(res);
       if (_v) {
-        {
-          int res = SWIG_AsVal_int(argv[2], NULL);
-          _v = SWIG_CheckState(res);
-        }
-        if (_v) {
-          {
-            int res = SWIG_AsVal_int(argv[3], NULL);
-            _v = SWIG_CheckState(res);
-          }
-          if (_v) {
-            {
-              int res = SWIG_AsVal_int(argv[4], NULL);
-              _v = SWIG_CheckState(res);
-            }
-            if (_v) {
-              {
-                int res = SWIG_AsVal_int(argv[5], NULL);
-                _v = SWIG_CheckState(res);
-              }
-              if (_v) {
-                {
-                  int res = SWIG_AsVal_int(argv[6], NULL);
-                  _v = SWIG_CheckState(res);
-                }
-                if (_v) {
-                  {
-                    int res = SWIG_AsVal_int(argv[7], NULL);
-                    _v = SWIG_CheckState(res);
-                  }
-                  if (_v) {
-                    {
-                      int res = SWIG_AsVal_int(argv[8], NULL);
-                      _v = SWIG_CheckState(res);
-                    }
-                    if (_v) {
-                      return _wrap_Feature_SetField__SWIG_7(self, args);
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
+        return _wrap_Feature_GetFieldAsDouble__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsDouble'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetFieldAsDouble(OGRFeatureShadow *,int)\n"
+    "    GetFieldAsDouble(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  int *arg7 = (int *) 0 ;
+  int *arg8 = (int *) 0 ;
+  int *arg9 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int temp3 ;
+  int res3 = SWIG_TMPOBJ ;
+  int temp4 ;
+  int res4 = SWIG_TMPOBJ ;
+  int temp5 ;
+  int res5 = SWIG_TMPOBJ ;
+  int temp6 ;
+  int res6 = SWIG_TMPOBJ ;
+  int temp7 ;
+  int res7 = SWIG_TMPOBJ ;
+  int temp8 ;
+  int res8 = SWIG_TMPOBJ ;
+  int temp9 ;
+  int res9 = SWIG_TMPOBJ ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  arg3 = &temp3;
+  arg4 = &temp4;
+  arg5 = &temp5;
+  arg6 = &temp6;
+  arg7 = &temp7;
+  arg8 = &temp8;
+  arg9 = &temp9;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDateTime",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (SWIG_IsTmpObj(res3)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res4)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res5)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg5)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res6)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg6)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res7)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg7)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res8)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg8)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_int, new_flags));
+  }
+  if (SWIG_IsTmpObj(res9)) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg9)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags));
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  int **arg4 = (int **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int nLen3 ;
+  int *pList3 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) (int nLen3, int *pList3) */
+    arg3 = &nLen3;
+    arg4 = &pList3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsIntegerList",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (int *nLen, const int **pList ) */
+    Py_DECREF(resultobj);
+    PyObject *out = PyList_New( *arg3 );
+    for( int i=0; i<*arg3; i++ ) {
+      PyObject *val = PyInt_FromLong( (*arg4)[i] );
+      PyList_SetItem( out, i, val );
+    }
+    resultobj = out;
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  double **arg4 = (double **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int nLen3 ;
+  double *pList3 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) (int nLen3, double *pList3) */
+    arg3 = &nLen3;
+    arg4 = &pList3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDoubleList",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (int *nLen, const double **pList ) */
+    Py_DECREF(resultobj);
+    PyObject *out = PyList_New( *arg3 );
+    for( int i=0; i<*arg3; i++ ) {
+      PyObject *val = PyFloat_FromDouble( (*arg4)[i] );
+      PyList_SetItem( out, i, val );
+    }
+    resultobj = out;
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsStringList",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) char **options -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSet",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSet",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSet(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_IsFieldSet__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_IsFieldSet__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_IsFieldSet'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    IsFieldSet(OGRFeatureShadow *,int)\n"
+    "    IsFieldSet(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetGeomFieldIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetGeomFieldIndex" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetFID",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureShadow_GetFID(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetFID",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFID" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_DumpReadable",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_DumpReadable(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_UnsetField",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_UnsetField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_UnsetField",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_UnsetField" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_UnsetField__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_UnsetField__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_UnsetField'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    UnsetField(OGRFeatureShadow *,int)\n"
+    "    UnsetField(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject *str3 = 0 ;
+  int bToFree3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    /* %typemap(in) (tostring argin) */
+    str3 = PyObject_Str( obj2 );
+    if ( str3 == 0 ) {
+      PyErr_SetString( PyExc_RuntimeError, "Unable to format argument as string");
+      SWIG_fail;
+    }
+    
+    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(freearg) (tostring argin) */
+    if ( str3 != NULL)
+    {
+      Py_DECREF(str3);
+    }
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (tostring argin) */
+    if ( str3 != NULL)
+    {
+      Py_DECREF(str3);
+    }
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject *str3 = 0 ;
+  int bToFree3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    /* %typemap(in) (tostring argin) */
+    str3 = PyObject_Str( obj2 );
+    if ( str3 == 0 ) {
+      PyErr_SetString( PyExc_RuntimeError, "Unable to format argument as string");
+      SWIG_fail;
+    }
+    
+    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) (tostring argin) */
+    if ( str3 != NULL)
+    {
+      Py_DECREF(str3);
+    }
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) (tostring argin) */
+    if ( str3 != NULL)
+    {
+      Py_DECREF(str3);
+    }
+    GDALPythonFreeCStr(arg3, bToFree3);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  double arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  double arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetField",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  int arg9 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  int val8 ;
+  int ecode8 = 0 ;
+  int val9 ;
+  int ecode9 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:Feature_SetField",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature_SetField" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature_SetField" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature_SetField" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature_SetField" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature_SetField" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature_SetField" "', argument " "9"" of type '" "int""'");
+  } 
+  arg9 = static_cast< int >(val9);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_6(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 ;
+  int arg7 ;
+  int arg8 ;
+  int arg9 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  int val8 ;
+  int ecode8 = 0 ;
+  int val9 ;
+  int ecode9 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:Feature_SetField",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetField" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetField" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature_SetField" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature_SetField" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature_SetField" "', argument " "6"" of type '" "int""'");
+  } 
+  arg6 = static_cast< int >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature_SetField" "', argument " "7"" of type '" "int""'");
+  } 
+  arg7 = static_cast< int >(val7);
+  ecode8 = SWIG_AsVal_int(obj7, &val8);
+  if (!SWIG_IsOK(ecode8)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature_SetField" "', argument " "8"" of type '" "int""'");
+  } 
+  arg8 = static_cast< int >(val8);
+  ecode9 = SWIG_AsVal_int(obj8, &val9);
+  if (!SWIG_IsOK(ecode9)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature_SetField" "', argument " "9"" of type '" "int""'");
+  } 
+  arg9 = static_cast< int >(val9);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetField__SWIG_7(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[10];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 9); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_2(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_double(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_4(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_0(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_3(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        {
+          int res = SWIG_AsVal_double(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_5(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetField__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              int res = SWIG_AsVal_int(argv[4], NULL);
+              _v = SWIG_CheckState(res);
+            }
+            if (_v) {
+              {
+                int res = SWIG_AsVal_int(argv[5], NULL);
+                _v = SWIG_CheckState(res);
+              }
+              if (_v) {
+                {
+                  int res = SWIG_AsVal_int(argv[6], NULL);
+                  _v = SWIG_CheckState(res);
+                }
+                if (_v) {
+                  {
+                    int res = SWIG_AsVal_int(argv[7], NULL);
+                    _v = SWIG_CheckState(res);
+                  }
+                  if (_v) {
+                    {
+                      int res = SWIG_AsVal_int(argv[8], NULL);
+                      _v = SWIG_CheckState(res);
+                    }
+                    if (_v) {
+                      return _wrap_Feature_SetField__SWIG_6(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              int res = SWIG_AsVal_int(argv[4], NULL);
+              _v = SWIG_CheckState(res);
+            }
+            if (_v) {
+              {
+                int res = SWIG_AsVal_int(argv[5], NULL);
+                _v = SWIG_CheckState(res);
+              }
+              if (_v) {
+                {
+                  int res = SWIG_AsVal_int(argv[6], NULL);
+                  _v = SWIG_CheckState(res);
+                }
+                if (_v) {
+                  {
+                    int res = SWIG_AsVal_int(argv[7], NULL);
+                    _v = SWIG_CheckState(res);
+                  }
+                  if (_v) {
+                    {
+                      int res = SWIG_AsVal_int(argv[8], NULL);
+                      _v = SWIG_CheckState(res);
+                    }
+                    if (_v) {
+                      return _wrap_Feature_SetField__SWIG_7(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetField'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetField(OGRFeatureShadow *,int,char const *)\n"
+    "    SetField(OGRFeatureShadow *,char const *,char const *)\n"
+    "    SetField(OGRFeatureShadow *,int,int)\n"
+    "    SetField(OGRFeatureShadow *,char const *,int)\n"
+    "    SetField(OGRFeatureShadow *,int,double)\n"
+    "    SetField(OGRFeatureShadow *,char const *,double)\n"
+    "    SetField(OGRFeatureShadow *,int,int,int,int,int,int,int,int)\n"
+    "    SetField(OGRFeatureShadow *,char const *,int,int,int,int,int,int,int)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int *arg4 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldIntegerList",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj2) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    arg3 = PySequence_Size(obj2);
+    arg4 = (int*) malloc(arg3*sizeof(int));
+    for( int i = 0; i<arg3; i++ ) {
+      PyObject *o = PySequence_GetItem(obj2,i);
+      if ( !PyArg_Parse(o,"i",&arg4[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      Py_DECREF(o);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg4) {
+      free((void*) arg4);
+    }
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg4) {
+      free((void*) arg4);
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  double *arg4 = (double *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldDoubleList",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    /* %typemap(in,numinputs=1) (int nList, double* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj2) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    arg3 = PySequence_Size(obj2);
+    arg4 = (double*) malloc(arg3*sizeof(double));
+    for( int i = 0; i<arg3; i++ ) {
+      PyObject *o = PySequence_GetItem(obj2,i);
+      if ( !PyArg_Parse(o,"d",&arg4[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not a number");
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      Py_DECREF(o);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(freearg) (int nList, double* pList) */
+    if (arg4) {
+      free((void*) arg4);
+    }
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, double* pList) */
+    if (arg4) {
+      free((void*) arg4);
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  char **arg3 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldStringList",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj2)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    int size = PySequence_Size(obj2);
+    for (int i = 0; i < size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj2,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg3 = CSLAddString( arg3, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg3 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldBinaryFromHexString",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return resultobj;
+fail:
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldBinaryFromHexString",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[4];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetFieldBinaryFromHexString__SWIG_0(self, args);
+        }
+      }
+    }
+  }
+  if (argc == 3) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_Feature_SetFieldBinaryFromHexString__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetFieldBinaryFromHexString'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    SetFieldBinaryFromHexString(OGRFeatureShadow *,int,char const *)\n"
+    "    SetFieldBinaryFromHexString(OGRFeatureShadow *,char const *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  int arg3 = (int) 1 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "other",(char *) "forgiving", NULL 
+  };
+  OGRErr result;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Feature_SetFrom",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFrom" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFrom" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+  if (obj2) {
+    ecode3 = SWIG_AsVal_int(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFrom" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:Feature_SetFromWithMap",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFromWithMap" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFromWithMap" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFromWithMap" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
+    /* check if is List */
+    if ( !PySequence_Check(obj3) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    arg4 = PySequence_Size(obj3);
+    arg5 = (int*) malloc(arg4*sizeof(int));
+    for( int i = 0; i<arg4; i++ ) {
+      PyObject *o = PySequence_GetItem(obj3,i);
+      if ( !PyArg_Parse(o,"i",&arg5[i]) ) {
+        PyErr_SetString(PyExc_TypeError, "not an integer");
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      Py_DECREF(o);
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg5) {
+      free((void*) arg5);
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if (resultobj == Py_None ) {
+      Py_DECREF(resultobj);
+      resultobj = 0;
+    }
+    if (resultobj == 0) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg5) {
+      free((void*) arg5);
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetStyleString",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetStyleString",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetStyleString" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRFieldType result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldType" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRFieldType result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldType" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldType(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetFieldType__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetFieldType__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldType'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GetFieldType(OGRFeatureShadow *,int)\n"
+    "    GetFieldType(OGRFeatureShadow *,char const *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *Feature_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFeatureShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_delete_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_FeatureDefn",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FeatureDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_OGRFeatureDefnShadow(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  char *arg1 = (char *) NULL ;
+  int res1 ;
+  char *buf1 = 0 ;
+  int alloc1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *  kwnames[] = {
+    (char *) "name_null_ok", NULL 
+  };
+  OGRFeatureDefnShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|O:new_FeatureDefn",kwnames,&obj0)) SWIG_fail;
+  if (obj0) {
+    res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FeatureDefn" "', argument " "1"" of type '" "char const *""'");
+    }
+    arg1 = reinterpret_cast< char * >(buf1);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_NEW |  0 );
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  return resultobj;
+fail:
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetFieldCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRFieldDefnShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetFieldDefn",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetFieldIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_AddFieldDefn",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
   }
-  
+  resultobj = SWIG_Py_Void();
+  return resultobj;
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetField'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    SetField(OGRFeatureShadow *,int,char const *)\n"
-    "    SetField(OGRFeatureShadow *,char const *,char const *)\n"
-    "    SetField(OGRFeatureShadow *,int,int)\n"
-    "    SetField(OGRFeatureShadow *,char const *,int)\n"
-    "    SetField(OGRFeatureShadow *,int,double)\n"
-    "    SetField(OGRFeatureShadow *,char const *,double)\n"
-    "    SetField(OGRFeatureShadow *,int,int,int,int,int,int,int,int)\n"
-    "    SetField(OGRFeatureShadow *,char const *,int,int,int,int,int,int,int)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
-  int *arg4 = (int *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldIntegerList",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetGeomFieldCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  {
-    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
-    /* check if is List */
-    if ( !PySequence_Check(obj2) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
-      SWIG_fail;
-    }
-    arg3 = PySequence_Size(obj2);
-    arg4 = (int*) malloc(arg3*sizeof(int));
-    for( int i = 0; i<arg3; i++ ) {
-      PyObject *o = PySequence_GetItem(obj2,i);
-      if ( !PyArg_Parse(o,"i",&arg4[i]) ) {
-        PyErr_SetString(PyExc_TypeError, "not an integer");
-        Py_DECREF(o);
-        SWIG_fail;
-      }
-      Py_DECREF(o);
-    }
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+    result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11308,74 +14287,89 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg4) {
-      free((void*) arg4);
-    }
-  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg4) {
-      free((void*) arg4);
-    }
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
-  int arg3 ;
-  double *arg4 = (double *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldDoubleList",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetGeomFieldDefn",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
-    /* %typemap(in,numinputs=1) (int nList, double* pList)*/
-    /* check if is List */
-    if ( !PySequence_Check(obj2) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
-      SWIG_fail;
+    if ( bUseExceptions ) {
+      CPLErrorReset();
     }
-    arg3 = PySequence_Size(obj2);
-    arg4 = (double*) malloc(arg3*sizeof(double));
-    for( int i = 0; i<arg3; i++ ) {
-      PyObject *o = PySequence_GetItem(obj2,i);
-      if ( !PyArg_Parse(o,"d",&arg4[i]) ) {
-        PyErr_SetString(PyExc_TypeError, "not a number");
-        Py_DECREF(o);
-        SWIG_fail;
+    result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
-      Py_DECREF(o);
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetGeomFieldIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+    result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11383,98 +14377,47 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(freearg) (int nList, double* pList) */
-    if (arg4) {
-      free((void*) arg4);
-    }
-  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) (int nList, double* pList) */
-    if (arg4) {
-      free((void*) arg4);
-    }
-  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_AddGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  char **arg3 = (char **) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:Feature_SetFieldStringList",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_AddGeomFieldDefn",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
   {
-    /* %typemap(in) char **options */
-    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-    if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
-  #if PY_VERSION_HEX < 0x03000000
-      || PyString_Check(obj2)
-  #endif
-      ) {
-      PyErr_SetString(PyExc_TypeError,"not a sequence");
-      SWIG_fail;
-    }
-    
-    int size = PySequence_Size(obj2);
-    for (int i = 0; i < size; i++) {
-      PyObject* pyObj = PySequence_GetItem(obj2,i);
-      if (PyUnicode_Check(pyObj))
-      {
-        char *pszStr;
-        Py_ssize_t nLen;
-        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-        arg3 = CSLAddString( arg3, pszStr );
-        Py_XDECREF(pyUTF8Str);
-      }
-#if PY_VERSION_HEX >= 0x03000000
-      else if (PyBytes_Check(pyObj))
-      arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
-#else
-      else if (PyString_Check(pyObj))
-      arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
-#endif
-      else
-      {
-        Py_DECREF(pyObj);
-        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-        SWIG_fail;
-      }
-      Py_DECREF(pyObj);
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+    OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11483,67 +14426,40 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(s
     }
   }
   resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg3 );
-  }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg3 );
-  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  int arg3 = (int) 1 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  char *  kwnames[] = {
-    (char *) "self",(char *) "other",(char *) "forgiving", NULL 
-  };
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|O:Feature_SetFrom",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_DeleteGeomFieldDefn",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFrom" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFrom" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-  if (obj2) {
-    ecode3 = SWIG_AsVal_int(obj2, &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFrom" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+    result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11574,70 +14490,66 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-  int arg3 ;
-  int arg4 ;
-  int *arg5 = (int *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  OGRErr result;
+  OGRwkbGeometryType result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:Feature_SetFromWithMap",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetGeomType",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFromWithMap" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFromWithMap" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFromWithMap" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   {
-    /* %typemap(in,numinputs=1) (int nList, int* pList)*/
-    /* check if is List */
-    if ( !PySequence_Check(obj3) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
-      SWIG_fail;
+    if ( bUseExceptions ) {
+      CPLErrorReset();
     }
-    arg4 = PySequence_Size(obj3);
-    arg5 = (int*) malloc(arg4*sizeof(int));
-    for( int i = 0; i<arg4; i++ ) {
-      PyObject *o = PySequence_GetItem(obj3,i);
-      if ( !PyArg_Parse(o,"i",&arg5[i]) ) {
-        PyErr_SetString(PyExc_TypeError, "not an integer");
-        Py_DECREF(o);
-        SWIG_fail;
+    result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
-      Py_DECREF(o);
     }
   }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRwkbGeometryType arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetGeomType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeomType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+  } 
+  arg2 = static_cast< OGRwkbGeometryType >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+    OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11645,60 +14557,106 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg5) {
-      free((void*) arg5);
-    }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_GetReferenceCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetReferenceCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetReferenceCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
+    if ( bUseExceptions ) {
+      CPLErrorReset();
     }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+    result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
   }
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FeatureDefn_IsGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_IsGeometryIgnored",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   {
-    /* %typemap(freearg) (int nList, int* pList) */
-    if (arg5) {
-      free((void*) arg5);
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
     }
   }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
+  PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetStyleString",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetGeometryIgnored",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+    OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11706,41 +14664,32 @@ SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_IsStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetStyleString",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_IsStyleIgnored",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetStyleString" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg2 = reinterpret_cast< char * >(buf2);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+    result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11748,18 +14697,16 @@ SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self)
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11767,24 +14714,23 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM
   int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRFieldType result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldType",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetStyleIgnored",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldType" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+    OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11792,37 +14738,36 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FeatureDefn_IsSame(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFeatureDefnShadow *arg2 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRFieldType result;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldType",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_IsSame",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsSame" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldType" "', argument " "2"" of type '" "char const *""'");
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_IsSame" "', argument " "2"" of type '" "OGRFeatureDefnShadow *""'"); 
   }
-  arg2 = reinterpret_cast< char * >(buf2);
+  arg2 = reinterpret_cast< OGRFeatureDefnShadow * >(argp2);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -11832,7 +14777,7 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+    result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11841,87 +14786,37 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM
     }
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Feature_GetFieldType(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
-  
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
-      if (_v) {
-        return _wrap_Feature_GetFieldType__SWIG_0(self, args);
-      }
-    }
-  }
-  if (argc == 2) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_Feature_GetFieldType__SWIG_1(self, args);
-      }
-    }
-  }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldType'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GetFieldType(OGRFeatureShadow *,int)\n"
-    "    GetFieldType(OGRFeatureShadow *,char const *)\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *Feature_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *FeatureDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFeatureShadow, SWIG_NewClientData(obj));
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_delete_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_FeatureDefn",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_FieldDefn",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FeatureDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FieldDefn" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRFeatureDefnShadow(arg1);
+    delete_OGRFieldDefnShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11936,31 +14831,42 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  char *arg1 = (char *) NULL ;
+  char *arg1 = (char *) "unnamed" ;
+  OGRFieldType arg2 = (OGRFieldType) OFTString ;
   int res1 ;
   char *buf1 = 0 ;
   int alloc1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   char *  kwnames[] = {
-    (char *) "name_null_ok", NULL 
+    (char *) "name_null_ok",(char *) "field_type", NULL 
   };
-  OGRFeatureDefnShadow *result = 0 ;
+  OGRFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|O:new_FeatureDefn",kwnames,&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OO:new_FieldDefn",kwnames,&obj0,&obj1)) SWIG_fail;
   if (obj0) {
     res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FeatureDefn" "', argument " "1"" of type '" "char const *""'");
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FieldDefn" "', argument " "1"" of type '" "char const *""'");
     }
     arg1 = reinterpret_cast< char * >(buf1);
   }
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_FieldDefn" "', argument " "2"" of type '" "OGRFieldType""'");
+    } 
+    arg2 = static_cast< OGRFieldType >(val2);
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+    result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11968,7 +14874,7 @@ SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObj
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_NEW |  0 );
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_NEW |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   return resultobj;
 fail:
@@ -11977,25 +14883,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetName",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+    result = (char *)OGRFieldDefnShadow_GetName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12010,115 +14916,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetFieldCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  OGRFieldDefnShadow *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetFieldDefn",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  int result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_GetFieldIndex",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetNameRef",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+    result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12126,37 +14942,36 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(se
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_AddFieldDefn",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetName",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FieldDefn_SetName" "', argument " "2"" of type '" "char const *""'");
   }
-  arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
+  arg2 = reinterpret_cast< char * >(buf2);
   {
     if (!arg2) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -12166,7 +14981,7 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+    OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12175,31 +14990,33 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(sel
     }
   }
   resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRwkbGeometryType result;
+  OGRFieldType result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetGeomType",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetType",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+    result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12214,10 +15031,10 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  OGRwkbGeometryType arg2 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldType arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -12225,22 +15042,22 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetGeomType",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeomType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetType" "', argument " "2"" of type '" "OGRFieldType""'");
   } 
-  arg2 = static_cast< OGRwkbGeometryType >(val2);
+  arg2 = static_cast< OGRFieldType >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+    OGRFieldDefnShadow_SetType(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12255,58 +15072,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_GetReferenceCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_GetReferenceCount",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetReferenceCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_FeatureDefn_IsGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  OGRJustification result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_IsGeometryIgnored",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetJustify",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+    result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12321,10 +15105,10 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-  int arg2 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRJustification arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -12332,22 +15116,22 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPA
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetGeometryIgnored",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetJustify",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetJustify" "', argument " "2"" of type '" "OGRJustification""'");
   } 
-  arg2 = static_cast< int >(val2);
+  arg2 = static_cast< OGRJustification >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+    OGRFieldDefnShadow_SetJustify(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12362,25 +15146,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_IsStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FeatureDefn_IsStyleIgnored",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetWidth",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+    result = (int)OGRFieldDefnShadow_GetWidth(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12395,9 +15179,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12406,22 +15190,22 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FeatureDefn_SetStyleIgnored",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetWidth",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetWidth" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+    OGRFieldDefnShadow_SetWidth(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12436,31 +15220,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *FeatureDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
-SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_FieldDefn",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetPrecision",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FieldDefn" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRFieldDefnShadow(arg1);
+    result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12468,49 +15246,40 @@ SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyOb
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  char *arg1 = (char *) "unnamed" ;
-  OGRFieldType arg2 = (OGRFieldType) OFTString ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
+  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char *  kwnames[] = {
-    (char *) "name_null_ok",(char *) "field_type", NULL 
-  };
-  OGRFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OO:new_FieldDefn",kwnames,&obj0,&obj1)) SWIG_fail;
-  if (obj0) {
-    res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FieldDefn" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-  }
-  if (obj1) {
-    ecode2 = SWIG_AsVal_int(obj1, &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_FieldDefn" "', argument " "2"" of type '" "OGRFieldType""'");
-    } 
-    arg2 = static_cast< OGRFieldType >(val2);
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetPrecision",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
+  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetPrecision" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+    OGRFieldDefnShadow_SetPrecision(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12518,16 +15287,14 @@ SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObjec
       }
     }
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_NEW |  0 );
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
@@ -12535,17 +15302,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyO
   PyObject * obj0 = 0 ;
   char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetName",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetTypeName",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetName(arg1);
+    result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12560,25 +15327,34 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRFieldType arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetNameRef",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_GetFieldTypeName",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "2"" of type '" "OGRFieldType""'");
+  } 
+  arg2 = static_cast< OGRFieldType >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+    result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12593,39 +15369,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetName",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_IsIgnored",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FieldDefn_SetName" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+    result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12633,34 +15395,40 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyO
       }
     }
   }
-  resultobj = SWIG_Py_Void();
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRFieldType result;
+  PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetType",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetIgnored",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+    OGRFieldDefnShadow_SetIgnored(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12668,40 +15436,38 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyO
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *FieldDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFieldDefnShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_delete_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRFieldType arg2 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetType",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GeomFieldDefn",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GeomFieldDefn" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetType" "', argument " "2"" of type '" "OGRFieldType""'");
-  } 
-  arg2 = static_cast< OGRFieldType >(val2);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetType(arg1,arg2);
+    delete_OGRGeomFieldDefnShadow(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12716,25 +15482,42 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_new_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
+  char *arg1 = (char *) "" ;
+  OGRwkbGeometryType arg2 = (OGRwkbGeometryType) wkbUnknown ;
+  int res1 ;
+  char *buf1 = 0 ;
+  int alloc1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  OGRJustification result;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "name_null_ok",(char *) "field_type", NULL 
+  };
+  OGRGeomFieldDefnShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetJustify",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OO:new_GeomFieldDefn",kwnames,&obj0,&obj1)) SWIG_fail;
+  if (obj0) {
+    res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_GeomFieldDefn" "', argument " "1"" of type '" "char const *""'");
+    }
+    arg1 = reinterpret_cast< char * >(buf1);
+  }
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_GeomFieldDefn" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
+    } 
+    arg2 = static_cast< OGRwkbGeometryType >(val2);
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+    result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12742,40 +15525,34 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_POINTER_NEW |  0 );
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   return resultobj;
 fail:
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRJustification arg2 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetJustify",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:GeomFieldDefn_GetName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetJustify" "', argument " "2"" of type '" "OGRJustification""'");
-  } 
-  arg2 = static_cast< OGRJustification >(val2);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetJustify(arg1,arg2);
+    result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12783,32 +15560,32 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetWidth",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:GeomFieldDefn_GetNameRef",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+    result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12816,40 +15593,46 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), Py
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_FromCharPtr((const char *)result);
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int arg2 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetWidth",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:GeomFieldDefn_SetName",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GeomFieldDefn_SetName" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetWidth" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetWidth(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12858,31 +15641,33 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), Py
     }
   }
   resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  OGRwkbGeometryType result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetPrecision",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:GeomFieldDefn_GetType",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+    result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12897,10 +15682,10 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  int arg2 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OGRwkbGeometryType arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -12908,22 +15693,22 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self)
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetPrecision",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:GeomFieldDefn_SetType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetPrecision" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
   } 
-  arg2 = static_cast< int >(val2);
+  arg2 = static_cast< OGRwkbGeometryType >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetType(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12938,25 +15723,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
-  char *result = 0 ;
+  OSRSpatialReferenceShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_GetTypeName",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:GeomFieldDefn_GetSpatialRef",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+    result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12964,41 +15749,40 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-  OGRFieldType arg2 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_GetFieldTypeName",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:GeomFieldDefn_SetSpatialRef",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "2"" of type '" "OGRFieldType""'");
-  } 
-  arg2 = static_cast< OGRFieldType >(val2);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -13006,32 +15790,32 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(s
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:FieldDefn_IsIgnored",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"O:GeomFieldDefn_IsIgnored",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+    result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -13046,9 +15830,9 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
+  OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -13057,22 +15841,22 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self),
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:FieldDefn_SetIgnored",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OO:GeomFieldDefn_SetIgnored",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
   }
-  arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
+  arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+    OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -13087,10 +15871,10 @@ fail:
 }
 
 
-SWIGINTERN PyObject *FieldDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *GeomFieldDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_OGRFieldDefnShadow, SWIG_NewClientData(obj));
+  SWIG_TypeNewClientData(SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
@@ -13204,7 +15988,10 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkt(PyObject *SWIGUNUSEDPARM(self),
   if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:CreateGeometryFromWkt",kwnames,&obj0,&obj1)) SWIG_fail;
   {
     /* %typemap(in) (char **ignorechange) */
-    PyArg_Parse( obj0, "s", &val1 );
+    if( !PyArg_Parse( obj0, "s", &val1 ) ) {
+      PyErr_SetString( PyExc_TypeError, "not a string" );
+      SWIG_fail;
+    }
     arg1 = &val1;
   }
   if (obj1) {
@@ -17613,6 +20400,16 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
+	 { (char *)"new_StyleTable", _wrap_new_StyleTable, METH_VARARGS, (char *)"new_StyleTable() -> StyleTable"},
+	 { (char *)"delete_StyleTable", _wrap_delete_StyleTable, METH_VARARGS, (char *)"delete_StyleTable(StyleTable self)"},
+	 { (char *)"StyleTable_AddStyle", _wrap_StyleTable_AddStyle, METH_VARARGS, (char *)"StyleTable_AddStyle(StyleTable self, char pszName, char pszStyleString) -> int"},
+	 { (char *)"StyleTable_LoadStyleTable", _wrap_StyleTable_LoadStyleTable, METH_VARARGS, (char *)"StyleTable_LoadStyleTable(StyleTable self, char utf8_path) -> int"},
+	 { (char *)"StyleTable_SaveStyleTable", _wrap_StyleTable_SaveStyleTable, METH_VARARGS, (char *)"StyleTable_SaveStyleTable(StyleTable self, char utf8_path) -> int"},
+	 { (char *)"StyleTable_Find", _wrap_StyleTable_Find, METH_VARARGS, (char *)"StyleTable_Find(StyleTable self, char pszName) -> char"},
+	 { (char *)"StyleTable_ResetStyleStringReading", _wrap_StyleTable_ResetStyleStringReading, METH_VARARGS, (char *)"StyleTable_ResetStyleStringReading(StyleTable self)"},
+	 { (char *)"StyleTable_GetNextStyle", _wrap_StyleTable_GetNextStyle, METH_VARARGS, (char *)"StyleTable_GetNextStyle(StyleTable self) -> char"},
+	 { (char *)"StyleTable_GetLastStyleName", _wrap_StyleTable_GetLastStyleName, METH_VARARGS, (char *)"StyleTable_GetLastStyleName(StyleTable self) -> char"},
+	 { (char *)"StyleTable_swigregister", StyleTable_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Driver_name_get", _wrap_Driver_name_get, METH_VARARGS, (char *)"Driver_name_get(Driver self) -> char"},
 	 { (char *)"Driver_CreateDataSource", (PyCFunction) _wrap_Driver_CreateDataSource, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"Driver_CreateDataSource(Driver self, char utf8_path, char options = None) -> DataSource\n"
@@ -18114,6 +20911,19 @@ static PyMethodDef SwigMethods[] = {
 		"hLayer:  handle to the result of a previous OGR_DS_ExecuteSQL() call.\n"
 		"\n"
 		""},
+	 { (char *)"DataSource_GetStyleTable", _wrap_DataSource_GetStyleTable, METH_VARARGS, (char *)"\n"
+		"DataSource_GetStyleTable(DataSource self) -> StyleTable\n"
+		"\n"
+		"OGRStyleTableH\n"
+		"OGR_DS_GetStyleTable(OGRDataSourceH hDS) \n"
+		""},
+	 { (char *)"DataSource_SetStyleTable", _wrap_DataSource_SetStyleTable, METH_VARARGS, (char *)"\n"
+		"DataSource_SetStyleTable(DataSource self, StyleTable table)\n"
+		"\n"
+		"void\n"
+		"OGR_DS_SetStyleTable(OGRDataSourceH hDS, OGRStyleTableH hStyleTable)\n"
+		"\n"
+		""},
 	 { (char *)"DataSource_swigregister", DataSource_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Layer_GetRefCount", _wrap_Layer_GetRefCount, METH_VARARGS, (char *)"\n"
 		"Layer_GetRefCount(Layer self) -> int\n"
@@ -18122,7 +20932,8 @@ static PyMethodDef SwigMethods[] = {
 		"hLayer) \n"
 		""},
 	 { (char *)"Layer_SetSpatialFilter", _wrap_Layer_SetSpatialFilter, METH_VARARGS, (char *)"\n"
-		"Layer_SetSpatialFilter(Layer self, Geometry filter)\n"
+		"SetSpatialFilter(Geometry filter)\n"
+		"Layer_SetSpatialFilter(Layer self, int iGeomField, Geometry filter)\n"
 		"\n"
 		"void\n"
 		"OGR_L_SetSpatialFilter(OGRLayerH hLayer, OGRGeometryH hGeom)\n"
@@ -18161,8 +20972,9 @@ static PyMethodDef SwigMethods[] = {
 		"cleared, but no new one instituted. \n"
 		""},
 	 { (char *)"Layer_SetSpatialFilterRect", _wrap_Layer_SetSpatialFilterRect, METH_VARARGS, (char *)"\n"
-		"Layer_SetSpatialFilterRect(Layer self, double minx, double miny, double maxx, \n"
-		"    double maxy)\n"
+		"SetSpatialFilterRect(double minx, double miny, double maxx, double maxy)\n"
+		"Layer_SetSpatialFilterRect(Layer self, int iGeomField, double minx, double miny, \n"
+		"    double maxx, double maxy)\n"
 		"\n"
 		"void\n"
 		"OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double\n"
@@ -18622,7 +21434,8 @@ static PyMethodDef SwigMethods[] = {
 		"feature count, -1 if count not known. \n"
 		""},
 	 { (char *)"Layer_GetExtent", (PyCFunction) _wrap_Layer_GetExtent, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_GetExtent(Layer self, int force = 1, int can_return_null = 0)\n"
+		"Layer_GetExtent(Layer self, int force = 1, int can_return_null = 0, \n"
+		"    int geom_field = 0)\n"
 		"\n"
 		"OGRErr OGR_L_GetExtent(OGRLayerH\n"
 		"hLayer, OGREnvelope *psExtent, int bForce)\n"
@@ -18962,6 +21775,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"OGR 1.9.0 \n"
 		""},
+	 { (char *)"Layer_CreateGeomField", (PyCFunction) _wrap_Layer_CreateGeomField, METH_VARARGS | METH_KEYWORDS, (char *)"Layer_CreateGeomField(Layer self, GeomFieldDefn field_def, int approx_ok = 1) -> OGRErr"},
 	 { (char *)"Layer_StartTransaction", _wrap_Layer_StartTransaction, METH_VARARGS, (char *)"\n"
 		"Layer_StartTransaction(Layer self) -> OGRErr\n"
 		"\n"
@@ -19030,6 +21844,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"OGRERR_NONE on success. \n"
 		""},
+	 { (char *)"Layer_FindFieldIndex", _wrap_Layer_FindFieldIndex, METH_VARARGS, (char *)"Layer_FindFieldIndex(Layer self, char pszFieldName, int bExactMatch) -> int"},
 	 { (char *)"Layer_GetSpatialRef", _wrap_Layer_GetSpatialRef, METH_VARARGS, (char *)"\n"
 		"Layer_GetSpatialRef(Layer self) -> SpatialReference\n"
 		"\n"
@@ -19122,6 +21937,18 @@ static PyMethodDef SwigMethods[] = {
 		"    char options = None, GDALProgressFunc callback = None, \n"
 		"    void callback_data = None) -> OGRErr\n"
 		""},
+	 { (char *)"Layer_GetStyleTable", _wrap_Layer_GetStyleTable, METH_VARARGS, (char *)"\n"
+		"Layer_GetStyleTable(Layer self) -> StyleTable\n"
+		"\n"
+		"OGRStyleTableH\n"
+		"OGR_L_GetStyleTable(OGRLayerH hLayer) \n"
+		""},
+	 { (char *)"Layer_SetStyleTable", _wrap_Layer_SetStyleTable, METH_VARARGS, (char *)"\n"
+		"Layer_SetStyleTable(Layer self, StyleTable table)\n"
+		"\n"
+		"void\n"
+		"OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable) \n"
+		""},
 	 { (char *)"Layer_swigregister", Layer_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_Feature", _wrap_delete_Feature, METH_VARARGS, (char *)"delete_Feature(Feature self)"},
 	 { (char *)"new_Feature", (PyCFunction) _wrap_new_Feature, METH_VARARGS | METH_KEYWORDS, (char *)"new_Feature(FeatureDefn feature_def) -> Feature"},
@@ -19213,6 +22040,18 @@ static PyMethodDef SwigMethods[] = {
 		"an handle to internal feature geometry. This object should not be\n"
 		"modified. \n"
 		""},
+	 { (char *)"Feature_SetGeomField", _wrap_Feature_SetGeomField, METH_VARARGS, (char *)"\n"
+		"SetGeomField(int iField, Geometry geom) -> OGRErr\n"
+		"Feature_SetGeomField(Feature self, char name, Geometry geom) -> OGRErr\n"
+		""},
+	 { (char *)"Feature_SetGeomFieldDirectly", _wrap_Feature_SetGeomFieldDirectly, METH_VARARGS, (char *)"\n"
+		"SetGeomFieldDirectly(int iField, Geometry geom) -> OGRErr\n"
+		"Feature_SetGeomFieldDirectly(Feature self, char name, Geometry geom) -> OGRErr\n"
+		""},
+	 { (char *)"Feature_GetGeomFieldRef", _wrap_Feature_GetGeomFieldRef, METH_VARARGS, (char *)"\n"
+		"GetGeomFieldRef(int iField) -> Geometry\n"
+		"Feature_GetGeomFieldRef(Feature self, char name) -> Geometry\n"
+		""},
 	 { (char *)"Feature_Clone", _wrap_Feature_Clone, METH_VARARGS, (char *)"\n"
 		"Feature_Clone(Feature self) -> Feature\n"
 		"\n"
@@ -19297,6 +22136,11 @@ static PyMethodDef SwigMethods[] = {
 		"an handle to the field definition (from the OGRFeatureDefn). This is\n"
 		"an internal reference, and should not be deleted or modified. \n"
 		""},
+	 { (char *)"Feature_GetGeomFieldCount", _wrap_Feature_GetGeomFieldCount, METH_VARARGS, (char *)"Feature_GetGeomFieldCount(Feature self) -> int"},
+	 { (char *)"Feature_GetGeomFieldDefnRef", _wrap_Feature_GetGeomFieldDefnRef, METH_VARARGS, (char *)"\n"
+		"GetGeomFieldDefnRef(int id) -> GeomFieldDefn\n"
+		"Feature_GetGeomFieldDefnRef(Feature self, char name) -> GeomFieldDefn\n"
+		""},
 	 { (char *)"Feature_GetFieldAsString", _wrap_Feature_GetFieldAsString, METH_VARARGS, (char *)"\n"
 		"GetFieldAsString(int id) -> char\n"
 		"Feature_GetFieldAsString(Feature self, char name) -> char\n"
@@ -19535,6 +22379,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"the field index, or -1 if no matching field is found. \n"
 		""},
+	 { (char *)"Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex, METH_VARARGS, (char *)"Feature_GetGeomFieldIndex(Feature self, char name) -> int"},
 	 { (char *)"Feature_GetFID", _wrap_Feature_GetFID, METH_VARARGS, (char *)"\n"
 		"Feature_GetFID(Feature self) -> int\n"
 		"\n"
@@ -19698,6 +22543,10 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"papszValues:  the values to assign. \n"
 		""},
+	 { (char *)"Feature_SetFieldBinaryFromHexString", _wrap_Feature_SetFieldBinaryFromHexString, METH_VARARGS, (char *)"\n"
+		"SetFieldBinaryFromHexString(int id, char pszValue)\n"
+		"Feature_SetFieldBinaryFromHexString(Feature self, char name, char pszValue)\n"
+		""},
 	 { (char *)"Feature_SetFrom", (PyCFunction) _wrap_Feature_SetFrom, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"Feature_SetFrom(Feature self, Feature other, int forgiving = 1) -> OGRErr\n"
 		"\n"
@@ -19929,6 +22778,11 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"hNewField:  handle to the new field definition. \n"
 		""},
+	 { (char *)"FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldCount(FeatureDefn self) -> int"},
+	 { (char *)"FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldDefn(FeatureDefn self, int i) -> GeomFieldDefn"},
+	 { (char *)"FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldIndex(FeatureDefn self, char name) -> int"},
+	 { (char *)"FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_AddGeomFieldDefn(FeatureDefn self, GeomFieldDefn defn)"},
+	 { (char *)"FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_DeleteGeomFieldDefn(FeatureDefn self, int idx) -> OGRErr"},
 	 { (char *)"FeatureDefn_GetGeomType", _wrap_FeatureDefn_GetGeomType, METH_VARARGS, (char *)"\n"
 		"FeatureDefn_GetGeomType(FeatureDefn self) -> OGRwkbGeometryType\n"
 		"\n"
@@ -20068,6 +22922,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"bIgnore:  ignore state \n"
 		""},
+	 { (char *)"FeatureDefn_IsSame", _wrap_FeatureDefn_IsSame, METH_VARARGS, (char *)"FeatureDefn_IsSame(FeatureDefn self, FeatureDefn other_defn) -> int"},
 	 { (char *)"FeatureDefn_swigregister", FeatureDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_FieldDefn", _wrap_delete_FieldDefn, METH_VARARGS, (char *)"delete_FieldDefn(FieldDefn self)"},
 	 { (char *)"new_FieldDefn", (PyCFunction) _wrap_new_FieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FieldDefn(char name_null_ok = \"unnamed\", OGRFieldType field_type = OFTString) -> FieldDefn"},
@@ -20288,6 +23143,18 @@ static PyMethodDef SwigMethods[] = {
 		"ignore:  ignore state \n"
 		""},
 	 { (char *)"FieldDefn_swigregister", FieldDefn_swigregister, METH_VARARGS, NULL},
+	 { (char *)"delete_GeomFieldDefn", _wrap_delete_GeomFieldDefn, METH_VARARGS, (char *)"delete_GeomFieldDefn(GeomFieldDefn self)"},
+	 { (char *)"new_GeomFieldDefn", (PyCFunction) _wrap_new_GeomFieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_GeomFieldDefn(char name_null_ok = \"\", OGRwkbGeometryType field_type = wkbUnknown) -> GeomFieldDefn"},
+	 { (char *)"GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName, METH_VARARGS, (char *)"GeomFieldDefn_GetName(GeomFieldDefn self) -> char"},
+	 { (char *)"GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef, METH_VARARGS, (char *)"GeomFieldDefn_GetNameRef(GeomFieldDefn self) -> char"},
+	 { (char *)"GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName, METH_VARARGS, (char *)"GeomFieldDefn_SetName(GeomFieldDefn self, char name)"},
+	 { (char *)"GeomFieldDefn_GetType", _wrap_GeomFieldDefn_GetType, METH_VARARGS, (char *)"GeomFieldDefn_GetType(GeomFieldDefn self) -> OGRwkbGeometryType"},
+	 { (char *)"GeomFieldDefn_SetType", _wrap_GeomFieldDefn_SetType, METH_VARARGS, (char *)"GeomFieldDefn_SetType(GeomFieldDefn self, OGRwkbGeometryType type)"},
+	 { (char *)"GeomFieldDefn_GetSpatialRef", _wrap_GeomFieldDefn_GetSpatialRef, METH_VARARGS, (char *)"GeomFieldDefn_GetSpatialRef(GeomFieldDefn self) -> SpatialReference"},
+	 { (char *)"GeomFieldDefn_SetSpatialRef", _wrap_GeomFieldDefn_SetSpatialRef, METH_VARARGS, (char *)"GeomFieldDefn_SetSpatialRef(GeomFieldDefn self, SpatialReference srs)"},
+	 { (char *)"GeomFieldDefn_IsIgnored", _wrap_GeomFieldDefn_IsIgnored, METH_VARARGS, (char *)"GeomFieldDefn_IsIgnored(GeomFieldDefn self) -> int"},
+	 { (char *)"GeomFieldDefn_SetIgnored", _wrap_GeomFieldDefn_SetIgnored, METH_VARARGS, (char *)"GeomFieldDefn_SetIgnored(GeomFieldDefn self, int bIgnored)"},
+	 { (char *)"GeomFieldDefn_swigregister", GeomFieldDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"CreateGeometryFromWkb", (PyCFunction) _wrap_CreateGeometryFromWkb, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkb(int len, SpatialReference reference = None) -> Geometry"},
 	 { (char *)"CreateGeometryFromWkt", (PyCFunction) _wrap_CreateGeometryFromWkt, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkt(char val, SpatialReference reference = None) -> Geometry"},
 	 { (char *)"CreateGeometryFromGML", _wrap_CreateGeometryFromGML, METH_VARARGS, (char *)"CreateGeometryFromGML(char input_string) -> Geometry"},
@@ -21443,8 +24310,10 @@ static swig_type_info _swigt__p_OGRDriverShadow = {"_p_OGRDriverShadow", "OGRDri
 static swig_type_info _swigt__p_OGRFeatureDefnShadow = {"_p_OGRFeatureDefnShadow", "OGRFeatureDefnShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRFieldDefnShadow = {"_p_OGRFieldDefnShadow", "OGRFieldDefnShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRGeomFieldDefnShadow = {"_p_OGRGeomFieldDefnShadow", "OGRGeomFieldDefnShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRGeometryShadow = {"_p_OGRGeometryShadow", "OGRGeometryShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRStyleTableShadow = {"_p_OGRStyleTableShadow", "OGRStyleTableShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OSRCoordinateTransformationShadow = {"_p_OSRCoordinateTransformationShadow", "OSRCoordinateTransformationShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
@@ -21463,8 +24332,10 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_OGRFeatureDefnShadow,
   &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRFieldDefnShadow,
+  &_swigt__p_OGRGeomFieldDefnShadow,
   &_swigt__p_OGRGeometryShadow,
   &_swigt__p_OGRLayerShadow,
+  &_swigt__p_OGRStyleTableShadow,
   &_swigt__p_OSRCoordinateTransformationShadow,
   &_swigt__p_OSRSpatialReferenceShadow,
   &_swigt__p_char,
@@ -21483,8 +24354,10 @@ static swig_cast_info _swigc__p_OGRDriverShadow[] = {  {&_swigt__p_OGRDriverShad
 static swig_cast_info _swigc__p_OGRFeatureDefnShadow[] = {  {&_swigt__p_OGRFeatureDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFieldDefnShadow[] = {  {&_swigt__p_OGRFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRGeomFieldDefnShadow[] = {  {&_swigt__p_OGRGeomFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRGeometryShadow[] = {  {&_swigt__p_OGRGeometryShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRStyleTableShadow[] = {  {&_swigt__p_OGRStyleTableShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRCoordinateTransformationShadow[] = {  {&_swigt__p_OSRCoordinateTransformationShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
@@ -21503,8 +24376,10 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_OGRFeatureDefnShadow,
   _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRFieldDefnShadow,
+  _swigc__p_OGRGeomFieldDefnShadow,
   _swigc__p_OGRGeometryShadow,
   _swigc__p_OGRLayerShadow,
+  _swigc__p_OGRStyleTableShadow,
   _swigc__p_OSRCoordinateTransformationShadow,
   _swigc__p_OSRSpatialReferenceShadow,
   _swigc__p_char,
@@ -22164,8 +25039,10 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "OLCFastSetNextByIndex",SWIG_FromCharPtr("FastSetNextByIndex"));
   SWIG_Python_SetConstant(d, "OLCStringsAsUTF8",SWIG_FromCharPtr("StringsAsUTF8"));
   SWIG_Python_SetConstant(d, "OLCIgnoreFields",SWIG_FromCharPtr("IgnoreFields"));
+  SWIG_Python_SetConstant(d, "OLCCreateGeomField",SWIG_FromCharPtr("CreateGeomField"));
   SWIG_Python_SetConstant(d, "ODsCCreateLayer",SWIG_FromCharPtr("CreateLayer"));
   SWIG_Python_SetConstant(d, "ODsCDeleteLayer",SWIG_FromCharPtr("DeleteLayer"));
+  SWIG_Python_SetConstant(d, "ODsCCreateGeomFieldAfterCreateLayer",SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
   SWIG_Python_SetConstant(d, "ODrCCreateDataSource",SWIG_FromCharPtr("CreateDataSource"));
   SWIG_Python_SetConstant(d, "ODrCDeleteDataSource",SWIG_FromCharPtr("DeleteDataSource"));
   
diff --git a/swig/python/extensions/osr_wrap.cpp b/swig/python/extensions/osr_wrap.cpp
index ec13aaa..5ecb8e7 100644
--- a/swig/python/extensions/osr_wrap.cpp
+++ b/swig/python/extensions/osr_wrap.cpp
@@ -3249,6 +3249,9 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *s
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(OSRSpatialReferenceShadow *self){
+    return OSREPSGTreatsAsNorthingEasting(self);
+  }
 
 #include <limits.h>
 #if !defined(SWIG_NO_LLONG_MAX)
@@ -4572,6 +4575,39 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_EPSGTreatsAsNorthingEasting(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:SpatialReference_EPSGTreatsAsNorthingEasting",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_EPSGTreatsAsNorthingEasting" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_SpatialReference_SetAuthority(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -10570,7 +10606,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPA
   arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
   {
     /* %typemap(in) (char **ignorechange) */
-    PyArg_Parse( obj1, "s", &val2 );
+    if( !PyArg_Parse( obj1, "s", &val2 ) ) {
+      PyErr_SetString( PyExc_TypeError, "not a string" );
+      SWIG_fail;
+    }
     arg2 = &val2;
   }
   {
@@ -12910,6 +12949,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_IsLocal", _wrap_SpatialReference_IsLocal, METH_VARARGS, (char *)"SpatialReference_IsLocal(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_IsVertical", _wrap_SpatialReference_IsVertical, METH_VARARGS, (char *)"SpatialReference_IsVertical(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_EPSGTreatsAsLatLong", _wrap_SpatialReference_EPSGTreatsAsLatLong, METH_VARARGS, (char *)"SpatialReference_EPSGTreatsAsLatLong(SpatialReference self) -> int"},
+	 { (char *)"SpatialReference_EPSGTreatsAsNorthingEasting", _wrap_SpatialReference_EPSGTreatsAsNorthingEasting, METH_VARARGS, (char *)"SpatialReference_EPSGTreatsAsNorthingEasting(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority, METH_VARARGS, (char *)"\n"
 		"SpatialReference_SetAuthority(SpatialReference self, char pszTargetKey, char pszAuthority, \n"
 		"    int nCode) -> OGRErr\n"
@@ -13889,6 +13929,44 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "SRS_UL_ROD_CONV",SWIG_FromCharPtr("5.02921005842012"));
   SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke",SWIG_FromCharPtr("Link_Clarke"));
   SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke_CONV",SWIG_FromCharPtr("0.2011661949"));
+  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER",SWIG_FromCharPtr("Kilometer"));
+  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER_CONV",SWIG_FromCharPtr("1000."));
+  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER",SWIG_FromCharPtr("Decimeter"));
+  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER_CONV",SWIG_FromCharPtr("0.1"));
+  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER",SWIG_FromCharPtr("Centimeter"));
+  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER_CONV",SWIG_FromCharPtr("0.01"));
+  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER",SWIG_FromCharPtr("Millimeter"));
+  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER_CONV",SWIG_FromCharPtr("0.001"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE",SWIG_FromCharPtr("Nautical_Mile_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE_CONV",SWIG_FromCharPtr("1852.0"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH",SWIG_FromCharPtr("Inch_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH_CONV",SWIG_FromCharPtr("0.0254"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT",SWIG_FromCharPtr("Foot_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD",SWIG_FromCharPtr("Yard_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD_CONV",SWIG_FromCharPtr("0.9144"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE_CONV",SWIG_FromCharPtr("1609.344"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM",SWIG_FromCharPtr("Fathom_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM_CONV",SWIG_FromCharPtr("1.8288"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN",SWIG_FromCharPtr("Chain_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN_CONV",SWIG_FromCharPtr("20.1168"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK",SWIG_FromCharPtr("Link_International"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK_CONV",SWIG_FromCharPtr("0.201168"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH",SWIG_FromCharPtr("Inch_US_Surveyor"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH_CONV",SWIG_FromCharPtr("0.025400050800101603"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD",SWIG_FromCharPtr("Yard_US_Surveyor"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD_CONV",SWIG_FromCharPtr("0.914401828803658"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN",SWIG_FromCharPtr("Chain_US_Surveyor"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN_CONV",SWIG_FromCharPtr("20.11684023368047"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_US_Surveyor"));
+  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE_CONV",SWIG_FromCharPtr("1609.347218694437"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD",SWIG_FromCharPtr("Yard_Indian"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD_CONV",SWIG_FromCharPtr("0.91439523"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT",SWIG_FromCharPtr("Foot_Indian"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT_CONV",SWIG_FromCharPtr("0.30479841"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN",SWIG_FromCharPtr("Chain_Indian"));
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN_CONV",SWIG_FromCharPtr("20.11669506"));
   SWIG_Python_SetConstant(d, "SRS_UA_DEGREE",SWIG_FromCharPtr("degree"));
   SWIG_Python_SetConstant(d, "SRS_UA_DEGREE_CONV",SWIG_FromCharPtr("0.0174532925199433"));
   SWIG_Python_SetConstant(d, "SRS_UA_RADIAN",SWIG_FromCharPtr("radian"));
diff --git a/swig/python/fallback_build_mingw32_under_unix.sh b/swig/python/fallback_build_mingw32_under_unix.sh
index f0c393e..443b72e 100755
--- a/swig/python/fallback_build_mingw32_under_unix.sh
+++ b/swig/python/fallback_build_mingw32_under_unix.sh
@@ -5,9 +5,12 @@
 
 # You may need to customize the following versions to match your cross-compiler
 # name and your native python installation
-CXX=i586-mingw32msvc-g++
+if test "x${CXX}" = "x"; then
+  CXX=i586-mingw32msvc-g++
+else
+  CXX="${CXX}"
+fi
 PYTHONHOME=$HOME/.wine/drive_c/Python27
-OUTDIR=build/lib.win32-2.7/osgeo
 PYTHONLIB=python27
 
 if test -d ${PYTHONHOME}/Lib/site-packages/numpy/core/include; then
@@ -24,6 +27,17 @@ CFLAGS="-O2 -D__MSVCRT_VERSION__=0x0601"
 # Run native python
 wine ${PYTHONHOME}/python setup.py build
 
+# Determine OUTDIR
+if test -d build/lib.win32-2.7; then
+  OUTDIR=build/lib.win32-2.7/osgeo
+elif test -d build/lib.win-amd64-2.7; then
+  OUTDIR=build/lib.win-amd64-2.7/osgeo
+  CFLAGS="-DMS_WIN64 $CFLAGS"
+else
+  echo "Cannot determine OUTDIR"
+  exit 1
+fi
+
 # Build extensions
 ${CXX} ${CFLAGS} extensions/gdal_wrap.cpp -shared -o ${OUTDIR}/_gdal.pyd ${INCFLAGS} ${LINKFLAGS}
 ${CXX} ${CFLAGS} extensions/ogr_wrap.cpp -shared -o ${OUTDIR}/_ogr.pyd ${INCFLAGS} ${LINKFLAGS}
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index ec3b199..457b0c1 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -335,6 +335,10 @@ class MajorObject(_object):
         """SetDescription(self, char pszNewDesc)"""
         return _gdal.MajorObject_SetDescription(self, *args)
 
+    def GetMetadataDomainList(self, *args):
+        """GetMetadataDomainList(self) -> char"""
+        return _gdal.MajorObject_GetMetadataDomainList(self, *args)
+
     def GetMetadata_Dict(self, *args):
         """GetMetadata_Dict(self, char pszDomain = "") -> char"""
         return _gdal.MajorObject_GetMetadata_Dict(self, *args)
@@ -629,6 +633,27 @@ def GDAL_GCP_set_Id(*args):
 def GCPsToGeoTransform(*args):
   """GCPsToGeoTransform(int nGCPs, int bApproxOK = 1) -> RETURN_NONE"""
   return _gdal.GCPsToGeoTransform(*args)
+class VirtualMem(_object):
+    """Proxy of C++ CPLVirtualMemShadow class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, VirtualMem, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, VirtualMem, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gdal.delete_VirtualMem
+    __del__ = lambda self : None;
+    def GetAddr(self, *args):
+        """GetAddr(self)"""
+        return _gdal.VirtualMem_GetAddr(self, *args)
+
+    def Pin(self, *args):
+        """Pin(self, size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)"""
+        return _gdal.VirtualMem_Pin(self, *args)
+
+VirtualMem_swigregister = _gdal.VirtualMem_swigregister
+VirtualMem_swigregister(VirtualMem)
+
 class AsyncReader(_object):
     """Proxy of C++ GDALAsyncReaderShadow class"""
     __swig_setmethods__ = {}
@@ -767,6 +792,26 @@ class Dataset(MajorObject):
         """EndAsyncReader(self, AsyncReader ario)"""
         return _gdal.Dataset_EndAsyncReader(self, *args)
 
+    def GetVirtualMem(self, *args, **kwargs):
+        """
+        GetVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
+            int nYSize, int nBufXSize, int nBufYSize, 
+            GDALDataType eBufType, int band_list, int bIsBandSequential, 
+            size_t nCacheSize, size_t nPageSizeHint, 
+            char options = None) -> VirtualMem
+        """
+        return _gdal.Dataset_GetVirtualMem(self, *args, **kwargs)
+
+    def GetTiledVirtualMem(self, *args, **kwargs):
+        """
+        GetTiledVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
+            int nYSize, int nTileXSize, int nTileYSize, 
+            GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, 
+            size_t nCacheSize, 
+            char options = None) -> VirtualMem
+        """
+        return _gdal.Dataset_GetTiledVirtualMem(self, *args, **kwargs)
+
     def ReadRaster1(self, *args, **kwargs):
         """
         ReadRaster1(self, int xoff, int yoff, int xsize, int ysize, int buf_xsize = None, 
@@ -800,11 +845,15 @@ class Dataset(MajorObject):
                 buf_string, buf_xsize, buf_ysize, buf_type, band_list,
                 buf_pixel_space, buf_line_space, buf_band_space )
 
-    def ReadRaster(self, xoff, yoff, xsize, ysize,
+    def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                    buf_xsize = None, buf_ysize = None, buf_type = None,
                    band_list = None,
                    buf_pixel_space = None, buf_line_space = None, buf_band_space = None ):
 
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
         if band_list is None:
             band_list = range(1,self.RasterCount+1)
         if buf_xsize is None:
@@ -819,6 +868,70 @@ class Dataset(MajorObject):
                                             buf_xsize, buf_ysize, buf_type,
                                             band_list, buf_pixel_space, buf_line_space, buf_band_space )
 
+    def GetVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, bufxsize=None, bufysize=None,
+                           datatype = None, band_list = None, band_sequential = True,
+                           cache_size = 10 * 1024 * 1024, page_size_hint = 0,
+                           options = None):
+        """Return a NumPy array for the dataset, seen as a virtual memory mapping.
+           If there are several bands and band_sequential = True, an element is
+           accessed with array[band][y][x].
+           If there are several bands and band_sequential = False, an element is
+           accessed with array[y][x][band].
+           If there is only one band, an element is accessed with array[y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
+        if bufxsize is None:
+            bufxsize = self.RasterXSize
+        if bufysize is None:
+            bufysize = self.RasterYSize
+        if datatype is None:
+            datatype = self.GetRasterBand(1).DataType
+        if band_list is None:
+            band_list = range(1,self.RasterCount+1)
+        if options is None:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,band_list,band_sequential,cache_size,page_size_hint)
+        else:
+            virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,band_list,band_sequential,cache_size,page_size_hint, options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+    def GetTiledVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, tilexsize=256, tileysize=256,
+                           datatype = None, band_list = None, tile_organization = gdalconst.GTO_BSQ,
+                           cache_size = 10 * 1024 * 1024, options = None):
+        """Return a NumPy array for the dataset, seen as a virtual memory mapping with
+           a tile organization.
+           If there are several bands and tile_organization = gdal.GTO_TIP, an element is
+           accessed with array[tiley][tilex][y][x][band].
+           If there are several bands and tile_organization = gdal.GTO_BIT, an element is
+           accessed with array[tiley][tilex][band][y][x].
+           If there are several bands and tile_organization = gdal.GTO_BSQ, an element is
+           accessed with array[band][tiley][tilex][y][x].
+           If there is only one band, an element is accessed with array[tiley][tilex][y][x].
+           Any reference to the array must be dropped before the last reference to the
+           related dataset is also dropped.
+        """
+        import gdalnumeric
+        if xsize is None:
+            xsize = self.RasterXSize
+        if ysize is None:
+            ysize = self.RasterYSize
+        if datatype is None:
+            datatype = self.GetRasterBand(1).DataType
+        if band_list is None:
+            band_list = range(1,self.RasterCount+1)
+        if options is None:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,band_list,tile_organization,cache_size)
+        else:
+            virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,band_list,tile_organization,cache_size, options)
+        return gdalnumeric.VirtualMemGetArray( virtualmem )
+
     def GetSubDatasets(self):
         sd_list = []
         
@@ -1069,6 +1182,27 @@ class Band(MajorObject):
         """SetCategoryNames(self, char papszCategoryNames) -> CPLErr"""
         return _gdal.Band_SetCategoryNames(self, *args)
 
+    def GetVirtualMem(self, *args, **kwargs):
+        """
+        GetVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
+            int nYSize, int nBufXSize, int nBufYSize, 
+            GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, 
+            char options = None) -> VirtualMem
+        """
+        return _gdal.Band_GetVirtualMem(self, *args, **kwargs)
+
+    def GetVirtualMemAuto(self, *args, **kwargs):
+        """GetVirtualMemAuto(self, GDALRWFlag eRWFlag, char options = None) -> VirtualMem"""
+        return _gdal.Band_GetVirtualMemAuto(self, *args, **kwargs)
+
+    def GetTiledVirtualMem(self, *args, **kwargs):
+        """
+        GetTiledVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
+            int nYSize, int nTileXSize, int nTileYSize, 
+            GDALDataType eBufType, size_t nCacheSize, char options = None) -> VirtualMem
+        """
+        return _gdal.Band_GetTiledVirtualMem(self, *args, **kwargs)
+
     def ReadRaster1(self, *args, **kwargs):
         """
         ReadRaster1(self, int xoff, int yoff, int xsize, int ysize, int buf_xsize = None, 
@@ -1081,10 +1215,15 @@ class Band(MajorObject):
         """ReadBlock(self, int xoff, int yoff) -> CPLErr"""
         return _gdal.Band_ReadBlock(self, *args, **kwargs)
 
-    def ReadRaster(self, xoff, yoff, xsize, ysize,
+    def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                      buf_xsize = None, buf_ysize = None, buf_type = None,
                      buf_pixel_space = None, buf_line_space = None ):
 
+        if xsize is None:
+            xsize = self.XSize
+        if ysize is None:
+            ysize = self.YSize
+
         return _gdal.Band_ReadRaster1(self, xoff, yoff, xsize, ysize,
                                       buf_xsize, buf_ysize, buf_type,
                                       buf_pixel_space, buf_line_space)
@@ -1102,6 +1241,69 @@ class Band(MajorObject):
 
         return gdalnumeric.BandWriteArray( self, array, xoff, yoff )
 
+    def GetVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                           xsize=None, ysize=None, bufxsize=None, bufysize=None,
+                           datatype = None,
+                           cache_size = 10 * 1024 * 1024, page_size_hint = 0,
+                           options = None):
+          """Return a NumPy array for the band, seen as a virtual memory mapping.
+             An element is accessed with array[y][x].
+             Any reference to the array must be dropped before the last reference to the
+             related dataset is also dropped.
+          """
+          import gdalnumeric
+          if xsize is None:
+              xsize = self.XSize
+          if ysize is None:
+              ysize = self.YSize
+          if bufxsize is None:
+              bufxsize = self.XSize
+          if bufysize is None:
+              bufysize = self.YSize
+          if datatype is None:
+              datatype = self.DataType
+          if options is None:
+              virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,cache_size,page_size_hint)
+          else:
+              virtualmem = self.GetVirtualMem(eAccess,xoff,yoff,xsize,ysize,bufxsize,bufysize,datatype,cache_size,page_size_hint,options)
+          return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+    def GetVirtualMemAutoArray(self, eAccess = gdalconst.GF_Read, options = None):
+          """Return a NumPy array for the band, seen as a virtual memory mapping.
+             An element is accessed with array[y][x].
+             Any reference to the array must be dropped before the last reference to the
+             related dataset is also dropped.
+          """
+          import gdalnumeric
+          if options is None:
+              virtualmem = self.GetVirtualMemAuto(eAccess)
+          else:
+              virtualmem = self.GetVirtualMemAuto(eAccess,options)
+          return gdalnumeric.VirtualMemGetArray( virtualmem )
+
+    def GetTiledVirtualMemArray(self, eAccess = gdalconst.GF_Read, xoff=0, yoff=0,
+                             xsize=None, ysize=None, tilexsize=256, tileysize=256,
+                             datatype = None,
+                             cache_size = 10 * 1024 * 1024, options = None):
+          """Return a NumPy array for the band, seen as a virtual memory mapping with
+             a tile organization.
+             An element is accessed with array[tiley][tilex][y][x].
+             Any reference to the array must be dropped before the last reference to the
+             related dataset is also dropped.
+          """
+          import gdalnumeric
+          if xsize is None:
+              xsize = self.XSize
+          if ysize is None:
+              ysize = self.YSize
+          if datatype is None:
+              datatype = self.DataType
+          if options is None:
+              virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,cache_size)
+          else:
+              virtualmem = self.GetTiledVirtualMem(eAccess,xoff,yoff,xsize,ysize,tilexsize,tileysize,datatype,cache_size,options)
+          return gdalnumeric.VirtualMemGetArray( virtualmem )
+
     def __get_array_interface__(self):
         shape = [1, self.XSize, self.YSize]
         
@@ -1243,6 +1445,20 @@ class RasterAttributeTable(_object):
         """GetRowOfValue(self, double dfValue) -> int"""
         return _gdal.RasterAttributeTable_GetRowOfValue(self, *args)
 
+    def ChangesAreWrittenToFile(self, *args):
+        """ChangesAreWrittenToFile(self) -> int"""
+        return _gdal.RasterAttributeTable_ChangesAreWrittenToFile(self, *args)
+
+    def WriteArray(self, array, field, start=0):
+        import gdalnumeric
+
+        return gdalnumeric.RATWriteArray(self, array, field, start)
+
+    def ReadAsArray(self, field, start=0, length=None):
+        import gdalnumeric
+
+        return gdalnumeric.RATReadArray(self, field, start, length)
+
 RasterAttributeTable_swigregister = _gdal.RasterAttributeTable_swigregister
 RasterAttributeTable_swigregister(RasterAttributeTable)
 
diff --git a/swig/python/osgeo/gdal_array.py b/swig/python/osgeo/gdal_array.py
index c1dbdb6..b4e7d9e 100644
--- a/swig/python/osgeo/gdal_array.py
+++ b/swig/python/osgeo/gdal_array.py
@@ -66,6 +66,32 @@ except AttributeError:
     _newclass = 0
 
 
+class VirtualMem(_object):
+    """Proxy of C++ CPLVirtualMemShadow class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, VirtualMem, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, VirtualMem, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gdal_array.delete_VirtualMem
+    __del__ = lambda self : None;
+    def GetAddr(self):
+        """GetAddr(self)"""
+        return _gdal_array.VirtualMem_GetAddr(self)
+
+    def Pin(self, start_offset = 0, nsize = 0, bWriteOp = 0):
+        """
+        Pin(self, size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)
+        Pin(self, size_t start_offset = 0, size_t nsize = 0)
+        Pin(self, size_t start_offset = 0)
+        Pin(self)
+        """
+        return _gdal_array.VirtualMem_Pin(self, start_offset, nsize, bWriteOp)
+
+VirtualMem_swigregister = _gdal_array.VirtualMem_swigregister
+VirtualMem_swigregister(VirtualMem)
+
 
 def GetArrayFilename(*args):
   """GetArrayFilename(PyArrayObject psArray) -> retStringAndCPLFree"""
@@ -77,6 +103,24 @@ def BandRasterIONumPy(*args, **kwargs):
         int ysize, PyArrayObject psArray, int buf_type) -> CPLErr
     """
   return _gdal_array.BandRasterIONumPy(*args, **kwargs)
+
+def VirtualMemGetArray(*args):
+  """VirtualMemGetArray(VirtualMem virtualmem)"""
+  return _gdal_array.VirtualMemGetArray(*args)
+
+def RATValuesIONumPyWrite(*args, **kwargs):
+  """
+    RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, 
+        PyArrayObject psArray) -> CPLErr
+    """
+  return _gdal_array.RATValuesIONumPyWrite(*args, **kwargs)
+
+def RATValuesIONumPyRead(*args, **kwargs):
+  """
+    RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, 
+        int nLength) -> PyObject
+    """
+  return _gdal_array.RATValuesIONumPyRead(*args, **kwargs)
 import numpy
 import _gdal_array
 
@@ -111,7 +155,7 @@ def OpenArray( array, prototype_ds = None ):
     
     
 def flip_code(code):
-    if isinstance(code, type):
+    if isinstance(code, (numpy.dtype,type)):
         # since several things map to complex64 we must carefully select
         # the opposite that is an exact match (ticket 1518)
         if code == numpy.int8:
@@ -130,7 +174,7 @@ def flip_code(code):
             return None
 
 def NumericTypeCodeToGDALTypeCode(numeric_type):
-    if not isinstance(numeric_type, type):
+    if not isinstance(numeric_type, (numpy.dtype,type)):
         raise TypeError("Input must be a type")
     return flip_code(numeric_type)
 
@@ -270,6 +314,50 @@ def BandWriteArray( band, array, xoff=0, yoff=0 ):
     return BandRasterIONumPy( band, 1, xoff, yoff, xsize, ysize,
                                 array, datatype )
 
+def RATWriteArray(rat, array, field, start=0):
+    """
+    Pure Python implementation of writing a chunk of the RAT
+    from a numpy array. Type of array is coerced to one of the types
+    (int, double, string) supported. Called from RasterAttributeTable.WriteArray
+    """
+    if array is None:
+        raise ValueError("Expected array of dim 1")
+
+    # if not the array type convert it to handle lists etc
+    if not isinstance(array, numpy.ndarray):
+        array = numpy.array(array)
+
+    if array.ndim != 1:
+        raise ValueError("Expected array of dim 1")
+
+    if (start + array.size) > rat.GetRowCount():
+        raise ValueError("Array too big to fit into RAT from start position")
+
+    if numpy.issubdtype(array.dtype, numpy.integer):
+        # is some type of integer - coerce to standard int
+        # TODO: must check this is fine on all platforms
+        # confusingly numpy.int 64 bit even if native type 32 bit
+        array = array.astype(numpy.int32)
+    elif numpy.issubdtype(array.dtype, numpy.floating):
+        # is some type of floating point - coerce to double
+        array = array.astype(numpy.double)
+    elif numpy.issubdtype(array.dtype, numpy.character):
+        # cast away any kind of Unicode etc
+        array = array.astype(numpy.character)
+    else:
+        raise ValueError("Array not of a supported type (integer, double or string)")
+
+    return RATValuesIONumPyWrite(rat, field, start, array)
+
+def RATReadArray(rat, field, start=0, length=None):
+    """
+    Pure Python implementation of reading a chunk of the RAT
+    into a numpy array. Called from RasterAttributeTable.ReadAsArray
+    """
+    if length is None:
+        length = rat.GetRowCount() - start
+
+    return RATValuesIONumPyRead(rat, field, start, length)
     
 def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
     """
diff --git a/swig/python/osgeo/gdalconst.py b/swig/python/osgeo/gdalconst.py
index fa61e18..22b0a6e 100644
--- a/swig/python/osgeo/gdalconst.py
+++ b/swig/python/osgeo/gdalconst.py
@@ -176,5 +176,8 @@ GARIO_PENDING = _gdalconst.GARIO_PENDING
 GARIO_UPDATE = _gdalconst.GARIO_UPDATE
 GARIO_ERROR = _gdalconst.GARIO_ERROR
 GARIO_COMPLETE = _gdalconst.GARIO_COMPLETE
+GTO_TIP = _gdalconst.GTO_TIP
+GTO_BIT = _gdalconst.GTO_BIT
+GTO_BSQ = _gdalconst.GTO_BSQ
 
 
diff --git a/swig/python/osgeo/ogr.py b/swig/python/osgeo/ogr.py
index 02f0806..dba8c11 100644
--- a/swig/python/osgeo/ogr.py
+++ b/swig/python/osgeo/ogr.py
@@ -122,8 +122,10 @@ OLCDeleteFeature = _ogr.OLCDeleteFeature
 OLCFastSetNextByIndex = _ogr.OLCFastSetNextByIndex
 OLCStringsAsUTF8 = _ogr.OLCStringsAsUTF8
 OLCIgnoreFields = _ogr.OLCIgnoreFields
+OLCCreateGeomField = _ogr.OLCCreateGeomField
 ODsCCreateLayer = _ogr.ODsCCreateLayer
 ODsCDeleteLayer = _ogr.ODsCDeleteLayer
+ODsCCreateGeomFieldAfterCreateLayer = _ogr.ODsCCreateGeomFieldAfterCreateLayer
 ODrCCreateDataSource = _ogr.ODrCCreateDataSource
 ODrCDeleteDataSource = _ogr.ODrCDeleteDataSource
 
@@ -139,6 +141,51 @@ def DontUseExceptions(*args):
   """DontUseExceptions()"""
   return _ogr.DontUseExceptions(*args)
 import osr
+class StyleTable(_object):
+    """Proxy of C++ OGRStyleTableShadow class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, StyleTable, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, StyleTable, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args): 
+        """__init__(self) -> StyleTable"""
+        this = _ogr.new_StyleTable(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _ogr.delete_StyleTable
+    __del__ = lambda self : None;
+    def AddStyle(self, *args):
+        """AddStyle(self, char pszName, char pszStyleString) -> int"""
+        return _ogr.StyleTable_AddStyle(self, *args)
+
+    def LoadStyleTable(self, *args):
+        """LoadStyleTable(self, char utf8_path) -> int"""
+        return _ogr.StyleTable_LoadStyleTable(self, *args)
+
+    def SaveStyleTable(self, *args):
+        """SaveStyleTable(self, char utf8_path) -> int"""
+        return _ogr.StyleTable_SaveStyleTable(self, *args)
+
+    def Find(self, *args):
+        """Find(self, char pszName) -> char"""
+        return _ogr.StyleTable_Find(self, *args)
+
+    def ResetStyleStringReading(self, *args):
+        """ResetStyleStringReading(self)"""
+        return _ogr.StyleTable_ResetStyleStringReading(self, *args)
+
+    def GetNextStyle(self, *args):
+        """GetNextStyle(self) -> char"""
+        return _ogr.StyleTable_GetNextStyle(self, *args)
+
+    def GetLastStyleName(self, *args):
+        """GetLastStyleName(self) -> char"""
+        return _ogr.StyleTable_GetLastStyleName(self, *args)
+
+StyleTable_swigregister = _ogr.StyleTable_swigregister
+StyleTable_swigregister(StyleTable)
+
 class Driver(_object):
     """Proxy of C++ OGRDriverShadow class"""
     __swig_setmethods__ = {}
@@ -725,6 +772,25 @@ class DataSource(_object):
         """
         return _ogr.DataSource_ReleaseResultSet(self, *args)
 
+    def GetStyleTable(self, *args):
+        """
+        GetStyleTable(self) -> StyleTable
+
+        OGRStyleTableH
+        OGR_DS_GetStyleTable(OGRDataSourceH hDS) 
+        """
+        return _ogr.DataSource_GetStyleTable(self, *args)
+
+    def SetStyleTable(self, *args):
+        """
+        SetStyleTable(self, StyleTable table)
+
+        void
+        OGR_DS_SetStyleTable(OGRDataSourceH hDS, OGRStyleTableH hStyleTable)
+
+        """
+        return _ogr.DataSource_SetStyleTable(self, *args)
+
     def Destroy(self):
       "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
       _ogr.delete_DataSource( self )
@@ -814,6 +880,7 @@ class Layer(_object):
     def SetSpatialFilter(self, *args):
         """
         SetSpatialFilter(self, Geometry filter)
+        SetSpatialFilter(self, int iGeomField, Geometry filter)
 
         void
         OGR_L_SetSpatialFilter(OGRLayerH hLayer, OGRGeometryH hGeom)
@@ -856,6 +923,8 @@ class Layer(_object):
     def SetSpatialFilterRect(self, *args):
         """
         SetSpatialFilterRect(self, double minx, double miny, double maxx, double maxy)
+        SetSpatialFilterRect(self, int iGeomField, double minx, double miny, double maxx, 
+            double maxy)
 
         void
         OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double
@@ -1366,7 +1435,7 @@ class Layer(_object):
 
     def GetExtent(self, *args, **kwargs):
         """
-        GetExtent(self, int force = 1, int can_return_null = 0)
+        GetExtent(self, int force = 1, int can_return_null = 0, int geom_field = 0)
 
         OGRErr OGR_L_GetExtent(OGRLayerH
         hLayer, OGREnvelope *psExtent, int bForce)
@@ -1726,6 +1795,10 @@ class Layer(_object):
         """
         return _ogr.Layer_AlterFieldDefn(self, *args)
 
+    def CreateGeomField(self, *args, **kwargs):
+        """CreateGeomField(self, GeomFieldDefn field_def, int approx_ok = 1) -> OGRErr"""
+        return _ogr.Layer_CreateGeomField(self, *args, **kwargs)
+
     def StartTransaction(self, *args):
         """
         StartTransaction(self) -> OGRErr
@@ -1803,6 +1876,10 @@ class Layer(_object):
         """
         return _ogr.Layer_RollbackTransaction(self, *args)
 
+    def FindFieldIndex(self, *args):
+        """FindFieldIndex(self, char pszFieldName, int bExactMatch) -> int"""
+        return _ogr.Layer_FindFieldIndex(self, *args)
+
     def GetSpatialRef(self, *args):
         """
         GetSpatialRef(self) -> SpatialReference
@@ -1918,6 +1995,24 @@ class Layer(_object):
         """
         return _ogr.Layer_Erase(self, *args, **kwargs)
 
+    def GetStyleTable(self, *args):
+        """
+        GetStyleTable(self) -> StyleTable
+
+        OGRStyleTableH
+        OGR_L_GetStyleTable(OGRLayerH hLayer) 
+        """
+        return _ogr.Layer_GetStyleTable(self, *args)
+
+    def SetStyleTable(self, *args):
+        """
+        SetStyleTable(self, StyleTable table)
+
+        void
+        OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable) 
+        """
+        return _ogr.Layer_SetStyleTable(self, *args)
+
     def Reference(self):
       "For backwards compatibility only."
       pass
@@ -2107,6 +2202,27 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeometryRef(self, *args)
 
+    def SetGeomField(self, *args):
+        """
+        SetGeomField(self, int iField, Geometry geom) -> OGRErr
+        SetGeomField(self, char name, Geometry geom) -> OGRErr
+        """
+        return _ogr.Feature_SetGeomField(self, *args)
+
+    def SetGeomFieldDirectly(self, *args):
+        """
+        SetGeomFieldDirectly(self, int iField, Geometry geom) -> OGRErr
+        SetGeomFieldDirectly(self, char name, Geometry geom) -> OGRErr
+        """
+        return _ogr.Feature_SetGeomFieldDirectly(self, *args)
+
+    def GetGeomFieldRef(self, *args):
+        """
+        GetGeomFieldRef(self, int iField) -> Geometry
+        GetGeomFieldRef(self, char name) -> Geometry
+        """
+        return _ogr.Feature_GetGeomFieldRef(self, *args)
+
     def Clone(self, *args):
         """
         Clone(self) -> Feature
@@ -2203,6 +2319,17 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldDefnRef(self, *args)
 
+    def GetGeomFieldCount(self, *args):
+        """GetGeomFieldCount(self) -> int"""
+        return _ogr.Feature_GetGeomFieldCount(self, *args)
+
+    def GetGeomFieldDefnRef(self, *args):
+        """
+        GetGeomFieldDefnRef(self, int id) -> GeomFieldDefn
+        GetGeomFieldDefnRef(self, char name) -> GeomFieldDefn
+        """
+        return _ogr.Feature_GetGeomFieldDefnRef(self, *args)
+
     def GetFieldAsString(self, *args):
         """
         GetFieldAsString(self, int id) -> char
@@ -2468,6 +2595,10 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldIndex(self, *args)
 
+    def GetGeomFieldIndex(self, *args):
+        """GetGeomFieldIndex(self, char name) -> int"""
+        return _ogr.Feature_GetGeomFieldIndex(self, *args)
+
     def GetFID(self, *args):
         """
         GetFID(self) -> int
@@ -2655,6 +2786,13 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldStringList(self, *args)
 
+    def SetFieldBinaryFromHexString(self, *args):
+        """
+        SetFieldBinaryFromHexString(self, int id, char pszValue)
+        SetFieldBinaryFromHexString(self, char name, char pszValue)
+        """
+        return _ogr.Feature_SetFieldBinaryFromHexString(self, *args)
+
     def SetFrom(self, *args, **kwargs):
         """
         SetFrom(self, Feature other, int forgiving = 1) -> OGRErr
@@ -2812,29 +2950,63 @@ class Feature(_object):
         """Returns the values of fields by the given name"""
         if key == 'this':
             return self.__dict__[key]
-        try:
-            return self.GetField(key)
-        except:
-            raise AttributeError(key)
+
+        idx = self.GetFieldIndex(key)
+        if idx < 0:
+            idx = self.GetGeomFieldIndex(key)
+            if idx < 0:
+                raise AttributeError(key)
+            else:
+                return self.GetGeomFieldRef(idx)
+        else:
+            return self.GetField(idx)
 
 
 
     def __setattr__(self, key, value):
         """Set the values of fields by the given name"""
-        if key != 'this' and key != 'thisown' and self.GetFieldIndex(key) != -1:
-            return self.SetField2(key,value)
-        else:
+        if key == 'this' or key == 'thisown':
             self.__dict__[key] = value
+        else:
+            idx = self.GetFieldIndex(key)
+            if idx != -1:
+                self.SetField2(idx,value)
+            else:
+                idx = self.GetGeomFieldIndex(key)
+                if idx != -1:
+                    self.SetGeomField(idx, value)
+                else:
+                    self.__dict__[key] = value
 
 
     def __getitem__(self, key):
         """Returns the values of fields by the given name / field_index"""
-        return self.GetField(key)
+        if isinstance(key, str):
+            fld_index = self.GetFieldIndex(key)
+        if fld_index < 0:
+            if isinstance(key, str):
+                fld_index = self.GetGeomFieldIndex(key)
+            if fld_index < 0:
+                raise ValueError("Illegal field requested in GetField()")
+            else:
+                return self.GetGeomFieldRef(fld_index)
+        else:
+            return self.GetField(fld_index)
 
 
     def __setitem__(self, key, value):
         """Returns the value of a field by field name / index"""
-        self.SetField2( key, value )    
+        if isinstance(key, str):
+            fld_index = self.GetFieldIndex(key)
+        if fld_index < 0:
+            if isinstance(key, str):
+                fld_index = self.GetGeomFieldIndex(key)
+            if fld_index < 0:
+                raise ValueError("Illegal field requested in SetField()")
+            else:
+                return self.SetGeomField( fld_index, value )
+        else:
+            return self.SetField2( fld_index, value )
 
     def GetField(self, fld_index):
         if isinstance(fld_index, str):
@@ -2862,6 +3034,8 @@ class Feature(_object):
     def SetField2(self, fld_index, value):
         if isinstance(fld_index, str):
             fld_index = self.GetFieldIndex(fld_index)
+        if (fld_index < 0) or (fld_index > self.GetFieldCount()):
+            raise ValueError("Illegal field requested in SetField2()")
 
         if value is None:
             self.UnsetField( fld_index )
@@ -3089,6 +3263,26 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_AddFieldDefn(self, *args)
 
+    def GetGeomFieldCount(self, *args):
+        """GetGeomFieldCount(self) -> int"""
+        return _ogr.FeatureDefn_GetGeomFieldCount(self, *args)
+
+    def GetGeomFieldDefn(self, *args):
+        """GetGeomFieldDefn(self, int i) -> GeomFieldDefn"""
+        return _ogr.FeatureDefn_GetGeomFieldDefn(self, *args)
+
+    def GetGeomFieldIndex(self, *args):
+        """GetGeomFieldIndex(self, char name) -> int"""
+        return _ogr.FeatureDefn_GetGeomFieldIndex(self, *args)
+
+    def AddGeomFieldDefn(self, *args):
+        """AddGeomFieldDefn(self, GeomFieldDefn defn)"""
+        return _ogr.FeatureDefn_AddGeomFieldDefn(self, *args)
+
+    def DeleteGeomFieldDefn(self, *args):
+        """DeleteGeomFieldDefn(self, int idx) -> OGRErr"""
+        return _ogr.FeatureDefn_DeleteGeomFieldDefn(self, *args)
+
     def GetGeomType(self, *args):
         """
         GetGeomType(self) -> OGRwkbGeometryType
@@ -3249,6 +3443,10 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_SetStyleIgnored(self, *args)
 
+    def IsSame(self, *args):
+        """IsSame(self, FeatureDefn other_defn) -> int"""
+        return _ogr.FeatureDefn_IsSame(self, *args)
+
     def Destroy(self):
       "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
       _ogr.delete_FeatureDefn( self )
@@ -3547,6 +3745,63 @@ class FieldDefn(_object):
 FieldDefn_swigregister = _ogr.FieldDefn_swigregister
 FieldDefn_swigregister(FieldDefn)
 
+class GeomFieldDefn(_object):
+    """Proxy of C++ OGRGeomFieldDefnShadow class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GeomFieldDefn, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GeomFieldDefn, name)
+    __repr__ = _swig_repr
+    __swig_destroy__ = _ogr.delete_GeomFieldDefn
+    __del__ = lambda self : None;
+    def __init__(self, *args, **kwargs): 
+        """__init__(self, char name_null_ok = "", OGRwkbGeometryType field_type = wkbUnknown) -> GeomFieldDefn"""
+        this = _ogr.new_GeomFieldDefn(*args, **kwargs)
+        try: self.this.append(this)
+        except: self.this = this
+    def GetName(self, *args):
+        """GetName(self) -> char"""
+        return _ogr.GeomFieldDefn_GetName(self, *args)
+
+    def GetNameRef(self, *args):
+        """GetNameRef(self) -> char"""
+        return _ogr.GeomFieldDefn_GetNameRef(self, *args)
+
+    def SetName(self, *args):
+        """SetName(self, char name)"""
+        return _ogr.GeomFieldDefn_SetName(self, *args)
+
+    def GetType(self, *args):
+        """GetType(self) -> OGRwkbGeometryType"""
+        return _ogr.GeomFieldDefn_GetType(self, *args)
+
+    def SetType(self, *args):
+        """SetType(self, OGRwkbGeometryType type)"""
+        return _ogr.GeomFieldDefn_SetType(self, *args)
+
+    def GetSpatialRef(self, *args):
+        """GetSpatialRef(self) -> SpatialReference"""
+        return _ogr.GeomFieldDefn_GetSpatialRef(self, *args)
+
+    def SetSpatialRef(self, *args):
+        """SetSpatialRef(self, SpatialReference srs)"""
+        return _ogr.GeomFieldDefn_SetSpatialRef(self, *args)
+
+    def IsIgnored(self, *args):
+        """IsIgnored(self) -> int"""
+        return _ogr.GeomFieldDefn_IsIgnored(self, *args)
+
+    def SetIgnored(self, *args):
+        """SetIgnored(self, int bIgnored)"""
+        return _ogr.GeomFieldDefn_SetIgnored(self, *args)
+
+    type = property(GetType, SetType)
+    name = property(GetName, SetName)
+    srs = property(GetSpatialRef, SetSpatialRef)
+
+GeomFieldDefn_swigregister = _ogr.GeomFieldDefn_swigregister
+GeomFieldDefn_swigregister(GeomFieldDefn)
+
 
 def CreateGeometryFromWkb(*args, **kwargs):
   """CreateGeometryFromWkb(int len, SpatialReference reference = None) -> Geometry"""
diff --git a/swig/python/osgeo/osr.py b/swig/python/osgeo/osr.py
index d8f4577..58ad949 100644
--- a/swig/python/osgeo/osr.py
+++ b/swig/python/osgeo/osr.py
@@ -170,6 +170,44 @@ SRS_UL_ROD = _osr.SRS_UL_ROD
 SRS_UL_ROD_CONV = _osr.SRS_UL_ROD_CONV
 SRS_UL_LINK_Clarke = _osr.SRS_UL_LINK_Clarke
 SRS_UL_LINK_Clarke_CONV = _osr.SRS_UL_LINK_Clarke_CONV
+SRS_UL_KILOMETER = _osr.SRS_UL_KILOMETER
+SRS_UL_KILOMETER_CONV = _osr.SRS_UL_KILOMETER_CONV
+SRS_UL_DECIMETER = _osr.SRS_UL_DECIMETER
+SRS_UL_DECIMETER_CONV = _osr.SRS_UL_DECIMETER_CONV
+SRS_UL_CENTIMETER = _osr.SRS_UL_CENTIMETER
+SRS_UL_CENTIMETER_CONV = _osr.SRS_UL_CENTIMETER_CONV
+SRS_UL_MILLIMETER = _osr.SRS_UL_MILLIMETER
+SRS_UL_MILLIMETER_CONV = _osr.SRS_UL_MILLIMETER_CONV
+SRS_UL_INTL_NAUT_MILE = _osr.SRS_UL_INTL_NAUT_MILE
+SRS_UL_INTL_NAUT_MILE_CONV = _osr.SRS_UL_INTL_NAUT_MILE_CONV
+SRS_UL_INTL_INCH = _osr.SRS_UL_INTL_INCH
+SRS_UL_INTL_INCH_CONV = _osr.SRS_UL_INTL_INCH_CONV
+SRS_UL_INTL_FOOT = _osr.SRS_UL_INTL_FOOT
+SRS_UL_INTL_FOOT_CONV = _osr.SRS_UL_INTL_FOOT_CONV
+SRS_UL_INTL_YARD = _osr.SRS_UL_INTL_YARD
+SRS_UL_INTL_YARD_CONV = _osr.SRS_UL_INTL_YARD_CONV
+SRS_UL_INTL_STAT_MILE = _osr.SRS_UL_INTL_STAT_MILE
+SRS_UL_INTL_STAT_MILE_CONV = _osr.SRS_UL_INTL_STAT_MILE_CONV
+SRS_UL_INTL_FATHOM = _osr.SRS_UL_INTL_FATHOM
+SRS_UL_INTL_FATHOM_CONV = _osr.SRS_UL_INTL_FATHOM_CONV
+SRS_UL_INTL_CHAIN = _osr.SRS_UL_INTL_CHAIN
+SRS_UL_INTL_CHAIN_CONV = _osr.SRS_UL_INTL_CHAIN_CONV
+SRS_UL_INTL_LINK = _osr.SRS_UL_INTL_LINK
+SRS_UL_INTL_LINK_CONV = _osr.SRS_UL_INTL_LINK_CONV
+SRS_UL_US_INCH = _osr.SRS_UL_US_INCH
+SRS_UL_US_INCH_CONV = _osr.SRS_UL_US_INCH_CONV
+SRS_UL_US_YARD = _osr.SRS_UL_US_YARD
+SRS_UL_US_YARD_CONV = _osr.SRS_UL_US_YARD_CONV
+SRS_UL_US_CHAIN = _osr.SRS_UL_US_CHAIN
+SRS_UL_US_CHAIN_CONV = _osr.SRS_UL_US_CHAIN_CONV
+SRS_UL_US_STAT_MILE = _osr.SRS_UL_US_STAT_MILE
+SRS_UL_US_STAT_MILE_CONV = _osr.SRS_UL_US_STAT_MILE_CONV
+SRS_UL_INDIAN_YARD = _osr.SRS_UL_INDIAN_YARD
+SRS_UL_INDIAN_YARD_CONV = _osr.SRS_UL_INDIAN_YARD_CONV
+SRS_UL_INDIAN_FOOT = _osr.SRS_UL_INDIAN_FOOT
+SRS_UL_INDIAN_FOOT_CONV = _osr.SRS_UL_INDIAN_FOOT_CONV
+SRS_UL_INDIAN_CHAIN = _osr.SRS_UL_INDIAN_CHAIN
+SRS_UL_INDIAN_CHAIN_CONV = _osr.SRS_UL_INDIAN_CHAIN_CONV
 SRS_UA_DEGREE = _osr.SRS_UA_DEGREE
 SRS_UA_DEGREE_CONV = _osr.SRS_UA_DEGREE_CONV
 SRS_UA_RADIAN = _osr.SRS_UA_RADIAN
@@ -258,6 +296,10 @@ class SpatialReference(_object):
         """EPSGTreatsAsLatLong(self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsLatLong(self, *args)
 
+    def EPSGTreatsAsNorthingEasting(self, *args):
+        """EPSGTreatsAsNorthingEasting(self) -> int"""
+        return _osr.SpatialReference_EPSGTreatsAsNorthingEasting(self, *args)
+
     def SetAuthority(self, *args):
         """SetAuthority(self, char pszTargetKey, char pszAuthority, int nCode) -> OGRErr"""
         return _osr.SpatialReference_SetAuthority(self, *args)
diff --git a/swig/python/samples/README b/swig/python/samples/README
index 701d3c3..e76bef3 100644
--- a/swig/python/samples/README
+++ b/swig/python/samples/README
@@ -97,6 +97,14 @@ ogr_layer_algebra.py    Application for executing OGR layer algebra operations.
 gdalpythonserver.py     A Python script that can be used as the value of GDAL_API_PROXY_SERVER config. option
                         Redirects on GDAL implementation, but could be used to implement a Python GDAL driver.
 
+ogr_dispatch.py         Dispatch features into layers according to the value of
+                        some fields or the geometry type.
+
+wcs_virtds_params.py    Generates MapServer WCS layer definition from a tileindex with mixed SRS
+
+ogr_build_junction_table.py Create junction tables for layers coming from GML datasources
+                            that reference other objects in _href fields
+
 ------------------------------------------------------------------------------
 Ports of .c/.cpp utilities
 ------------------------------------------------------------------------------
diff --git a/swig/python/samples/fft.py b/swig/python/samples/fft.py
index 64d2ac2..6528d74 100755
--- a/swig/python/samples/fft.py
+++ b/swig/python/samples/fft.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: fft.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: fft.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to perform forward and inverse two-dimensional fast
@@ -9,6 +9,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/gdal2grd.py b/swig/python/samples/gdal2grd.py
index 1a36488..2fa776c 100755
--- a/swig/python/samples/gdal2grd.py
+++ b/swig/python/samples/gdal2grd.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal2grd.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: gdal2grd.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to write out ASCII GRD rasters (used in Golden Software
@@ -10,6 +10,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/gdal_cp.py b/swig/python/samples/gdal_cp.py
index 848f379..51fb2ac 100755
--- a/swig/python/samples/gdal_cp.py
+++ b/swig/python/samples/gdal_cp.py
@@ -1,13 +1,13 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal_cp.py 23166 2011-10-02 17:48:48Z rouault $
+# $Id: gdal_cp.py 27044 2014-03-16 23:41:27Z rouault $
 #
 #  Project:  GDAL samples
 #  Purpose:  Copy a virtual file
 #  Author:   Even Rouault <even dot rouault at mines dash paris dot org>
 #
 ###############################################################################
-#  Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+#  Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
 #
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/gdal_ls.py b/swig/python/samples/gdal_ls.py
index 3ec9681..8745fd2 100755
--- a/swig/python/samples/gdal_ls.py
+++ b/swig/python/samples/gdal_ls.py
@@ -1,13 +1,14 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: gdal_ls.py 22993 2011-08-27 23:44:06Z rouault $
+# $Id: gdal_ls.py 27044 2014-03-16 23:41:27Z rouault $
 #
 #  Project:  GDAL samples
 #  Purpose:  Display the list of files in a virtual directory, like /vsicurl or /vsizip
 #  Author:   Even Rouault <even dot rouault at mines dash paris dot org>
 #
 ###############################################################################
-#  Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+#  Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
 #
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
@@ -80,7 +81,10 @@ def display_file(fout, dirname, prefix, filename, longformat, check_open = False
     else:
         line = filename_displayed + "\n"
 
-    fout.write(line)
+    try:
+        fout.write(line.encode('utf-8'))
+    except:
+        fout.write(line)
 
 def readDir(fout, dirname, prefix, longformat, recurse, depth, recurseInZip, recurseInTGZ, first = False):
 
diff --git a/swig/python/samples/gdal_vrtmerge.py b/swig/python/samples/gdal_vrtmerge.py
index 1e01f0c..7b18ede 100755
--- a/swig/python/samples/gdal_vrtmerge.py
+++ b/swig/python/samples/gdal_vrtmerge.py
@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*- 
 # Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
 # Copyright (C) 2005  Gabriel Ebner <ge at gabrielebner.at>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
diff --git a/swig/python/samples/gdalcompare.py b/swig/python/samples/gdalcompare.py
deleted file mode 100755
index 511b8c2..0000000
--- a/swig/python/samples/gdalcompare.py
+++ /dev/null
@@ -1,277 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#******************************************************************************
-#
-#  Project:  GDAL
-#  Purpose:  Compare two files for differences and report.
-#  Author:   Frank Warmerdam, warmerdam at pobox.com
-#
-#******************************************************************************
-#  Copyright (c) 2012, Frank Warmerdam <warmerdam at pobox.com>
-#
-#  Permission is hereby granted, free of charge, to any person obtaining a
-#  copy of this software and associated documentation files (the "Software"),
-#  to deal in the Software without restriction, including without limitation
-#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
-#  and/or sell copies of the Software, and to permit persons to whom the
-#  Software is furnished to do so, subject to the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#******************************************************************************
-
-import os
-import sys
-import filecmp
-
-from osgeo import gdal, osr
-
-#######################################################
-def compare_metadata(golden_md, new_md, id):
-  if golden_md is None and new_md is None:
-    return 0
-
-  found_diff = 0
-
-  if len(list(golden_md.keys())) != len(list(new_md.keys())):
-    print('Difference in %s metadata key count' % id)
-    print('  Golden Keys: ' + str(list(golden_md.keys())))
-    print('  New Keys: ' + str(list(new_md.keys())))
-    found_diff += 1
-
-  for key in list(golden_md.keys()):
-    if key not in new_md:
-      print('New %s metadata lacks key \"%s\"' % (id, key))
-      found_diff += 1
-    elif new_md[key] != golden_md[key]:
-      print('Metadata value difference for key "' + key + '"')
-      print('  Golden: "' + golden_md[key] + '"')
-      print('  New:    "' + new_md[key] + '"')
-      found_diff += 1
-
-  return found_diff
-
-
-#######################################################
-# Review and report on the actual image pixels that differ.
-def compare_image_pixels(golden_band, new_band, id):
-  diff_count = 0
-  max_diff = 0
-
-  for line in range(golden_band.YSize):
-    golden_line = golden_band.ReadAsArray(0, line, golden_band.XSize, 1)[0]
-    new_line = new_band.ReadAsArray(0, line, golden_band.XSize, 1)[0]
-    diff_line = golden_line - new_line
-    max_diff = max(max_diff,abs(diff_line).max())
-    diff_count += len(diff_line.nonzero()[0])
-
-  print('  Pixels Differing: ' + str(diff_count))
-  print('  Maximum Pixel Difference: ' + str(max_diff))
-
-#######################################################
-def compare_band(golden_band, new_band, id):
-  found_diff = 0
-
-  if golden_band.DataType != new_band.DataType:
-    print('Band %s pixel types differ.' % id)
-    print('  Golden: ' + gdal.GetDataTypeName(golden_band.DataType))
-    print('  New:    ' + gdal.GetDataTypeName(new_band.DataType))
-    found_diff += 1
-
-  if golden_band.GetNoDataValue() != new_band.GetNoDataValue():
-    print('Band %s nodata values differ.' % id)
-    print('  Golden: ' + str(golden_band.GetNoDataValue()))
-    print('  New:    ' + str(new_band.GetNoDataValue()))
-    found_diff += 1
-
-  if golden_band.GetColorInterpretation() != new_band.GetColorInterpretation():
-    print('Band %s color interpretation values differ.' % id)
-    print('  Golden: ' +  gdal.GetColorInterpretationName(golden_band.GetColorInterpretation()))
-    print('  New:    ' + gdal.GetColorInterpretationName(new_band.GetColorInterpretation()))
-    found_diff += 1
-
-  if golden_band.Checksum() != new_band.Checksum():
-    print('Band %s checksum difference:' % id)
-    print('  Golden: ' + str(golden_band.Checksum()))
-    print('  New:    ' + str(new_band.Checksum()))
-    found_diff += 1
-    compare_image_pixels(golden_band,new_band, id)
-
-  # Check overviews
-  if golden_band.GetOverviewCount() != new_band.GetOverviewCount():
-    print('Band %s overview count difference:' % id)
-    print('  Golden: ' + str(golden_band.GetOverviewCount()))
-    print('  New:    ' + str(new_band.GetOverviewCount()))
-    found_diff += 1
-  else:
-    for i in range(golden_band.GetOverviewCount()):
-      compare_band(golden_band.GetOverview(i),
-                   new_band.GetOverview(i),
-                   id + ' overview ' + str(i))
-
-  # Metadata
-  found_diff += compare_metadata(golden_band.GetMetadata(),
-                                 new_band.GetMetadata(),
-                                 'Band ' + id)
-
-  # TODO: Color Table, gain/bias, units, blocksize, mask, min/max
-
-  return found_diff
-
-#######################################################
-def compare_srs(golden_wkt, new_wkt):
-  if golden_wkt == new_wkt:
-    return 0
-
-  print('Difference in SRS!')
-
-  golden_srs = osr.SpatialReference(golden_wkt)
-  new_srs = osr.SpatialReference(new_wkt)
-
-  if golden_srs.IsSame(new_srs):
-    print('  * IsSame() reports them as equivelent.')
-  else:
-    print('  * IsSame() reports them as different.')
-
-  print('  Golden:')
-  print('  ' + golden_srs.ExportToPrettyWkt())
-  print('  New:')
-  print('  ' + new_srs.ExportToPrettyWkt())
-
-  return 1
-
-#######################################################
-def compare_db(golden_db, new_db):
-  found_diff = 0
-
-  # SRS
-  found_diff += compare_srs(golden_db.GetProjection(),
-                            new_db.GetProjection())
-
-  # GeoTransform
-  golden_gt = golden_db.GetGeoTransform()
-  new_gt = new_db.GetGeoTransform()
-  if golden_gt != new_gt:
-    print('GeoTransforms Differ:')
-    print('  Golden: ' + str(golden_gt))
-    print('  New:    ' + str(new_gt))
-    found_diff += 1
-
-  # Metadata
-  found_diff += compare_metadata(golden_db.GetMetadata(),
-                                 new_db.GetMetadata(),
-                                 'Dataset')
-
-  # Bands
-  if golden_db.RasterCount != new_db.RasterCount:
-    print('Band count mismatch (golden=%d, new=%d)' \
-        % (golden_db.RasterCount, new_db.RasterCount))
-    found_diff += 1
-
-  else:
-    for i in range(golden_db.RasterCount):
-      found_diff += compare_band(golden_db.GetRasterBand(i+1),
-                                 new_db.GetRasterBand(i+1),
-                                 str(i+1))
-
-  return found_diff
-
-#######################################################
-def compare_sds(golden_db, new_db):
-  found_diff = 0
-  
-  golden_sds = golden_db.GetMetadata('SUBDATASETS')
-  new_sds = new_db.GetMetadata('SUBDATASETS')
-
-  count = len(list(golden_sds.keys())) / 2
-  for i in range(count):
-    key = 'SUBDATASET_%d_NAME' % (i+1)
-
-    sub_golden_db = gdal.Open(golden_sds[key])
-    sub_new_db = gdal.Open(new_sds[key])
-
-    sds_diff = compare_db(sub_golden_db, sub_new_db)
-    found_diff += sds_diff
-    if sds_diff > 0:
-      print('%d differences found between:\n  %s\n  %s' \
-            % (sds_diff, golden_sds[key],new_sds[key]))
-
-  return found_diff
-  
-#######################################################
-def Usage():
-  print('Usage: gdalcompare.py [-sds] <golden_file> <new_file>')
-  sys.exit(1)
-
-#######################################################
-#
-# Mainline
-#
-
-if __name__ == '__main__':
-
-  # Default GDAL argument parsing.
-  argv = gdal.GeneralCmdLineProcessor( sys.argv )
-  if argv is None:
-    sys.exit( 0 )
-
-  if len(argv) == 1:
-    Usage()
-
-  # Script argument parsing.
-  golden_file = None
-  new_file = None
-  check_sds = 0
-
-  i = 1
-  while  i < len(argv):
-
-    if argv[i] == '-sds':
-      check_sds = 1
-
-    elif golden_file is None:
-      golden_file = argv[i]
-
-    elif new_file is None:
-      new_file = argv[i]
-
-    else:
-      print('Urecognised argument: ' + argv[i])
-      Usage()
-
-    i = i + 1
-    # next argument
-
-  #### Compare Files ####
-
-  found_diff = 0
-
-  # compare raw binary files.
-  try:
-    os.stat(golden_file)
-    
-    if not filecmp.cmp(golden_file,new_file):
-      print('Files differ at the binary level.')
-      found_diff += 1
-  except:
-    print('Skipped binary file comparison, golden file not in filesystem.')
-
-  # compare as GDAL Datasets.
-  golden_db = gdal.Open(golden_file)
-  new_db = gdal.Open(new_file)
-  found_diff += compare_db(golden_db, new_db)
-
-  if check_sds:
-    found_diff += compare_sds(golden_db, new_db)
-    
-  print('Differences Found: ' + str(found_diff))
-
-  sys.exit(found_diff)
diff --git a/swig/python/samples/gdalcopyproj.py b/swig/python/samples/gdalcopyproj.py
index c409c4e..1bb2f37 100755
--- a/swig/python/samples/gdalcopyproj.py
+++ b/swig/python/samples/gdalcopyproj.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalcopyproj.py 23368 2011-11-13 11:18:25Z rouault $
+#  $Id: gdalcopyproj.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Name:     gdalcopyproj.py
 #  Project:  GDAL Python Interface
@@ -12,6 +12,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2005, Frank Warmerdam
+#  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/gdalinfo.py b/swig/python/samples/gdalinfo.py
index e776428..ca680a4 100755
--- a/swig/python/samples/gdalinfo.py
+++ b/swig/python/samples/gdalinfo.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #/******************************************************************************
-# * $Id: gdalinfo.py 22986 2011-08-27 14:20:16Z rouault $
+# * $Id: gdalinfo.py 27044 2014-03-16 23:41:27Z rouault $
 # *
 # * Project:  GDAL Utilities
 # * Purpose:  Python port of Commandline application to list info about a file.
@@ -9,7 +9,7 @@
 # * Port from gdalinfo.c whose author is Frank Warmerdam
 # *
 # ******************************************************************************
-# * Copyright (c) 2010, Even Rouault
+# * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # * Copyright (c) 1998, Frank Warmerdam
 # *
 # * Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/swig/python/samples/gdalpythonserver.py b/swig/python/samples/gdalpythonserver.py
index 2b62afe..a862e39 100755
--- a/swig/python/samples/gdalpythonserver.py
+++ b/swig/python/samples/gdalpythonserver.py
@@ -8,7 +8,7 @@
 # * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
 # *
 # ******************************************************************************
-# * Copyright (c) 2013, Even Rouault, <even dot rouault at mines-paris dot org>
+# * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
 # *
 # * Permission is hereby granted, free of charge, to any person obtaining a
 # * copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/histrep.py b/swig/python/samples/histrep.py
index 337baab..dd7ad96 100755
--- a/swig/python/samples/histrep.py
+++ b/swig/python/samples/histrep.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: histrep.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: histrep.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python Samples
 # Purpose:  Report histogram from file.
@@ -8,6 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2005, Frank Warmerdam, warmerdam at pobox.com
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/hsv_merge.py b/swig/python/samples/hsv_merge.py
index 67f8e4f..a9114b6 100755
--- a/swig/python/samples/hsv_merge.py
+++ b/swig/python/samples/hsv_merge.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: hsv_merge.py 22986 2011-08-27 14:20:16Z rouault $
+#  $Id: hsv_merge.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Script to merge greyscale as intensity into an RGB(A) image, for
@@ -10,6 +10,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2009, Frank Warmerdam
+#  Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/load2odbc.py b/swig/python/samples/load2odbc.py
index 4b59009..418c5e7 100755
--- a/swig/python/samples/load2odbc.py
+++ b/swig/python/samples/load2odbc.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: load2odbc.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: load2odbc.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  OGR Python samples
 # Purpose:  Load ODBC table to an ODBC datastore.  Uses direct SQL 
@@ -9,6 +9,7 @@
 #
 ###############################################################################
 # Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/ogr2ogr.py b/swig/python/samples/ogr2ogr.py
index 2ea8a29..0fd9bf8 100755
--- a/swig/python/samples/ogr2ogr.py
+++ b/swig/python/samples/ogr2ogr.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #/******************************************************************************
-# * $Id: ogr2ogr.py 24949 2012-09-22 11:12:02Z rouault $
+# * $Id: ogr2ogr.py 27044 2014-03-16 23:41:27Z rouault $
 # *
 # * Project:  OpenGIS Simple Features Reference Implementation
 # * Purpose:  Python port of a simple client for translating between formats.
@@ -10,7 +10,7 @@
 # * Port from ogr2ogr.cpp whose author is Frank Warmerdam
 # *
 # ******************************************************************************
-# * Copyright (c) 2010, Even Rouault
+# * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
 # * Copyright (c) 1999, Frank Warmerdam
 # *
 # * Permission is hereby granted, free of charge, to any person obtaining a
@@ -165,6 +165,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
     papszSelFields = None
     pszSQLStatement = None
     eGType = -2
+    bPromoteToMulti = False
     eGeomOp = GeomOperation.NONE
     dfGeomOpParam = 0
     papszFieldTypesToString = []
@@ -253,6 +254,8 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                 eGType = ogr.wkbNone
             elif EQUAL(args[iArg+1],"GEOMETRY"):
                 eGType = ogr.wkbUnknown
+            elif EQUAL(args[iArg+1],"PROMOTE_TO_MULTI"):
+                bPromoteToMulti = True
             elif EQUAL(args[iArg+1],"POINT"):
                 eGType = ogr.wkbPoint
             elif EQUAL(args[iArg+1],"LINESTRING"):
@@ -710,7 +713,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                                         bNullifyOutputSRS, \
                                         poSourceSRS, \
                                         papszSelFields, \
-                                        bAppend, eGType, nCoordDim, bOverwrite, \
+                                        bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                         papszFieldTypesToString, \
                                         bWrapDateline, \
                                         bExplodeCollections, \
@@ -721,7 +724,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
             if psInfo is None or not TranslateLayer( psInfo, poDS, poResultSet, poODS, \
                                 poOutputSRS, bNullifyOutputSRS, \
-                                eGType, nCoordDim, \
+                                eGType, bPromoteToMulti, nCoordDim, \
                                 eGeomOp, dfGeomOpParam, \
                                 nCountLayerFeatures, \
                                 poClipSrc, poClipDst, \
@@ -825,7 +828,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                                            bNullifyOutputSRS, \
                                            poSourceSRS, \
                                            papszSelFields, \
-                                           bAppend, eGType, nCoordDim, bOverwrite, \
+                                           bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                            papszFieldTypesToString, \
                                            bWrapDateline, \
                                            bExplodeCollections, \
@@ -854,7 +857,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                 if psInfo is not None:
                     if not TranslateLayer(psInfo, poDS, poLayer, poODS, \
                                         poOutputSRS, bNullifyOutputSRS,  \
-                                        eGType, nCoordDim, \
+                                        eGType, bPromoteToMulti, nCoordDim, \
                                         eGeomOp, dfGeomOpParam,  \
                                         0,  \
                                         poClipSrc, poClipDst,  \
@@ -987,7 +990,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                                        bNullifyOutputSRS, \
                                        poSourceSRS, \
                                        papszSelFields, \
-                                       bAppend, eGType, nCoordDim, bOverwrite, \
+                                       bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                                        papszFieldTypesToString, \
                                        bWrapDateline, \
                                        bExplodeCollections, \
@@ -999,7 +1002,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             if (psInfo is None or \
                 not TranslateLayer( psInfo, poDS, poLayer, poODS, \
                                     poOutputSRS, bNullifyOutputSRS, \
-                                    eGType, nCoordDim, \
+                                    eGType, bPromoteToMulti, nCoordDim, \
                                     eGeomOp, dfGeomOpParam, \
                                     panLayerCountFeatures[iLayer], \
                                     poClipSrc, poClipDst, \
@@ -1189,7 +1192,7 @@ def SetZ (poGeom, dfZ ):
 
 def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     bTransform,  poOutputSRS, bNullifyOutputSRS, poSourceSRS, papszSelFields, \
-                    bAppend, eGType, nCoordDim, bOverwrite, \
+                    bAppend, eGType, bPromoteToMulti, nCoordDim, bOverwrite, \
                     papszFieldTypesToString, bWrapDateline, \
                     bExplodeCollections, pszZField, pszWHERE) :
 
@@ -1284,8 +1287,14 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
         if eGType == -2:
             eGType = poSrcFDefn.GetGeomType()
 
+            n25DBit = eGType & ogr.wkb25DBit
+            if bPromoteToMulti:
+                if wkbFlatten(eGType) == ogr.wkbLineString:
+                    eGType = ogr.wkbMultiLineString | n25DBit
+                elif wkbFlatten(eGType) == ogr.wkbPolygon:
+                    eGType = ogr.wkbMultiPolygon | n25DBit
+
             if bExplodeCollections:
-                n25DBit = eGType & ogr.wkb25DBit
                 if wkbFlatten(eGType) == ogr.wkbMultiPoint:
                     eGType = ogr.wkbPoint | n25DBit
                 elif wkbFlatten(eGType) == ogr.wkbMultiLineString:
@@ -1487,7 +1496,7 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
 def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
                     poOutputSRS, bNullifyOutputSRS, \
-                    eGType, nCoordDim, eGeomOp, dfGeomOpParam, \
+                    eGType, bPromoteToMulti, nCoordDim, eGeomOp, dfGeomOpParam, \
                     nCountLayerFeatures, \
                     poClipSrc, poClipDst, bExplodeCollections, nSrcFileSize, \
                     pnReadFeatureCount, pfnProgress, pProgressArg) :
@@ -1641,10 +1650,12 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
                 if bForceToPolygon:
                     poDstFeature.SetGeometryDirectly(ogr.ForceToPolygon(poDstGeometry))
 
-                elif bForceToMultiPolygon:
+                elif bForceToMultiPolygon or \
+                        (bPromoteToMulti and wkbFlatten(poDstGeometry.GetGeometryType()) == ogr.wkbPolygon):
                     poDstFeature.SetGeometryDirectly(ogr.ForceToMultiPolygon(poDstGeometry))
 
-                elif bForceToMultiLineString:
+                elif bForceToMultiLineString or \
+                        (bPromoteToMulti and wkbFlatten(poDstGeometry.GetGeometryType()) == ogr.wkbLineString):
                     poDstFeature.SetGeometryDirectly(ogr.ForceToMultiLineString(poDstGeometry))
 
             gdal.ErrorReset()
diff --git a/swig/python/samples/ogr2vrt.py b/swig/python/samples/ogr2vrt.py
index 18512f2..b283040 100755
--- a/swig/python/samples/ogr2vrt.py
+++ b/swig/python/samples/ogr2vrt.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: tigerpoly.py 13104 2007-11-26 21:23:48Z hobu $
+# $Id: ogr2vrt.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  OGR Python samples
 # Purpose:  Create OGR VRT from source datasource
@@ -8,6 +9,7 @@
 #
 ###############################################################################
 # Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+# Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
@@ -68,7 +70,7 @@ def Esc(x):
 
 #############################################################################
 def Usage():
-    print('Usage: ogr2vrt.py [-relative] [-schema] ')
+    print('Usage: ogr2vrt.py [-relative] [-schema] [-feature_count] [-extent]')
     print('                  in_datasource out_vrtfile [layers]')
     print('')
     sys.exit(1)
@@ -81,6 +83,8 @@ outfile = None
 layer_list = []
 relative = "0"
 schema=0
+feature_count=0
+extent=0
 
 argv = gdal.GeneralCmdLineProcessor( sys.argv )
 if argv is None:
@@ -96,6 +100,15 @@ while i < len(argv):
     elif arg == '-schema':
         schema = 1
 
+    elif arg == '-feature_count':
+        feature_count = 1
+
+    elif arg == '-extent':
+        extent = 1
+
+    elif arg[0] == '-':
+        Usage()
+
     elif infile is None:
         infile = arg
 
@@ -110,6 +123,14 @@ while i < len(argv):
 if outfile is None:
     Usage()
 
+if schema and feature_count:
+    sys.stderr.write('Ignoring -feature_count when used with -schema.\n')
+    feature_count = 0
+
+if schema and extent:
+    sys.stderr.write('Ignoring -extent when used with -schema.\n')
+    extent = 0
+    
 #############################################################################
 # Open the datasource to read.
 
@@ -141,13 +162,43 @@ for name in layer_list:
         vrt += '    <SrcLayer>@dummy@</SrcLayer>\n' 
     else:
         vrt += '    <SrcLayer>%s</SrcLayer>\n' % Esc(name)
-    vrt += '    <GeometryType>%s</GeometryType>\n' \
-           % GeomType2Name(layerdef.GetGeomType())
-    srs = layer.GetSpatialRef()
-    if srs is not None:
-        vrt += '    <LayerSRS>%s</LayerSRS>\n' \
-               % (Esc(srs.ExportToWkt()))
-    
+
+    # Historic format for mono-geometry layers
+    if layerdef.GetGeomFieldCount() == 0:
+        vrt += '    <GeometryType>wkbNone</GeometryType>\n'
+    elif layerdef.GetGeomFieldCount() == 1:
+        vrt += '    <GeometryType>%s</GeometryType>\n' \
+            % GeomType2Name(layerdef.GetGeomType())
+        srs = layer.GetSpatialRef()
+        if srs is not None:
+            vrt += '    <LayerSRS>%s</LayerSRS>\n' \
+                % (Esc(srs.ExportToWkt()))
+        if extent:
+            (xmin, xmax, ymin, ymax) = layer.GetExtent()
+            vrt += '    <ExtentXMin>%.15g</ExtentXMin>\n' % xmin
+            vrt += '    <ExtentYMin>%.15g</ExtentYMin>\n' % ymin
+            vrt += '    <ExtentXMax>%.15g</ExtentXMax>\n' % xmax
+            vrt += '    <ExtentYMax>%.15g</ExtentYMax>\n' % ymax
+
+    # New format for multi-geometry field support
+    else:
+        for fld_index in range(layerdef.GetGeomFieldCount()):
+            src_fd = layerdef.GetGeomFieldDefn( fld_index )
+            vrt += '    <GeometryField name="%s">\n' % src_fd.GetName()
+            vrt += '      <GeometryType>%s</GeometryType>\n' \
+                    % GeomType2Name(src_fd.GetType())
+            srs = src_fd.GetSpatialRef()
+            if srs is not None:
+                vrt += '      <SRS>%s</SRS>\n' \
+                        % (Esc(srs.ExportToWkt()))
+            if extent:
+                (xmin, xmax, ymin, ymax) = layer.GetExtent(geom_field = fld_index)
+                vrt += '      <ExtentXMin>%.15g</ExtentXMin>\n' % xmin
+                vrt += '      <ExtentYMin>%.15g</ExtentYMin>\n' % ymin
+                vrt += '      <ExtentXMax>%.15g</ExtentXMax>\n' % xmax
+                vrt += '      <ExtentYMax>%.15g</ExtentYMax>\n' % ymax
+            vrt += '    </GeometryField>\n'
+
     # Process all the fields.
     for fld_index in range(layerdef.GetFieldCount()):
         src_fd = layerdef.GetFieldDefn( fld_index )
@@ -183,7 +234,10 @@ for name in layer_list:
         if src_fd.GetPrecision() > 0:
             vrt += ' precision="%d"' % src_fd.GetPrecision()
         vrt += '/>\n'
-        
+
+    if feature_count:
+        vrt += '    <FeatureCount>%d</FeatureCount>\n' % layer.GetFeatureCount()
+
     vrt += '  </OGRVRTLayer>\n'
 
 vrt += '</OGRVRTDataSource>\n' 
diff --git a/swig/python/samples/ogr_build_junction_table.py b/swig/python/samples/ogr_build_junction_table.py
new file mode 100644
index 0000000..d9463a2
--- /dev/null
+++ b/swig/python/samples/ogr_build_junction_table.py
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+#******************************************************************************
+#  $Id$
+# 
+#  Name:     $Id$
+#  Project:  
+#  Purpose:  Build a junction table from _href fields
+#  Author:   Even Rouault, <even dot rouault at mines-paris dot org>
+#
+# ******************************************************************************
+#  Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+# 
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+# 
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#******************************************************************************
+
+
+from osgeo import gdal
+from osgeo import ogr
+import os
+import sys
+
+
+def Usage():
+    print('Usage: ogr_build_junction_table.py [-append|-overwrite] datasource_name [layer_name]')
+    print('')
+    print('This utility is aimed at creating junction tables for layers coming from GML datasources')
+    print('that reference other objects in _href fields')
+    print('')
+    sys.exit(1)
+
+def build_junction_table(ds, lyr, ifield, bAppend, bOverwrite):
+
+    first_table = lyr.GetName()
+    second_table = lyr.GetLayerDefn().GetFieldDefn(ifield).GetName()[0:-5]
+    junction_table_name = first_table + '_' + second_table
+
+    gdal.PushErrorHandler('CPLQuietErrorHandler')
+    junction_lyr = ds.GetLayerByName(junction_table_name)
+    gdal.PopErrorHandler()
+    if junction_lyr is not None:
+        if bOverwrite:
+            for i in range(ds.GetLayerCount()):
+                if ds.GetLayer(i).GetName() == junction_table_name:
+                    if ds.DeleteLayer(i) != 0:
+                        print('Cannot delete layer %s for recreation' % junction_table_name)
+                        return False
+                    else:
+                        junction_lyr = None
+                    break
+        elif not bAppend:
+            print('Layer %s already exists' % junction_table_name)
+            return False
+
+    if junction_lyr is None:
+        junction_lyr = ds.CreateLayer(junction_table_name, geom_type = ogr.wkbNone)
+        if junction_lyr is None:
+            print('Cannot create layer %s' % junction_table_name)
+            return False
+        print('Creating layer %s...' % junction_table_name)
+
+        fld_defn = ogr.FieldDefn(first_table + '_gml_id', ogr.OFTString)
+        if junction_lyr.CreateField(fld_defn) != 0:
+            print('Cannot create field %s' % fld_defn.GetName())
+            return False
+
+        fld_defn = ogr.FieldDefn(second_table + '_gml_id', ogr.OFTString)
+        if junction_lyr.CreateField(fld_defn) != 0:
+            print('Cannot create field %s' % fld_defn.GetName())
+            return False
+
+        gdal.PushErrorHandler('CPLQuietErrorHandler')
+        ds.ExecuteSQL('CREATE INDEX idx_%s_gml_id ON %s(gml_id)' % (first_table, first_table))
+        ds.ExecuteSQL('CREATE INDEX idx_%s_gml_id ON %s(gml_id)' % (second_table, second_table))
+        ds.ExecuteSQL('CREATE INDEX idx_%s_gml_id ON %s(%s)' % (junction_table_name+'_'+first_table, junction_table_name,first_table + '_gml_id'))
+        ds.ExecuteSQL('CREATE INDEX idx_%s_gml_id ON %s(%s)' % (junction_table_name+'_'+second_table, junction_table_name,second_table + '_gml_id'))
+        gdal.PopErrorHandler()
+
+    lyr.ResetReading()
+    field_type = lyr.GetLayerDefn().GetFieldDefn(ifield).GetType()
+
+    junction_lyr.StartTransaction()
+    count_features = 0
+
+    for feat in lyr:
+        gml_id = feat.GetFieldAsString('gml_id')
+        if field_type == ogr.OFTStringList:
+            href_list = feat.GetFieldAsStringList(ifield)
+        else:
+            href = feat.GetFieldAsString(ifield)
+            if href[0] == '(' and href.find(':') > 0 and href[-1] == ')':
+                href_list = href[href.find(':')+1:-1].split(',')
+            else:
+                href_list = [ href ]
+
+        for href in href_list:
+            target_feature = ogr.Feature(junction_lyr.GetLayerDefn())
+            target_feature.SetField(0, gml_id)
+            if href[0] == '#':
+                href = href[1:]
+            target_feature.SetField(1, href)
+            junction_lyr.CreateFeature(target_feature)
+            target_feature = None
+
+            count_features = count_features + 1
+            if count_features == 200:
+                junction_lyr.CommitTransaction()
+                junction_lyr.StartTransaction()
+                count_features = 0
+
+    junction_lyr.CommitTransaction()
+
+    return True
+
+
+def process_layer(ds, lyr_name, bAppend, bOverwrite):
+    lyr = ds.GetLayerByName(lyr_name)
+    if lyr is None:
+        print('Cannot find layer %s in datasource' % lyr_name)
+        return False
+    lyr_defn = lyr.GetLayerDefn()
+
+    if lyr_defn.GetFieldIndex('gml_id') < 0:
+        return True
+
+    ret = True
+    for ifield in range(lyr_defn.GetFieldCount()):
+        if lyr_defn.GetFieldDefn(ifield).GetName().endswith("_href"):
+            if not build_junction_table(ds, lyr, ifield, bAppend, bOverwrite):
+                ret = False
+    return ret
+
+argv = sys.argv
+argv = ogr.GeneralCmdLineProcessor( argv )
+
+ds_name = None
+lyr_name = None
+bAppend = False
+bOverwrite = False
+
+nArgc = len(argv)
+iArg = 1
+while iArg < nArgc:
+
+    if argv[iArg] == '-append':
+        bAppend = True
+
+    elif argv[iArg] == '-overwrite':
+        bOverwrite = True
+
+    elif argv[iArg][0] == '-':
+        Usage()
+
+    elif ds_name is None:
+        ds_name = argv[iArg]
+
+    elif lyr_name is None:
+        lyr_name = argv[iArg]
+
+    iArg = iArg + 1
+
+if ds_name is None:
+    Usage()
+
+if bAppend and bOverwrite:
+    print('Only one of -append or -overwrite can be used')
+    sys.exit(1)
+
+ds = ogr.Open(ds_name, update = 1)
+if ds is None:
+    print('Cannot open %s in update mode' % ds_name)
+    sys.exit(1)
+
+ret = True
+if lyr_name is not None:
+    ret = process_layer(ds, lyr_name, bAppend, bOverwrite)
+else:
+    for i in range(ds.GetLayerCount()):
+        if not process_layer(ds, ds.GetLayer(i).GetName(), bAppend, bOverwrite):
+            ret = False
+ds = None
+
+if ret:
+    sys.exit(0)
+else:
+    sys.exit(1)
diff --git a/swig/python/samples/ogr_dispatch.py b/swig/python/samples/ogr_dispatch.py
new file mode 100644
index 0000000..83546c2
--- /dev/null
+++ b/swig/python/samples/ogr_dispatch.py
@@ -0,0 +1,399 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id: ogr_dispatch.py 27044 2014-03-16 23:41:27Z rouault $
+#
+# Project:  GDAL/OGR samples
+# Purpose:  Dispatch features into layers according to the value of some fields
+#           or the geometry type.
+# Author:   Even Rouault <even dot rouault at mines dash paris dot org>
+#
+###############################################################################
+# Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+from osgeo import ogr
+from osgeo import osr
+import sys
+
+###############################################################
+# Usage()
+
+def Usage():
+    print('ogr_dispatch.py [-f format] -src name -dst name [-field field]+')
+    print('                [-25D_as_2D] [-multi_as_single]')
+    print('                [-remove_dispatch_fields] [-prefix_with_layer_name]')
+    print('                [-dsco KEY=VALUE]* [-lco KEY=VALUE]* [-a_srs srs_def]')
+    print('                [-style_as_field] [-where restricted_where] [-gt n] [-quiet]')
+    print('')
+    print('Dispatch features into layers according to the value of some fields or the')
+    print('geometry type.')
+    print('')
+    print('Arguments:')
+    print(' -f format: name of the driver to use to create the destination dataset')
+    print('            (default \'ESRI Shapefile\').')
+    print(' -src name: name of the source dataset.')
+    print(' -dst name: name of the destination dataset (existing or to be created).')
+    print(' -field field: name of a field to use to dispatch features. May also')
+    print('                        be \'OGR_GEOMETRY\'. At least, one occurence needed.')
+    print(' -25D_as_2D: for dispatching, consider 2.5D geometries as 2D.')
+    print(' -multi_as_single: for dispatching, consider MULTIPOLYGON as POLYGON and')
+    print('                   MULTILINESTRING as LINESTRING.')
+    print(' -remove_dispatch_fields: remove the dispatch fields from the target layer definitions.')
+    print(' -prefix_with_layer_name: prefix the target layer name with the source layer name.')
+    print(' -dsco KEY=VALUE: dataset creation option. May be repeated.')
+    print(' -lco KEY=VALUE: layer creation option. May be repeated.')
+    print(' -a_srs srs_def: assign a SRS to the target layers. Source layer SRS is otherwise used.')
+    print(' -style_as_field: add a OGR_STYLE field with the content of the feature style string.')
+    print(' -where restricted_where: where clause to filter source features.')
+    print(' -gt n: group n features per transaction (default 200).')
+    print('')
+    print('Example :')
+    print('  ogr_dispatch.py -src in.dxf -dst out -field Layer -field OGR_GEOMETRY')
+    print('')
+
+    return 1
+
+###############################################################################
+
+def EQUAL(a, b):
+    return a.lower() == b.lower()
+
+###############################################################
+# wkbFlatten()
+
+def wkbFlatten(x):
+    return x & (~ogr.wkb25DBit)
+
+###############################################################
+
+class Options:
+    def __init__(self):
+        self.lco = []
+        self.dispatch_fields = []
+        self.b25DAs2D = False
+        self.bMultiAsSingle = False
+        self.bRemoveDispatchFields = False
+        self.poOutputSRS = None
+        self.bNullifyOutputSRS = False
+        self.bPrefixWithLayerName = False
+        self.bStyleAsField = False
+        self.nGroupTransactions = 200
+        self.bQuiet = False
+
+###############################################################
+# GeometryTypeToName()
+
+def GeometryTypeToName(eGeomType, options):
+
+    if options.b25DAs2D:
+        eGeomType = wkbFlatten(eGeomType)
+
+    if eGeomType == ogr.wkbPoint:
+        return 'POINT'
+    elif eGeomType == ogr.wkbLineString:
+        return 'LINESTRING'
+    elif eGeomType == ogr.wkbPolygon:
+        return 'POLYGON'
+    elif eGeomType == ogr.wkbMultiPoint:
+        return 'MULTIPOINT'
+    elif eGeomType == ogr.wkbMultiLineString:
+        if options.bMultiAsSingle:
+            return 'LINESTRING'
+        else:
+            return 'MULTILINESTRING'
+    elif eGeomType == ogr.wkbMultiPolygon:
+        if options.bMultiAsSingle:
+            return 'POLYGON'
+        else:
+            return 'MULTIPOLYGON'
+    elif eGeomType == ogr.wkbGeometryCollection:
+        return 'GEOMETRYCOLLECTION'
+    elif eGeomType == ogr.wkbPoint25D:
+        return 'POINT25D'
+    elif eGeomType == ogr.wkbLineString25D:
+        return 'LINESTRING25D'
+    elif eGeomType == ogr.wkbPolygon25D:
+        return 'POLYGON25D'
+    elif eGeomType == ogr.wkbMultiPoint25D:
+        return 'MULTIPOINT25D'
+    elif eGeomType == ogr.wkbMultiLineString25D:
+        if options.bMultiAsSingle:
+            return 'LINESTRING25D'
+        else:
+            return 'MULTILINESTRING25D'
+    elif eGeomType == ogr.wkbMultiPolygon25D:
+        if options.bMultiAsSingle:
+            return 'POLYGON25D'
+        else:
+            return 'MULTIPOLYGON25D'
+    elif eGeomType == ogr.wkbGeometryCollection25D:
+        return 'GEOMETRYCOLLECTION25D'
+    else:
+        # Shouldn't happen
+        return 'UNKNOWN'
+
+###############################################################
+# get_out_lyr_name()
+
+def get_out_lyr_name(src_lyr, feat, options):
+    if options.bPrefixWithLayerName:
+        out_lyr_name = src_lyr.GetName()
+    else:
+        out_lyr_name = ''
+
+    for dispatch_field in options.dispatch_fields:
+        if EQUAL(dispatch_field, 'OGR_GEOMETRY'):
+            geom = feat.GetGeometryRef()
+            if geom is None:
+                val = 'NONE'
+            else:
+                val = GeometryTypeToName(geom.GetGeometryType(), options)
+        else:
+            if feat.IsFieldSet(dispatch_field):
+                val = feat.GetFieldAsString(dispatch_field)
+            else:
+                val = 'null'
+
+        if out_lyr_name == '':
+            out_lyr_name = val
+        else:
+            out_lyr_name = out_lyr_name + '_' + val
+
+    return out_lyr_name
+
+###############################################################
+# get_layer_and_map()
+
+def get_layer_and_map(out_lyr_name, src_lyr, dst_ds, layerMap, geom_type, options):
+
+    if out_lyr_name not in layerMap:
+        if options.poOutputSRS is not None or options.bNullifyOutputSRS:
+            srs = options.poOutputSRS
+        else:
+            srs = src_lyr.GetSpatialRef()
+        out_lyr = dst_ds.GetLayerByName(out_lyr_name)
+        if out_lyr is None:
+            if not options.bQuiet:
+                print('Creating layer %s' % out_lyr_name)
+            out_lyr = dst_ds.CreateLayer(out_lyr_name, srs = srs, \
+                                geom_type = geom_type, options = options.lco)
+            if out_lyr is None:
+                return 1
+            src_field_count = src_lyr.GetLayerDefn().GetFieldCount()
+            panMap = [ -1 for i in range(src_field_count) ]
+            for i in range(src_field_count):
+                field_defn = src_lyr.GetLayerDefn().GetFieldDefn(i)
+                if options.bRemoveDispatchFields:
+                    found = False
+                    for dispatch_field in options.dispatch_fields:
+                        if EQUAL(dispatch_field, field_defn.GetName()):
+                            found = True
+                            break
+                    if found:
+                        continue
+                idx = out_lyr.GetLayerDefn().GetFieldIndex(field_defn.GetName())
+                if idx >= 0:
+                    panMap[i] = idx
+                elif out_lyr.CreateField(field_defn) == 0:
+                    panMap[i] = out_lyr.GetLayerDefn().GetFieldCount() - 1
+            if options.bStyleAsField:
+                out_lyr.CreateField(ogr.FieldDefn('OGR_STYLE', ogr.OFTString))
+        else:
+            panMap = None
+        layerMap[out_lyr_name] = [out_lyr, panMap]
+    else:
+        out_lyr = layerMap[out_lyr_name][0]
+        panMap = layerMap[out_lyr_name][1]
+
+    return (out_lyr, panMap)
+
+###############################################################
+# convert_layer()
+
+def convert_layer(src_lyr, dst_ds, layerMap, options):
+
+    current_out_lyr = None
+    nFeaturesInTransaction = 0
+
+    for feat in src_lyr:
+
+        out_lyr_name = get_out_lyr_name(src_lyr, feat, options)
+
+        geom = feat.GetGeometryRef()
+        if geom is not None:
+            geom_type = geom.GetGeometryType()
+        else:
+            geom_type = ogr.wkbUnknown
+
+        (out_lyr, panMap) = get_layer_and_map(out_lyr_name, src_lyr, dst_ds, \
+                                              layerMap, geom_type, options)
+
+        if options.nGroupTransactions > 0:
+            if out_lyr != current_out_lyr:
+                if current_out_lyr is not None:
+                    current_out_lyr.CommitTransaction()
+                current_out_lyr = out_lyr
+                current_out_lyr.StartTransaction()
+                nFeaturesInTransaction = 0
+
+            if nFeaturesInTransaction == options.nGroupTransactions:
+                current_out_lyr.CommitTransaction()
+                current_out_lyr.StartTransaction()
+        else:
+            current_out_lyr = out_lyr
+
+        out_feat = ogr.Feature(out_lyr.GetLayerDefn())
+        if panMap is not None:
+            out_feat.SetFromWithMap( feat, 1, panMap )
+        else:
+            out_feat.SetFrom(feat)
+        if options.bStyleAsField:
+            style = feat.GetStyleString()
+            if style is not None:
+                out_feat.SetField('OGR_STYLE', style)
+        out_lyr.CreateFeature(out_feat)
+
+        nFeaturesInTransaction = nFeaturesInTransaction + 1
+
+    if options.nGroupTransactions > 0 and current_out_lyr is not None:
+        current_out_lyr.CommitTransaction()
+
+    return 1
+
+###############################################################
+# ogr_dispatch()
+
+def ogr_dispatch(argv, progress = None, progress_arg = None):
+
+    src_filename = None
+    dst_filename = None
+    format = "ESRI Shapefile"
+    options = Options()
+    dsco = []
+    pszWHERE = None
+
+    if len(argv) == 0:
+        return Usage()
+
+    i = 0
+    while i < len(argv):
+        arg = argv[i]
+        if EQUAL(arg, '-src') and i+1 < len(argv):
+            i = i + 1
+            src_filename = argv[i]
+        elif EQUAL(arg, '-dst') and i+1 < len(argv):
+            i = i + 1
+            dst_filename = argv[i]
+        elif EQUAL(arg, '-f') and i+1 < len(argv):
+            i = i + 1
+            format = argv[i]
+
+        elif EQUAL(arg,'-a_srs') and i+1 < len(argv):
+            i = i + 1
+            pszOutputSRSDef = argv[i]
+            if EQUAL(pszOutputSRSDef, "NULL") or \
+               EQUAL(pszOutputSRSDef, "NONE"):
+                options.bNullifyOutputSRS = True
+            else:
+                options.poOutputSRS = osr.SpatialReference()
+                if options.poOutputSRS.SetFromUserInput( pszOutputSRSDef ) != 0:
+                    print( "Failed to process SRS definition: %s" % pszOutputSRSDef )
+                    return 1
+        elif EQUAL(arg, '-dsco') and i+1 < len(argv):
+            i = i + 1
+            dsco.append(argv[i])
+        elif EQUAL(arg, '-lco') and i+1 < len(argv):
+            i = i + 1
+            lco.append(argv[i])
+        elif EQUAL(arg, '-field') and i+1 < len(argv):
+            i = i + 1
+            options.dispatch_fields.append(argv[i])
+        elif EQUAL(arg, '-25D_as_2D'):
+            options.b25DAs2D = True
+        elif EQUAL(arg, '-multi_as_single'):
+            options.bMultiAsSingle = True
+        elif EQUAL(arg, '-remove_dispatch_fields'):
+            options.bRemoveDispatchFields = True
+        elif EQUAL(arg, '-prefix_with_layer_name'):
+            options.bPrefixWithLayerName = True
+        elif EQUAL(arg, '-style_as_field'):
+            options.bStyleAsField = True
+        elif (EQUAL(arg,"-tg") or \
+                EQUAL(arg,"-gt"))  and i+1 < len(argv):
+            i = i + 1
+            options.nGroupTransactions = int(argv[i])
+        elif EQUAL(arg,"-where") and i+1 < len(argv):
+            i = i + 1
+            pszWHERE = argv[i]
+        elif EQUAL(arg, '-quiet'):
+            options.bQuiet = True
+        else:
+            print('Unrecognized argument : %s' % arg)
+            return Usage()
+        i = i + 1
+
+    if src_filename is None:
+        print('Missing -src')
+        return 1
+
+    if dst_filename is None:
+        print('Missing -dst')
+        return 1
+
+    if len(options.dispatch_fields) == 0:
+        print('Missing -dispatch_field')
+        return 1
+
+    src_ds = ogr.Open(src_filename)
+    if src_ds is None:
+        print('Cannot open source datasource %s' % src_filename)
+        return 1
+
+    dst_ds = ogr.Open(dst_filename, update = 1)
+    if dst_ds is not None:
+        if len(options.dsco) != 0:
+            print('-dsco should not be specified for an existing datasource')
+            return 1
+    else:
+        dst_ds = ogr.GetDriverByName(format).CreateDataSource(dst_filename, options = dsco)
+    if dst_ds is None:
+        print('Cannot open or create target datasource %s' % dst_filename)
+        return 1
+
+    layerMap = {}
+
+    for src_lyr in src_ds:
+        if pszWHERE is not None:
+            src_lyr.SetAttributeFilter(pszWHERE)
+        ret = convert_layer(src_lyr, dst_ds, layerMap, options)
+        if ret != 0:
+            return ret
+
+
+    return 0
+
+###############################################################
+# Entry point
+
+if __name__ == '__main__':
+    argv = ogr.GeneralCmdLineProcessor( sys.argv )
+    sys.exit(ogr_dispatch(argv[1:]))
diff --git a/swig/python/samples/ogr_layer_algebra.py b/swig/python/samples/ogr_layer_algebra.py
index 418cf60..59d6f1f 100644
--- a/swig/python/samples/ogr_layer_algebra.py
+++ b/swig/python/samples/ogr_layer_algebra.py
@@ -1,14 +1,14 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: ogr_layer_algebra.py 25468 2013-01-06 18:28:32Z rouault $
+#  $Id: ogr_layer_algebra.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for executing OGR layer algebra operations
 #  Author:   Even Rouault, even dot rouault at mines-paris dot org
 # 
 #******************************************************************************
-#  Copyright (c) 2013, Even Rouault
+#  Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/ogrinfo.py b/swig/python/samples/ogrinfo.py
index 0ebfed0..274ccb0 100755
--- a/swig/python/samples/ogrinfo.py
+++ b/swig/python/samples/ogrinfo.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #/******************************************************************************
-# * $Id: ogrinfo.py 23329 2011-11-05 21:09:07Z rouault $
+# * $Id: ogrinfo.py 27044 2014-03-16 23:41:27Z rouault $
 # *
 # * Project:  OpenGIS Simple Features Reference Implementation
 # * Purpose:  Python port of a simple client for viewing OGR driver data.
@@ -9,7 +9,7 @@
 # * Port from ogrinfo.cpp whose author is Frank Warmerdam
 # *
 # ******************************************************************************
-# * Copyright (c) 2010, Even Rouault
+# * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
 # * Copyright (c) 1999, Frank Warmerdam
 # *
 # * Permission is hereby granted, free of charge, to any person obtaining a
@@ -73,6 +73,7 @@ def main(argv = None):
     pszSQLStatement = None
     pszDialect = None
     options = {}
+    pszGeomField = None
 
     if argv is None:
         argv = sys.argv
@@ -115,6 +116,10 @@ def main(argv = None):
             poSpatialFilter.AddGeometry(oRing)
             iArg = iArg + 4
 
+        elif EQUAL(argv[iArg],"-geomfield") and iArg < nArgc-1:
+            iArg = iArg + 1
+            pszGeomField = argv[iArg]
+
         elif EQUAL(argv[iArg],"-where") and iArg < nArgc-1:
             iArg = iArg + 1
             pszWHERE = argv[iArg]
@@ -211,8 +216,11 @@ def main(argv = None):
         if papszLayers is not None:
             print( "layer names ignored in combination with -sql." )
 
-        poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, 
-                                        pszDialect )
+        if pszGeomField is None:
+            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+                                            pszDialect )
+        else:
+            poResultSet = poDS.ExecuteSQL( pszSQLStatement, None, pszDialect )
 
         if poResultSet is not None:
             if pszWHERE is not None:
@@ -220,7 +228,10 @@ def main(argv = None):
                     print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
                     return 1
 
-            ReportOnLayer( poResultSet, None, None, options )
+            if pszGeomField is not None:
+                ReportOnLayer( poResultSet, None, pszGeomField, poSpatialFilter, options )
+            else:
+                ReportOnLayer( poResultSet, None, None, None, options )
             poDS.ReleaseResultSet( poResultSet )
 
     #gdal.Debug( "OGR", "GetLayerCount() = %d\n", poDS.GetLayerCount() )
@@ -240,6 +251,16 @@ def main(argv = None):
                 if not bAllLayers:
                     line = "%d: %s" % (iLayer+1, poLayer.GetLayerDefn().GetName())
 
+                    nGeomFieldCount = poLayer.GetLayerDefn().GetGeomFieldCount()
+                    if nGeomFieldCount > 1:
+                        line = line + " ("
+                        for iGeom in range(nGeomFieldCount):
+                            if iGeom > 0:
+                                line = line + ", "
+                            poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
+                            line = line + "%s" % ogr.GeometryTypeToName( poGFldDefn.GetType() )
+                        line = line + ")"
+
                     if poLayer.GetLayerDefn().GetGeomType() != ogr.wkbUnknown:
                         line = line + " (%s)" % ogr.GeometryTypeToName( poLayer.GetLayerDefn().GetGeomType() )
 
@@ -248,7 +269,7 @@ def main(argv = None):
                     if iRepeat != 0:
                         poLayer.ResetReading()
 
-                    ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options )
+                    ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options )
 
         else:
 #/* -------------------------------------------------------------------- */ 
@@ -264,7 +285,7 @@ def main(argv = None):
                 if iRepeat != 0:
                     poLayer.ResetReading()
 
-                ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options )
+                ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options )
 
 #/* -------------------------------------------------------------------- */
 #/*      Close down.                                                     */
@@ -280,7 +301,7 @@ def main(argv = None):
 def Usage():
 
     print( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]\n"
-            "               [-spat xmin ymin xmax ymax] [-fid fid]\n"
+            "               [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]\n"
             "               [-sql statement] [-al] [-so] [-fields={YES/NO}]\n"
             "               [-geom={YES/NO/SUMMARY}][--formats]\n"
             "               datasource_name [layer [layer ...]]")
@@ -290,7 +311,7 @@ def Usage():
 #/*                           ReportOnLayer()                            */
 #/************************************************************************/
 
-def ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options ):
+def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
 
     poDefn = poLayer.GetLayerDefn()
 
@@ -303,7 +324,14 @@ def ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options ):
             return
 
     if poSpatialFilter is not None:
-        poLayer.SetSpatialFilter( poSpatialFilter )
+        if pszGeomField is not None:
+            iGeomField = poLayer.GetLayerDefn().GetGeomFieldIndex(pszGeomField)
+            if iGeomField >= 0:
+                poLayer.SetSpatialFilter( iGeomField, poSpatialFilter )
+            else:
+                print("WARNING: Cannot find geometry field %s." % pszGeomField)
+        else:
+            poLayer.SetSpatialFilter( poSpatialFilter )
 
 #/* -------------------------------------------------------------------- */
 #/*      Report various overall information.                             */
@@ -313,26 +341,52 @@ def ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options ):
     print( "Layer name: %s" % poDefn.GetName() )
 
     if bVerbose:
-        print( "Geometry: %s" % ogr.GeometryTypeToName( poDefn.GetGeomType() ) )
+        nGeomFieldCount = poLayer.GetLayerDefn().GetGeomFieldCount()
+        if nGeomFieldCount > 1:
+            for iGeom in range(nGeomFieldCount):
+                poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
+                print( "Geometry (%s): %s" % (poGFldDefn.GetNameRef(), ogr.GeometryTypeToName( poGFldDefn.GetType() ) ))
+        else:
+            print( "Geometry: %s" % ogr.GeometryTypeToName( poDefn.GetGeomType() ) )
         
         print( "Feature Count: %d" % poLayer.GetFeatureCount() )
         
-        oExt = poLayer.GetExtent(True, can_return_null = True)
-        if oExt is not None:
-            print("Extent: (%f, %f) - (%f, %f)" % (oExt[0], oExt[1], oExt[2], oExt[3]))
-
-        if poLayer.GetSpatialRef() is None:
-            pszWKT = "(unknown)"
+        if nGeomFieldCount > 1:
+            for iGeom in range(nGeomFieldCount):
+                poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
+                oExt = poLayer.GetExtent(True, geom_field = iGeom, can_return_null = True)
+                if oExt is not None:
+                    print("Extent (%s): (%f, %f) - (%f, %f)" % (poGFldDefn.GetNameRef(), oExt[0], oExt[2], oExt[1], oExt[3]))
         else:
-            pszWKT = poLayer.GetSpatialRef().ExportToPrettyWkt()
-
-        print( "Layer SRS WKT:\n%s" % pszWKT )
+            oExt = poLayer.GetExtent(True, can_return_null = True)
+            if oExt is not None:
+                print("Extent: (%f, %f) - (%f, %f)" % (oExt[0], oExt[2], oExt[1], oExt[3]))
+
+        if nGeomFieldCount > 1:
+            for iGeom in range(nGeomFieldCount):
+                poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
+                if poGFldDefn.GetSpatialRef() is None:
+                    pszWKT = "(unknown)"
+                else:
+                    pszWKT = poGFldDefn.GetSpatialRef().ExportToPrettyWkt()
+                print( "SRS WKT (%s):\n%s" % (poGFldDefn.GetNameRef(), pszWKT) )
+        else:
+            if poLayer.GetSpatialRef() is None:
+                pszWKT = "(unknown)"
+            else:
+                pszWKT = poLayer.GetSpatialRef().ExportToPrettyWkt()
+            print( "Layer SRS WKT:\n%s" % pszWKT )
     
         if len(poLayer.GetFIDColumn()) > 0:
             print( "FID Column = %s" % poLayer.GetFIDColumn() )
     
-        if len(poLayer.GetGeometryColumn()) > 0:
-            print( "Geometry Column = %s" % poLayer.GetGeometryColumn() )
+        if nGeomFieldCount > 1:
+            for iGeom in range(nGeomFieldCount):
+                poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
+                print( "Geometry Column %d = %s" % (iGeom + 1, poGFldDefn.GetNameRef() ))
+        else:
+            if len(poLayer.GetGeometryColumn()) > 0:
+                print( "Geometry Column = %s" % poLayer.GetGeometryColumn() )
 
         for iAttr in range(poDefn.GetFieldCount()):
             poField = poDefn.GetFieldDefn( iAttr )
@@ -394,10 +448,17 @@ def DumpReadableFeature( poFeature, options = None ):
         if 'DISPLAY_STYLE' not in options or EQUAL(options['DISPLAY_STYLE'], 'yes'):
             print("  Style = %s" % GetStyleString() )
 
-    poGeometry = poFeature.GetGeometryRef()
-    if poGeometry is not None:
+    nGeomFieldCount = poFeature.GetGeomFieldCount()
+    if nGeomFieldCount > 0:
         if 'DISPLAY_GEOMETRY' not in options or not EQUAL(options['DISPLAY_GEOMETRY'], 'no'):
-            DumpReadableGeometry( poGeometry, "  ", options)
+            for iField in range(nGeomFieldCount):
+                poGFldDefn = poFeature.GetDefnRef().GetGeomFieldDefn(iField)
+                poGeometry = poFeature.GetGeomFieldRef(iField)
+                if poGeometry is not None:
+                    sys.stdout.write("  ")
+                    if len(poGFldDefn.GetNameRef()) > 0 and nGeomFieldCount > 1:
+                        sys.stdout.write("%s = " % poGFldDefn.GetNameRef() )
+                    DumpReadableGeometry( poGeometry, "", options)
 
     print('')
 
diff --git a/swig/python/samples/ogrupdate.py b/swig/python/samples/ogrupdate.py
index e61b83e..8ac696c 100644
--- a/swig/python/samples/ogrupdate.py
+++ b/swig/python/samples/ogrupdate.py
@@ -1,14 +1,14 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogrupdate.py 25346 2012-12-25 22:38:21Z rouault $
+# $Id: ogrupdate.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL/OGR samples
 # Purpose:  Update an existing datasource with features from another one
 # Author:   Even Rouault <even dot rouault at mines dash paris dot org>
 #
 ###############################################################################
-# Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
+# Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/rel.py b/swig/python/samples/rel.py
index fee860c..f634cc9 100755
--- a/swig/python/samples/rel.py
+++ b/swig/python/samples/rel.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: rel.py 24538 2012-06-04 18:30:34Z antonio $
+# $Id: rel.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to produce a shaded relief image from elevation data
@@ -8,6 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/tigerpoly.py b/swig/python/samples/tigerpoly.py
index 5afcdc1..2db8817 100755
--- a/swig/python/samples/tigerpoly.py
+++ b/swig/python/samples/tigerpoly.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: tigerpoly.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: tigerpoly.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  OGR Python samples
 # Purpose:  Assemble TIGER Polygons.
@@ -8,6 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+# Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/tolatlong.py b/swig/python/samples/tolatlong.py
index 9d723b3..7f01d4b 100755
--- a/swig/python/samples/tolatlong.py
+++ b/swig/python/samples/tolatlong.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: tolatlong.py 19386 2010-04-11 19:20:36Z rouault $
+# $Id: tolatlong.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to read coordinate system and geotransformation matrix
@@ -10,6 +10,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+# Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/val_at_coord.py b/swig/python/samples/val_at_coord.py
index d5fe78b..87c4cef 100755
--- a/swig/python/samples/val_at_coord.py
+++ b/swig/python/samples/val_at_coord.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: val_at_coord.py 20674 2010-09-22 17:50:33Z rouault $
+# $Id: val_at_coord.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Outputs the value of the raster bands at a given
@@ -8,7 +8,7 @@
 # Author:   Even Rouault
 #
 ###############################################################################
-# Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
+# Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/val_repl.py b/swig/python/samples/val_repl.py
index 2e7bc71..4e73472 100755
--- a/swig/python/samples/val_repl.py
+++ b/swig/python/samples/val_repl.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: val_repl.py 19920 2010-06-26 10:59:03Z rouault $
+# $Id: val_repl.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to replace specified values from the input raster file
@@ -11,6 +11,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
+# Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/samples/wcs_virtds_params.py b/swig/python/samples/wcs_virtds_params.py
new file mode 100644
index 0000000..51f25e6
--- /dev/null
+++ b/swig/python/samples/wcs_virtds_params.py
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+#******************************************************************************
+#  $Id$
+# 
+#  Name:     wcs_virtds_params.py
+#  Project:  GDAL Python Interface
+#  Purpose:  Generates MapServer WCS layer definition from a tileindex with mixed SRS
+#  Author:   Even Rouault, <even dot rouault at mines-paris dot org>
+#
+# ******************************************************************************
+#  Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+# 
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+# 
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#******************************************************************************
+
+
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
+import os
+import sys
+
+
+def Usage():
+    print('Usage: wcs_virtds_params.py [-lyr_name name] [-tileindex field_name] [-t_srs srsdef] -src_srs_name field_name ogr_ds_tileindex')
+    sys.exit(1)
+
+argv = sys.argv
+argv = ogr.GeneralCmdLineProcessor( argv )
+
+ogr_ds_name = None
+lyr_name = None
+
+tileitem = 'location'
+tilesrs = None
+srsname = None
+
+nArgc = len(argv)
+iArg = 1
+while iArg < nArgc:
+
+    if argv[iArg] == "-lyr_name" and iArg < nArgc-1:
+        iArg = iArg + 1
+        lyr_name = argv[iArg]
+
+    elif argv[iArg] == "-tileindex" and iArg < nArgc-1:
+        iArg = iArg + 1
+        tileitem = argv[iArg]
+
+    elif argv[iArg] == "-src_srs_name" and iArg < nArgc-1:
+        iArg = iArg + 1
+        tilesrs = argv[iArg]
+
+    elif argv[iArg] == "-t_srs" and iArg < nArgc-1:
+        iArg = iArg + 1
+        srsname = argv[iArg]
+
+    elif argv[iArg][0] == '-':
+        Usage()
+
+    elif ogr_ds_name is None:
+        ogr_ds_name = argv[iArg]
+
+    iArg = iArg + 1
+
+if ogr_ds_name is None or tilesrs is None:
+    Usage()
+
+ogr_ds = ogr.Open(ogr_ds_name)
+if ogr_ds is None:
+    raise Exception('cannot open %s' % ogr_ds_name)
+if ogr_ds.GetLayerCount() == 1:
+    lyr = ogr_ds.GetLayer(0)
+elif lyr_name is None:
+    raise Exception('-lyr_name should be specified')
+else:
+    lyr = ogr_ds.GetLayerByName(lyr_name)
+
+if lyr.GetLayerDefn().GetFieldIndex(tileitem) < 0:
+    raise Exception('%s field cannot be found in layer definition' % tileitem)
+
+if lyr.GetLayerDefn().GetFieldIndex(tilesrs) < 0:
+    raise Exception('%s field cannot be found in layer definition' % tilesrs)
+
+lyr_srs = lyr.GetSpatialRef()
+if srsname is not None:
+    srs = osr.SpatialReference()
+    if srs.SetFromUserInput(srsname) != 0:
+        raise Exception('invalid value for -t_srs : %s' % srsname)
+
+    # Sanity check
+    if lyr_srs is not None:
+        lyr_srs_proj4 = lyr_srs.ExportToProj4()
+        lyr_srs = osr.SpatialReference()
+        lyr_srs.SetFromUserInput(lyr_srs_proj4)
+        lyr_srs_proj4 = lyr_srs.ExportToProj4()
+
+        srs_proj4 = srs.ExportToProj4()
+        if lyr_srs_proj4 != srs_proj4:
+            raise Exception('-t_srs overrides the layer SRS in an incompatible way : (%s, %s)' % (srs_proj4, lyr_srs_proj4))
+else:
+    srs = lyr_srs
+
+if srs is None:
+    raise Exception('cannot fetch source SRS')
+
+srs.AutoIdentifyEPSG()
+authority_name = srs.GetAuthorityName(None)
+authority_code = srs.GetAuthorityCode(None)
+dst_wkt = srs.ExportToWkt()
+if authority_name != 'EPSG' or authority_code is None:
+    raise Exception('cannot fetch source SRS as EPSG:XXXX code : %s' % dst_wkt)
+
+counter = 0
+xres = 0
+yres = 0
+
+while True:
+    feat = lyr.GetNextFeature()
+    if feat is None:
+        break
+    #feat.DumpReadable()
+
+    gdal_ds_name = feat.GetField(tileitem)
+    if not os.path.isabs(gdal_ds_name):
+        gdal_ds_name = os.path.join(os.path.dirname(ogr_ds_name), gdal_ds_name)
+    gdal_ds = gdal.Open(gdal_ds_name)
+    if gdal_ds is None:
+        raise Exception('cannot open %s' % gdal_ds_name)
+    warped_vrt_ds = gdal.AutoCreateWarpedVRT(gdal_ds, None, dst_wkt)
+    if warped_vrt_ds is None:
+        raise Exception('cannot warp %s to %s' % (gdal_ds_name, dst_wkt))
+    gt = warped_vrt_ds.GetGeoTransform()
+    xres += gt[1]
+    yres += gt[5]
+    warped_vrt_ds = None
+
+    counter = counter + 1
+
+if counter == 0:
+    raise Exception('tileindex is empty')
+
+xres /= counter
+yres /= counter
+(xmin, xmax, ymin, ymax) = lyr.GetExtent()
+xsize = (int)((xmax - xmin) / xres + 0.5)
+ysize = (int)((ymax - ymin) / abs(yres) + 0.5)
+
+layername = lyr.GetName()
+
+if ogr_ds.GetDriver().GetName() != 'ESRI Shapefile':
+    print("""LAYER
+  NAME "%s_tileindex"
+  TYPE POLYGON
+  STATUS OFF
+  CONNECTIONTYPE OGR
+  CONNECTION "%s,%s"
+  PROJECTION
+    "+init=epsg:%s" 
+  END
+END""" % (layername, ogr_ds_name, lyr.GetName(), authority_code))
+    print("")
+
+    tileindex = "%s_tileindex" % layername
+else:
+    tileindex = ogr_ds_name
+
+print("""LAYER
+  NAME "%s"
+  TYPE RASTER
+  STATUS ON
+  TILEINDEX "%s"
+  TILEITEM "%s"
+  TILESRS "%s"
+  PROJECTION
+    "+init=epsg:%s" 
+  END
+  METADATA   
+   "wcs_label"       "%s"
+   "wcs_rangeset_name"   "Range 1"  ### required to support DescribeCoverage request
+   "wcs_rangeset_label"  "My Label" ### required to support DescribeCoverage request
+   "wcs_extent"      "%f %f %f %f"
+   "wcs_size"        "%d %d"
+   "wcs_resolution"  "%f %f"
+  END
+END""" % (layername, tileindex, tileitem, tilesrs, authority_code, layername, xmin, ymin, xmax, ymax, xsize, ysize, xres, abs(yres)))
diff --git a/swig/python/scripts/epsg_tr.py b/swig/python/scripts/epsg_tr.py
index 1653d4f..3549fd2 100755
--- a/swig/python/scripts/epsg_tr.py
+++ b/swig/python/scripts/epsg_tr.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: epsg_tr.py 19102 2010-03-15 23:41:44Z warmerdam $
+#  $Id: epsg_tr.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  CFS OGC MapServer
 #  Purpose:  Script to create WKT and PROJ.4 dictionaries for EPSG GCS/PCS
@@ -9,6 +9,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
+#  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gcps2wld.py b/swig/python/scripts/gcps2wld.py
index 4742f43..2f337ad 100755
--- a/swig/python/scripts/gcps2wld.py
+++ b/swig/python/scripts/gcps2wld.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gcps2wld.py 18952 2010-02-28 11:59:53Z rouault $
+#  $Id: gcps2wld.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Name:     gcps2wld
 #  Project:  GDAL Python Interface
@@ -10,6 +10,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2002, Frank Warmerdam
+#  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdal2tiles.py b/swig/python/scripts/gdal2tiles.py
index 97dff39..498d737 100755
--- a/swig/python/scripts/gdal2tiles.py
+++ b/swig/python/scripts/gdal2tiles.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gdal2tiles.py 25611 2013-02-07 10:24:56Z bishop $
+#  $Id: gdal2tiles.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 # Project:  Google Summer of Code 2007, 2008 (http://code.google.com/soc/)
 # Support:  BRGM (http://www.brgm.fr)
@@ -15,6 +16,7 @@
 #
 ###############################################################################
 # Copyright (c) 2008, Klokan Petr Pridal
+# Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
@@ -56,7 +58,7 @@ except:
     # 'antialias' resampling is not available
     pass
 
-__version__ = "$Id: gdal2tiles.py 25611 2013-02-07 10:24:56Z bishop $"
+__version__ = "$Id: gdal2tiles.py 27044 2014-03-16 23:41:27Z rouault $"
 
 resampling_list = ('average','near','bilinear','cubic','cubicspline','lanczos','antialias')
 profile_list = ('mercator','geodetic','raster') #,'zoomify')
@@ -352,15 +354,23 @@ class GlobalGeodetic(object):
        WMS, KML    Web Clients, Google Earth  TileMapService
     """
 
-    def __init__(self, tileSize = 256):
+    def __init__(self, tmscompatible, tileSize = 256):
         self.tileSize = tileSize
+        if tmscompatible is not None:
+            # Defaults the resolution factor to 0.703125 (2 tiles @ level 0)
+            # Adhers to OSGeo TMS spec http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic
+            self.resFact = 180.0 / self.tileSize
+        else:
+            # Defaults the resolution factor to 1.40625 (1 tile @ level 0)
+            # Adheres OpenLayers, MapProxy, etc default resolution for WMTS
+            self.resFact = 360.0 / self.tileSize
 
-    def LatLonToPixels(self, lat, lon, zoom):
-        "Converts lat/lon to pixel coordinates in given zoom of the EPSG:4326 pyramid"
+    def LonLatToPixels(self, lon, lat, zoom):
+        "Converts lon/lat to pixel coordinates in given zoom of the EPSG:4326 pyramid"
 
-        res = 180.0 / self.tileSize / 2**zoom
-        px = (180 + lat) / res
-        py = (90 + lon) / res
+        res = self.resFact / 2**zoom
+        px = (180 + lon) / res
+        py = (90 + lat) / res
         return px, py
 
     def PixelsToTile(self, px, py):
@@ -370,16 +380,16 @@ class GlobalGeodetic(object):
         ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
         return tx, ty
 
-    def LatLonToTile(self, lat, lon, zoom):
-        "Returns the tile for zoom which covers given lat/lon coordinates"
+    def LonLatToTile(self, lon, lat, zoom):
+        "Returns the tile for zoom which covers given lon/lat coordinates"
 
-        px, py = self.LatLonToPixels( lat, lon, zoom)
+        px, py = self.LonLatToPixels( lon, lat, zoom)
         return self.PixelsToTile(px,py)
 
     def Resolution(self, zoom ):
         "Resolution (arc/pixel) for given zoom level (measured at Equator)"
 
-        return 180.0 / self.tileSize / 2**zoom
+        return self.resFact / 2**zoom
         #return 180 / float( 1 << (8+zoom) )
 
     def ZoomForPixelSize(self, pixelSize ):
@@ -394,7 +404,7 @@ class GlobalGeodetic(object):
 
     def TileBounds(self, tx, ty, zoom):
         "Returns bounds of the given tile"
-        res = 180.0 / self.tileSize / 2**zoom
+        res = self.resFact / 2**zoom
         return (
             tx*self.tileSize*res - 180,
             ty*self.tileSize*res - 90,
@@ -655,6 +665,8 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
                           help="Resume mode. Generate only missing files.")
         p.add_option('-a', '--srcnodata', dest="srcnodata", metavar="NODATA",
                           help="NODATA transparency value to assign to the input data")
+        p.add_option('-d', '--tmscompatible', dest="tmscompatible", action="store_true",
+                          help="When using the geodetic profile, specifies the base resolution as 0.703125 or 2 tiles at zoom level 0.")
         p.add_option("-v", "--verbose",
                           action="store_true", dest="verbose",
                           help="Print status messages to stdout")
@@ -980,7 +992,7 @@ gdal2tiles temp.vrt""" % self.input )
 
         if self.options.profile == 'geodetic':
 
-            self.geodetic = GlobalGeodetic() # from globalmaptiles.py
+            self.geodetic = GlobalGeodetic(self.options.tmscompatible) # from globalmaptiles.py
 
             # Function which generates SWNE in LatLong for given tile
             self.tileswne = self.geodetic.TileLatLonBounds
@@ -988,8 +1000,8 @@ gdal2tiles temp.vrt""" % self.input )
             # Generate table with min max tile coordinates for all zoomlevels
             self.tminmax = list(range(0,32))
             for tz in range(0, 32):
-                tminx, tminy = self.geodetic.LatLonToTile( self.ominx, self.ominy, tz )
-                tmaxx, tmaxy = self.geodetic.LatLonToTile( self.omaxx, self.omaxy, tz )
+                tminx, tminy = self.geodetic.LonLatToTile( self.ominx, self.ominy, tz )
+                tmaxx, tmaxy = self.geodetic.LonLatToTile( self.omaxx, self.omaxy, tz )
                 # crop tiles extending world limits (+-180,+-90)
                 tminx, tminy = max(0, tminx), max(0, tminy)
                 tmaxx, tmaxy = min(2**(tz+1)-1, tmaxx), min(2**tz-1, tmaxy)
@@ -1952,6 +1964,10 @@ gdal2tiles temp.vrt""" % self.input )
         args['tileformat'] = self.tileext
         args['publishurl'] = self.options.url
         args['copyright'] = self.options.copyright
+        if self.options.tmscompatible:
+            args['tmsoffset'] = "-1"
+        else:
+            args['tmsoffset'] = ""
         if self.options.profile == 'raster':
             args['rasterzoomlevels'] = self.tmaxz+1
             args['rastermaxresolution'] = 2**(self.nativezoom) * self.out_gt[1]
@@ -2079,7 +2095,7 @@ gdal2tiles temp.vrt""" % self.input )
                   map = new OpenLayers.Map(options);
 
                   var wms = new OpenLayers.Layer.WMS("VMap0",
-                      "http://labs.metacarta.com/wms-c/Basic.py?",
+                      "http://tilecache.osgeo.org/wms-c/Basic.py?",
                       {
                           layers: 'basic',
                           format: 'image/png'
@@ -2172,7 +2188,7 @@ gdal2tiles temp.vrt""" % self.input )
                   var res = this.getServerResolution();
                   var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
                   var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
-                  var z = this.getServerZoom()-1;
+                  var z = this.getServerZoom()%(tmsoffset)s;
                   var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
                   var url = this.url;
                   if (OpenLayers.Util.isArray(url)) {
diff --git a/swig/python/scripts/gdal_auth.py b/swig/python/scripts/gdal_auth.py
index 3119eae..96f60d2 100755
--- a/swig/python/scripts/gdal_auth.py
+++ b/swig/python/scripts/gdal_auth.py
@@ -38,10 +38,17 @@ import os
 import time
 import webbrowser
 
+SCOPES = {
+    'ft' : 'https://www.googleapis.com/auth/fusiontables',
+    'gme' : 'https://www.googleapis.com/auth/mapsengine',
+    'gme.ro' : 'https://www.googleapis.com/auth/mapsengine.readonly',
+    }
+
 # =============================================================================
 # 	Usage()
 # =============================================================================
 def Usage():
+    print('')
     print('Usage: gdal_auth_py [-s scope]' )
     print('       - interactive use.')
     print('')
@@ -49,13 +56,16 @@ def Usage():
     print('Usage: gdal_auth.py login [-s scope] ')
     print('Usage: gdal_auth.py auth2refresh [-s scope] auth_token')
     print('Usage: gdal_auth.py refresh2access [-s scope] refresh_token')
+    print('')
+    print('scopes: ft/gme/gme.ro/full_url')
+    print('')
     sys.exit(1)
 
 # =============================================================================
 # 	Mainline
 # =============================================================================
 
-scope = 'https://www.googleapis.com/auth/fusiontables'
+scope = SCOPES['ft']
 token_in = None
 command = None
 
@@ -69,7 +79,14 @@ while i < len(argv):
     arg = argv[i]
 
     if arg == '-s' and i < len(argv)-1:
-        scope = argv[i+1]
+        if argv[i+1] in SCOPES:
+            scope = SCOPES[argv[i+1]]
+        elif argv[i+1].startswith('http'):
+            scope = argv[i+1]
+        else:
+            print('Scope %s not recognised.' % argv[i+1])
+            Usage()
+            sys.exit(1)
         i = i + 1
 
     elif arg[0] == '-':
diff --git a/swig/python/scripts/gdal_calc.dox b/swig/python/scripts/gdal_calc.dox
new file mode 100644
index 0000000..8f3ebbd
--- /dev/null
+++ b/swig/python/scripts/gdal_calc.dox
@@ -0,0 +1,62 @@
+
+/*! \page gdal_calc gdal_calc.py
+
+Command line raster calculator with numpy syntax
+
+\section gdal_calc_synopsis SYNOPSIS
+
+\verbatim
+gdal_calc.py [-A <filename>] [--A_band] [-B...-Z filename] [other_options]
+
+Options:
+  -h, --help            show this help message and exit
+  --calc=CALC           calculation in gdalnumeric syntax using +-/* or any
+                        numpy array functions (i.e. logical_and())
+  -A A                  input gdal raster file, note you can use any letter
+                        A-Z
+  --A_band=A_BAND       number of raster band for file A (default 0)
+  --outfile=OUTF        output file to generate or fill
+  --NoDataValue=NODATAVALUE
+                        set output nodata value (Defaults to datatype specific
+                        value)
+  --type=TYPE           output datatype, must be one of ['Int32', 'Int16',
+                        'Float64', 'UInt16', 'Byte', 'UInt32', 'Float32']
+  --format=FORMAT       GDAL format for output file (default 'GTiff')
+  --creation-option=CREATION_OPTIONS, --co=CREATION_OPTIONS
+                        Passes a creation option to the output format driver.
+                        Multiple options may be listed. See format specific
+                        documentation for legal creation options for each
+                        format.
+  --allBands=ALLBANDS   process all bands of given raster (A-Z)
+  --overwrite           overwrite output file if it already exists
+  --debug               print debugging information
+\endverbatim
+
+\section gdal_edit_description DESCRIPTION
+
+Command line raster calculator with numpy syntax. Use any basic arithmetic supported by numpy arrays such as +-*\ along with logical operators such as >.  Note that all files must have the same dimensions, but no projection checking is performed.
+
+\section gdal_edit_example EXAMPLE
+
+add two files together
+\verbatim
+gdal_calc.py -A input1.tif -B input2.tif --outfile=result.tif --calc="A+B"
+\endverbatim
+
+average of two layers
+\verbatim
+gdal_calc.py -A input.tif -B input2.tif --outfile=result.tif --calc="(A+B)/2"
+\endverbatim
+
+set values of zero and below to null
+\verbatim
+gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
+\endverbatim
+
+\if man
+\section gdal_edit_author AUTHORS
+Chris Yesson <chris dot yesson at ioz dot ac dot uk>
+Etienne Tourigny <etourigny dot dev at gmail dot com>
+\endif
+*/
+
diff --git a/swig/python/scripts/gdal_calc.py b/swig/python/scripts/gdal_calc.py
index c8728b1..82021c8 100755
--- a/swig/python/scripts/gdal_calc.py
+++ b/swig/python/scripts/gdal_calc.py
@@ -3,11 +3,12 @@
 #******************************************************************************
 # 
 #  Project:  GDAL
-#  Purpose:  Command line raster calculator for gdal supported files
+#  Purpose:  Command line raster calculator with numpy syntax
 #  Author:   Chris Yesson, chris.yesson at ioz.ac.uk
 # 
 #******************************************************************************
 #  Copyright (c) 2010, Chris Yesson <chris.yesson at ioz.ac.uk>
+#  Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
@@ -29,7 +30,7 @@
 #******************************************************************************
 
 ################################################################
-# Command line raster calculator for gdal supported files. Use any basic arithmetic supported by numpy arrays such as +-*\ along with logical operators such as >.  Note that all files must be the same dimensions, but no projection checking is performed.  Use gdal_calc.py --help for list of options.
+# Command line raster calculator with numpy syntax. Use any basic arithmetic supported by numpy arrays such as +-*\ along with logical operators such as >.  Note that all files must have the same dimensions, but no projection checking is performed.  Use gdal_calc.py --help for list of options.
 
 # example 1 - add two files together
 # gdal_calc.py -A input1.tif -B input2.tif --outfile=result.tif --calc="A+B"
@@ -107,12 +108,28 @@ def doit(opts, args):
             if opts.debug:
                 print("file %s: %s, dimensions: %s, %s, type: %s" %(myI,myF,DimensionsCheck[0],DimensionsCheck[1],myDataType[i]))
 
+    # process allBands option
+    allBandsIndex=None
+    allBandsCount=1
+    if opts.allBands:
+        try:
+            allBandsIndex=myAlphaList.index(opts.allBands)
+        except ValueError:
+            print("Error! allBands option was given but Band %s not found.  Cannot proceed" % (opts.allBands))
+            return
+        allBandsCount=myFiles[allBandsIndex].RasterCount
+        if allBandsCount <= 1:
+            allBandsIndex=None
+
     ################################################################
     # set up output file
     ################################################################
 
     # open output file exists
     if os.path.isfile(opts.outF) and not opts.overwrite:
+        if allBandsIndex is not None:
+            print("Error! allBands option was given but Output file exists, must use --overwrite option!")
+            return
         if opts.debug:
             print("Output file %s exists - filling in results into file" %(opts.outF))
         myOut=gdal.Open(opts.outF, gdal.GA_Update)
@@ -141,23 +158,23 @@ def doit(opts, args):
         # create file
         myOutDrv = gdal.GetDriverByName(opts.format)
         myOut = myOutDrv.Create(
-            opts.outF, DimensionsCheck[0], DimensionsCheck[1], 1,
+            opts.outF, DimensionsCheck[0], DimensionsCheck[1], allBandsCount,
             gdal.GetDataTypeByName(myOutType), opts.creation_options)
 
         # set output geo info based on first input layer
         myOut.SetGeoTransform(myFiles[0].GetGeoTransform())
         myOut.SetProjection(myFiles[0].GetProjection())
 
-        myOutB=myOut.GetRasterBand(1)
         if opts.NoDataValue!=None:
             myOutNDV=opts.NoDataValue
         else:
             myOutNDV=DefaultNDVLookup[myOutType]
-        myOutB.SetNoDataValue(myOutNDV)
-        # write to band
-        myOutB=None
-        # refetch band
-        myOutB=myOut.GetRasterBand(1)
+
+        for i in range(1,allBandsCount+1):
+            myOutB=myOut.GetRasterBand(i)
+            myOutB.SetNoDataValue(myOutNDV)
+            # write to band
+            myOutB=None
 
     if opts.debug:
         print("output file: %s, dimensions: %s, %s, type: %s" %(opts.outF,myOut.RasterXSize,myOut.RasterYSize,gdal.GetDataTypeName(myOutB.DataType)))
@@ -182,80 +199,91 @@ def doit(opts, args):
     # variables for displaying progress
     ProgressCt=-1
     ProgressMk=-1
-    ProgressEnd=nXBlocks*nYBlocks
+    ProgressEnd=nXBlocks*nYBlocks*allBandsCount
     
     ################################################################
-    # start looping through blocks of data
+    # start looping through each band in allBandsCount
     ################################################################
 
-    # loop through X-lines
-    for X in range(0,nXBlocks):
-
-        # in the rare (impossible?) case that the blocks don't fit perfectly
-        # change the block size of the final piece
-        if X==nXBlocks-1:
-             nXValid = DimensionsCheck[0] - X * myBlockSize[0]
-             myBufSize = nXValid*nYValid
-
-        # find X offset
-        myX=X*myBlockSize[0]
-
-        # reset buffer size for start of Y loop
-        nYValid = myBlockSize[1]
-        myBufSize = nXValid*nYValid
-
-        # loop through Y lines
-        for Y in range(0,nYBlocks):
-            ProgressCt+=1
-            if 10*ProgressCt/ProgressEnd%10!=ProgressMk:
-                ProgressMk=10*ProgressCt/ProgressEnd%10
-                from sys import version_info
-                if version_info >= (3,0,0):
-                    exec('print("%d.." % (10*ProgressMk), end=" ")')
-                else:
-                    exec('print 10*ProgressMk, "..",')
-
-            # change the block size of the final piece
-            if Y==nYBlocks-1:
-                nYValid = DimensionsCheck[1] - Y * myBlockSize[1]
-                myBufSize = nXValid*nYValid
+    for bandNo in range(1,allBandsCount+1):
 
-            # find Y offset
-            myY=Y*myBlockSize[1]
+        ################################################################
+        # start looping through blocks of data
+        ################################################################
 
-            # create empty buffer to mark where nodata occurs
-            myNDVs=numpy.zeros(myBufSize)
-            myNDVs.shape=(nYValid,nXValid)
+        # loop through X-lines
+        for X in range(0,nXBlocks):
 
-            # fetch data for each input layer
-            for i,Alpha in enumerate(myAlphaList):
-
-                # populate lettered arrays with values
-                myval=BandReadAsArray(myFiles[i].GetRasterBand(myBands[i]),
-                                      xoff=myX, yoff=myY,
-                                      win_xsize=nXValid, win_ysize=nYValid)
-
-                # fill in nodata values
-                myNDVs=1*numpy.logical_or(myNDVs==1, myval==myNDV[i])
-
-                # create an array of values for this block
-                exec("%s=myval" %Alpha)
-                myval=None
-
-
-            # try the calculation on the array blocks
-            try:
-                myResult = eval(opts.calc)
-            except:
-                print("evaluation of calculation %s failed" %(opts.calc))
-                raise
-
-            # propogate nodata values 
-            # (set nodata cells to zero then add nodata value to these cells)
-            myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
+            # in the rare (impossible?) case that the blocks don't fit perfectly
+            # change the block size of the final piece
+            if X==nXBlocks-1:
+                nXValid = DimensionsCheck[0] - X * myBlockSize[0]
+                myBufSize = nXValid*nYValid
 
-            # write data block to the output file
-            BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY)
+            # find X offset
+            myX=X*myBlockSize[0]
+
+            # reset buffer size for start of Y loop
+            nYValid = myBlockSize[1]
+            myBufSize = nXValid*nYValid
+
+            # loop through Y lines
+            for Y in range(0,nYBlocks):
+                ProgressCt+=1
+                if 10*ProgressCt/ProgressEnd%10!=ProgressMk:
+                    ProgressMk=10*ProgressCt/ProgressEnd%10
+                    from sys import version_info
+                    if version_info >= (3,0,0):
+                        exec('print("%d.." % (10*ProgressMk), end=" ")')
+                    else:
+                        exec('print 10*ProgressMk, "..",')
+
+                # change the block size of the final piece
+                if Y==nYBlocks-1:
+                    nYValid = DimensionsCheck[1] - Y * myBlockSize[1]
+                    myBufSize = nXValid*nYValid
+
+                # find Y offset
+                myY=Y*myBlockSize[1]
+
+                # create empty buffer to mark where nodata occurs
+                myNDVs=numpy.zeros(myBufSize)
+                myNDVs.shape=(nYValid,nXValid)
+
+                # fetch data for each input layer
+                for i,Alpha in enumerate(myAlphaList):
+
+                    # populate lettered arrays with values
+                    if allBandsIndex is not None and allBandsIndex==i:
+                        myBandNo=bandNo
+                    else:
+                        myBandNo=myBands[i]
+                    myval=BandReadAsArray(myFiles[i].GetRasterBand(myBandNo),
+                                          xoff=myX, yoff=myY,
+                                          win_xsize=nXValid, win_ysize=nYValid)
+
+                    # fill in nodata values
+                    myNDVs=1*numpy.logical_or(myNDVs==1, myval==myNDV[i])
+
+                    # create an array of values for this block
+                    exec("%s=myval" %Alpha)
+                    myval=None
+
+
+                # try the calculation on the array blocks
+                try:
+                    myResult = eval(opts.calc)
+                except:
+                    print("evaluation of calculation %s failed" %(opts.calc))
+                    raise
+
+                # propogate nodata values 
+                # (set nodata cells to zero then add nodata value to these cells)
+                myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
+
+                # write data block to the output file
+                myOutB=myOut.GetRasterBand(bandNo)
+                BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY)
 
     print("100 - Done")
     #print("Finished - Results written to %s" %opts.outF)
@@ -272,17 +300,18 @@ def main():
     # hack to limit the number of input file options close to required number
     for myAlpha in AlphaList[0:len(sys.argv)-1]:
         eval('parser.add_option("-%s", dest="%s", help="input gdal raster file, note you can use any letter A-Z")' %(myAlpha, myAlpha))
-        eval('parser.add_option("--%s_band", dest="%s_band", default=0, type=int, help="number of raster band for file %s")' %(myAlpha, myAlpha, myAlpha))
+        eval('parser.add_option("--%s_band", dest="%s_band", default=0, type=int, help="number of raster band for file %s (default 0)")' %(myAlpha, myAlpha, myAlpha))
 
-    parser.add_option("--outfile", dest="outF", default='gdal_calc.tif', help="output file to generate or fill.")
-    parser.add_option("--NoDataValue", dest="NoDataValue", type=float, help="set output nodatavalue (Defaults to datatype specific values)")
-    parser.add_option("--type", dest="type", help="set datatype must be one of %s" % list(DefaultNDVLookup.keys()))
+    parser.add_option("--outfile", dest="outF", default='gdal_calc.tif', help="output file to generate or fill")
+    parser.add_option("--NoDataValue", dest="NoDataValue", type=float, help="set output nodata value (Defaults to datatype specific value)")
+    parser.add_option("--type", dest="type", help="output datatype, must be one of %s" % list(DefaultNDVLookup.keys()))
     parser.add_option("--format", dest="format", default="GTiff", help="GDAL format for output file (default 'GTiff')")
     parser.add_option(
         "--creation-option", "--co", dest="creation_options", default=[], action="append",
-        help="Passes a creation option to the output format driver. Multiple"
-        "options may be listed. See format specific documentation for legal"
+        help="Passes a creation option to the output format driver. Multiple "
+        "options may be listed. See format specific documentation for legal "
         "creation options for each format.")
+    parser.add_option("--allBands", dest="allBands", default="", help="process all bands of given raster (A-Z)")
     parser.add_option("--overwrite", dest="overwrite", action="store_true", help="overwrite output file if it already exists")
     parser.add_option("--debug", dest="debug", action="store_true", help="print debugging information")
 
diff --git a/swig/python/scripts/gdal_edit.dox b/swig/python/scripts/gdal_edit.dox
index 0e83744..129670a 100644
--- a/swig/python/scripts/gdal_edit.dox
+++ b/swig/python/scripts/gdal_edit.dox
@@ -6,7 +6,7 @@ Edit in place various information of an existing GDAL dataset
 \section gdal_edit_synopsis SYNOPSIS
 
 \verbatim
-gdal_edit [--help-general] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
+gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
           [-tr xres yres] [-unsetgt] [-a_nodata value]
           [-gcp pixel line easting northing [elevation]]*
           [-mo "META-TAG=VALUE"]*  datasetname
@@ -26,6 +26,11 @@ Gives a brief usage message for the generic GDAL commandline options
 and exit.
 </dd>
 
+<dt> <b>-ro</b></dt>:<dd> (GDAL >= 1.11)
+Open the dataset in read-only. Might be usefull for drivers refusing to
+use the dataset in update-mode. In which case, updated information will go
+into PAM .aux.xml files.</dd>
+
 <dt> <b>-a_srs</b> <i>srs_def</i>:</dt><dd>
 
 Defines the target coordinate system.  This coordinate system will be
@@ -42,8 +47,7 @@ Both must be positive values.</dd>
 Remove the georeference information.</dd>
 
 <dt> <b>-a_nodata</b> <i>value</i>:</dt><dd>
-Assign a specified nodata value to output bands. Can be set to <i>none</i>
-to remove a nodata value if one exists for the dataset.</dd>
+Assign a specified nodata value to output bands.</dd>
 
 <dt> <b>-gcp</b> <i>pixel line easting northing [elevation]</i>:</dt><dd>
 Add the indicated ground control point to the dataset.  This option 
diff --git a/swig/python/scripts/gdal_edit.py b/swig/python/scripts/gdal_edit.py
index eff5790..9e829ef 100755
--- a/swig/python/scripts/gdal_edit.py
+++ b/swig/python/scripts/gdal_edit.py
@@ -1,14 +1,14 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: gdal_edit.py 25549 2013-01-26 11:17:10Z rouault $
+# $Id: gdal_edit.py 27044 2014-03-16 23:41:27Z rouault $
 #
 #  Project:  GDAL samples
 #  Purpose:  Edit in place various information of an existing GDAL dataset
 #  Author:   Even Rouault <even dot rouault at mines dash paris dot org>
 #
 ###############################################################################
-#  Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
+#  Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
 #
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,7 @@ from osgeo import gdal
 from osgeo import osr
 
 def Usage():
-    print('Usage: gdal_edit [--help-general] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]')
+    print('Usage: gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]')
     print('                 [-tr xres yres] [-unsetgt] [-a_nodata value] ')
     print('                 [-gcp pixel line easting northing [elevation]]*')
     print('                 [-mo "META-TAG=VALUE"]*  datasetname')
@@ -69,13 +69,16 @@ def gdal_edit(argv):
     xres = None
     yres = None
     unsetgt = False
+    ro = False
     molist = []
     gcp_list = []
 
     i = 1
     argc = len(argv)
     while i < argc:
-        if argv[i] == '-a_srs' and i < len(argv)-1:
+        if argv[i] == '-ro':
+            ro = True
+        elif argv[i] == '-a_srs' and i < len(argv)-1:
             srs = argv[i+1]
             i = i + 1
         elif argv[i] == '-a_ullr' and i < len(argv)-4:
@@ -147,7 +150,10 @@ def gdal_edit(argv):
         print('')
         return Usage()
 
-    ds = gdal.Open(datasetname, gdal.GA_Update)
+    if ro:
+        ds = gdal.Open(datasetname)
+    else:
+        ds = gdal.Open(datasetname, gdal.GA_Update)
     if ds is None:
         return -1
 
diff --git a/swig/python/scripts/gdal_fillnodata.py b/swig/python/scripts/gdal_fillnodata.py
index e4778ea..a86fd0a 100755
--- a/swig/python/scripts/gdal_fillnodata.py
+++ b/swig/python/scripts/gdal_fillnodata.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_fillnodata.py 23153 2011-10-01 13:40:24Z rouault $
+#  $Id: gdal_fillnodata.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for filling nodata areas in a raster by interpolation
@@ -8,6 +8,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
+#  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdal_merge.py b/swig/python/scripts/gdal_merge.py
index efd8800..3844886 100755
--- a/swig/python/scripts/gdal_merge.py
+++ b/swig/python/scripts/gdal_merge.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal_merge.py 24064 2012-03-04 00:34:19Z warmerdam $
+# $Id: gdal_merge.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Project:  InSAR Peppers
 # Purpose:  Module to extract data from many rasters into one output.
@@ -8,6 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+# Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
diff --git a/swig/python/scripts/gdal_polygonize.py b/swig/python/scripts/gdal_polygonize.py
index eb092df..c38afd8 100755
--- a/swig/python/scripts/gdal_polygonize.py
+++ b/swig/python/scripts/gdal_polygonize.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gdal_polygonize.py 25664 2013-02-22 15:43:33Z rouault $
+#  $Id: gdal_polygonize.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for converting raster data to a vector polygon layer.
@@ -9,6 +9,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
+#  Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdal_proximity.py b/swig/python/scripts/gdal_proximity.py
index c0ecd6f..36230c2 100755
--- a/swig/python/scripts/gdal_proximity.py
+++ b/swig/python/scripts/gdal_proximity.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_proximity.py 23152 2011-10-01 13:39:52Z rouault $
+#  $Id: gdal_proximity.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Name:     gdalproximity
 #  Project:  GDAL Python Interface
@@ -9,6 +9,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
+#  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdal_retile.py b/swig/python/scripts/gdal_retile.py
index c38bf59..c3685f1 100755
--- a/swig/python/scripts/gdal_retile.py
+++ b/swig/python/scripts/gdal_retile.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-#  $Id: gdal_retile.py 24037 2012-02-28 17:21:35Z rouault $
+#  $Id: gdal_retile.py 27044 2014-03-16 23:41:27Z rouault $
 #
 # Purpose:  Module for retiling (merging) tiles and building tiled pyramids
 # Author:   Christian Meuller, christian.mueller at nvoe.at
@@ -8,6 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2007, Christian Mueller
+# Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdal_sieve.py b/swig/python/scripts/gdal_sieve.py
index e5bd7a2..a19bfd1 100755
--- a/swig/python/scripts/gdal_sieve.py
+++ b/swig/python/scripts/gdal_sieve.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_sieve.py 19392 2010-04-12 18:27:09Z rouault $
+#  $Id: gdal_sieve.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for applying sieve filter to raster data.
@@ -8,6 +8,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
+#  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/gdalcompare.dox b/swig/python/scripts/gdalcompare.dox
new file mode 100644
index 0000000..505116d
--- /dev/null
+++ b/swig/python/scripts/gdalcompare.dox
@@ -0,0 +1,50 @@
+
+/*! \page gdalcompare gdalcompare.py
+
+compare two images
+
+\section gdalcompare_synopsis SYNOPSIS
+
+\verbatim
+gdalcompare.py [-sds] golden_file new_file
+\endverbatim
+
+\section gdalcompare_description DESCRIPTION
+
+The gdalcompare.py script compares two GDAL supported datasets and reports
+the differences.  In addition to reporting differences to the standard out
+the script will also return the difference count in it's exit value. 
+
+Image pixels, and various metadata are checked.  There is also a byte by
+byte comparison done which will count as one difference.  So if it is 
+only important that the GDAL visible data is identical a difference count
+of 1 (the binary difference) should be considered acceptable. 
+
+
+<dl>
+
+<dt> <b>-sds</b>:</dt><dd>
+If this flag is passed the script will compare all subdatasets that are part
+of the dataset, otherwise subdatasets are ignored.
+
+<dt> <i>golden_file</i>:</dt><dd>
+The file that is considered correct, referred to as the golden file.
+
+<dt> <i>new_file</i>:</dt><dd>
+The file being compared to the golden file, referred to as the new file.
+
+</dl>
+
+Note that the gdalcompare.py script can also be called as a library from 
+python code though it is not typically in the python path for including. The
+primary entry point is gdalcompare.compare() which takes a golden gdal.Dataset
+and a new gdal.Dataset as arguments and returns a difference count (excluding
+the binary comparison).  The gdalcompare.compare_sds() entry point can be used
+to compare subdatasets.
+
+\if man
+\section gdalcompare_author AUTHORS
+Frank Warmerdam <warmerdam at pobox.com>
+\endif
+*/
+
diff --git a/swig/python/scripts/gdalcompare.py b/swig/python/scripts/gdalcompare.py
new file mode 100755
index 0000000..d0a63fa
--- /dev/null
+++ b/swig/python/scripts/gdalcompare.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#******************************************************************************
+#
+#  Project:  GDAL
+#  Purpose:  Compare two files for differences and report.
+#  Author:   Frank Warmerdam, warmerdam at pobox.com
+#
+#******************************************************************************
+#  Copyright (c) 2012, Frank Warmerdam <warmerdam at pobox.com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#******************************************************************************
+
+import os
+import sys
+import filecmp
+
+from osgeo import gdal, osr
+
+#######################################################
+def compare_metadata(golden_md, new_md, id):
+  if golden_md is None and new_md is None:
+    return 0
+
+  found_diff = 0
+
+  if len(list(golden_md.keys())) != len(list(new_md.keys())):
+    print('Difference in %s metadata key count' % id)
+    print('  Golden Keys: ' + str(list(golden_md.keys())))
+    print('  New Keys: ' + str(list(new_md.keys())))
+    found_diff += 1
+
+  for key in list(golden_md.keys()):
+    if key not in new_md:
+      print('New %s metadata lacks key \"%s\"' % (id, key))
+      found_diff += 1
+    elif new_md[key] != golden_md[key]:
+      print('Metadata value difference for key "' + key + '"')
+      print('  Golden: "' + golden_md[key] + '"')
+      print('  New:    "' + new_md[key] + '"')
+      found_diff += 1
+
+  return found_diff
+
+
+#######################################################
+# Review and report on the actual image pixels that differ.
+def compare_image_pixels(golden_band, new_band, id):
+  diff_count = 0
+  max_diff = 0
+
+  for line in range(golden_band.YSize):
+    golden_line = golden_band.ReadAsArray(0, line, golden_band.XSize, 1)[0]
+    new_line = new_band.ReadAsArray(0, line, golden_band.XSize, 1)[0]
+    diff_line = golden_line - new_line
+    max_diff = max(max_diff,abs(diff_line).max())
+    diff_count += len(diff_line.nonzero()[0])
+
+  print('  Pixels Differing: ' + str(diff_count))
+  print('  Maximum Pixel Difference: ' + str(max_diff))
+
+#######################################################
+def compare_band(golden_band, new_band, id):
+  found_diff = 0
+
+  if golden_band.DataType != new_band.DataType:
+    print('Band %s pixel types differ.' % id)
+    print('  Golden: ' + gdal.GetDataTypeName(golden_band.DataType))
+    print('  New:    ' + gdal.GetDataTypeName(new_band.DataType))
+    found_diff += 1
+
+  if golden_band.GetNoDataValue() != new_band.GetNoDataValue():
+    print('Band %s nodata values differ.' % id)
+    print('  Golden: ' + str(golden_band.GetNoDataValue()))
+    print('  New:    ' + str(new_band.GetNoDataValue()))
+    found_diff += 1
+
+  if golden_band.GetColorInterpretation() != new_band.GetColorInterpretation():
+    print('Band %s color interpretation values differ.' % id)
+    print('  Golden: ' +  gdal.GetColorInterpretationName(golden_band.GetColorInterpretation()))
+    print('  New:    ' + gdal.GetColorInterpretationName(new_band.GetColorInterpretation()))
+    found_diff += 1
+
+  if golden_band.Checksum() != new_band.Checksum():
+    print('Band %s checksum difference:' % id)
+    print('  Golden: ' + str(golden_band.Checksum()))
+    print('  New:    ' + str(new_band.Checksum()))
+    found_diff += 1
+    compare_image_pixels(golden_band,new_band, id)
+
+  # Check overviews
+  if golden_band.GetOverviewCount() != new_band.GetOverviewCount():
+    print('Band %s overview count difference:' % id)
+    print('  Golden: ' + str(golden_band.GetOverviewCount()))
+    print('  New:    ' + str(new_band.GetOverviewCount()))
+    found_diff += 1
+  else:
+    for i in range(golden_band.GetOverviewCount()):
+      compare_band(golden_band.GetOverview(i),
+                   new_band.GetOverview(i),
+                   id + ' overview ' + str(i))
+
+  # Metadata
+  found_diff += compare_metadata(golden_band.GetMetadata(),
+                                 new_band.GetMetadata(),
+                                 'Band ' + id)
+
+  # TODO: Color Table, gain/bias, units, blocksize, mask, min/max
+
+  return found_diff
+
+#######################################################
+def compare_srs(golden_wkt, new_wkt):
+  if golden_wkt == new_wkt:
+    return 0
+
+  print('Difference in SRS!')
+
+  golden_srs = osr.SpatialReference(golden_wkt)
+  new_srs = osr.SpatialReference(new_wkt)
+
+  if golden_srs.IsSame(new_srs):
+    print('  * IsSame() reports them as equivelent.')
+  else:
+    print('  * IsSame() reports them as different.')
+
+  print('  Golden:')
+  print('  ' + golden_srs.ExportToPrettyWkt())
+  print('  New:')
+  print('  ' + new_srs.ExportToPrettyWkt())
+
+  return 1
+
+#######################################################
+def compare_db(golden_db, new_db):
+  found_diff = 0
+
+  # SRS
+  found_diff += compare_srs(golden_db.GetProjection(),
+                            new_db.GetProjection())
+
+  # GeoTransform
+  golden_gt = golden_db.GetGeoTransform()
+  new_gt = new_db.GetGeoTransform()
+  if golden_gt != new_gt:
+    print('GeoTransforms Differ:')
+    print('  Golden: ' + str(golden_gt))
+    print('  New:    ' + str(new_gt))
+    found_diff += 1
+
+  # Metadata
+  found_diff += compare_metadata(golden_db.GetMetadata(),
+                                 new_db.GetMetadata(),
+                                 'Dataset')
+
+  # Bands
+  if golden_db.RasterCount != new_db.RasterCount:
+    print('Band count mismatch (golden=%d, new=%d)' \
+        % (golden_db.RasterCount, new_db.RasterCount))
+    found_diff += 1
+
+  elif golden_db.RasterXSize != new_db.RasterXSize or \
+       golden_db.RasterYSize != new_db.RasterYSize:
+    print('Image dimension mismatch (golden=%dx%d, new=%dx%d)' \
+          % (golden_db.RasterXSize, golden_db.RasterYSize,
+             new_db.RasterXSize, new_db.RasterYSize))
+    found_diff += 1
+  else:
+    for i in range(golden_db.RasterCount):
+      found_diff += compare_band(golden_db.GetRasterBand(i+1),
+                                 new_db.GetRasterBand(i+1),
+                                 str(i+1))
+
+  return found_diff
+
+#######################################################
+def compare_sds(golden_db, new_db):
+  found_diff = 0
+  
+  golden_sds = golden_db.GetMetadata('SUBDATASETS')
+  new_sds = new_db.GetMetadata('SUBDATASETS')
+
+  count = len(list(golden_sds.keys())) / 2
+  for i in range(count):
+    key = 'SUBDATASET_%d_NAME' % (i+1)
+
+    sub_golden_db = gdal.Open(golden_sds[key])
+    sub_new_db = gdal.Open(new_sds[key])
+
+    sds_diff = compare_db(sub_golden_db, sub_new_db)
+    found_diff += sds_diff
+    if sds_diff > 0:
+      print('%d differences found between:\n  %s\n  %s' \
+            % (sds_diff, golden_sds[key],new_sds[key]))
+
+  return found_diff
+  
+#######################################################
+def Usage():
+  print('Usage: gdalcompare.py [-sds] <golden_file> <new_file>')
+  sys.exit(1)
+
+#######################################################
+#
+# Mainline
+#
+
+if __name__ == '__main__':
+
+  # Default GDAL argument parsing.
+  argv = gdal.GeneralCmdLineProcessor( sys.argv )
+  if argv is None:
+    sys.exit( 0 )
+
+  if len(argv) == 1:
+    Usage()
+
+  # Script argument parsing.
+  golden_file = None
+  new_file = None
+  check_sds = 0
+
+  i = 1
+  while  i < len(argv):
+
+    if argv[i] == '-sds':
+      check_sds = 1
+
+    elif golden_file is None:
+      golden_file = argv[i]
+
+    elif new_file is None:
+      new_file = argv[i]
+
+    else:
+      print('Urecognised argument: ' + argv[i])
+      Usage()
+
+    i = i + 1
+    # next argument
+
+  #### Compare Files ####
+
+  found_diff = 0
+
+  # compare raw binary files.
+  try:
+    os.stat(golden_file)
+    
+    if not filecmp.cmp(golden_file,new_file):
+      print('Files differ at the binary level.')
+      found_diff += 1
+  except:
+    print('Skipped binary file comparison, golden file not in filesystem.')
+
+  # compare as GDAL Datasets.
+  golden_db = gdal.Open(golden_file)
+  new_db = gdal.Open(new_file)
+  found_diff += compare_db(golden_db, new_db)
+
+  if check_sds:
+    found_diff += compare_sds(golden_db, new_db)
+    
+  print('Differences Found: ' + str(found_diff))
+
+  sys.exit(found_diff)
diff --git a/swig/python/scripts/pct2rgb.py b/swig/python/scripts/pct2rgb.py
index e03cb37..76ed7fe 100755
--- a/swig/python/scripts/pct2rgb.py
+++ b/swig/python/scripts/pct2rgb.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: pct2rgb.py 25674 2013-02-23 15:21:10Z rouault $
+#  $Id: pct2rgb.py 27044 2014-03-16 23:41:27Z rouault $
 # 
 #  Name:     pct2rgb
 #  Project:  GDAL Python Interface
@@ -9,6 +9,7 @@
 # 
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
+#  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
 # 
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
diff --git a/swig/python/scripts/rgb2pct.py b/swig/python/scripts/rgb2pct.py
index 16f3138..7f6a7eb 100755
--- a/swig/python/scripts/rgb2pct.py
+++ b/swig/python/scripts/rgb2pct.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: rgb2pct.py 26002 2013-05-14 03:33:55Z warmerdam $
+#  $Id: rgb2pct.py 26001 2013-05-14 03:24:22Z warmerdam $
 # 
 #  Name:     rgb2pct
 #  Project:  GDAL Python Interface
diff --git a/swig/python/setup.py b/swig/python/setup.py
index 6f4866c..b1859aa 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -7,7 +7,7 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '1.10.1'
+gdal_version = '1.11.0'
 
 import sys
 import os
diff --git a/update_copyright.py b/update_copyright.py
new file mode 100644
index 0000000..195e211
--- /dev/null
+++ b/update_copyright.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id: update_copyright.py 27043 2014-03-16 23:32:18Z rouault $
+#
+# Project:  GDAL/OGR
+# Purpose:  Update copyright info in headers
+# Author:   Even Rouault <even dot rouault at mines-paris dot org>
+#
+###############################################################################
+# Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
+#
+# Permission is hereby granted, free of charge, to any person oxyzaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import os
+
+# WARNING: Only works from a git repository !
+
+# Please edit for a different author
+author_in_file = 'ouault'
+git_author = 'Even Rouault'
+full_author = 'Even Rouault <even dot rouault at mines-paris dot org>'
+
+for dirname, dirnames, filenames in os.walk('.'):
+
+    if dirname.find('.svn') >= 0:
+        continue
+    if dirname.find('.git') >= 0:
+        continue
+    if dirname.find('libpng') >= 0:
+        continue
+    if dirname.find('libjpeg') >= 0:
+        continue
+    if dirname.find('libtiff') >= 0:
+        continue
+    if dirname.find('giflib') >= 0:
+        continue
+    if dirname.find('libgeotiff') >= 0:
+        continue
+    if dirname.find('libjson') >= 0:
+        continue
+
+    # print path to all filenames.
+    for filename in filenames:
+        if filename.find('.svn') >= 0:
+            continue
+        if filename.find('.h') < 0 and filename.find('.c') < 0 and filename.find('.py') < 0:
+            continue
+        if filename == 'e00read.c' or filename == 'e00compr.h':
+            continue
+        fullfilename = os.path.join(dirname, filename)
+
+        #print(fullfilename)
+        minyear = -1
+        maxyear = -1
+
+        # Find if we have authored something and commit numbers to ignore (commits that originate from other authors)
+        ret = os.popen('git log %s' % fullfilename)
+        lines = ret.readlines()
+        i = 0
+        nlines = len(lines)
+        found_commit = False
+        commits_to_ignore = []
+        while i < nlines:
+            line = lines[i][0:-1]
+            if line.find('Author:') == 0 and line.find(git_author) >= 0:
+                i = i + 1
+                #line = lines[i][0:-1]
+                #year = int(line.split(' ')[7])
+                i = i + 1
+                i = i + 1
+                commit_number = lines[i-4][7:15]
+                ignore_commit = False
+                while i < nlines:
+                    line = lines[i][0:-1]
+                    if line.find('commit') == 0:
+                        break
+                    if line.find('(by') >= 0 or line.find('contributed by') >= 0 or \
+                       line.find('patch') >= 0 or line.find('Patch') >= 0 or \
+                       line.find('Update copyright') >= 0 or line.find('From: ') >= 0 or \
+                       line.find('Add BLX Magellan Topo driver') >= 0:
+                        ignore_commit = True
+                    i = i + 1
+                if ignore_commit:
+                    commits_to_ignore.append(commit_number)
+                else:
+                    found_commit = True
+            else:
+                i = i + 1
+
+        if not found_commit:
+            continue
+
+        # Count how many lines we have authored
+        ret = os.popen('git blame %s' % fullfilename)
+        lines = ret.readlines()
+        i = 0
+        nlines = len(lines)
+        count_matching_lines = 0
+        while i < nlines:
+            line = lines[i][0:-1]
+            ignore = False
+            for commit in commits_to_ignore:
+                if line.find(commit) == 0:
+                    ignore = True
+            if not ignore and line.find('Copyright') < 0:
+                idx = line.find("(" + git_author)
+                if idx > 0:
+                    count_matching_lines = count_matching_lines + 1
+                    line = line[idx+len(git_author)+1:]
+                    idx = line.find(' 20')
+                    year = int(line[idx+1:idx+5])
+                    if minyear < 0 or year < minyear:
+                        minyear = year
+                    if maxyear < 0 or year > maxyear:
+                        maxyear = year
+            i = i + 1
+
+        # only clame copyright if we have authored more than 10 lines
+        if count_matching_lines < 10:
+            continue
+
+        print(fullfilename + ' %d-%d' % (minyear, maxyear))
+        f = open(fullfilename, 'rb')
+        f2 = open(fullfilename + '.tmp', 'wb')
+        lines = f.readlines()
+        i = 0
+        nlines = len(lines)
+        already_added = False
+        if filename.find('.py') >= 0:
+            prefix = '# '
+        else:
+            prefix = ' * '
+        while i < nlines:
+            line = lines[i]
+            if not already_added and line.find('Copyright') >= 0:
+                already_added = True
+                if line.find('#  ') == 0:
+                    prefix = '#  '
+                elif line.find('# * ') == 0:
+                    prefix = '# * '
+                elif line.find('// ') == 0:
+                    prefix = '// '
+                while line.find(author_in_file) < 0:
+                    f2.write(line)
+                    i = i + 1
+                    line = lines[i]
+                    if (line.find('Copyright') < 0 and len(line.strip()) < 10) or line.find('Permission to use') > 0:
+                        break
+                if minyear < maxyear :
+                    f2.write('%sCopyright (c) %d-%d, %s\n' % (prefix, minyear, maxyear, full_author))
+                else:
+                    f2.write('%sCopyright (c) %d, %s\n' % (prefix, minyear, full_author))
+                if line.find(author_in_file) < 0:
+                    f2.write(line)
+            else:
+                f2.write(line)
+            i = i + 1
+        f.close()
+        f2.close()
+        os.rename(fullfilename + '.tmp', fullfilename)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gdal.git



More information about the Pkg-grass-devel mailing list